<?xml version="1.0" encoding=""?>
        <?xml-stylesheet type="text/css" href="http://www.tuxz.net/blog/"?>
<rss version="2.0"
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:admin="http://webns.net/mvcb/"
 xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title>Alexandre De Dommelin</title>
<atom:link href="http://www.tuxz.net/blog/rss.xml" rel="self" type="application/rss+xml" />
<link>http://www.tuxz.net/</link>
<description></description>
<dc:language></dc:language>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:date>2013-02-02T11:03:32+00:00</dc:date>
<admin:generatorAgent rdf:resource="http://nanoblogger.sourceforge.net" />

<item>
<link>http://www.tuxz.net/blog/archives/2012/12/09/jslogger_-_track_client-side_errors_using_php_sta/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2012/12/09/jslogger_-_track_client-side_errors_using_php_sta/</guid>
<title>JSLogger - Track Client-Side errors using PHP, StatsD and Graphite </title>
<dc:date>2012-12-09T20:48:31+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:subject> Articles</dc:subject>
<description><![CDATA[<p>
You're already monitoring, graphing, all errors / warnings / events on your infrastructure, but do you track what happens in your clients' web browser ? Websites are now heavily relying on client-side functions, so not keeping an eye on proper JavaScript execution is terribly stupid.<br/>
<br/>
JSLogger is roughly composed of :
</p>
<ul>
  <li>a JavaScript payload (payload.js) to be included in your pages which call your receiver on window.onerror() passing error details,</li>
  <li>a PHP script (jslog.php) which will receive and dispatch events to StatsD / Graphite &amp; MySQL database.</li>
</ul>
<p>
Code is available on <a href="https://github.com/adedommelin/jslogger">my github</a>.<br/>
Just pull everything, create your table, edit the settings in jslog.php and URL in payload.js, include it into your pages and you're done !
</p>
<div style="text-align:center">
<img src="/blog/images/jslogger_graphite.png" alt="jslogger_graphite"/>
</div>]]></description>

</item>
<item>
<link>http://www.tuxz.net/blog/archives/2012/09/25/high_availability_-_automated_origin_failover_usin/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2012/09/25/high_availability_-_automated_origin_failover_usin/</guid>
<title>High Availability - Automated origin failover using CloudFlare, Nagios and OpenShift </title>
<dc:date>2012-09-25T19:04:49+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>

