Email newsletter HTML/CSS rules

October 18th, 2012

I keep forgetting this rules I made for myself, so here they are. Target platforms:
gmail, hotmail, yahoo, outlook 2007, outlook express, iphone mail, android gmail

  • Basically, dont use a stylesheet – do inline styles on divs and spans (trust me – this will reduce your cross-browser issues)
  • Dont use h1, h2, p, etc – just use div and span (other tags have their own styles in yahoo etc)
  • Only use margins, don’t use padding
  • Use margins, but only like this: margin-right, margin-bottom, margin-left
  • So, you need top margin?: use a general padder like this:

    <div style="margin-bottom: 16px;">
    <table cellpadding="0" cellspacing="0"><tr><td></td></tr></table>
    </div>
    
  • Don’t use colour shortcuts like this: #efe. Write it fully, eg: #eeffee
  • Need a solid line?
    <div style="border-top: 1px solid black; font-size: 0px;">&nbsp;</div>
    

    If you have set the line height in a parent div you might want to add

    line-height: 0px

    to the above solid line div. Althought, I’ve found it’s best to avoid line-height altogether (outlook)

  • Fine-print not fine enough in iPhone mail? (ok you’re allowed to use stylesheet now :)
    <style type="text/css">
    div, span { -webkit-text-size-adjust:none; }
    </style> 
    
  • Need to right-align an image? Pop it in a table
    <table cellpadding="0" cellspacing="0" align="right">
      <tr>
        <td>
          <img src="image.jpg" alt="" />
        </td>
      </tr>
    </table>
    
    

If you follow these strict rules you shouldn’t be compaining about Outlook 2007 (lowest common denominator)

UTF-8 setup (again) – for Debian Squeeze

March 9th, 2012

This post is mostly for my own reference – but maybe you will find it useful. Here are my current Linux, Apache, MySQL, PHP settings for supporting UTF-8 properly!

Linux
—–

# dpkg-reconfigure locales

I chose: en_NZ.UTF-8 UTF-8

Apache
——

edit file /etc/apache2/conf.d/charset
uncomment the line:
AddDefaultCharset UTF-8

MySQL
—–

make sure these settings are in /etc/mysql/my.cnf:

[mysqld]
character_set_server=utf8
collation_server=utf8_unicode_ci

[client]
default-character-set=utf8

PHP

make sure these settings are in /etc/php5/apache2/php.ini and /etc/php5/cli/php.ini:

default_charset = utf-8

And in all scripts, when you make the mysql connection, always do this:

mysql_set_charset(‘utf8′);

Speed test: PHP vs Perl vs Python vs Go vs C

August 30th, 2010

Recently I have needed to run a cron job every minute on a high load web server. As am currently most fluent in PHP I naturally wrote my script in PHP. However, as it’s running every minute, I do want it to be as fast as possible. Seeing as the script was very simple, I thought that the most time required to run is in loading the PHP interpreter. Maybe i could use a compiled language instead? What about Google’s new language Go?

NOTE: This was not an overall speed test. I am just trying to find out which approach would be fastest for running a cron job every minute. None of the programs tested run through a web server.

Anyway, for my test I wrote a “hello, world” command line app in each language and ran the program 1000 times. Without any further ado, here are the results, from fastest to slowest:

C: 5.37 seconds

Go: 6.23 seconds

Perl: 7.97 seconds

Python: 20.64 seconds

PHP: 41.31 seconds

There you go! PHP is a bit slow for this kind of thing! But I’m not going to write all my scripts in Go or C now (what a hassle!). So, for me…. perl wins!

Ahh, good old perl, my faithful friend! I will never forget you!

Ubuntu for mother in law = yay!

November 10th, 2009

As I wrote in previous post, my personal experience trying to use ubuntu as a php development box was very brief!

