How to determine what version of Debian you are running
March 2010 - Starting a terminal session and running this
uname -a
...will tell you the architecture (x86 or AMD64), Linux kernel version number, and whatever name you gave to your custom kernel. But to find out whether you're running Etch (4.0) or Lenny (5.0) run this
cat /etc/issue
Links
Debian
http://www.debian.org/
Why does Google Analytics underreport my web site traffic?
August 2009 - Well, this isn't really a How To, but it certainly should address a question a lot of people have about Google Analytics:
Google Analytics uses a JavaScript include to report your web site's traffic back to the Google Mothership.
If there's something wrong with your web site serious enough to cause JavaScript to fail (it could be as simple as an unclosed HTML tag) Google Analytics won't report back and that information won't be collected.
Furthermore, Google Analytics won't report on hits (visitors) you're getting on your RSS feeds, media, or any file your previous web developer should have told you he/she could not include the Google Analytics JavaScript.
How to solve the problem:
Your web site (on a shared or dedicated server) is very likely logging ALL traffic on your web site, and your web hosting provider probably provides a tool like AWstats to view the statistics. It's not as pretty as Google Analytics, but it's complete.
Look at another software and means of collecting and reporting on your web site's traffic. There will be a Yellahoose blog about this in the near future.
Contact a professional to review your web site and fix the problem causing Google Analytics to fail to correctly report your web site's traffic in the first place.
How to use rsync over ssh
February 2009 -
rsync is a good tool, and like a shell an essential tool in the system administrators toolbox. To use it over
ssh use the remote shell option:
rsync -e ssh -az * sbody@remotehost:~/Stuff/
How to trim leading and trailing whitespace in JavaScript
January 2009 - Most languages have a
trim() or
strip() language to remove leading and trailing whitespace. JavaScript doesn't. But you can add your own function easily:
function trim(somestring) {
return somestring.replace(/^\s+|\s+$/g, '');
}
How to keep Mac OS X updated via the command line
December 2008 - Yes, Aqua is great, and easy, powerful and beautiful, but if the Mac OS X Server you're trying to update is "headless" (doesn't have a monitor attached) and Remote Desktop isn't running, you can keep things up-to-date with
softwareupdate.
Links
About
softwareudpate at Apple
http://support.apple.com/kb/HT1974
Also, try launching Terminal, typeing
man softwareupdate, and pressing Return.
How to create a random string in Python
October 2008 - It's simple.
Python:
#!python
import string
from random import choice
def get_rand_str(len = 8):
chars = "%s%s" % (string.letters, string.digits)
rand_str = ""
for i in range(len):
rand_str = "%s%s" % (rand_str, choice(chars))
return rand_str
print get_rand_str(32)
PHP:
<?php
function get_rand_str($len = 8) {
$chars = sprintf("%s%s%s",
join("", range("a", "z")),
join("", range("A", "Z")),
join("", range("0", "9")));
$rand_str = '';
for ($i = 0; $i < $len; $i++) {
$rand_str .= $chars{rand(0, strlen($chars))};
}
return $rand_str;
}
echo get_rand_str(32);
?>
Perl is very similar to PHP:
#!perl
use strict;
sub get_rand_str {
my $len = shift;
my @chars = ("a".."z", "A".."Z", "0".."9");
my $rand_str = '';
for (my $i = 0; $i < $len; $i++) {
$rand_str .= $chars[rand(@chars)];
}
return $rand_str;
}
print get_rand_str(32) ."\n";
How to remove Subversion's hidden files (mistakenly) added to a web site's source files
October 2008 - The open source version control software Subversion is a great tool for keeping files, including web site files, in sync amongst developers working in different (geographic) locations. But occassionally a web designer or not-to-savvy developer will use FTP and upload files they've checked out from the Subversion repository. Unless their FTP software is smart enough and has been configured to omit hidden files (i.e. files beginning with "."), that means they'll upload files Subversion uses to manage the checked out sources. These aren't files you want on the web site, and it'll create problems for other team members grabbing the files from the web site.
Here's a simple shell command to recursively remove the ".svn" folder and enclosing files from the web site. Make sure you cd into the right directory!
find . -name .svn -print0 | xargs -0 rm -rf
Links
Subversion
http://subversion.tigris.org
http://svnbook.red-bean.com/en/1.0/svn-book.html
Intro to UNIX shell scripting
http://www.hsrl.rutgers.edu/ug/shell_help.html
How to create a list of countries using Perl
September 2008 - Install Locale::Country using CPAN. Then use the following:
#!/usr/bin/perl
use strict;
use Locale::Country;
my @countries = all_country_names();
foreach my $country (sort(@countries)) {
printf("\"%s\" => \"%s\"\n",
uc(country2code($country)), $country);
}
Links
CPAN
http://search.cpan.org
Locale::Country
http://search.cpan.org/~neilb/Locale-Codes-2.07/lib/Locale/Country.pod
How to programmatically check whether a web server is serving web pages
August 2008 - The goal is simple: Get the contents of the page you want to check, parse the contents (HTML source), and match on text you know is in the page. I check for something near the tail end of the HTML, like some string in Google Analytics' included JavaScript... if it should be there.
If you want to check the web site, checking that the web site's home page (whatever is the default, i.e. "index.html") should be sufficient.
Perl first.
#!/usr/bin/perl
use strict;
use LWP::Simple;
sub sitesalive {
my ($url, $pattern) = @_;
my $src = get($url);
if (! defined($src)) {
return 0;
}
if ($src =~ /$pattern/i) {
return 1;
} else {
return 0;
}
}
if ($#ARGV + 1 != 2) {
print "Need 2 arguments:\n* URL to get the HTML source from\n* The text (or regex) to look for in the source\n";
} else {
my $url = $ARGV[0];
my $regex = $ARGV[1];
if (sitesalive($url, $regex)) {
print "Ok!\n";
} else {
print "Not ok!\n";
}
}
exit 1;
Python next.
#!/usr/bin/python
import urllib, re, sys
def sitesalive(url, pattern):
try:
fh = urllib.urlopen(url)
html = fh.read()
if re.compile(pattern).search(html, 1):
return True
else:
return False
except URLError, err:
print err.reason
if len(sys.argv) - 1 <> 2:
print "Need 2 arguments:\n* URL to get the HTML source from\n* The text (or regex) to look for in the source"
else:
url = sys.argv[1]
regex = sys.argv[2]
if sitesalive(url, regex):
print "Ok!"
else:
print "Not ok!"
sys.exit()
Finally, Java.
import java.net.*;
import java.io.*;
import java.util.regex.*;
public class checkwebsite {
private static boolean sitesalive(String url, String regex) {
try {
Pattern pattern = Pattern.compile(regex);
URL page = new URL(url);
BufferedReader br = new BufferedReader(
new InputStreamReader(page.openStream())
);
String line;
while ((line = br.readLine()) != null) {
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
return true;
}
}
return false;
} catch (IOException err) {
System.out.println("Couldn't open '"+ url +"'. Error: "+ err.getMessage());
return false;
}
}
public static void main(String args[]) {
if (args.length != 2) {
System.out.println("Need 2 arguments:\n* URL to get the HTML source from\n* The text (or regex) to look for in the source");
} else {
String url = args[0];
String regex = args[1];
if (sitesalive(url, regex)) {
System.out.println("Ok!");
} else {
System.out.println("Not ok!");
}
}
}
}
Links
Perl's LWP and regular expressions
http://search.cpan.org/~gaas/libwww-perl-5.800/lib/LWP.pm
http://www.perl.com/doc/manual/html/pod/perlre.html
Python's urllib and pattern matching
http://docs.python.org/lib/module-urllib.html
Java's regular expression library
http://java.sun.com/developer/technicalArticles/releases/1.4regex/
http://java.sun.com/docs/books/tutorial/essential/regex/
How to create enumerated values in PostgreSQL tables
August 2008 - MySQL has an ENUM data type to allow database administrators the ability to restrict data in a column (field). For example, this:
CREATE TABLE beatles (
beatle ENUM('John','Paul','George','Ringo')
);
... will make a table allowing only John
or Paul
or George
or Ringo as values in the "beatle" column. But how do you do something similar in PostgreSQL where the ENUM data type doesn't actually exist?
Easy. Set a constraint:
CREATE TABLE beatles (
beatle VARCHAR(12) CHECK (beatle IN ('John','Paul','George','Ringo'))
);
Links
MySQL's ENUM
http://dev.mysql.com/doc/refman/5.0/en/enum.html
PostgreSQL's constraints
http://www.postgresql.org/docs/8.1/interactive/ddl-constraints.html
How to make Yucatecan pumpkinseed dip
July 2008 - Rick Bayless is the well known author of the
Authentic Mexican cookbook. (He lives in the Chicago neighborhood I lived in before moving back to the U.S. east coast.) I watched him make this dip on
Create TV and was suprised by the simplicity of the recipe and its great taste.
It's a good recipe!
http://www.rickbayless.com/recipe/view?recipeID=25
Links
Wikipedia entry for Rick Bayless
http://en.wikipedia.org/wiki/Rick_Bayless
Frontera Grill and Topolobampo
http://www.fronterakitchens.com/restaurants/restaurants.html
How to hide users from Mac OS X's login screen
July 2008 - Mac OS X is a UNIX operating system. As such some applications run as daemons with their own users. For example, I use PostgreSQL and MySQL on my Macs. Both the MySQL and PostgreSQL installers, one from
www.mysql.com and the other from
Marc Liyange's www.entropy.ch site, create users: mysql for MySQL and postgres for PostgreSQL.
I don't want these users to appear in the login window when I start my Mac. Using Terminal and default, the Mac OS X application that writes preference settings, I can hide these non-user users.
sudo defaults write /Library/Preferences/com.apple.loginwindow HiddenUsersList -array-add postgres
Links:
Manual page for defaults at ADC
http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/defaults.1.html
How to address historical data when your organization migrates its data management system
June 2008 - Data migration and the ability to transform data from one system to another is a discipline all its own in the IT industry.
Some organizations can afford to throw away data in their legacy systems when they migrate their data management systems, or they can deal with the clunky work flow of running legacy systems in parallel with their new systems, but most cannot. To enable the smooth operation of an organization before and after their systems migration, and to empower decision makers with a continuity of reporting necessary to determine where an organization is operating efficiently and where it might improve, migrating data from one system to another is usually required.
Migrating data isn't always easy. For reasons of cost and the simple architecture of one data management system versus another it's usually not sensible to say, "We want all the information in our old system put into the new system!" It does require some hard decisions about what data is really important to the organization and what data exist only because previous organizational practices and the legacy data management system facilitated its collection.
Data migration can be of an enormous benefit to an organization too. Even with the best quality control practices data management from an organizational perpective can be difficult. There will be suspect data in long running data management systems. As part of any data migration process information can and should be reviewed and QA-ed and QC-ed.
The benefit of having historical information in your organization's new data management system is unquestionable. It can minimize the disruption caused when migrating the data management software, it can tell you how information your organization collects as part of its business works with the inevitable new work flow represented by the new data management system, it can minimize confusion that will happen when one data management system reports differently than another, and it can provide you with a real, substantial story about your organization's work.
How to automatically backup Trac and Subversion
April 2008 - Trac, the good open source management tool for software development projects, and Subversion, the open source version control system, work very well together. But how to automate backups on UNIX... It's easy.
Create a pair of shell scripts: backup_trac.sh and backup_svn.sh. Contents for backup_trac.sh:
#!/bin/sh
TRACSITES=/path/to/trac
BACKUPS=/path/to/trac/backups
cd $TRACSITES
for file in *
do
if [ -d "$file" ]
then
trac-admin $TRACSITES/$file hotcopy $BACKUPS/$file.dump
tar -czvf $BACKUPS/$file.dump.tar.gz $BACKUPS/$file.dump
fi
done
rm -Rf $BACKUPS/*.dump
exit 0
This will backup the SQLite databases (assumption: you're using SQLite as the back-end) and all data comprising the Wiki and ticketing systems.
Contents for backup_svn.sh:
#!/bin/sh
SCSITES=/path/to/svn
BACKUPS=/path/to/svn/backups
cd $SCSITES
for file in *
do
if [ -d "$file" ]
then
svnadmin dump $SCSITES/$file > $BACKUPS/$file.dump
fi
done
exit 0
Finally, add them to a privileged users's crontab.
Links:
Trac and Edgewall (developers of Trac)
http://trac.edgewall.org
http://www.edgewall.org/
Subversion
http://subversion.tigris.org
UNIX shell scripting
http://www.dartmouth.edu/~rc/classes/ksh/print_pages.shtml
April 2008 - Yellahoose's Portland office has a Linksys RV042 router and an Apple Airport Extreme Basestation bridged on the LAN. The Airport Extreme was the only gotcha. Considering this, I need first to install MRTG. In Debian, that can be done easily using APT:
apt-get update
apt-get install mrtg
I also recommend snmpwalk. On some UNIX operating systems (Mac OS X included), it's installed by default. I had to install it on Debian, with some other utilities:
apt-get install snmp
Download and installed the MIB for the Apple Airport Extreme BaseStation. The MIB is here:
http://docs.info.apple.com/article.html?artnum=120227
The MRTG package in Debian will also install cfgmaker, a tool for automatically discovering what the target device will report. I can use cfgmaker to create a single MRTG config for both these devices – the first makes the config for the router, the second for the Airport Extreme:
cfgmaker public@10.0.0.1 > /etc/mrtg.cfg
cfgmaker public@10.0.0.50 >> /etc/mrtg.cfg
Then I creat a file to make my MRTG website index page in /var/www/mrtg/newindex.sh:
#!/bin/sh
indexmaker /etc/mrtg.cfg --output /var/www/mrtg/index.html --title Yellahoose
And I initialized it with sh /var/www/mrtg/newindex.sh run via command-line. At the webserver address (e.g., http://localhost/mrtg/ or whatever), I have my MRTG reports.
Links:
MRTG and RRD Tool
http://oss.oetiker.ch/mrtg
http://oss.oetiker.ch/rrdtool
SNMP (at Wikipedia)
http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol
How to enable the DOM inspector in Safari
March 2008 - Safari, the browser based on KHTML built-in to Mac OS X, has a good web page debugger, including an excellent DOM inspector. To enable it, quit Safari (if you're running it), start Terminal, and execute this command:
defaults write com.apple.Safari IncludeDebugMenu 1
When you restart Safari you'll have a "Debug" menu. When you control-click on a web page, you'll have a contextual menu with "Inspect Element" as an option.
Links:
Safari
http://www.apple.com/safari/
How to improve query performance in MySQL and PostgreSQL
February 2008 - There are a number of reasons why even a straightforward SQL query might not return records as quickly as would be expected. MySQL and PostgreSQL, both excellent open source database softwares, provide databases administrators and even capable web developers with tools for analyzing how queries are executed, with clues for how to improve the SQL and/or tables used by the SQL, i.e. where an index might be added or how existing table indexes or filters are being utilized.
Here's an example using MySQL:
EXPLAIN EXTENDED
SELECT t1.col1, t1.col2, t1.col3, t2.col1, t2.col2, t2.col3
FROM mytable AS t1 JOIN myothertable AS t2
ON t1.id = t2.parentid
WHERE t2.col4 LIKE '%someval%';
Here's an example using PostgreSQL:
EXPLAIN ANALYZE
SELECT t1.col1, t1.col2, t1.col3, t2.col1, t2.col2, t2.col3
FROM mytable AS t1 JOIN myothertable AS t2
ON t1.id = t2.parentid
WHERE t2.col4 LIKE '%someval%';
Links:
EXPLAIN for MySQL 5.0
http://dev.mysql.com/doc/refman/5.0/en/explain.html
EXPLAIN for PostgreSQL 8.1
http://www.postgresql.org/docs/8.1/static/sql-explain.html
How to design a many-to-many association in a relational database
Feburary 2008 - One of the most common tasks in relational database design is implementing a many-to-many association between one table and another. Some (usually web graphic designers) take the values from one table and put them into a text field in the other with a clear delimiter, like a carriage return, separating them. Some (usually Perl programmers programmers) create a third table and take these same values and populate this child table, essentially creating a hash table... and a broken database with a one-to-many association and a table without any referential integrity whatsoever.
The proper way to design a many-to-many association with real referential integrity in the database is easy.
For non-database geeks reading this, here's the simple business case example for what we're trying to do: We're designing a database for Elizabethan plays, including the works of William Shakespeare (Hamlet, Much Ado About Nothing, Henry V, etc.). Starting with a diagram, designing a one-to-many association is easy:
And here's the CREATE TABLE SQL to create these tables:
CREATE TABLE authors (
authorid SERIAL PRIMARY KEY,
firstname VARCHAR(128) NOT NULL,
lastname VARCHAR(128) NOT NULL
);
CREATE UNIQUE INDEX authoridx
ON authors (firstname, lastname);
INSERT INTO authors (firstname, lastname)
VALUES ('William','Shakespeare')
CREATE TABLE plays (
authorid INT NOT NULL REFERENCES authors (authorid),
playid SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL
);
CREATE UNIQUE INDEX playidx
ON plays (authorid, title);
INSERT INTO plays (authorid,title)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'William'
AND lastname = 'Shakespeare'
),'Hamlet');
INSERT INTO plays (authorid,title)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'William'
AND lastname = 'Shakespeare'
),'Much Ado About Nothing');
INSERT INTO plays (authorid,title)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'William'
AND lastname = 'Shakespeare'
),'Henry V');
This will work fine if you're only tracking plays Shakespeare wrote
as the only author. But late in his life Shakespeare collaborated with other other playwrights, including John Fletcher on Henry VIII and Two Noble Kinsmen. Though an extremely clever designer might change the data type of the Author ID column to accommodate a list of values, the one-to-many association (one author for one or more plays) doesn't work. We need to design a many-to-many association so that a play can have more than one author:
Here's the TABLE SQL to create these tables:
CREATE TABLE authors (
authorid SERIAL PRIMARY KEY,
firstname VARCHAR(128) NOT NULL,
lastname VARCHAR(128) NOT NULL
);
CREATE UNIQUE INDEX authoridx
ON authors (firstname, lastname);
INSERT INTO authors (firstname, lastname)
VALUES ('William','Shakespeare')
INSERT INTO authors (firstname, lastname)
VALUES ('John','Fletcher')
CREATE TABLE plays (
playid SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL
);
CREATE UNIQUE INDEX playidx
ON plays (title);
INSERT INTO plays (title) VALUES ('Hamlet');
INSERT INTO plays (title) VALUES ('Much Ado About Nothing');
INSERT INTO plays (title) VALUES ('Henry V');
INSERT INTO plays (title) VALUES ('Henry VIII');
INSERT INTO plays (title) VALUES ('Two Noble Kinsmen');
CREATE TABLE playauthors (
playid INT NOT NULL REFERENCES plays (playid),
authorid INT NOT NULL REFERENCES authors (authorid)
);
CREATE UNIQUE INDEX playauthoridx
ON playauthors (playid, authorid);
INSERT INTO playauthors (authorid, playid)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'William'
AND lastname = 'Shakespeare'
),(
SELECT playid
FROM plays
WHERE title = 'Hamlet'
));
INSERT INTO playauthors (authorid, playid)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'William'
AND lastname = 'Shakespeare'
),(
SELECT playid
FROM plays
WHERE title = 'Much Ado About Nothing'
));
INSERT INTO playauthors (authorid, playid)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'William'
AND lastname = 'Shakespeare'
),(
SELECT playid
FROM plays
WHERE title = 'Henry V'
));
INSERT INTO playauthors (authorid, playid)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'William'
AND lastname = 'Shakespeare'
),(
SELECT playid
FROM plays
WHERE title = 'Henry VIII'
));
INSERT INTO playauthors (authorid, playid)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'William'
AND lastname = 'Shakespeare'
),(
SELECT playid
FROM plays
WHERE title = 'Two Noble Kinsmen'
));
INSERT INTO playauthors (authorid, playid)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'John'
AND lastname = 'Fletcher'
),(
SELECT playid
FROM plays
WHERE title = 'Henry VIII'
));
INSERT INTO playauthors (authorid, playid)
VALUES ((
SELECT authorid
FROM authors
WHERE firstname = 'John'
AND lastname = 'Fletcher'
),(
SELECT playid
FROM plays
WHERE title = 'Two Noble Kinsmen'
));
Here's the SQL to get the info:
SELECT
plays.title,
authors.firstname,
authors.lastname
FROM plays
JOIN playauthors ON plays.playid = playauthors.playid
JOIN authors ON playauthors.authorid = authors.authorid
And finally here's the data:
title | firstname | lastname
------------------------+-----------+-------------
Hamlet | William | Shakespeare
Much Ado About Nothing | William | Shakespeare
Henry V | William | Shakespeare
Henry VIII | William | Shakespeare
Henry VIII | John | Fletcher
Two Noble Kinsmen | William | Shakespeare
Two Noble Kinsmen | John | Fletcher
Links:
Relational database model and methodology at Wikipedia
http://en.wikipedia.org/wiki/Relational_model
C.J. Date's page at Wikipedia
Date's written some good books on relational database design
http://en.wikipedia.org/wiki/Christopher_J._Date
Portland Stage
Much Ado About Nothing is playing at Portland Stage 2/26 - 3/23
http://www.portlandstage.com
How to set HTML form field tab indexes automatically
January 2008 - Tab indexes for HTML form fields can be hard to manage in large and samll forms. Some WYSIWYG HTML editors set these indexes automatically. But the indexes can be set easily in programming websites. For in examples, in PHP, initialize a variable for the tab index:
<?php $tabindex = 1; ?>
Then, in your HTML form fields, simply print and increment the index. Here's the full PHP page rendering the HTML form:
<?php $tabindex = 1; ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Tab Index</title>
<style type="text/css" title="text/css" media="screen">
/* <![CDATA[ */
html, body {
font-family: arial, geneva, sans-serif;
font-size: 12px;
}
.Form_Row {
width: 425px;
float: left;
}
.Form_Label {
width: 90px;
float: left;
}
.Form_Field {
width: 335px;
float: left;
}
/* ]]> */
</style>
</head>
<body>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">
<div class="Form_Row">
<div class="Form_Label">
<label for="First_Name">First Name:</label>
</div>
<div class="Form_Field">
<input name="First_Name" id="First_Name" type="text" tabindex="<?php echo $tabindex++; ?>" />
</div>
</div>
<div style="clear: both;"></div>
<div class="Form_Row">
<div class="Form_Label">
<label for="Last_Name">Last Name:</label>
</div>
<div class="Form_Field">
<input name="Last_Name" id="Last_Name" type="text" tabindex="<?php echo $tabindex++; ?>" />
</div>
</div>
<div style="clear: both;"></div>
<div class="Form_Row">
<div class="Form_Label">
Gender:
</div>
<div class="Form_Field">
<input name="Male" id="Male" type="radio" value="Male" tabindex="<?php echo $tabindex++; ?>" />
<label for="Male">Male</label>
<input name="Female" id="Female" type="radio" value="Female" tabindex="<?php echo $tabindex++; ?>" />
<label for="Female">Female</label>
</div>
</div>
<div style="clear: both;"></div>
<div class="Form_Row">
<div class="Form_Label">
</div>
<div class="Form_Field">
<br />
<input name="Action" id="Action" type="submit" value="Submit" tabindex="<?php echo $tabindex++; ?>" />
<input name="Action" id="Action" type="submit" value="Nevemind" tabindex="<?php echo $tabindex++; ?>" />
</div>
</div>
<div style="clear: both;"></div>
</form>
</body>
</html>
How to make Mac OS X's Finder create aliases that can be used in Terminal
December 2007 - My primary desktop computers use Apple's Mac OS X. I spend most of my day using the Finder and other Aqua applications as much as I use Terminal. The Finder creates aliases, the same as it's done since System 7, but the aliases aren't navigable by commandline, in Terminal.
Yes, I know
ln -s ../Whatever Link\ to\ Whatever will create a file the Finder can navigate. But the Finder should create files Mac OS X's UNIX commandline applications can use.
I raised this issue with my cousin, a hardware and network consultant in Atlanta, Georgia, and he pointed me to a plugin to enable this.
Links:
SymbolicLinker
http://seiryu.home.comcast.net/~seiryu/symboliclinker.html
Complete Technology Partners
http://www.completepartners.com
How to get glass cut at Home Depot
December 2007 - In Portland, Maine, you cannot... get glass cut at Home Depot. It's (and I am quoting the no doubt well-meaning person at the Customer Service desk on Allen Avenue) "too dangerous."
Lowe's and Maine Hardware will both cut glass.
Links:
http://www.wikihow.com/Cut-Glass
How to add latitude and longitude lines to MapServer
November 2007 - This shows how to add lat/lon lines, or a graticule, to MapServer without adding an external vector data set. The code snippet below is from MapServer's map file.
LAYER
NAME "Latitude/Longitude"
METADATA
"DESCRIPTION" "Latitude/Longitude"
END
TYPE line
STATUS on
TRANSPARENCY 40
CLASS
NAME "Graticule"
COLOR 255 255 255
LABEL
COLOR 255 255 255
FONT vera
TYPE truetype
SIZE 8
POSITION auto
PARTIALS false
BUFFER 5
END
END
PROJECTION
"proj=latlong"
END
GRID
LABELFORMAT DDMM
MAXARCS 2
MAXINTERVAL 2
MAXSUBDIVIDE 2
END
END
MapServer is a free and open source GIS tool for web-based applications. Yellahoose has developed a number of MapServer applications. Review the news page for examples.
Links:
MapServer
http://mapserver.gis.umn.edu
How to validate email addresses in JavaScript, Perl, PHP, Python and C
November 2007 – A common task (or it should be a common task) when collecting info for opt-in emails, like a "Join our mailing list!" feature, email validation, is making certain stuff entered in an email address field is in fact a valid email. The crudest way to do this is to split the parts of what's entered — most programming languages have string functions allowing this — a more efficient and in my opinion elegant way to validate email addresses is by using a regular expression and pattern matching.
Below are examples, in JavaScript, C, Perl, PHP and Python, showing how to easily and correctly validate emails using regex.
JavaScript.
function valid_email(email){
if (email.match(/^[A-Za-z0-9_\+-]+(\.[A-Za-z0-9_\+-]+)*@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.([A-Za-z]{2,4})$/)){
return true;
}else{
return false;
}
}
PHP.
function valid_email($email = '') {
if (preg_match('/^[A-Za-z0-9_\+-]+(\.[A-Za-z0-9_\+-]+)*@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.([A-Za-z]{2,4})$/', $email)) {
return true;
} else {
return false;
}
}
Perl.
sub valid_email {
$email = shift;
if ($email =~ /^[A-Za-z0-9_\+-]+(\.[A-Za-z0-9_\+-]+)*@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.([A-Za-z]{2,4})$/) {
return 1;
} else {
return 0;
}
}
Python.
import re
def valid_email(email):
patt = re.compile("^[A-Za-z0-9_\+-]+(\.[A-Za-z0-9_\+-]+)*@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.([A-Za-z]{2,4})$")
if patt.match(email):
return 1
else:
return 0
C.
#include <regex.h>
int valid_email(const char *email) {
regex_t re;
int res;
char *pattern = "^[A-Za-z0-9_\\+-]+(\\.[A-Za-z0-9_\\+-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*\\.([A-Za-z]{2,4})$";
if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) {
return 0;
} else {
res = regexec(&re, email, (size_t)0, NULL, 0);
regfree(&re);
if (res != 0) {
return 0;
} else {
return 1;
}
}
}
How to vertically and horizontally center a <div>
October 2007 - Here's how to create a vertically and horizontally centered box in XHTML without tables.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Vertically and horizontally centered div</title>
<style type="text/css" title="text/css" media="screen">
/* <![CDATA[ */
html, body {
padding: 0;
margin: 0;
font-size: 11px;
font-family: verdana, sans-serif;
color: #333;
}
#Centered_Box {
position: absolute;
top: 50%;
left: 50%;
width: 250px;
height: 250px;
margin-top: -125px;
margin-left: -125px;
border: 1px solid #444;
}
#Centered_Box .Text {
line-height: 250px;
text-align: center;
}
/* ]]> */
</style>
</head>
<body>
<div id="Centered_Box">
<div class="Text">This is a centered box.</div>
</div>
</body>
</html>
How to implement firewall rules in IPFW on FreeBSD
September 2007 - FreeBSD is another UNIX variant operating system. It's very well documents, and its software management system, called Ports, makes it almost as easy as Debian's APT to install and update software while allowing for a high level of customizability in the installation process.
There are several firewall tools for FreeBSD. Below is a simple shell script with rules for IPFW. It allows for a basic web server set up, with DNS, HTTP, HTTPS and SSH access.
#!/bin/sh
IPF="ipfw -q add"
ipfw -q -f flush
$IPF 001 allow all from any to any via lo0
$IPF 002 deny all from any to 127.0.0.0/8
$IPF 003 deny all from 127.0.0.0/8 to any
$IPF 004 deny tcp from any to any frag
$IPF 101 check-state
$IPF 102 allow tcp from any to any established
$IPF 103 allow all from any to any out keep-state
$IPF 104 allow icmp from any to any
$IPF 201 allow udp from any to any 53 in
$IPF 202 allow tcp from any to any 53 in
$IPF 203 allow udp from any to any 53 out
$IPF 204 allow tcp from any to any 53 out
$IPF 211 allow tcp from any to any 22 in
$IPF 212 allow tcp from any to any 22 out
$IPF 221 allow tcp from any to any 80 in
$IPF 222 allow tcp from any to any 80 out
$IPF 231 allow tcp from any to any 443 in
$IPF 232 allow tcp from any to any 443 out
$IPF 501 deny log all from any to any
Links:
FreeBSD
http://www.freebsd.org
Firewalls on FreeBSD and IPFW specifically
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/firewalls.html
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/firewalls-ipfw.html
How to proxy Plone through Apache
August 2007 - Plone, the content management system based on Zope and written in Python, is a good tool for online collaboration. Unfortunately Plone by default runs in Zope on a non-standard TCP/IP port. By "non-standard" I mean that users behind firewalls with limited rules — access only to basic Internet services, like web, email and FTP — cannot access the Plone site.
A not-so-simple way around this is to contact the firewall administrator and get him or her to open access to port 9673, or whatever port Plone is running on. The problem with this is you'll have to do this each user, assuming that users are connecting from different locations. That'll take a lot of time!
A simple and proactive thing to do is to proxy Plone through Apache and the standard and most probably accessible HTTP port.
ProxyPass /PloneSite http://localhost:8080/VirtualHostBase/http/www.yourdomain.com:80/VirtualHostRoot/PloneSite/
Links:
Apache, httpd.conf and mod_proxy
http://www.apache.org
http://httpd.apache.org/docs/2.0/mod/core.html
http://httpd.apache.org/docs/2.0/mod/mod_proxy.html
Plone
http://www.plone.org