Open Source Wiki

September 10th, 2009

I was recently asked to create a knowledge base system at work… knowing that there were plenty mature open source projects that would work well, I opted not to write my own and instead chose one called MoinMoin.

To be honest I did not paticullary care what language it was written in (I can program in anything). My primary concerns were stability and simplicity. My decision in selecting MoinMoin was based primarily on the fact that the people who would be responsible for adding content did not have a solid grasp on basic web technologies, would have a difficult time learning HTML, and whom I did not trust to afford the luxury of a WYSIWYG editor.

MoinMoin allows new pages to be created simply by typing in the address you want, sub pages are created as subdirectories, and content is added in plain-text format using special identifiers which are later cast to html and styles (depending on which template you use). I felt that it included an adequate amount of embedded how-to documentation for them and that the syntax should be realitively easy for them to grasp in a short time.

I did have some issues with the install… but as usual, it was my fault and I soon had it running within its own application pool on IIS. I tested the system extensively for performance in cpu and memory overhead and it runs like a champ. Time will tell if the office actually uses it though 8-)

If you have any suggestions, questions, or experiences setting up your own Wiki I would be happy to hear from you so please comment.

For additonal help with wiki selection I recommend an article published by O’Reilly: Choosing a WIKI

web development

Google Definitions

September 10th, 2009

Many of you may already be well aware of google definitions… apparently its been around since 2007. I stumbled across this tonight (this morning) and thought it was pretty neat. The search format is as follows:

definition:programmers

definition:micah

*notice the related search shown for “micah moore”. I guess I need a better last name. 8-)

This could quite easily be utilized for a dictionary feature inside your own software… granted its not a webservice, and there is no doubrt in my mind theres one out there, but it isn’t a far fetched idea to query the page and parse out the definition with a simple regex.

-peace & keep on programming

news

ColdFusion UDF Library

December 16th, 2008

I am excited to announce that the programmers.org ColdFusion UDF Extension Library is now freely available.

Part of being a good developer is the act of working smarter and not harder. And there is no better way to accomplish this than through code reuse. Adding your own Extension Library to ColdFusion is a direct and powerful way to increase the speed and consistency of your development.

Uncategorized

Extending Coldfusion with UDFs

December 3rd, 2008

I cobbled together a few functions you may find useful this morning. As you can see they are simple, albeit useful, and so I wanted to share them here. Enjoy, and keep on coding!

/*
FUNCTION:   ArrayFindString
PURPOSE:    Searches inside the specified array (array_obj)
              for a string matching string (str)
PARAMETERS: 1. array_obj: the array containing the strings you
                 want to try to match to str
            2. str: the string you will be looking for in array_obj
RETURNS:    boolean
NOTE:       not case sensitive
*/
function ArrayFindString(array_obj, str){
var i = 1;

for (i = 1; i lte arrayLen(array_obj); i = i + 1)
if (array_obj[i] eq str) return true;

return false;
}

/*
FUNCTION: 	ArrayContainsString
PURPOSE: 	Searches inside the specified array (array_obj) for a
                  string that contains the string (str)
PARAMETERS: 	1. array_obj: the array containing the strings you want
                     to try to match to str
                2. str: the string you will be looking for in array_obj
RETURNS: 	boolean
NOTE: 		not case sensitive
*/
function ArrayContainsString(array_obj, str){
var i = 1;

for (i = 1; i lte arrayLen(array_obj); i = i + 1)
if (findNoCase(str, array_obj[i])) return true;

return false;
}

/*
FUNCTION: 	StringSearchArray
PURPOSE: 	Searches inside the specified string (str) for any
string matches contained in the array (array_obj)
PARAMETERS: 	1. str: the string you will be searching inside of
                2. array_obj: the array containing the strings you want
                     to look for in str
RETURNS: 	boolean
NOTE: 		not case sensitive
*/
function StringSearchArray(str, array_obj){
var i = 1;

for (i = 1; i lte arrayLen(array_obj); i = i + 1)
if (findNoCase(array_obj[i], str)) return true;

return false;
}

If your curious, I use StringSearchArray to control which areas of my application require user login:

...
foldersNoLogin = arrayNew(1);
foldersNoLogin[1] = "/login";
foldersNoLogin[2] = "/registration";
</cfscript>
<cfif not isDefined("session.loggedin") or session.loggedin eq false>
<cfif not StringSearchArray(cgi.path_info, foldersNoLogin)>
	<cflocation addtoken="no" url="/login/">