However, i was impressed by the GUI side of things in Xubuntu (ubuntu but with the lightweight xfce desktop), and when my mother in law’s (really!) laptop blew up – I took the opprtunity to spread the ubuntu/linux buzz up a generation! :)

My own windows desktop workstation (yes I use windows for my PHP programming – of course the PHP /apache side runs on linux!!) got a weird hardware problem, something to do with USB, and Windows kept rebooting itself, but linux boot cds worked fine… So I thought, oh well, if I cant really use this myself, why not chuck linux on it and give it away!

Mother-in-law literally just writes email and browses the web (maybe writing a few google docs) so i think linux gui is perfect for her….

So… after a fairly easy install…. viola! My crappy old desktop is reborn as a super simple NET PC!!! She loves it!

Hooray for linux, hooray for Xubuntu – rescuing obsolete hardware worldwide! :)

A brief flirtation with Ubuntu as development box

August 29th, 2009

Recently I’ve been using this awesome persistent version of Xubuntu on my USB pen drive. It’s great for fixing computers, virus scanning, etc.

http://www.pendrivelinux.com/usb-xubuntu-904-persistent-install-windows/

It even detected my wireless adapter with no hassles – and the awesome thing is that all your settings are saved to disk!!

I was so happy that I thought I’d try xubuntu as a PHP/MySQL development box…

Installed great, looks good, BUT… OH NO .. mysql can’t start anymore… some weird access problem!! argh!!!

I’ve never had anything like this with Debian before… WTF is going on?!

Anyway, back to Debian for development. Ahhhh…. good old trusty Debian. YAY!!!!

UTF-8 checklist

April 27th, 2009

Character encodings have been driving me insane lately….

- stuff pasted from word wont display properly

- funny square characters in the browser

- smartĀ  quotes from word don’t display properly

So here’ s a handy list of things i have been trying. Some things mgiht work for you, some might not. Let me know if you have anything to add!

Apache

AddDefaultCharset UTF-8

MySQL

On connect – SET NAMES ‘utf8′

Convert: ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
or:

<?
$dbname = $argv[1];
if(!$dbname) {
print “no database specified\n”;
exit;
}
$dbh = mysql_connect(‘localhost’, ‘username’, ‘password’, 1);
mysql_select_db($dbname);
$sql = “SHOW TABLES”;
$res = mysql_query($sql, $dbh);
while($row = mysql_fetch_assoc($res)) {
$sql2 = “ALTER TABLE $row['Tables_in_{$dbname}'] CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci”;
print $sql2 . “\n”;
}
?>

http://www.oreillynet.com/onlamp/blog/2006/01/turning_mysql_data_in_latin1_t.html

http://gentoo-wiki.com/TIP_Convert_latin1_to_UTF-8_in_MySQL

Also, once all of your databases are utf8 you could set these options in my.cnf:

[mysqld]
default-character-set=utf8
default-collation=utf8_unicode_ci

[client]
default-character-set=utf8

PHP/HTML

<meta http-equiv=”content-type” content=”text/html; charset=utf8″ />
use htmlentities like this:
htmlentities($string, ENT_COMPAT, ‘UTF-8′)

Magpie RSS:
$rss = new MagpieRSS($rss_string, ‘UTF-8′, ‘UTF-8′, false);

How to setup hobbit/xymon, including MySQL graphs

August 1st, 2008

Updated 2011-06-20 – updated for ‘xymon’

Setting up xymon client

adduser --disabled-login xymon
cd /usr/src
wget http://downloads.sourceforge.net/project/xymon/Xymon/4.3.3/xymon-4.3.3.tar.gz
tar -zxvf xymon-4.3.3.tar.gz
cd xymon-4.3.3
./configure.client

(config=server)
(user=xymon)
(home=/home/xymon)

make
make install
su - xymon -c "/home/xymon/client/runclient.sh start"

Install MySQL/Apache Montioring on client

1. Create a mysql user ‘monitoring’, eg:

