If you haven’t noticed, yet, many of my recent developments have been for, and regarding Debian.

A current client is a RedHat Enterprise 4, CentOS, FreeBSD, and Debian shop, with Debian being on the front end. As the key systems are integrated to a unified OS approach, one of the most important aspects is to keep your front end systems up to date with security, first and foremost, then consistant features (with the legacy, where appropriate), and finally, new bells and whistles.

This ensures your deliverability; I can’t understand how large companies like YouTube manage to redirect people to a page saying ‘Sorry, guys, it’s that time of the week again. Everything’s down for a few hours.’

That’s awful design, and incredibly useless if your whole product is reliant on actually being available to make money.

Yet, I digress. This is now “Web 2.0” where the game seems to be “content over form.” All hail the new Emperor.. just as soon as he finishes touching up his body paint.

I’m all for commerce, and advertising is just a side effect of consumerism. However, I don’t want to see ads when I’m checking my bank account online. I consider this pretty crass, and sad that my bank would opt to allow such things.

Below is the information I’ve discovered to make it go away:

If you do not want to receive prescreened offers of credit from this or other companies, call the consumer reporting agencies toll free, 888-567-8688; or write: TransUnion Name Removal Option, P.O. Box 505, Woodlyn, PA 19094; Equifax Information Service Center, P.O. Box 740123, Atlanta, GA 30374-0123; or Experian Direct Marketing, P.O. Box 919, Allen, TX 75013.

Thankfully, BofA made this fairly easy to find today (after three years of no opt out information). Perhaps they were sued.

This is incredibly simple, but it’s amazing how many people (ab)use Perl to do something that awk was designed for.

Here’s how to find your existing Linux styled ethernet interfaces:

%ifconfig -a | awk '(/inet\ addr/||/^eth/||/^lo/)&&!/127/ \
gsub(/inet\ addr:/, "") { print $1}'
eth0
10.10.0.212
eth1
85.92.154.212
eth1:1
192.168.30.1
lo
127.0.0.1

Those of you who might be able to read that will ask: Why not /127/? It’s a dummy test. :)

Long story short, due to political (licensing) reasons, MySQL support was removed from Apache’s APR base. Here’s how to get it back and fix a few bugs in the default driver (the default causes it to die with various named virtualhosts):

First, ensure you have the ability to build all of the requirements:

# apt-get build-dep libaprutil1 libaprutil1-dev

Then, install the libmysqlclient support (the new MySQL 5 driver):
# apt-get install libmysqlclient15-dev wget apache2.2-common

Get the necessary driver
# apt-get source apr-util
# cd ./apr-util-1.2.7+dfsg/dbd
# wget 'http://apache.webthing.com/svn/apache/apr/apr_dbd_mysql.c'
# cd ..

Get the timeout patch.
  1. wget ‘http://issues.apache.org/bugzilla/attachment.cgi?id=20479’ -o apr.patch
  2. patch < apr.patch

Build libaprutil1.
# vi debian/rules
.. add —with-mysql=/usr to the configure line ..
# (fakeroot) debian/rules binary

Install APR (add dev if required.)
# dpkg -i ../libaprutil1_1.2.7+dfsg-2_i386.deb \
   ../libaprutil1-dev_1.2.7+dfsg-2_i386.deb

Get the Apache source
# apt-get source apache2
# cd apache2-2.2.3/modules/database/

Update the database driver
# wget 'http://svn.apache.org/viewvc/httpd/httpd/trunk/modules\
/database/mod_dbd.c?view=co'
# mv 'mod_dbd.c?view=co' mod_dbd.c

Build the new Apache:
# cd ../..
# (fakeroot) debian/rules binary

Install the new Apache (I need PHP, so I use prefork):
# dpkg -i ../apache2-mpm-prefork_2.2.3-4_i386.deb \
   ../apache2-utils_2.2.3-4_i386.deb

Now, go ahead and enable it, then restart:

#ln -s /etc/apache2/mods-available/dbd.load /etc/apache2/mods-enabled/
#/etc/init.d/apache2 restart

You may wish to tag your custom Apache to keep it from being overwritten by standard apt upgrades:

#for n in libapr1 libapr1-dev libaprutil1 \
libaprutil1-dev apache2-mpm-prefork \
apache2-utils apache2.2-common; do echo $n hold | \
dpkg --set-selections; done

You’re all set!

[Edit: When I wrote this initially, I was thinking of an older way to flag packages with apt; the proper way is to set them with dpkg. Thanks to Bart Cilfone for noticing my err.]