<description><![CDATA[<h5>Context</h5>
A few days ago, after repeated downtimes, Steve Souders twitted :
<blockquote class="twitter-tweet"><p>How does a small hosted site (like mine) get redundancy? Two hosting companies &amp; DNS round robin? Any cookbook solutions?</p>&mdash; souders (@souders) <a href="https://twitter.com/souders/status/249221747495297024" data-datetime="2012-09-21T19:01:09+00:00">September 21, 2012</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<br/>
<p>
I found this question very interesting, and here is an answer. My criteria was to build something without refactoring all my current setup, roughly composed of :
<ul>
<li>CloudFlare as CDN in front of www.tuxz.net,</li>
<li>Nagios as monitoring system,</li>
<li>A blog powered by Nanoblogger,</li>
<li>Dokuwiki,</li>
<li>A lot of custom PHP scripts ...</li>
</ul>
<br/>
All of this running in an OpenVZ container on a single physical server somewhere on the planet.<br/>
Oh ! and also a (no longer) unused free account on OpenShift (RedHat Platform as a Service) :-)
</p>

<h5>Creating origin failover site</h5>
<p>First create a new application on OpenShift, called "failover". This application will be accessible through (depending on what your namespace is set to) : http://failover-tuxz.rhcloud.com/<br/>
<br/>
Right now, your application is empty and only accessible using its default domain name. As we want it (at the end) to answer requests targeted to our main domain name, we need to add it as an alias. This operation can only be performed using the OpenShift client. The installation is quite straightforward :</p>
<pre>
$ sudo gem install rhc
$ rhc setup
</pre>
<p><br/>You can now add your alias and use git to clone your brand new OpenShift application on your current origin, ie :</p>
<pre>
$ rhc app add-alias -a failover --alias www.tuxz.net
$ git clone ssh://xxxxxxxxxxxxx@failover-tuxz.rhcloud.com/~/git/failover.git/ /var/www/www-failover.tuxz.net/
$ tree -L 1 /var/www/
/var/www
|-- www-failover.tuxz.net
|-- www.tuxz.net
</pre>
<p><br/>Now you just need to create a custom crontab to rsync, statify, torture then commit &amp; push changes to your OpenShift application :</p>
<pre>
#!/bin/bash
PRIMARY_ROOT="/var/www/www.tuxz.net"
FAILOVER_ROOT="/var/www/www-failover.tuxz.net/php"
TS=`date`
rsync -rvl --delete ${PRIMARY_ROOT}/ ${FAILOVER_ROOT}/

#- do all your custom stuff here -#
cd ${FAILOVER_ROOT}/
git add .
git commit -m "www.tuxz.net - ${TS}"
git push
</pre>                                                                                                                                                                                                                  
<p>At this time, your OpenShift app should contain the exact (or tortured) copy of your primary origin.</p>

<h5>Modifying DNS configuration</h5>
<p>To make identification easier, update your DNS configuration to add 2 CNAME "www-primary" and "www-failover" pointing respectively to your primary server &amp; your OpenShift application, then CNAME your "www" entry to "www-primary" &amp; enable CloudFlare servies on it.<br/>You should end up with results similar as : </p>
<pre>
$ dig -t CNAME +short www-primary.tuxz.net
fw0.tuxz.net.

$ dig -t CNAME +short www-failover.tuxz.net
failover-tuxz.rhcloud.com.

$ dig -t CNAME +short www.tuxz.net
cf-protected-www.tuxz.net.
</pre>

<h5>Configuring Nagios to switch traffic to failover site in case of primary origin failure</h5>
<p>We are going to use Nagios events handler built-in mechanism, which allow us to run scripts "when something happens".<br/>
In our case we're going to run a script interacting with CloudFlare DNS API and change the value of our origin server for our main domain.<br/>
<br/>
Here is the relevant part of the Nagios configuration :</p>
<pre>
define service {
  use generic-service
  host_name www-primary.tuxz.net
  service_description Ensure that primary origin is healthy
  check_command your_command
  contact_groups admins
  max_check_attempts 4
  event_handler switch_to_failover_site
}

# commands.cfg
define command {
  command_name switch_to_failover_site
  command_line /usr/local/nagios/libexec/eventhandlers/switch_to_failover_site.sh $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$ $HOSTADDRESS$ $HOSTDOWNTIME$ $SERVICEDOWNTIME$
}
</pre>
<p><br/>And the content of <i>switch_to_failover_site.sh</i> :</p>
<pre>
#!/bin/sh

CLOUDFLARE_API_KEY="111111111"
CLOUDFLARE_LOGIN="toto@example.com"
DNS_ZONE="example.com"
DNS_ENTRY="www.example.com"
DNS_ENTRY_ID="1111111"
DNS_ENTRY_TYPE="CNAME"
DNS_ENTRY_FAILOVER="www-failover.example.com"

__switch_to_failover() {
  /usr/bin/curl https://www.cloudflare.com/api_json.html \
    -d "a=rec_edit" \
    -d "tkn=${CLOUDFLARE_API_KEY}" \
    -d "id=${DNS_ENTRY_ID}" \
    -d "email=${CLOUDFLARE_LOGIN}" \
    -d "z=${DNS_ZONE}" \
    -d "type=${DNS_ENTRY_TYPE}" \
    -d "name=${DNS_ENTRY}" \
    -d "content=${DNS_ENTRY_FAILOVER}" \
    -d "ttl=1" \
    -d "service_mode=1"
}


[ "$1" = "CRITICAL" ] || exit 0
if [ "$2" = "SOFT" ];
then
  if [ $3 -eq 3 ];
  then
    servicestatus="$5""$6";
    [ "$servicestatus" = "00" ] && __switch_to_failover;
  fi;
fi;
</pre>
<p>
Notes about this script :
<ul>
  <li>Customize variables at the top with your domain entries and cloudflare credentials / API key</li>
  <li>DNS_ENTRY_ID can be obtained by querying the API with the "rec_load_all" parameter (see <a href="http://www.cloudflare.com/docs/client-api.html#s3.3">CloudFlare API Doc</a>)</li>
  <li>The script will trigger origin switch after 3 fail checks</li>
</ul>
<br/>
<br/>
One interesting side effect of using CloudFlare is that there's almost no DNS propagation delay. In fact your main entry is "publicly" not modified (still CNAME'd to cf-protected-www.tuxz.net) but the update is quickly propagated to the CloudFlare infrastructure. My tests shown an appox. 1 minute delay.
</p>]]></description>

