A Chrome Extension Attempt

posted Feb 7, 2010, 7:32 PM by Philip Saxton

Far too many websites seem to enjoy breaking CSS specification in specifying an explicit foreground color without the background, or vice versa. This generally goes unnoticed as most people use the default dark foreground and light background their browser provides. When one prefers to change their default colors, however these sites become unreadable. After hours of searching for a  Firefox or Chrome plugin to force these sites to a minimum of contrast, I find none available. 

Thus, I have decided to create CCF, the CSS Color Fixer for Chrome. The first task would be to walk the DOM tree of the page to inspect the color values for each element. This wound up being a lot trickier than I had envisioned. In my many attempts I also created a log class for JavaScript which tabs the log output to make it more readable. Next, would be to check the foreground and background colors of each element to ensure a certain amount of contrast. This second part is still in progress.

var log = {
  "tnum" : 0                                                   ,
  "tabs" : ""                                                  ,
  "s"    : "                                                  ",
  "tab"  : function() {
    this.tnum += 2;
    this.tabs = this.s.substring(0,this.tnum);
  }                                                            ,
  "untab": function() {
    this.tnum = (this.tnum >= 2) ? this.tnum-2 : 0;
    this.tabs = this.s.substring(0,this.tnum);
  }                                                            ,
  "write": function(expr) {
function domFuncWalk(obj, func) {
  log.write("Found: ";;

  if(obj.firstElementChild) {
    domFuncWalk(obj.firstElementChild, func);
  log.write("Finished: ";
  if(obj.nextElementSibling) {
    domFuncWalk(obj.nextElementSibling, func);

function checkColor(element) {
  //get foreground color as an array [r, g, b]
  temp = getComputedStyle(element).getPropertyValue("color");
  fg = temp.substring(4,temp.length-1).split(",");
  fgt = Number(fg[0])+Number(fg[1])+Number(fg[2]);

  //do the same for background color
  temp = window.getComputedStyle(element).getPropertyValue("background-color");
  temp = (temp.substring(0,4)=="rgba") ? temp.substring(5,temp.length-1) : temp.substring(4,temp.length-1);
  bg = temp.split(",");
  bgt = Number(bg[0])+Number(bg[1])+Number(bg[2]);
  log.write("Before filter");
  log.write("fg: "+fg+"\tfgt: "+fgt);
  log.write("bg: "+bg+"\tbgt: "+bgt);
  if(fgt == 0 && bgt != 0)"inherit";
  else if(fgt != 0 && bgt == 0)"inherit";
  temp = getComputedStyle(element).getPropertyValue("color");
  fg = temp.substring(4,temp.length-1).split(",");
  temp = window.getComputedStyle(element).getPropertyValue("background-color");
  temp = (temp.substring(0,4)=="rgba") ? temp.substring(5,temp.length-1) : temp.substring(4,temp.length-1);
  bg = temp.split(",");

  log.write("After Filter");
  log.write("fg: "+fg+"\tfgt: "+fgt);
  log.write("bg: "+bg+"\tbgt: "+bgt);

domFuncWalk(document.body, checkColor);

Creating an extension for Chrome is exceedingly simple. The above saved in a file called contentscript.js along with the following file saved as manifest.json will create the plugin. There is a packed .crx available below, however. Be sure to check back for updates if you do choose to install the partially completed work.

  "name": "CSS Color Fixer",
  "version": "0.3.29",
  "description": "Forces web pages to be standards compliant by removing foreground or background of an element if both are not explicit in an effort to make pages readable with any theme.",

  "content_scripts": [
      "matches": ["http://*/*", "https://*/*"],
      "js": ["contentscript.js"],
      "run_at": "document_idle",
      "all_frames": true

Apache Web Server Setup

posted Dec 19, 2009, 9:42 PM by Philip Saxton   [ updated Dec 19, 2009, 9:45 PM ]

This document attempts to detail the installation and setup of the apache http server. The goals of the web server are to serve http requests for a small number of virtual hosts. The underlying operating system for this document is Debian GNU/Linux 5.0 (Lenny). Installation of supporting programs is not documented as it is beyond the scope of this document.

Why apache

apache is not the only http server available. In some situations it is not even the best option. apache has been chosen for this document because it is by far the most popular http server and has a nearly endless variety of plug ins and development options available.


There are four server models or 'MPM's available under Debian for apache. prefork has been selected for this document because it is required for mod_php.

Other MPMs available are:
  event - which is also thread based but passes threads off after they are received.
  itk - which is based on prefork and allows vhosts to use their own user and group IDs.
  worker - a threaded server model

As usual with Debian, installation is quite straight forward:

# aptitude install apache2-mpm-prefork;


In Debian, apache configuration files are kept under /etc/apache2. The distribution default settings are kept in apache2.conf. Any of the settings in apache2.conf should be changed by setting the same variable in httpd.conf as this is read in after apache2.conf. Changes made to apache2.conf may be overwritten if the apache server installation is upgraded or modified. ports.conf exists to specify which ports apache should listen.

apache mods are controlled by the mods-available/ and mods-enabled/ directories. When an apache module is installed it will place load file and possibly a config file in the mods-available/ directory. The conf and load files should be sym-linked in the mods-enabled/ directory and the conf file edited to suit the needs of the server.

Virtual hosts are defined in the sites-available/ directory and are activated by sym-linking to the file in the sites-enabled/ directory. This way one can just remove the sym-link in the sites-enabled/ folder to deactivate a site without losing the configuration.

Any remaining server wide configuration bits can be placed in files in the conf.d directory. Below is a summary of the default files upon installation. Some of the files in mods-available/ and mods-enabled/ have been snipped for brevity. Note how the files in the *-enabled/ directories are links to their *-available/ counterparts.

  apache2.conf    httpd.conf         ports.conf
  conf.d/         mods-available/    sites-available/
  envvars         mods-enabled/      sites-enabled/
  alias.conf      asis.load          authz_host.load
  alias.load      auth_basic.load
  alias.conf -> ../mods-available/alias.conf
  alias.load -> ../mods-available/alias.load
  auth_basic.load -> ../mods-available/auth_basic.load
  default         default-ssl
  000-default -> ../sites-available/default

Changes made to ANY of the configuration files will require apache to be restarted before the changes will take effect.

 Setting Up Virtual Hosts 

The default apache configuration coming from the Debian package is set up to use virtual hosts. This is not a bad idea even if the server will only be hosting a single site as there is no performance penalty and more sites can be added later if needed with minimal changes necessary.

For the first virtual host the 000-default link in the sites-enabled/ directory will be removed. Once the real default site has been created in sites-available/ the link will be recreated to it.

To create a new site:

# cd /etc/apache2;
# cp sites-available/default sites-available/site.tld;
# editor sites-available/site.tld;
  <VirtualHost *:80>
        ServerAdmin webmaster@site.tld                 ## Correct email addr
        DocumentRoot /srv/www/site.tld                 ## Correct site name
        <Directory />                                  ## Remove
                Options FollowSymLinks                 ##  |
                AllowOverride None                     ##  |
        </Directory>                                   ## _V_
        <Directory /srv/www/site.tld>                  ## Correct site path
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/        ## Remove if no cgi
        <Directory "/usr/lib/cgi-bin">                 ##  |
                AllowOverride None                     ##  |
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny                       ##  |
                Allow from all                         ##  |
        </Directory>                                   ## _V_
        ErrorLog /var/log/apache2/error.site_tld.log   ## Add site name
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
                                                       ## Add site name
        CustomLog /var/log/apache2/access.site_tld.log combined
       Alias /doc/ "/usr/share/doc/"                   ## Remove
      <Directory "/usr/share/doc/">                    ##  |
          Options Indexes MultiViews FollowSymLinks    ##  |
          AllowOverride None                           ##  |
          Order deny,allow                             ##  |
          Deny from all                                ##  |
          Allow from ::1/128       ##  |
      </Directory>                                     ## _V_
# mkdir -p /srv/www/site.tld;
# chown www-data:www-data /srv/www/site.tld;
                                                 ## XXX is a counter,
                                                 ## 000 becomes default site
# ln -s sites-available/site.tld sites-enabled/XXX-site.tld;
# apache2ctl graceful;

Installing Modules

Modules for apache can be installed through aptitude as well. This document will install php5 as an example. Other modules may be installed in a similar fashion.

# aptitude install php5;

The php5 package automatically creates the links required to enable php on the apache server. The following example illustrates how this may be done for packages which do not automatically set themselves as enabled. Either way, after installing the mod, the apache server will need to be restarted to make use of the new features.

# cd /etc/apache2/mods-enabled;
# ln -s ../mods-available/php5.conf .;
# ln -s ../mods-available/php5.load .;
# apache2ctl graceful;                         ## Restart the apache server

Write and Draw

posted Dec 19, 2009, 9:55 AM by Philip Saxton   [ updated Dec 19, 2009, 10:18 AM ]

Here are pages for a child to practice learning to write letters with space provided to draw pictures of things which start with the letter enforcing the learning concept.
Note: If your computer cannot open these files, you will need to install a program for reading scalable vector graphic or ".svg" files. I recommend InkScape.

Courier Mail Server Setup

posted Dec 19, 2009, 9:55 AM by Philip Saxton   [ updated Nov 16, 2011, 7:16 PM ]

This document attempts to describe the process for setting up a full featured mail server using Debian GNU/Linux 5.0 (Lenny) and the Courier mail suite (version 0.60.0-2). Prior to the first section, the OS is a core install with no extra "collections" added. After installation sudo, less, nfs-client, ssh, screen, and mutt packages have been installed. These are not strictly necessary and are mentioned in the interest of full disclosure. The installation procedure is beyond the scope of this document. Courier-base is configured to use configuration directories rather than files as this is required to use the optional web admin module.

Sections "Configure authdaemond," "Setup SMTP" and "Setup POP3 and/or IMAP" are required for a basic mail server setup. Further sections are optional and extend the functionality of the mail server.

Why Courier

There are many different mail suites available for Linux users. There are many more recipes to follow to mangle parts from each of those mail suites together to form a single functional(?) mail server. After struggling through three or four of those recipes, I began to wonder why none of these mail suites were capable of doing what they were intended to, perform the whole gamut of functions desired using a single codebase. I decided to try creating a homologous server with Courier for little more reason than I liked the name and I remember seeing it in a lot of recipes often just used for the IMAP server. If you are looking for me to convince you that Courier is the be all/end all of mail servers, you should probably do some research to decide what fits your requirements. If you are looking to have a single suite to power all of your Internet communications needs that is relatively basic to setup, read on.

While writing this manual, I have found many things I like about Courier. Having a central "authdaemon" makes configuration of the individual modules a breeze and abstracts much of the parts I found confusing in many other recipes. Also, Courier has most of the pieces which other recipes seem to grab from every suite under the sun as standard modules: SMTP (MTA, MSA and MDA), POP3, IMAP, mail lists, calendaring, shared IMAP folders, webmail, webadmin, server side filtering, SSL, LDAP integration, and even a Fax<=>Mail gateway. Often there is little configuration required aside from installation as you can see in the sections below.

Configure authdaemond

authdaemond is the heart of the Courier mail system. It authenticates users for POP3, IMAP, and SMTP auth servers as well as routes mail to the correct box. There are several modules for authdaemond which provide Courier with a wide range of functions. authpam, authuserdb, and authpostgresql will be described in this document.

authdaemond is part of the base package of courier. To install:

# aptitude install courier-base;


The authpam module is the most basic and allows for mail to be delivered to system accounts. authpam is installed and activated by default. Creating new accounts is done by adding a login account to Debian on the mail system. All domains configured as local will have messages delivered to the corresponding system account. The biggest downside to this is that every mail user must be given a login acount and that different addresses, like and, are delivered to the same mailbox.


The authuserdb module uses integrated GDBM support to manage a small database of addresses for routing and authentication. The Courier website claims this is sufficient for up to several thousand mailboxes, beyond which a full SQL backed module such as authpostgresql is recommended.

Note: You must configure SMTP to accept and handle virtual mail seperately.

Setting up the authdaemonrc to use authuserdb involves editing the authdaemonrc configuration file and adding authuserdb to the module list. Userdb generates its database from files in the userdb directory. This directory must be root owned and have no group or world permissions. The Courier authdaemond will need to be restarted after this change.

# editor authdaemonrc;                     ## Find and change the following
    authmodulelist="authpam authuserdb"
# mkdir /etc/courier/userdb && chmod 0700 /etc/courier/userdb;
# /etc/init.d/courier-authdaemon restart;

Mailboxes may be added either through a command line utility or by editing the userdb configuration files directly. Once a user has been created, the `home' directory will need to be created and a maildir will need to be setup. Finally, run `makeuserdb' to add the new accounts to the userdb db.

Adding a mailbox from the command line:

# /usr/sbin/userdb \
>   set home=/var/mail/ uid=1000 gid=1000;
# /usr/sbin/userdbpw -md5 | sudo /usr/sbin/userdb \
> set systempw;
Password: pw
# mkdir /var/mail/;
# /usr/bin/maildirmake /var/mail/;
# chown -R 1000:1000 /var/mail/;
# /usr/sbin/makeuserdb

Note: There is a shell script in "Appendix: Shortcuts" to simplify this process.

And directly editing a configuration files:

# editor userdb/; systempw=$1$2whRdMzg$mZUtSRQoxXX7lQoJq8eSy/|home=/var/mail/|uid=1000|gid=1000
# mkdir /var/mail/;
# /usr/bin/maildirmake /var/mail/;
# chown -R 1000:1000 /var/mail/;
# /usr/sbin/makeuserdb;

Note: Each record for userdb MUST occupy one line. The formatting on this document may break the lines, but in operation this will not work.


The authpostgresql module integrates with the PostgreSQL database server to support many thousands of virtual mail users.

Note: A fully configured and running PostgreSQL instance is assumed.

Information for valid email addresses, their associated passwords and maildir locations is stored in a database table. First, an os user should be created to seperate the mail user database from other information kept in the db. A directory should be created for the courier schemas files to live.

# groupadd courierdb
# useradd -g courierdb courierdb
# mkdir /var/spool/courierdb
# chown courierdb:courierdb /var/spool/courierdb

Next, set up a database and table in Postgre:

# psql -U postgres template1         ## Configure postgres
= create user courierdb;
= create database courierdb with owner courierdb;
= \c courierdb courierdb
> CREATE TABLE mail_users (
     id serial NOT NULL,
     username character varying(64) NOT NULL,
     vhost character varying(64) NOT NULL,
     passwd character varying(64),
     maildir character varying(256),
     alias character varying(32)
> \q;

Finally set up authentication rights for the courierdb user in Postgre.

# editor pg_hba.conf;             ## Add the following to the users list
     local courierdb courierdb        trust

Once the postgre user and password have been setup, courier just needs to be configured to use it.

# editor authdaemonrc;            ## Find and change the following
# /etc/init.d/courier-authdaemon restart;
# editor authpgsqlrc
     PGSQL_HOST             localhost
     PGSQL_PORT             5432
     PGSQL_USERNAME         courierdb
     PGSQL_PASSWORD         # trusted
     PGSQL_DATABASE         courierdb
     PGSQL_USER_TABLE       mail_users
     PGSQL_CLEAR_PWFIELD    passwd
     PGSQL_LOGIN_FIELD      username || '@' || vhost

Setup SMTP

Install `courier-mta'. Configure which domains to accept mail for. Turn off DNS lookups and Ident authentication otherwise mail processing is too slow. Turn on SMTP authentication to allow mail to be sent away from the server. Restart the SMTP module to take the new settings.

# aptitude install courier-mta;
# cd /etc/courier;
# editor locals;
# editor esmtpacceptmailfor.dir/domains;
# /usr/lib/courier/makeacceptmailfor;
# editor esmtpd;                           ## Find and change the following
     TCPDOPTS="-stderrlogger=/usr/sbin/courierlogger -noidentlookup -nodnslookup"
# /etc/init.d/courier-mta restart;

Note: `esmtpacceptmailfor.dir/*' contains all domains for which mail is accepted via SMTP. `locals' contains domains for which mail will be handled as system mail.  `hosteddomains/*' (which is discussed in "Configure Virtual Mail") contains domains which are to be handled as virtual. Domains appearing in `estmtpacceptmailfor.dir/*' which are not handled locally or as virtual will be accepted and relayed.

Test mail setup using telnet to send a message:

# telnet hostname 25;
250-hostname Ok.
> MAIL From: <>
250 Ok.
> RCPT To: <>
250 Ok.
354 Ok.
> Date: Jan 1 1979 0:00:00
> From:
> To:
> Subject: Testing mail delivery
> Testing. Testing. 1, 2, 3.
> .
221 Bye.

Note: `localuser' should be an actual login account on the machine. `' should be a domain configured as local earlier in this step.

After issuing these commands, a message should arrive to localuser in ~/Maildir. Check this with:

localuser$ mutt -f ~/Maildir;

If mail has been received correctly, then the basic SMTP setup is complete.

Configure Virtual Mail

Note: Prior to this step you MUST have "Setup SMTP" and configured an authdaemond module capable of virtual mailboxes such as authuserdb or authpostgresql.

There are only two steps to setting up virtual mail. First, define the domains to handle as virtual mail. Next, define the addresses for those domains as found in the appropriate auth module section.

Define the domains by creating a file under the hosted domains directory and list each domain on a separate line. Don't forget that these domains must also be added to the `esmtpdacceptmailfor.dir/*' file for the smtp server to accept mail to these domains. Then, run `makehosteddomains' to compile the list into the hosteddomains.dat file.

# cd /etc/courier;
# editor esmtpdacceptmailfor.dir/domains
# /usr/lib/courier/makeacceptmailfor;
# editor hosteddomains/domains;
# /usr/lib/courier/makehosteddomains;

Once again, test the new setup with telnet as in the previous step and verify that mail is being properly delivered to virtual accounts.

Setup POP3 and/or IMAP

Install the courier-pop and courier-imap packages:

# aptitude install courier-pop courier-imap;

Done. Test POP3 using telnet as shown below.

# telnet hostname 110
+OK Hello there.
+OK Password required.
> PASS pw
+OK logged in.

And to test IMAP:

# telnet hostname 143
> 100 LOGIN pw
100 OK LOGIN Ok.

Note: For more information on interacting with servers through telnet, check out the latest RFCs defining the protocols: SMTP - RFC 2821, POP3 - RFC 1939, IMAP - RFC 3501.

Option: Installing maildrop

maildrop is a mail delivery agent which allows global and per-user filtering of messages. Users can place custom filtering rules in their home directory in a file called `.mailfilter'. This program is also useful to efficiently interface the Courier SMTP process with spam and virus filtering such as SpamAssassin and ClamAV. To install and set Courier to use maildrop:

# aptitude install courier-maildrop;
# editor /etc/courier/courierd             ## Find and change the following
     DEFAULTDELIVERY="| /usr/bin/maildrop"
# editor /etc/courier/maildroprc;                      ## Add the following
     /Received: from .* id\s+(.*)/:h
     SYSLOG="logger -i -p -t maildrop -- $MESSAGE_ID"
     `$SYSLOG maildrop started`
# /etc/init.d/courier-mta restart;

Note: Mind the positioning of curly braces ({ and }) in maildroprc. Maildrop considers their placement to be syntax. See `man maildropfilter' for more info.

Note: When "syntax errors" are seen in the logs for maildrop, running `echo | maildrop -V 9` will generally lead to the solution.

Option: Integrating With SpamAssassin

Note: "Installing maildrop" is required before this option can be performed.

SpamAssassin must be installed and configured. Patch spamd to use authdaemon to allow per-mailbox filtering and settings. After SpamAssassin is installed, create the maildrop rules to use it.

# aptitude install spamassassin;
# editor /etc/default/spamassassin;        ## Find and change the following
# cd /usr/share/perl5/Mail/SpamAssassin;
# wget htp://;
# vim /usr/sbin/spamd;                     ## Find and change the following
     use Mail::SpamAssassin::Timeout;
     use Mail::SpamAssassin::AuthCourier;
# /etc/init.d/spamassassin start;
# editor /etc/courier/maildroprc;                      ## Add the following
     import USER
     xfilter "spamc -u $USER"
     if (/^X-Spam-Level:.*$STARS.*/:h )
       `$SYSLOG message rejected by SpamAssassin`

Option: Integrating With ClamAV

Note: "Installing maildrop" is required before this option can be performed.

Install clamav. Copy the clampipe script from the documentation and change it to use reformail instead of formail. After setting up clamav, add an xfilter in maildrop to scan messages prior to accepting.

# aptitude install clamav;
# cp /usr/share/doc/clamav/examples/clampipe /usr/bin
# chmod +x /usr/bin/clampipe
# vim /usr/bin/clampipe                    ## Find and change the following
    open (FORMAIL, "|reformail -i 'X-Virii-Status: $status'")
# editor /etc/courier/maildroprc;                      ## Add the following
     xfilter "clampipe"
     if (/^X-Virii-Status: yes/:h)
       `$SYSLOG message rejected by ClamAV`

Option: Using SqWebMail

Very little official documentation is available regarding deployment of SqWebMail (see

First try: Install sqwebmail

# aptitude install sqwebmail

This seems to install apache2 and mysql. We will look at our options, because we want PostgresQL rather than MySQL and apache on a second machine. Most likely this means that we will be sharing our mailbox store via nfs. The test VM is too weak to be running mail and web daemons simultaneously, and we have plans for a stand-alone web server already.

Appendix: Shortcuts


addmailbox - shell script to add email users when using authuserdb:

# Uses userdb to add an email address to authuserdb. Creates and sets the
# permissions for the home folder and Maildir.
# Contributed by DaeGlo <>
if [ $# -eq 2 ] && [ $(id -u) -eq "0" ]; then
      echo "Adding email address \"${EMAIL}\"";
      /usr/sbin/userdb ${DOM}/${EMAIL} set home=${SPOOL}/${DOM}/${USER} \
        uid=5000 gid=5000;
      /usr/sbin/userdbpw -md5 | /usr/sbin/userdb ${DOM}/${EMAIL} set systempw;
      mkdir -p ${SPOOL}/${DOM}/${USER};
      /usr/bin/maildirmake ${SPOOL}/${DOM}/${USER}/Maildir;
      chown -R 5000:5000 ${SPOOL}/${DOM}/${USER};
    echo "Usage: $0 name domain
        where name@domain is the email address to add.
        Note: This script must be run as root.  ";


clampipe - perl script to use clamscan as a pipe which is required for maildrop

# Filters mail through clamav. Intented to be used as a maildrop xfilter,
# So it takes care to exit 0 on success, and nonzero on error. Adds a
# X-Virii-Status header.
# Contributed by Joey Hess <> to be used with procmail
# Modified by DaeGlo <> to NOT be used with procmail ;)
use strict;
use warnings;

my $msg=<>;

open (CLAM, "| clamscan --quiet -")
        || die "cannot run clamscan: $!";
# The --mbox support is flakey and requires a From header as in a real
# mbox.
print CLAM "From foo\n";
print CLAM $msg;
close CLAM;
# Returns status of 1 for virii.
my $status= ($? >> 8 == 1) ? "yes" : "no";

open (FORMAIL, "|reformail -i 'X-Virii-Status: $status'")
        || die "cannot run reformail: $!!";
print FORMAIL $msg
        || die "cannot write to reformail: $!";
        || die "reformail failed: $!";

exit 0;

Appendix: Sources

1-4 of 4