</cfif>
</cfif>

Free Stuff , , ,

Accepting online credit card and echeck transactions

November 23rd, 2008

At one point or another you’ll be faced with figuring out how to accept secure payments from your website. As with most things, once you know the basics it isn’t quite as daunting as you might expect it to be. But before you get started remember that the things you will need like a Merchant Account (from a bank), an Online Payment Gateway (such as Authorize.net), and SSL Certificates cost money. Prices vary, but the average cost of a merchant account runs around $100.00 for setup, and the Online Gateway will typically have a minimum monthly fee of $30.00 and a cost per transaction anywhere from 10 to 20 cents. SSL Certificate prices are all over the board depending upon who you go with but a good price is $200.00 a year. (Expect to pay more if you go with a name-brand company like VeriSign or want extra features.) Obviously these prices are subject to change quite radically (and vary widely depending upon who you decide to do business with) so you will need to shop around and decide what fits best for you. Make no mistake you should know exactly whos services you will be using and exactly how much it is going to cost BEFORE ever starting development on an e-commerce website. period.

Although there are three methods of implementation, we will be looking at the Advanced Integration Method (aim). Other options are available if you wish to have orders take place on a third party site, or enter transactions in manually. I recommend the Advanced Integration Method  because it allows you to incorporate the POS directly inside your own website or application; providing a professional stream lined interface where all the transactions take place in the background with no interruption to the user. 

For those of you who prefer to RTFM, take a look at The AIM Guide PDF.

The basic process of communicating with a payment gateway is simple. You send in a request for a POS and it responds back with the result. That result will contain sale deatils, for example, wether or not the credit card was accepted, and if not the reason why. In our case we will be sending our payment request via post data to:

  • secure.authorize.net/gateway/transact.dll (for production)
  • test.authorize.net/gateway/transact.dll (for testing)

 

In upcoming articles I will walk you through the basic steps using Coldfusion:

  1.    submitting payment data to authorize.net
  2.    interrpreting the response

 

Expect to see these published on Wednesday, 11/26/2008. In the meantime feel free to ask any questions and I will do my best to help out.

Note:

Although this article covers the defacto authorize.net implementation (which by the way works with almost every online payment gateway since they are usually resellers of authorize.net), you may wish to take a look at Google Checkout. As the service is relatively new, there are some current promotions and discounts in place. I haven’t looked into the product heavily but it looks fairly solid and the idea of not having the liability of holding credit card numbers, etc…. can take a lot of weight off your shoulders.

In my next article I will cover tying in shipping services through UPS or FEDEX to round out the e-commerce experience. Please feel free to ask any questions before hand if you can’t wait.

Tip:

If you don’t already have a good traffic base coming to your website, don’t go spending the money and using the time to build a payment infrastrcuture. New companies often make the mistake of spending money up front assuming “if we build it they will come”… unfortunately they quickly learn the hard way this is far from the truth. 

If you have already managed to establish a good traffic base or have marketing material ready to roll out take the time to double check your work. It only takes one bad experience for a user to never come back… work all the kinks out, do user studies, and make sure your hardware and software can support a sudden influx of customers without going down.

Advanced Stuff , ,

Caclulating the distance between Zip Codes

November 18th, 2008

Calculating the distance between zip codes is not nearly as difficult as you might expect. To get started you will need two things:

  1. A zip code database that contains longitude and latitude coordindates
  2. A formula for measuring the distance between one point and another on a circle (in this case our circle is the circumference of earth)
     

You can obtain a free zip code databse from Popular Data.com, or you may wish to try the US Census Beurau. Google (and a few other companies with mapping software) also has GEO Code/Data available but make sure you check the license agreement carefully.

Once you have all your data imported into your preferred database and you have a form setup to accept a Starting and Ending Zip you need to integrate the formula into your program. Enter the Haversine formula to the rescue.

Here is a SQL implementation that works fantastic for me:

CREATE function [dbo].[geoDistance] (@lat1 decimal(9,6), @lon1 decimal(9,6), @lat2 decimal(9,6), @lon2 decimal(9,6))
returns float
as
begin
     declare @result float
     declare @r int
     declare @kmpm float
     declare @lat1R float
     declare @lat2R float
     set @kmpm = 0.621371192
     set @r = 6371
     set @lat1R = radians(@lat1)
     set @lat2R = radians(@lat2)
     set @result = acos(sin(@lat1R)*
                        sin(@lat2R)+cos(@lat1R)*
                        cos(@lat2R)*cos(radians(@lon2-@lon1)))*
                        @r*@kmpm
     if @result is null set @result = 0
     return @result