</item>
<item>
<link>http://www.tuxz.net/blog/archives/2012/09/08/how_to_easily_build_native_packages_of_everything/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2012/09/08/how_to_easily_build_native_packages_of_everything/</guid>
<title>How to easily build native packages of everything with FPM </title>
<dc:date>2012-09-08T14:31:09+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:subject> Articles</dc:subject>
<description><![CDATA[<p>When having a lot of servers, relying on built-in package management tools to deploy software is a must just for :
<ul>
  <li>Dependencies</li>
  <li>Versioning capabilities</li>
  <li>File checksums / integrity</li>
  <li>Upgrades management</li>
  <li>Distribution (apt-get, yum ...)</li>
</ul>
Unfortunately, required versions are often not available, your home-made software neither. But building your own packages, no matter how good you get at it, can be a difficult and is a time consuming process.<br/>                                                                                                                                                         This is where FPM will help you : you'll be able to create in a few seconds a deb, rpm, solaris package and even a puppet module from a gem, python module, folder, or npm.            </p>                                                                                                                                                                                                                                                                                                                                                                          <h5>FPM installation</h5>
<p>FPM can be easily installed through gem :</p>
<pre>
$ sudo gem install fpm
</pre>
<p>
The code is also available on <a href="https://github.com/jordansissel/fpm">github</a>.
</p>


<h5>Example with nodejs</h5>
<pre>
$ wget -q http://nodejs.org/dist/v0.8.8/node-v0.8.8.tar.gz
$ tar -xzf node-v0.8.8.tar.gz
$ cd node-v0.8.8/
$ ./configure --prefix=/usr
$ make
[...]
$ mkdir /tmp/node-install
$ make install DESTDIR=/tmp/node-install
[...]
$ fpm -s dir -t rpm -n node -v 0.8.8 -C /tmp/node-install usr/bin usr/lib
</pre>

<p>Et voila ! You now have a shiny rpm package that you can deploy on your own infrastructure.<br/>
Full documentation and use cases are available on <a href="https://github.com/jordansissel/fpm/wiki">the official FPM wiki</a>.</p>]]></description>