CREATE USER 'monitoring'@'localhost' IDENTIFIED BY 'monitoring';

2. Install ext scripts::

cd /home/xymon/client
cvs -d:pserver:anon@cvs.hamish.geek.nz:/cvs co -d ext xymon-ext
chown xymon:xymon ext -R
chmod 700 ext -R

Set mysql password in the file:

bb-mysql.pl

Edit disk device in the files:

diskreads.sh
diskwrites.sh

Add lines to /home/xymon/client/etc/clientlaunch.cfg
(or on server, put them in /home/xymon/server/etc/tasks.cfg)

[mysql]
ENVFILE $XYMONCLIENTHOME/etc/xymonclient.cfg
CMD $XYMONCLIENTHOME/ext/bb-mysql.pl
LOGFILE $XYMONCLIENTHOME/logs/bb-mysql.log
INTERVAL 5m

[mysqlhq]
ENVFILE $XYMONCLIENTHOME/etc/xymonclient.cfg
CMD $XYMONCLIENTHOME/ext/mysqlhq
LOGFILE $XYMONCLIENTHOME/logs/mysqlhq.log
INTERVAL 5m

[mysqlht]
ENVFILE $XYMONCLIENTHOME/etc/xymonclient.cfg
CMD $XYMONCLIENTHOME/ext/mysqlht
LOGFILE $XYMONCLIENTHOME/logs/mysqlht.log
INTERVAL 5m

[mysqlhs]
ENVFILE $XYMONCLIENTHOME/etc/xymonclient.cfg
CMD $XYMONCLIENTHOME/ext/mysqlhs
LOGFILE $XYMONCLIENTHOME/logs/mysqlhs.log
INTERVAL 5m

[apachew]
ENVFILE $XYMONCLIENTHOME/etc/xymonclient.cfg
CMD $XYMONCLIENTHOME/ext/apache-workers.sh
LOGFILE $XYMONCLIENTHOME/logs/apache-workers.log
INTERVAL 5m

[diskreads]
ENVFILE $XYMONCLIENTHOME/etc/xymonclient.cfg
CMD $XYMONCLIENTHOME/ext/diskreads.sh
LOGFILE $XYMONCLIENTHOME/logs/diskreads.log
INTERVAL 5m

[diskwrites]
ENVFILE $XYMONCLIENTHOME/etc/xymonclient.cfg
CMD $XYMONCLIENTHOME/ext/diskwrites.sh
LOGFILE $XYMONCLIENTHOME/logs/diskwrites.log
INTERVAL 5m

[coretemp]
ENVFILE $XYMONCLIENTHOME/etc/xymonclient.cfg
CMD $XYMONCLIENTHOME/ext/coretemp.pl
LOGFILE $XYMONCLIENTHOME/logs/coretemp.log
INTERVAL 5m

restart xymon:

su -c "/home/xymon/client/runclient.sh start" xymon

Setting up xymon server

Add to settings in /home/xymon/server/etc/xymonserver.cfg

TEST2RRD="EXISTING_STUFF,apachew=ncv,mysqlht=ncv,mysqlhs=ncv,mysqlhq=ncv,diskreads=ncv,diskwrites=ncv,coretemp=ncv"

GRAPHS="EXISTING_STUFF,apachew,mysqlhq,mysqlht,mysqlhs,diskreads,diskwrites,coretemp"

NCV_apachew="numworkers:GAUGE"
NCV_mysqlht="numthreads:GAUGE"
NCV_mysqlhs="slowqueries:GAUGE"
NCV_mysqlhq="queriespersec:GAUGE"
NCV_diskreads="diskreads:GAUGE"
NCV_diskwrites="diskwrites:GAUGE"
NCV_coretemp="core0:GAUGE,core1:GAUGE,core2:GAUGE,core3:GAUGE"

add sections to /home/xymon/server/etc/graphs.cfg