[Edit 2: A clarification by Stephan Jansen appended for your information (steps above modified): The mod_dbd.so is located in the apache2.2-common package, so this needs to be install also.
Another issue: There is a bug in apr-util which causes authentication to fail after an mysql-connection timeout occures (default: 8 hours of inactivity). The Patch at bug #42841 resolved this problem for me.]

As many of the (few) readers of my blog of years ago know, I often work in PHP – it’s simpler than Perl for a small project, and is fairly universally available with most UNIX hosts these days. For those who are not familiar, it’s essentially ASP for UNIX hosts.

I figured I’d offer a rather trivial routine that’s useful for anyone who uses either libcURL in PHP or has URL wrappers within PHP enabled. The below has been reformatted to fit most browsers. I usually abuse ternary operators, but I wanted this to be legible for most PHP coders:

<?php

/*** get_http_content() by Shawn Holwegner, *** This function is placed under the GPL; I’m sure there are several *** thousand like it, some may be prettier. *** If you use this, please acknowledge so. *** Support and expansion is available for cash prizes. *** v 1.0: 4/13/2007 – ssh – Implemented full wrapper for cURL & *** file_get_contents() with AUTH_BASIC *** user:pass token support. ***/

function get_http_content($url, $fakeRefer=FALSE, $fullURLHack=FALSE, \ $userAgent=“Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)”, \ $saveHeaders=FALSE, $followRedirects=TRUE, $softTimeout=4, \ $hardTimeout=8) { // If we can’t parse the URL, it’s invalid: Quit here. $urlArray = parse_url($url) ? parse_url($url) : FALSE;

// First, look for, and hope that we have cURL. if (function_exists(‘curl_init’)) { if (isset($urlArray[‘port’]) // If we are not using the default port, set it up. curl_setopt($curl_session, CURLOPT_PORT, $urlArray[‘port’]); // Setup our user/pass session if required. if (isset($urlArray[‘user’]) && isset($urlArray[‘pass’])) { // We want allow transparent sending of user/pass combo for redirect curl_setopt($curl_session, CURLOPT_UNRESTRICTED_AUTH, TRUE); // Pass cURL our username:password combo in “user:pass” format curl_setopt($curl_session, CURLOPT_USERPWD, $urlArray[‘user’] . “:” \ . $urlArray[‘pass’]); // Accept Basic Authentication. curl_setopt($curl_session, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); } $curl_session = curl_init(); // We’re going to force ourselves to use GET, in case if the previous // request was a POST/HEAD curl_setopt($curl_session, CURLOPT_HTTPGET, TRUE); // Our ‘soft connection’ timeout (4sec) curl_setopt($curl_session, CURLOPT_CONNECTTIMEOUT, “$softTimeout”); // Force failure after this time (8sec) curl_setopt($curl_session, CURLOPT_TIMEOUT, “$hardTimeout”); // Set our UserAgent to look like a real browser, IE7 on Vista. curl_setopt($curl_session, CURLOPT_USERAGENT, “$userAgent”); // If we want to save our header (debugging purposes) if ($saveHeaders) { curl_setopt($curl_session, CURLOPT_HEADER, $saveHeaders); } // Do we want to follow redirects? if (!isset($urlArray[‘user’]) && !isset($urlArray[‘pass’])) { curl_setopt($curl_session, CURLOPT_FOLLOWLOCATION, $followRedirects); // Set cURL to create it’s own redirects, else, create our own. if ($followRedirects && !$fakeReferer) { // If we follow redirects, by default, use the cURL’s referrers curl_setopt($curl_session, CURLOPT_AUTOREFERER, TRUE); } else { // XXX —- This breaks HTTP Spec, and SHOULD NOT BE USED! if ($fullURLHack) { // Hack to rebuild URL without any builtin PHP functions. if (isset($urlArray[‘query’])) $urlArray[‘path’] = $urlArray[‘path’] . “?” . \ $urlArray[‘query’]; if (isset($urlArray[‘fragment’])) $urlArray[‘path’] = $urlArray[‘path’] . “#” . \ $urlArray[‘fragment’]; } // The fake referrer will rebuild our referrer from our path, // as per HTTP spec, if not prev. overloaded with the // fullURLHack above. curl_setopt($curl_session, CURLOPT_REFERER, \ $urlArray[‘scheme’] . “://” . $urlArray[‘host’] . \ “/” . $urlArray[‘path’]); if ($followRedirects) // We want to follow redirects, with fake referrer. curl_setopt($curl_session, CURLOPT_AUTOREFERER, TRUE); } // This is not threaded, and we don’t care. Return transfer. curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, true); // Set our request, finally. curl_setopt($curl_session, CURLOPT_URL, “$url”); // Actually do it $retString = curl_exec($curl_session); // Clean up, and close. curl_close($curl_session); // Ok, no cURL. Fine. } else { // If file_get_contents() exists, and we can get URLs // Note test for = equality, and not , as 0 FALSE, // but are not always the same type. (cry) if (function_exists('file_get_contents') && \ (ini_get('allow_url_fopen') = “1”)) { // Set ourselves up as a browser, no user agent, and // defaults are often bad. @ini_set(‘user_agent’, $userAgent); // Get it, or fail out. $retString = file_get_contents($url); if empty($retString) return FALSE; } else { // We can’t retrieve the URL, no, we’re not going to // write a socket wrapper. // Should return a different error, but obviously, // I don’t want to return an array. return FALSE; } } return $retString; }

?>


The above will use either php’s built in file_get_contents() with a URL wrapper, or libcURL, if possible. It’s hardly extensive, but it should allow you to get most data properly, it even supports basic user authentication.

Note that this does not support a raw socket only HTTP request; I’ve implemented those before; there’s virtually no need to do so today.

This system is not extensive enough for persistant connections; it’s not designed to be. It is a procedural method, not a class. There’s also no reason for this to be OOP, yet.

Note the warning about $fullURLHack – it will report the FULL URL for a referrer; however this is not in the HTTP spec. the HTTP spec ifications state to end referral with the path, pre-query. This allows for debugging, but should NOT be used in production.

...It’s a pretty long wrapper for a smarter file_get_contents(), I know. Welcome to Enterprise grade code.