</item>
<item>
<link>http://www.tuxz.net/blog/archives/2012/08/19/improving_website_security_with_http_headers/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2012/08/19/improving_website_security_with_http_headers/</guid>
<title>Improving website security with HTTP Headers </title>
<dc:date>2012-08-19T12:36:24+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:subject> Articles</dc:subject>
<description><![CDATA[<p>
Some security related features in HTTP headers have been developed. These controls can be used to modify the web browser behaviour and thus protect the user from browser based exploits. Unfortunately, an analysis on the top 1M websites (Alexa's rank) show that implementation of those security controls is at best minimal and actually closer to non-existent ...
</p>

<h5>X-XSS-Protection</h5>
<p>
This header is only interpreted by IE 8 &amp; 9.<br/>
It turns on XSS (Cross-Site-Scripting) protection which is turned off by default as it could potentially break some websites. To turn on the XSS filter, inject the header X-XSS-Protection "1; mode=block". Sending a value of "0" enforce the protection to be disabled. 
</p>
<pre>
X-XSS-Protection: "1; mode=block";
</pre>

<h5>X-Content-Type-Options: "nosniff"</h5>
<p>
This header protects browser from "mime" based attacks. It will prevent IE from MIME-sniffing a response away from the declared Content-Type. So if the server says the content is "<i>text/html</i>", the browser will render it as "<i>text/html</i>".
</p>
<pre>
X-Content-Type-Options: "nosniff";
</pre>

<h5>X-Frame-Options</h5>
<p>
The X-Frame-Options HTTP response header is used to indicate whether or not a browser is allowed to render a page in a &lt;frame&gt; or &lt;iframe&gt;. This can be used to avoid clickjacking attacks, by ensuring that your website will never be embedded into a malicious website.<br/><br/>
  Three values are supported :
  <ul style="list-style-type: circle;">
    <li><i>DENY</i> : Prevents any page to be rendered if loaded into a &lt;frame&gt; or &lt;iframe&gt; even from the same domain.</li>
    <li><i>SAMEORIGIN</i> : Prevents any page to be rendered if loaded into a &lt;frame&gt; or &lt;iframe&gt; from an external website.</li> 
    <li><i>ALLOW-FROM origin</i> : Prevent any page to be rendered if if the origin of the top-level browsing context is different than the origin value supplied with the Allow-From directive.</li>
  </ul>
</p>
<pre>
X-Frame-Options "DENY";
</pre>

<h5>X-Content-Security-Policy</h5>
<p>
This header is designed to specify how content interacts with your website. It helps mitigate and detect types of attacks such as XSS and data injection. <u>Important: all the inline scripts are prohibited by default when using CSP.</u><br/>
<br/>
Multiple combinations are possible :
</p>
Enforce all content to be served from the same domain
<pre>
X-Content-Security-Policy: allow 'self'
</pre>
Allow images to be loaded from everywhere, plugin content from trusted CDN, script from trusted domain
<pre>
X-Content-Security-Policy: allow 'self'; img-src *; \
                           object-src *.cdn.com; \
                           script-src trustedscripts.example.com
</pre>
Enforce all content to be loaded over SSL
<pre>
X-Content-Security-Policy: allow https://*:443
</pre>

<p>
You can also specify multiple headers (ie: server wide level + project specific directives) :
</p>
<pre>
X-Content-Security-Policy: allow *; script-src 'self'
X-Content-Security-Policy: allow *; script-src 'self'; media-src 'self';
</pre>]]></description>

</item>
<item>
<link>http://www.tuxz.net/blog/archives/2012/07/22/using_haproxy_to_block_80legs_ddos-toolcrawler/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2012/07/22/using_haproxy_to_block_80legs_ddos-toolcrawler/</guid>
<title>Using HAProxy to block 80legs (DDOS-tool|crawler)</title>
<dc:date>2012-07-22T15:32:40+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:subject> Tips</dc:subject>
<description><![CDATA[<div class="alert">
<b>Disclaimer : </b>This post does only reflect my personal opinion and can't be associated to the opinion of the company I work for.
</div>
<p>I've seen yesterday night something which could be described as a "DDOS attack" on one of the infrastructure I'm managing : during approx. 7h we've received a continuous huge amount of connections / HTTP requests coming from more than 1800 differents IP, mainly located in :
<ul>
	<li>Russian Federation</li>
	<li>Ukraine</li>
</ul>
This increase was brutal (not progressive, in 1-2 minutes), and disappeared the same way. A first analysis show that these connections were initiated by 80legs.com, a "distributed web-crawler" which allows anybody to <i>Setup [your own] web crawl in minutes and run it on over 50,000+ computers</i>, as we can see in the HTTP Headers : 
</p>
<pre>
User-Agent: Mozilla/5.0 (compatible; 008/0.83; http://www.80legs.com/webcrawler.html) Gecko/2008032620	
</pre>
<p>
After digging into google, it seems that many people had the same experience with this crawler and that requesting rate-limiting was not successful. Moreover, some people also describe the fact that denying 80legs in the robots.txt was not sufficient to prevent them to crawl you. So, in this case I suggest you to put preventive rules either in your Web Application Firewall or in your load-balancer / webserver to prevent them reaching / overloading your web infrastructure.<br/>
<br/>
Below an example of HAProxy configuration to tarpit all HTTP requests from this crawler : 
</p>
<pre>
frontend HTTP
	[...]
        #
        # Block all requests from 80legs
        #
        reqitarpit ^User-Agent:.*80legs*
</pre>]]></description>

</item>
<item>
<link>http://www.tuxz.net/blog/archives/2012/05/31/world_ipv6_launch_-_www_tuxz_net_is_ready/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2012/05/31/world_ipv6_launch_-_www_tuxz_net_is_ready/</guid>
<title>World IPv6 Launch - www.tuxz.net is ready !</title>
<dc:date>2012-05-31T13:29:39+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:subject> Foo</dc:subject>
<description><![CDATA[<p>
<div style="text-align: center"><img src="http://www.tuxz.net/images/World_IPv6_launch_banner_256.png" alt="ipv6_launch_banner" height="256"/></div><br/>
Major Internet service providers (ISPs), home networking equipment manufacturers, and web companies around the world are coming together to permanently enable IPv6 for their products and services by 6 June 2012, and www.tuxz.net is also IPv6 compliant :o)
</p>]]></description>

</item>
<item>
<link>http://www.tuxz.net/blog/archives/2012/04/08/cloudflare_haproxy_and_acls__how_to_protect_your/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2012/04/08/cloudflare_haproxy_and_acls__how_to_protect_your/</guid>
<title>CloudFlare, HAProxy and ACLs : how to protect your origin</title>
<dc:date>2012-04-08T21:27:05+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:subject> Articles</dc:subject>
<description><![CDATA[<p>
I'm now using CloudFlare (a CDN service) for tuxz.net which provides various features (Antispam, Web Application Firewall...).
</p>
<img src="/images/cf-web-badges-c-gray-on.png" alt="CloudFlare powered" style="margin: 15px 0px 15px 0px;"/>
<p>
One cool thing : they provide the full IP ranges of their platform so you can easily lock down your origin to only accept connections coming from the CloudFlare network.<br/>
Unfortunately, I'm hosting websites that don't use CloudFlare, so I can't put these restrictions directly in my firewall ... so let's have some fun at L7 with <strong>HAProxy</strong> & <strong>ACL</strong> feature.<br/>
<br/>
The use of Access Control Lists (ACL) provides a flexible solution to perform content switching and generally to take decisions based on content extracted from the request, the response or any environmental status. You can combine them to decide what to do with an incoming request (block, pass to a backend server ...).<br/>
In my case, I want to block all requests not targetted to the hosting platform which are not coming through the CloudFlare network, see below for the corresponding <strong>HAProxy</strong> configuration section :
</p>
<pre class="prettyprint linenums">
frontend HTTP
	[...]
	#
	# Block all requests not coming from CloudFlare Network
	#
	acl cloudflare_valid_ip src -f /etc/haproxy/cloudflareIPs
	block if !host_hdr_hosting !cloudflare_valid_ip

	use_backend web.tuxz.net if host_hdr_tuxz
	use_backend hosting.tuxz.net if host_hdr_hosting

</pre>
<p>
The "/etc/haproxy/cloudflareIPs" is basically a local copy of <a href="https://www.cloudflare.com/ips-v4">https://www.cloudflare.com/ips-v4</a>, which is updated each time a new IP Range is added. Don't forget to follow updates !
</p>]]></description>

</item>
<item>
<link>http://www.tuxz.net/blog/archives/2011/11/22/apache__inject_http_response_header_in_a_rewrited/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2011/11/22/apache__inject_http_response_header_in_a_rewrited/</guid>
<title>Apache : Inject HTTP response header in a rewrited URL using environment variable </title>
<dc:date>2011-11-22T20:11:31+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:subject> Tips</dc:subject>
<description><![CDATA[<p>
I've spent a few hours looking for a way to inject HTTP response headers in a rewrited URL directly from the Apache configuration.<br/>
<br/>
Here's the trick, in the RewriteRule just set a environment variable, ie: "addheader". <br/>
But unfortunately, this one can't be used as-is as a condition in the "Header" directive. In this case you'll need to rely on the presence / absence of the "REDIRECT_addheader" : 
</p>
<pre clas="sh_sh">
RewriteEngine On
RewriteRule ^([A-Z]{2})_([a-z]{2})$  /rewrite.php?a=$1&b=$2 [L,E=addheader:1]
Header set my-header "myvalue" env=REDIRECT_addheader
</pre>]]></description>

</item>
<item>
<link>http://www.tuxz.net/blog/archives/2011/11/19/puppet_talk__journ_eacutees_du_logiciel_libre_20/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2011/11/19/puppet_talk__journ_eacutees_du_logiciel_libre_20/</guid>
<title>Puppet Talk @ Journ&eacute;es du Logiciel Libre 2011 </title>
<dc:date>2011-11-19T10:31:32+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:subject> Foo</dc:subject>
<description><![CDATA[<p>
Here are the slides of the talk I've given at Journ&eacute;es du Logiciel Libre yesterday in Lyon (<a href="http://static.tuxz.net/docs/JDLL2011_Puppet.pdf">Download</a>)
</p>
<div style="width:425px" id="__ss_10234241"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/adedommelin/prsentation-puppet-journes-du-logiciel-libre-2011" title="Présentation Puppet Journées du Logiciel Libre 2011">Présentation Puppet Journées du Logiciel Libre 2011</a></strong><object id="__sse10234241" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=jdll2011puppet-111119101747-phpapp01&stripped_title=prsentation-puppet-journes-du-logiciel-libre-2011&userName=adedommelin" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><param name="wmode" value="transparent"/><embed name="__sse10234241" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=jdll2011puppet-111119101747-phpapp01&stripped_title=prsentation-puppet-journes-du-logiciel-libre-2011&userName=adedommelin" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="transparent" width="425" height="355"></embed></object><div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/adedommelin">Alexandre De Dommelin</a>.</div></div>]]></description>

</item>
<item>
<link>http://www.tuxz.net/blog/archives/2011/10/19/parse__ini_files_with_bash_and_sed/</link>
<guid isPermaLink="true">http://www.tuxz.net/blog/archives/2011/10/19/parse__ini_files_with_bash_and_sed/</guid>
<title>Parse .ini files with bash and sed </title>
<dc:date>2011-10-19T18:41:31+00:00</dc:date>
<dc:creator>Alexandre De Dommelin</dc:creator>
<dc:subject> Tips</dc:subject>
<description><![CDATA[<p>
Here's a very cool way to parse ini files inside a shell script.<br/>
The following snippet will declare variables in the current scope of your script from all the key/values pairs present in the matching section.
</p>
<pre class="sh_sh">
#!/bin/bash
CONFIG_FILE="config.ini"
SECTION="section_1"

eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
    -e 's/;.*$//' \
    -e 's/[[:space:]]*$//' \
    -e 's/^[[:space:]]*//' \
    -e "s/^\(.*\)=\([^\"']*\)$/\1=\"\2\"/" \
   < $CONFIG_FILE \
    | sed -n -e "/^\[$SECTION\]/,/^\s*\[/{/^[^;].*\=.*/p;}"`
</pre>
<p>To remove confusion with the license covering my articles, this snippet is available under the WTFPL license.</p>
<pre>
            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
                    Version 2, December 2004

 Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>

 Everyone is permitted to copy and distribute verbatim or modified
 copies of this license document, and changing it is allowed as long
 as the name is changed.

            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. You just DO WHAT THE FUCK YOU WANT TO.
</pre>]]></description>

</item>
</channel>
</rss>
