e107 Importer WordPress plugin v1.0 released !

After 3 years in limbo, here is a new stable version of my e107 Importer plugin for WordPress, proudly numbered 1.0 ! :)

This is the first time this plugin is available on the official WordPress plugin repository. This means easy upgrades for you ! :)

I’ve heavily updated the plugin to use the latest WordPress import framework, so everything is now cleanly integrated.

This version was tested with e107 v0.7.24 and WordPress 3.1-RC3.

Here is the changelog:

A note for developpers: the reference code base is now located on GitHub. That’s were all new code must be commited. WordPress’ Subversion repository is only a mirror.

If any question, please read the FAQ first.

New blog header and tiny WordPress theme customizations

I maintain a bunch of websites for friends on my server. In this context, Maomium‘s owner owed me some bucks for his .com domain name. Here is the envelope I received yesterday with a check:

Now that’s what I call a personalized letter ! This original artwork is so great that I had to share it.

The hours he put creating this original artwork mirror the effort I invested maintaining his digital properties (a WordPress blog, a Drupal-based online store and a ZenPhoto gallery). That’s the best thank you note I have received so far ! :)

Jim from Maomium is a really talented artist and really deserve attention. He used to have an online shop where you can buy his paintings and customized furnitures. But we shut it down some weeks ago. Its replacement is not available yet, so if you want to buy him unique hand-made piece of art, don’t hesitate to get in touch with him at jim@maomium.com.

And with Jim’s approval, I now use his letter’s artwork as my blog image header. It’s much better than the default theme image ! ;)

Talking about this , here is a quick tip to make minimal design changes to a WordPress theme. The idea is to put custom CSS directives in a widget, as below:

As widgets are site-wide, all these CSS customizations will be applied everywhere. Here is for example the code I applied on this site to hide blog’s name and description from TwentyTen‘s header:

<style type="text/css"><!--
#header {
  padding-top: 0;
}
#site-title a, #site-description {
  display: none;
}
--></style>

This quick and dirty hack is perfect for tiny customizations. It will make your CSS easier to maintain as you don’t have to modify the core style files or create a child theme.

Apache commands

  • Hide Subversion and Git directories content (source):
    RedirectMatch 404 /\.(svn|git)(/|$)
    
  • Disable rendering of PHP files coming from imported third party Javascript submodules (context):
    RedirectMatch 404 js-(.*)\.php$
    
  • Redirect any request to current year sub-directory (I used this for a yearly-updated static web page):
    RewriteEngine on
    RewriteRule !^/2010/ /2010/ [R=301,L]
    
  • Here is my template for domain-based virtual host routing:
    # Setup the main website access
    <VirtualHost *:80>
      ServerName example.com
      DocumentRoot /var/www/example
      # Add extra capabilities to let CMS like WordPress manage redirections
      <Directory /var/www/example>
        Options +FollowSymLinks +SymLinksIfOwnerMatch
      </Directory>
    </VirtualHost>
    # Redirect all other access to the website from different domains to the canonical URL
    <VirtualHost *:80>
      ServerName www.example.com
      ServerAlias *.example.com
      ServerAlias example.net *.example.net
      ServerAlias example.org *.example.org
      RedirectMatch permanent (.*) http://example.com$1
    </VirtualHost>
    
  • Insert dynamic headers in HTTP responses depending on the browser:
    BrowserMatchNoCase ".*MSIE\s[1-6].*" IS_DISGUSTING_BROWSER
    Header add X-advice-of-the-day "Save a kitten: use Firefox !" env=IS_DISGUSTING_BROWSER
    
  • Prevent WebDAV connexions (thanks Guillaume!):
    <Location />
      <Limit PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK PATCH>
        # Leaves GET (and HEAD), POST, PUT, DELETE, CONNECT, OPTIONS and TRACE alone
        Order allow,deny
        Deny from all
      </Limit>
    </Location>
    SetEnvIf Request_Method "OPTIONS" CLIENT_PROBE
    Header set Allow "GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE" env=CLIENT_PROBE
    
  • At work, we had to engineer a convoluted software architecture for our intranet to fit the network security policy of our customer. This had a bad side effect of letting the web statistic collector delete all cookies but its own, thus breaking intranet’s authentication. So we (thanks Matthieu!) came up with this unmaintainable hack on Apache side to hide our intranet’s cookies to NedStat’s Javascript embedded code:
    <LocationMatch "/(.*)">
      LoadModule headers_module modules/mod_headers.so
      RequestHeader edit Cookie "(app_cookie_001=[^;]*(; )*)" ""
      RequestHeader edit Cookie "(app_cookie_002=[^;]*(; )*)" ""
      RequestHeader edit Cookie "(app_cookie_003=[^;]*(; )*)" ""
    </LocationMatch>
    
  • Kill all apache processes and restart the service:
    /etc/init.d/apache2 stop ; pkill -9 -u www-data ; /etc/init.d/apache2 restart
    
  • Restart Apache service if no process found:
    [ `ps axu | grep -v "grep" | grep --count "www-data"` -le 0 ] && /etc/init.d/apache2 restart
    

Python commands

  • Add a Python’s debugger break point:
    import pdb; pdb.set_trace()
    
  • Replace accentuated characters by their ASCII equivalent in a unicode string:
    import unicodedata
    unicodedata.normalize('NFKD', u"éèàçÇÉȲ³¼ÀÁÂÃÄÅËÍÑÒÖÜÝåïš™").encode('ascii', 'ignore')
    
  • Lambda function to transform a string to a URL-friendly ID:
    getSafeURL = lambda s: '-'.join([w for w in ''.join(1).split('-') if w])
    
  • Sort a list of dicts by dict-key (source):
    import operator
    [dict(a=1, b=2, c=3), dict(a=2, b=2, c=2), dict(a=3, b=2, c=1)].sort(key=operator.itemgetter('c'))
    
  • Set urllib2 timeout (source):
    import socket
    socket.setdefaulttimeout(10)
    
  • Start a dumb HTTP server on port 8000 (source):
    python -m SimpleHTTPServer 8000
    

Date manipulation

  • Add a month to the current date:
    import datetime
    import dateutil
    datetime.date.today() + dateutil.relativedelta(months=1)
    

Package management

  • Generate a binary distribution of the current package:
    python ./setup.py sdist
    
  • Register, generate and upload to PyPi the current package as a source package, an egg and a dumb binary:
    python ./setup.py register sdist bdist_egg bdist_dumb upload
    
  • Here is how my ~/.pypirc looks like:
    [pypirc]
    servers = pypi
    [server-login]
    username:kdeldycke
    password:XXXXXXX