Sunday, November 14, 2010

PHP: Effortless CAPTCHA

Include the following code in your form action reciever:

$verif_box = $_POST["verif_box"];
    if(md5($verif_box).'a4xn' == $_COOKIE['tntcon']){
                      //they got the CAPTCHA correct
                    //they did not get CAPTCHA correct

Here is a snippet of the part of the form that displays the CAPTCHA:


<td valign="top">Type number you see:</td><td valign="top">

<input name="verif_box" type="text" id="verif_box" style="padding:2px; border:1px solid #CCCCCC; width:180px; height:14px;font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px;"/>

<img src="verificationImage.php?<?php echo rand(0,9999);?>" alt="verification image, type it in the box" width="50" height="24" align="absbottom" /><br />

<!-- if the variable "wrong_code" is sent from previous page then display the error field -->

<?php if(isset($_GET['wrong_code'])){?>

<div style="border:1px solid #990000; background-color:#D70000; color:#FFFFFF; padding:4px; padding-left:6px;width:295px;">Wrong verification code</div><br />

<?php ;}?>


<INPUT TYPE="SUBMIT" NAME="submit" VALUE="Submit">


Contents of verificationImage.php:

// -----------------------------------------
//  The Web Help .com
// -----------------------------------------
header('Content-type: image/jpeg');

$width = 50;
$height = 24;

$my_image = imagecreatetruecolor($width, $height);

imagefill($my_image, 0, 0, 0xFFFFFF);

// add noise
for ($c = 0; $c < 40; $c++){
    $x = rand(0,$width-1);
    $y = rand(0,$height-1);
    imagesetpixel($my_image, $x, $y, 0x000000);

$x = rand(1,10);
$y = rand(1,10);

$rand_string = rand(1000,9999);
imagestring($my_image, 5, $x, $y, $rand_string, 0x000000);



PHP: The Ultimate E-mail Verification Routine

function validEmail($email)
    $isValid = true;
    $atIndex = strrpos($email, "@");
    if (is_bool($atIndex) && !$atIndex)
    $isValid = false;
    $domain = substr($email, $atIndex+1);
    $local = substr($email, 0, $atIndex);
    $localLen = strlen($local);
    $domainLen = strlen($domain);
    if ($localLen < 1 || $localLen > 64)
    // local part length exceeded
    $isValid = false;
    else if ($domainLen < 1 || $domainLen > 255)
    // domain part length exceeded
    $isValid = false;
    else if ($local[0] == '.' || $local[$localLen-1] == '.')
    // local part starts or ends with '.'
    $isValid = false;
    else if (preg_match('/\\.\\./', $local))
    // local part has two consecutive dots
    $isValid = false;
    else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain))
    // character not valid in domain part
    $isValid = false;
    else if (preg_match('/\\.\\./', $domain))
    // domain part has two consecutive dots
    $isValid = false;
    else if
    // character not valid in local part unless
    // local part is quoted
    if (!preg_match('/^"(\\\\"|[^"])+"$/',
    $isValid = false;
    if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A")))
    // domain not found in DNS
    $isValid = false;
     return $isValid;

PHP and MySql Basics: Insert Query

//open conn to db
mysql_connect('dbhostserver','dbusername','password') or die("Failure to connect to db");


$as_value1 = addslashes($_POST['value1']);
$tr_value1 = trim($as_value1);

$as_value2 = addslashes($_POST['value2']);
$tr_value2 = trim($as_value2);

$query = "INSERT INTO table(value1, value2) VALUES ('$tr_value1', '$tr_value2')";
$result = mysql_query($query);
   $message = "Successfully added to db.";
   $message = "Could not add to db.";

PHP Basics: Connect to MySql and Query

//open conn to db
mysql_connect('dbhostserver','dbusername','password') or die("Failure to connect to db");


$query = "SELECT stuff FROM tablename";
$result = mysql_query($query);
while($name_row = mysql_fetch_row($result)){

Thursday, November 11, 2010

Transact SQL (T-SQL) Basics

DECLARE and SET Varibales
DECLARE @Mojo int
SET @Mojo = 1
SELECT @Mojo = Column FROM Table WHERE id=1

IF / ELSE IF / ELSE Statement
IF @Mojo < 1
'do something
ELSE IF @Mojo = 1
'do something
'do something

CASE Statement
WHEN (DateAdded IS NULL) THEN 'Unknown'
WHEN (DateDiff(day, DateAdded, getdate()) = 0) THEN 'Today'
WHEN (DateDiff(day, DateAdded, getdate()) = 1) THEN 'Yesterday'
WHEN (DateDiff(day, DateAdded, getdate()) = -1) THEN 'Tomorrow'
ELSE DATENAME(dw , DateAdded)
FROM Table


For some odd reason, I have it stuck in my mind that you need to use JOINS to find duplicates (maybe it was something that Access made you do way back in the day). I know there is SOMETHING out there that seems like it would be very easy to do in SQL but in fact involves duplicating the table in an alias. But finding duplicates isn't it.

SELECT username,
COUNT(username) AS NumberOfOccurences
FROM users
GROUP BY username
HAVING ( COUNT(username) > 1 )

Tuesday, October 26, 2010

Trying Out Amazon Associates

For the first time I'm going to try and monetize this site.

Wednesday, October 20, 2010

Old School WScript to Make Files Read-Write

If you frequently need to change the file attributes of one or more files from "Read Only" to "Read and Write" on Windows (like I have to do when dealing with the limitation of Visual SourceSafe), this quickie script will do the trick. Create a .vbs file with the following:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim arrayFileObjects(1)
set arrayFileObjects(0) = objFSO.GetFile("C:\BudgetTracker\App.config")
set arrayFileObjects(1) = objFSO.GetFile("C:\ApeSim\App.config")

for counter = 0 to ubound(arrayFileObjects)
if arrayFileObjects(counter).Attributes AND 1 then
'read-only, so set to read/write
arrayFileObjects(counter).Attributes = arrayFileObjects(counter).Attributes XOR 1
Wscript.echo ("one changed")
Wscript.echo ("one already ok")
End If


Tuesday, October 19, 2010

VB.NET, DB Nulls, and strings

If you are dealing with a database that isn't enforcing "no nulls" then you may frequently get nulls back when you are expecting a string. Although you could do this:

if dr.Item("middle_name") is DBNull.Value then
txtMiddleName.Text = ""

It is easier to just write:

txtMiddleName.Text = dr.Item("middle_name").ToString

because adding "ToString" will convert nulls to "" empty strings.
If you omit the "ToString", any nulls will generate an error (converting a Null to a String).

Monday, October 18, 2010


The syntax for inserting a new row (or record) into a table using data from a select is not very intuitive.

The INSERT syntax is:
INSERT tblFred(field1, field2, field3) VALUES( 'ape', 436, 0)
or if you are insert values for all columns in order:
INSERT tblFRED VALUES (23, 'ape', 436, 0)

But to use the INSERT with a SELECT, you omit the VALUES( ) phrase:
INSERT tblFred(field1, field2, field3) SELECT fieldA, fieldB, fieldC FROM tblSmedly

INSERT tblFred SELECT * FROM tblSmedly

Friday, October 15, 2010

Which edition of SQL Server 2005 is that?

SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel'), SERVERPROPERTY ('edition')

Tuesday, October 12, 2010

UNIX Date Format for SQL Server

UNIX date times are most often stored as seconds from midnight, January 1, 1970. If you are running into a date format that looks like, for example, "1286790650" or "1141541097", a ten digit number, it is most likely a UNIX time stamp. (also see ).

Here's how to convert on SQL Server:
dateadd(ss, 1234567890, '1970-01-01')
where 12345678790 is your date given in UNIX time stamp format.

This is also why 11:31 pm (in the UK) was so exciting on February 13, 2009.

Friday, September 10, 2010

Mungled SQL Server instances

So, you have before you a box that has seen its share of SQL Server instances over the years, had its security settings and various broadcast settings changed inconsistently, and you just want to get a handle on what you have. To get the instance names, do a search for the "perf-*.ini" files in the various database folders (i.e., "MSSQL.1").

For example, in:
C:\Program Files\Microsoft SQL Server\MSSQL.1\Binn
if the instance used for this database was "SMEDLY" then you'll find:

Wednesday, September 8, 2010

Regular Expression Search and Replace

Using Textpad's implementation of RegEx, the following will find all closing HTML/XML tags and add a carriage return after them:

search:  </[^>]*>
replace: \0 \n

Same thing, to create a carriage return before starting tags:

search:  <[^>]*>
replace: \n \0

This really helps when you are trying to view HTML that has been machine generated and appears in a single line.

Where Textpad uses the backslash (\) for the replacement sytax, other implementations of RegEx use the percent symbol (%).

Friday, September 3, 2010

My First Code Project Article

Couldn't afford the time to do something full out, but at least I finally went ahead and put something up there.

Searching Revision History Comments in Visual SourceSafe - CodeProject

My alias on Code Project is patrickpage.

Friday, August 27, 2010

List of Fonts Installed on PC

Important for Flash and Photoshop work, especially when moving to a different machine, where you might want to compare what's installed.

run: cmd
dir c:\windows\fonts > fontlist.txt

Yes, it is that easy!

Jargon, or A Rose is a Rose...

Adobe calls 'em listeners, Microsoft calls 'em delegates or handlers, ANSI C++ programmers would recognize "callback function", and Java programmers would say "huh?"

Tuesday, August 3, 2010

Installing SQL Server 2005: Collation

I had to make sure I had the collation settings set exactly as they were in a production instance of SQL Server. In the past, SQL Server gave you a single list of collation settings - code orders to pick from. I think the default was:

"SQL_Latin1_General_Cp1_CI_AI" ("sort order id" 54).

But since SQL Server 2005, the preferred way to set collation is now modular: you first select a "Collation designator" (i.e., alphabet) and then specify the "sort order" by selecting from various checkboxes:

  • binary
  • case-sensitve
  • accent-sensitive
  • binary-code point
  • kana sensitive
  • width-sensitive

So I had to figure out what the old collation setting string (in my case, "SQL Latin1_Cp1_CI_AS") meant, in this regard. As is kind of obvious, it contains the sort order settings as abbreviations. But just to make sure:

Code Page
Specifies a one- to four-digit number that identifies the code page used by the collation. CP1 specifies code page 1252, for all other code pages the complete code page number is specified. For example, CP1251 specifies code page 1251 and CP850 specifies code page 850.

Case Sensitivity

CI specifies case-insensitive, CS specifies case-sensitive.

Accent Sensitivity

AI specifies accent-insensitive, AS specifies accent-sensitive.

Sunday, June 20, 2010

Ajax before there was Ajax

Asynchronous Client-Server Interaction:
Hidden frame, using top/parent frame's variables to retain scope == HMLHTTPRequest (so long as the returned HTML is not significantly larger than the returned XML would be)

So long as the majority of server requests is nearly instantaneous, where "waiting for the user to pick something" is orders of magnitude more time consuming than processing the decision (which seemed to be true in 99.99% of all cases)...

The client was notified by the hidden frame calling (onload) a function in the parent/top frame. No big deal. In fact, is not this more efficient than weighing down the client script with the duty of monitoring/listening ....?

Constituent Parts

...and so begins my Useful Phrases page, kind of like the Good Jargon side of Jargon. Maybe I'll have a Good Jargon page and Bad Jargon page. Or a Useful get the point.

Jargon is tremendously important. Can't be overstated. It signals to other parties that you already understand (supposedly) a whole bunch o' stuff, per each Jargon uttered. For the most part, in day to day life, I've seen it as a Bad seems to have more drawbacks than benefits in what I've witnessed. Specifically, when switching back and forth between different programmer cultures (Windows vs. Linux, VB vs Java, etc), it is a major hindrance and causes more confusion than necessary. Often it seems Microsoft has deliberately adopted its own terms for Jargon that would otherwise be common between the two camps.

But I'm trying to adopt a more positive outlook on the matter. In either case, Jargon is Very Helpful when it comes to Documentation, in particular, making documentation Brief.

The other great benefit to Jargon is in exposing the genealogy of concepts. Much Jargon in programming is from upper level Mathematics, or Electrical Engineering.

Thursday, June 3, 2010

Retrieving text stored as an Image data type in SQL Server

So, you have an old database that relies on the Image data type to story rich text, and within the confines of SQL Management Studio, you want to read the contents. Turns out that the Image data type cannot convert to a varchar directly, like some of the newer binary data types can.

So you have to first translate it to binary and then convert that to varchar.

SELECT CONVERT(VARCHAR(8000),CONVERT(VARBINARY(8000),notepad_textimage)) from notepad

Incidentally, to get the size of the image data, use DATALENGTH (instead of LEN).

Wednesday, May 26, 2010

Mark Russinovich, Sysinternals and Malware

A very well-known tool used by those who administer their own or others computers is Sysinternals. What I didn't know is that these tools were created pretty much by a single author. What's more is that this author, Mark Russinovich, is a great speaker, and his presentations are a must watch for anyone interested in the inner workings of Windows. I appreciate his attitude (perhaps because it is devoid of just that, "attitude") and I could listen to his presentations all day.

The presentation that got me started on him is Advanced Malware Cleaning, but there are other similar presentation that focus on other tools in the Sysinternals suite available from that location.

Monday, May 24, 2010

Thoughts on Alternative Narrative of Social Networking Phenomenon

Perhaps its all about another desperate attempt to instantiate delusions of grandeur on the part of corporations.

A learned lesson of the Web about 6-8 years ago was no site can hope to capture users' sole attention.

To be sure, portals always tried to be that "one site". Granted, Yahoo goes back to the inception of the Web. But the battle came to a head some years later, when there was a pile on to be "THE" portal of record. But who won in the end? Google. An empty page with a textbox to enter a search term.

Corporations had a difficult time giving up on the hope of being "THE" site, and the mentality that users will spend, or care to spend, a vast amount of time on their site. Related to this desire is a desire to be ON THE (potential) CUSTOMER'S MIND. Mindshare. Similarly, a need to MANAGE customers... to hang on to some kind of control. Granted, its likely such CONTROL isn't even really necessary to succeed as provider of goods and services. But corporate mentality and record keeping require it.

So, having failed to be on the customers mind for the majority of the customer's online lifespan, corporations were seduced by the promise of SOCIAL NETWORKING as a means to be in the (potential) customer's online manage and keep track of. This imperative may in fact be the driver behind SOCIAL NETWORKING and the Web 2.0 interconnectedness pursuit.

Wednesday, May 19, 2010


Here is a handy cheat sheet for Microsoft's SQLCMD, when you don't have the luxury of SQL Server Management Studio.

To run some sql and have results sent to "output.txt",on local server:

>SQLCMD -S(local) -U sa -P changeme -q "use WONDERBEAN;select * from orders;" -o output.txt

To run some sql stored in "myScript.sql" and have results logged to "output.txt",
on local server,with instance called "instanceSmedly":

>SQLCMD -S(local)\instanceSmedly -U sa -P changeme -i myScript.sql -o output.txt

Typical use would be to do a restore. Here is a handy example of some restore sql syntax:

alter database WONDERBEAN SET single_user with rollback immediate;
restore database WONDERBEAN from disk = 'C:\Users\Howard\Documents\WONDERBEAN_1_1_2010.bak' with replace,recovery;
alter database WONDERBEAN set multi_user

Virtual Box : Time machine

I've been digging Sun's free VirtualBox over Microsoft's Virtual PC, and not only because of the Snapshot branching functionality. Here is how to disable the time in the guest operating system from syncing with the hosts, which is great for testing various scenarios.... vboxmanage setextradata vmname “VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDisabled” “1″

Tuesday, May 18, 2010

Sequence Diagrams from UML

Recently I've been taking another look at UML. Perhaps it was the result of talking to a software ARCHITECT for the first time in a while, or sub-consciously inserted from the news that Visual Studio 2010 will have some important UML features.

Many of the projects I work on involve first familiarizing myself with legacy code. To me this is almost always fascinating, like "This Old House". I have rarely found two programmers who code the same way. If there is similar architecture to something else I've come across, it almost always turns out to be auto-generated from Microsoft.

I have improvised various note-taking schemes over the years, which is great in that it allows me flexibility to deal with the idiosyncracies of the particular project at hand. On the other hand, one does long for some standards to be handed down. This would be all the more important when working on an excavation as a team.

So, I was delighted to become reacquainted with (because I'm sure I saw it somewhere before but didn't appreciate it) Ivar Jacobson's Sequence Diagrams. When dealing with a highly optimized object oriented architecture that lacks any documentation whatsoever, this is exactly the kind of approach you'd want to take in dissecting some codebase. Sure it was intended for design, but for my purposes, it is probably even more useful in reverse engineering.

Yet, as it seems with all UML models, there is an enormous lack of creativity when it comes to the drawing of symbols. I hope to find an implementation of Sequence Diagram models that has something more creative than a stick person.

Just learned that the UML creation tools in Visual Studio 2010 only come with the Ultimate version, not either the Professional nor the Premium. Bummer.

Friday, March 26, 2010

Immediate Window vs Command Window in Visual Studio

To issue a Visual Studio command in the Immediate window, you must preface the command with a greater than sign (>). To enter multiple commands, switch to the Command window.

The window used to enter the EvaluateStatement command determines whether an equals sign (=) is interpreted as a comparison operator or as an assignment operator.

In the Immediate window, an equals sign (=) is interpreted as an assignment operator.

In the Command window, by contrast, an equals sign (=) is interpreted as a comparison operator. You cannot use assignment operations in the Command window.

Some useful commands:
Collapses all collapsible section of code (classes, regions, etc.)

opens the toolbox window

>help whatever
opens up help for the keyword (in this case, whatever)

Friday, March 19, 2010

Did you know...

SQL Server started supporting multiple instances in the 2000 edition.

SQL Server Express Editions always install as a Named Instance, even if you only have one. The instance name, by default, is SQLEXPRESS.

The MSDE Edition of SQL Server 2000 installs as a Default Instance.

In SQL Server 2000, the TCP/IP port for a named Instance moves to 1434, and SQL Server 2000 directs the client to the proper Instance using SQL Server Resolution Protocol (SSRP).

In SQL Server 2005, Microsoft introduced a new service called the SQL Browser. This service listens on UDP port 1434 and directs the connection to the proper dynamically chosen TCP/IP port.

Each named Instance has a different location for program files and data files that is different from that of the other Instances of SQL Server. In SQL Server 2000, the directories look like this:

executable/program files:
\Program Files\Microsoft SQL Server\MSSQL$NameOfInstance\Binn
data files:
\Program Files\Microsoft SQL Server\MSSQL$NameOfInstance\Data

In SQL Server 2005 and higher, the files have a different structure. For the Default Instance:

executable/program files:
\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL
data files:
\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data

The maximum number of Instances supported in SQL Server 2000 and 2005 is 16 for the standard editions and lower, and 50 for the Enterprise Editions in 2005 and even more in later versions and higher edition numbers


  • Many Microsoft products: having both a "Settings..." and "Options..." choice on the menu
  • SQL Server's Mgt Studio: "Modify" and "Open table..." in the context menu (since "Open table..." is frequently used to MODIFY data).  "Modify" should be either "Schema" or "Modify table columns"....

Tuesday, March 16, 2010

Database DE-normalization and Violating Simplicity Principles

Timothy Claason, at SQL Server Central, writes:

"Denormalization is not a design strategy. It is a design work-around. Well normalized databases represent a good design strategy, but can often lead to a great deal of complexity when it comes to support, maintenance, and new development. A well designed database can mean that, in order to get specific data you need, you need to go through 5, 10, or even more tables which represent the data you're looking for. Though there are many solutions to this dilemma,such as virtual tables (views), programmatic solutions, temporary tables, and more, I think it's important to not discount the value of well-placed denormalization in the database. The intent of this article is to consider some use cases for denormalization, and from those use cases, assert some generalizations about when and why to use denormalization."


Wednesday, March 10, 2010

File Hash Checker

Download here

This is a simple utility I wrote that displays the hash code of one or two files, and then compares them to see if they are the same. I used this to find duplicate image files (where the names of the files could be different).

Friday, March 5, 2010

Conditional Compilation

#define test = true
class TestClass {
void test() {
#if test
// do something
// do something else

Here's the equivalent code in VB.NET:

#Const test = True
Class TestClass
Sub test()
#If test
'do something
'do something else
#End If
End Sub
End Class

Here's the same but using the DEBUG constant which is automatically set by Visual Studio based on whether you are in debug mode:

Class TestClass
Sub test()
'do something
'do something else
#End If
End Sub
End Class

Software Testing

Unit Tests
The major benefits to be had from unit testing are

1. It allows the developer test parts of an application without waiting for the other parts to be available.

2. Exceptional conditions can be tested for the unit

3. The debugging process is simplified by limiting the search for bugs to a small unit rather than the complete application.

4. It helps avoid lengthy compile-build-debug cycles when debugging difficult problems.

5. Detection and removal of defects can be done at a much lower cost.

Integration Testing
The purpose of this kind of testing is to verify whether the major subsystems of the application are integrated. It helps in uncovering the errors that may arise due to conflicts between different units of an application. Integration testing is performed in different ways.

Bottom Up Approach: The testing is commenced from the smallest subsystem and progresses up the hierarchy to cover the whole system. This methodology requires the developer to write a number of test driver programs that test the integration between the subsystems.

Top down Approach: This begins at the top. The top level interfaces are first tested and then the smaller sub systems are examined. Stubs are written for modules that are not ready for testing.

Umbrella Approach: The focus in this methodology is on testing the modules that have a high degree of user interaction. Stubs are used in place of process intensive modules. This enables the developer test the graphical user interface and improves the functionality of the interface.

Regression Testing
Regression testing is performed whenever the program is modified. The process involves the rerun of all the tests mentioned in the preceding sections. It has two main goals:

  1. Verification of known bugs that were corrected
  2. Verification of new bugs.

Testing International Applications
Applications created for international usage are to be tested by checking for the language, the country and dependencies. The following factors are to be considered when testing such applications:

  • Whether the application’s data and user interface conform to the locale’s standards for date, time, numeric values, currency, list separators and measurements.
  • Whether the application runs on different languages and culture variants.
  • If Unicode has not been used in the application the culture/locale code of the operating system will have to be set to the localized version of the application.
  • The Input data in the language should be supported by the localized version.
  • In this section of the lesson we have focused upon the testing of Windows applications. In the sections that follow we shall briefly look at tracing windows applications.