end

 

Here are some links to code in various other languages:

Caclulating the distance between Zip Codes using Python.
Caclulating the distance between Zip Codes using JavaScript.
Caclulating the distance between Zip Codes using C++.

 

*It is worth mentioning that the earth is not a perfect circle, so you should expect an inaccuracy somewhere around 2% depending upon where you are on the globe. For those who need more accuracy (about 3mm) check out the Vicenty’s Formula (which is based on the ellipsoidal model of earth).

Advanced Stuff ,

Email forwarding with SMS

November 14th, 2008

Forwarding your emails to your cellular phone is incredibly easy as all major carriers associate an email address directly with your telephone number:

Here are the major ones:

AT&T: phonenumber@txt.att.net
T-Mobile: phonenumber@tmomail.net
Virgin Mobile: phonenumber@vmobl.com
Sprint: phonenumber@messaging.sprintpcs.com
Verizon: phonenumber@vtext.com
Nextel: phonenumber@messaging.nextel.com

Quick Tips

Microsoft SQL: Restoring a table from a backup via script

November 14th, 2008

If you have done any signficant amount of programming in SQL you will have learned, with time, that nearly everything you can do in SQL Manager/Studio is 100% scriptable. Taking advantage of this can be a huge help with automating tasks… but you don’t need to bury your head in SQL Syntax to do so. Take the time to check out the wizards in studio, the context menus, etc… and you will almost always see a button or option to “generate script”. Get used to taking advantage of this because it will save you a multitude of headaches!

Here is a quick tip for restoring a table from a backup in script:

You cannot restore a database while it has active connections… to get around this you will need to set the database up in single_user mode (which deactivates all other connections except for your own). You will also need appropriate privelages to execute the commands like drop, restore, sp_adduser, and so on… db_creator roles are a simple solution for setting access priveleges but make sure you adequately protect the account as it opens up your database to lots of malicious activity if it were to fall in the wrong hands.

 

Here is a example to get you started down the right track:

--disconnect any one else so you can do the restore
ALTER DATABASE {your database}
    SET SINGLE_USER
    WITH ROLLBACK IMMEDIATE

USE MASTER 

--delete the old database (you could overwrite it instead
---if you wanted, merge, etc.)
DROP DATABASE {your database}

--restore the database from the backup
RESTORE DATABASE [{your database}]
   FROM  DISK = N'{insert full path to ur backup file here}' WITH  FILE = 1,
   MOVE N'{your backupset}' TO N'{insert your path and db name here}.mdf',
   MOVE N'{your backupset}_log' TO N'{insert your path and db name here}.ldf',
   NOUNLOAD,
   RECOVERY,
   REPLACE,
   STATS = 10

--grant privileges as necessary
use {your database}
exec sp_adduser '{user account}', '{user name}', 'db_datareader'

--reset the connection mode back to multi_user (this is important)
ALTER DATABASE {your database}
    SET MULTI_USER
    WITH ROLLBACK IMMEDIATE

MSDN Ref:
   1. Restore (Transact-SQL)
   2. sp_addUser (Transact-SQL)
   3. Drop Table (Transact-SQL)
   4. Alter Database (Transact-SQL)

Quick Tips

FREE CODE: Paging record list.

November 13th, 2008

When listing records from a database you will often need to break those records up into multiple pages, so that your users do not see hundreds of rows at once. What follows is a custom tag which does exactly that.

Parameters

  1. pageScale - (integer) Default 0. This will limit the number of pages returned depending on the current page. 0 means no scaling will occur.
    Example: pageScale=5, startRow=24, pageSize=8, records=64. Given these parameters this tag will return an array of 5 structures. The first page will start with 2 the last page will be 6. There are 8 total pages.
  2. startRow - (integer) Default 1. The first record of the current page.
  3. pageSize - (integer) Default 20. How many records to list per page.
  4. records - (integer) Default 0. How many records to page through.
  5. variable - (string) Default “pages”. The name of the array to create in the caller scope.

Source Code

Enjoy, it’s free. Until next time, dream in digital.

Free Stuff, web development ,

GMail voice and video chat

November 12th, 2008

Google does it again… are they on a mission for world domination? Released today, video chat straight in GMAIL!

news