[apachew]
TITLE Apache Workers
YAXIS Num
DEF:workers=apachew.rrd:numworkers:AVERAGE
LINE2:workers#00CCCC:Apache workers
COMMENT:\n
GPRINT:workers:LAST:Apache workers \: %5.1lf%s (cur)
GPRINT:workers:MAX: \: %5.1lf%s (max)
GPRINT:workers:MIN: \: %5.1lf%s (min)
GPRINT:workers:AVERAGE: \: %5.1lf%s (avg)\n

[mysqlht]
TITLE MySQL Threads
YAXIS Num
DEF:threads=mysqlht.rrd:numthreads:AVERAGE
LINE2:threads#00CCCC:MySQL threads
COMMENT:\n
GPRINT:threads:LAST:MySQL threads \: %5.1lf%s (cur)
GPRINT:threads:MAX: \: %5.1lf%s (max)
GPRINT:threads:MIN: \: %5.1lf%s (min)
GPRINT:threads:AVERAGE: \: %5.1lf%s (avg)\n

[mysqlhs]
TITLE MySQL Slow Queries
YAXIS Num
DEF:slow=mysqlhs.rrd:slowqueries:AVERAGE
LINE2:slow#ff0000:Slow queries
COMMENT:\n
GPRINT:slow:LAST:Slow queries \: %5.1lf%s (cur)
GPRINT:slow:MAX: \: %5.1lf%s (max)
GPRINT:slow:MIN: \: %5.1lf%s (min)
GPRINT:slow:AVERAGE: \: %5.1lf%s (avg)\n

[mysqlhq]
TITLE MySQL Queries Per Second
YAXIS Num
DEF:qps=mysqlhq.rrd:queriespersec:AVERAGE
LINE2:qps#ff0000:Queries per sec
COMMENT:\n
GPRINT:qps:LAST:Queries per sec \: %5.1lf%s (cur)
GPRINT:qps:MAX: \: %5.1lf%s (max)
GPRINT:qps:MIN: \: %5.1lf%s (min)
GPRINT:qps:AVERAGE: \: %5.1lf%s (avg)\n

[diskreads]
TITLE Disk reads
YAXIS Num
DEF:diskreads=diskreads.rrd:diskreads:AVERAGE
LINE2:diskreads#00CCCC:Disk reads
COMMENT:\n
GPRINT:diskreads:LAST:Disk reads\: %5.1lf%s (cur)
GPRINT:diskreads:MAX: \: %5.1lf%s (max)
GPRINT:diskreads:MIN: \: %5.1lf%s (min)
GPRINT:diskreads:AVERAGE: \: %5.1lf%s (avg)\n

[diskwrites]
TITLE Disk writes
YAXIS Num
DEF:diskwrites=diskwrites.rrd:diskwrites:AVERAGE
LINE2:diskwrites#00CCCC:Disk writes
COMMENT:\n
GPRINT:diskwrites:LAST:Disk writes \: %5.1lf%s (cur)
GPRINT:diskwrites:MAX: \: %5.1lf%s (max)
GPRINT:diskwrites:MIN: \: %5.1lf%s (min)
GPRINT:diskwrites:AVERAGE: \: %5.1lf%s (avg)\n

[coretemp]
TITLE Core Temperature
YAXIS Degrees C
DEF:core0=coretemp.rrd:core0:AVERAGE
DEF:core1=coretemp.rrd:core1:AVERAGE
DEF:core2=coretemp.rrd:core2:AVERAGE
DEF:core3=coretemp.rrd:core3:AVERAGE
LINE2:core0#FF0000:Core 0
LINE2:core1#00FF00:Core 1
LINE2:core2#0000FF:Core 2
LINE2:core3#FF66BB:Core 3
COMMENT:\n
GPRINT:core0:LAST:Core 0 \: %3.1lf%s (cur)
GPRINT:core0:MAX: \: %3.1lf%s (max)
GPRINT:core0:MIN: \: %3.1lf%s (min)
GPRINT:core0:AVERAGE: \: %3.1lf%s (avg)\n
GPRINT:core1:LAST:Core 1 \: %3.1lf%s (cur)
GPRINT:core1:MAX: \: %3.1lf%s (max)
GPRINT:core1:MIN: \: %3.1lf%s (min)
GPRINT:core1:AVERAGE: \: %3.1lf%s (avg)\n
GPRINT:core2:LAST:Core 2 \: %3.1lf%s (cur)
GPRINT:core2:MAX: \: %3.1lf%s (max)
GPRINT:core2:MIN: \: %3.1lf%s (min)
GPRINT:core2:AVERAGE: \: %3.1lf%s (avg)\n
GPRINT:core3:LAST:Core 3 \: %3.1lf%s (cur)
GPRINT:core3:MAX: \: %3.1lf%s (max)
GPRINT:core3:MIN: \: %3.1lf%s (min)
GPRINT:core3:AVERAGE: \: %3.1lf%s (avg)\n

Easy Setup of a CVS server on Debian Etch

July 26th, 2008

I tore my hair out over this for quite a while yesterday. Hopefully this might help someone else (and as a reminder to my self if I ever need to do this again). Ideally I wanted the following scenario:

- developer account ‘hamish’ who can read/write to the cvs server
- an anonymous account ‘anon’ who can only read from the cvs server

I wanted the developer accounts to connect with ssh and anon via pserver, however…this seems like a mission! Perhaps this is why sourceforge (who do it this way) have a horrible delay between the developer and anonymous servers – maybe the 2 schemes wont cooperate nice and easily!?

Anyway, so I decided to use plain old pserver for both developer and anonymous account. This made my life a lot easier, and I’m not that paranoid about security :)

Anyway, here goes…
1. Install cvs and cvsd

apt-get install cvs cvsd

When configuring cvsd I was asked which repositories to serve. I typed ‘/cvs’.

This means my repository will be available at cvs.myserver.com/cvs

2. Initialise the repository

cvs -d /var/lib/cvsd/cvs init

add the following line in /var/lib/cvsd/cvs/CVSROOT/config:
LockDir=/tmp

3. Allow write access to repository

chown cvsd:cvsd /var/lib/cvsd/cvs

4. Allow history file to be written

chown cvsd:cvsd /var/lib/cvsd/cvs/CVSROOT/history

5. Add developer use account

cvsd-passwd /var/lib/cvsd/cvs hamish

6. Allow developer to write to repository

echo “hamish” > /var/lib/cvsd/cvs/CVSROOT/writers

7. Setup anonymous account

cvsd-passwd /var/lib/cvsd/cvs anon

That’s it! Good luck!

Firefox 3 excitement….disappointment

November 22nd, 2007

I just read on slashdot – “ZDNet picks up on yesterday’s Firefox 3 beta 1 review by comparing the memory usage of Firefox 2 against the latest beta. The results from one of the tests is quite interesting, after loading 12 pages and waiting 5 minutes, 2 used 103,180KB and 3 used 62,312KB. IE used 89,756KB.”"

Oh how excited I was – the memory issues with FF 2 were why i went back to v1. Could I finally move on!?

The answer……….NO!!

The simple task of removing a link from my bookmarks toolbar sent FF3 into a spin…memory usage 720,000k and counting!! LOL!

What a joke.

Downgrade to Firefox 1.5 – Firefox 2 is a lemon!

November 9th, 2007

Ah, what a brilliant day. For months now I’ve been swearing about how bad Firefox 2 is – memory leaks, slow loading, crashing – it’s been the bane of my coding life. Anyway, finally today I took the time to scour the net for good old Firefox 1.5 – you can’t get it from the official firefox site. Anyway here it is:

http://filehippo.com/download_firefox/?2743

I can’t believe how much faster it is! My productivity has gone through the roof!