Search: in  

Rob Kennedy's Blog

Rob Kennedy is an avid and active .NET software developer who tends to have an opinion about everything. In the windows developer community for over 10 years, he has grown his career and opinions through experience.

September 2007 - Posts

  • Having Fun with Google Maps API

    I've been having fun at work here using the Google Maps API. Tasked to build a website for the TSA, I had to come up with coordinates for most major U.S. airports, map them accordingly, and color code the icons depending on their status. Sounds like a semi-easy task, but it was a little bit of a learning curve to get it all working correctly. I eventually did get it up and running, and working great. Check out the screen shot below:

    TSA - OASISAirport Location Selector I will eventually post up an easy how-to regarding how I got this working and give you some code to get a similar site up and running yourself.

    On a side note, some of the API documentation was a bit out of date as Google has merged the Map API with their AJAX API, so some of the function calls, specifically, GUnload() do not apparently exist now.

    Share this post: E-mail Having+Fun+with+Google+Maps+API | Submit Having+Fun+with+Google+Maps+API to Technorati | Submit Having+Fun+with+Google+Maps+API to del.icio.us | Submit Having+Fun+with+Google+Maps+API to digg.com | Submit Having+Fun+with+Google+Maps+API to reddit.com | Submit Having+Fun+with+Google+Maps+API to DotNetKicks | Add Having+Fun+with+Google+Maps+API to Live Bookmarks
  • My work is blocking access to my website!

    So I was just testing out some software this morning and decided to enter in my URL like so: http://www.robkennedy.com/ with the beginning www. notation. When I clicked the link I was taken to our Websense blocking screen:


    websense_bs

    Obviously this is total BS! The reason stated in the message is that they are now blocking "Social Networking & Personal Sites" What the hell. These policies are starting to get out of hand; my site is a personal site, but it's packed full of useful info I relay my co-workers to. There are TONS! I MEAN TONS! Of personal sites that I can still get access to, yet mine is blocked. BS! I guess they feel too many people are accessing my site here, without actually asking why, they go ahead and block it.

    I am really livid with this company's gestapo policies right now. Fuming...

    UPDATE: Well as of this morning my work is now blocking this address without the www. name. Whoever is in charge of this seems to be hell bent on blocking access to this site.  I have submitted a formal request to have the site domain unblocked.

    Share this post: E-mail My+work+is+blocking+access+to+my+website! | Submit My+work+is+blocking+access+to+my+website! to Technorati | Submit My+work+is+blocking+access+to+my+website! to del.icio.us | Submit My+work+is+blocking+access+to+my+website! to digg.com | Submit My+work+is+blocking+access+to+my+website! to reddit.com | Submit My+work+is+blocking+access+to+my+website! to DotNetKicks | Add My+work+is+blocking+access+to+my+website! to Live Bookmarks
  • Tagspace Beta broken

    tagspace_cap Well it's been about a week now since I've been unable to get into my Tagspace account. I know it's beta software and all I think the Microsoft guys could at least put a better support/reporting mechanism in place other than a one sentence error message with no other links.

    The error occurs when I go to login to my Personal section. I will login to live, and then when redirected I will be prompted with this message. If I return to the home page, I'm also prompted with this message. There appears to be a critical bug within the authentication, or query lookup system for a particular user. I can't tell if the public list of links is updating (showing that others are not having this issue) but I think I can safely state that the error reporting on that site is absolutely useless. Come on Microsoft, build it better! 

    Share this post: E-mail Tagspace+Beta+broken | Submit Tagspace+Beta+broken to Technorati | Submit Tagspace+Beta+broken to del.icio.us | Submit Tagspace+Beta+broken to digg.com | Submit Tagspace+Beta+broken to reddit.com | Submit Tagspace+Beta+broken to DotNetKicks | Add Tagspace+Beta+broken to Live Bookmarks
    Posted Sep 21 2007, 10:37 AM by RobK410 with 1 comment(s)
    Filed under:
  • Retrieving Column Descriptions from MS SQL

    Building a schema report of one's database is a requirement for version control in any businesses CM system. Often developers will use the Description extended property of MS SQL server to detail the purpose of a column. When it's time to write their schema report they usually wind up having to retype or copy and paste each of these lines since there is no detailed way on retrieving this information programmatically.

    Because the extended description property of a column is not returned in the SqlClient schema queries in ADO.net (Microsoft fix this bug!) or in SQL stored procedures like sp_columns_rowset one has to resort to other means on retrieving this simple field.

    After some research I found an article where a query was developed to retrieve the description field. Below is my contribution to this code that also checks to see what the SQL Server version is and executes the appropriate query for SQL 2005. Enjoy!

    DECLARE @TableName varchar(100)
    SELECT @TableName = 'yourtablename'
     
     
    -- This will determine if we're using version 9 (2005) of SQL Server, and execute code accordingly
     
    IF CAST(SUBSTRING(CAST(SERVERPROPERTY('productversion') as varchar),1,1) as int) >= 9
    BEGIN
          -- This is a SQL 2005 machine
          SELECT  
                [Table Name] = OBJECT_NAME(c.object_id), 
                [Column Name] = c.name, 
                [Description] = ex.value  
          FROM  
                sys.columns c  
          LEFT OUTER JOIN  
                sys.extended_properties ex  
          ON  
                ex.major_id = c.object_id 
                AND ex.minor_id = c.column_id  
                AND ex.name = 'MS_Description'  
          WHERE  
                OBJECTPROPERTY(c.object_id, 'IsMsShipped')=0  
                AND OBJECT_NAME(c.object_id) = @TableName
          ORDER  
                BY OBJECT_NAME(c.object_id), c.column_id
    END
    ELSE
    BEGIN
          -- assume this is a SQL 2000
          SELECT 
                [Table Name] = i_s.TABLE_NAME, 
                [Column Name] = i_s.COLUMN_NAME, 
                [Description] = s.value 
          FROM 
                INFORMATION_SCHEMA.COLUMNS i_s 
          LEFT OUTER JOIN 
                sysproperties s 
          ON 
                s.id = OBJECT_ID(i_s.TABLE_SCHEMA+'.'+i_s.TABLE_NAME) 
                AND s.smallid = i_s.ORDINAL_POSITION 
                AND s.name = 'MS_Description' 
          WHERE 
                OBJECTPROPERTY(OBJECT_ID(i_s.TABLE_SCHEMA+'.'+i_s.TABLE_NAME), 'IsMsShipped')=0 
                AND i_s.TABLE_NAME = @TableName
          ORDER BY
                i_s.TABLE_NAME, i_s.ORDINAL_POSITION 
    END

     

    UPDATE: I wanted to write a follow up for this as well since I came across some system provided stored procedures and functions that will provide access to this information as well and involves A LOT less typing:

    First is the fn_listextendedproperty function. It will return all the extended properties for the specified object types. An example of use is below:

    SELECT objname,name,value FROM fn_listextendedproperty
        (NULL,'user','dbo','table','Users',NULL,NULL)

    This will return the extended properties for the Users table.

    Now if I wanted just the Description of the table I would add a where clause:

    SELECT objname,name,value FROM fn_listextendedproperty
        (NULL,'user','dbo','table','Users',NULL,NULL)
    WHERE name='MS_Description'

    Now it will only return the description of the table.

    For a list columns and their description, we can do the following:

    SELECT objname,name,value FROM fn_listextendedproperty
        (NULL,'user','dbo','table','Users','column',NULL)

    Or for a specific column we can specify that in the last function parameter:

    SELECT objname,name,value FROM fn_listextendedproperty
        (NULL,'user','dbo','table','Users','column','UserName')

     

    Note that there are also three system provided stored procedures that also allow you to set and drop extended properties. These are sp_addextendedproperty, sp_updateextendedproperty, and sp_dropextendedproperty. Quickly, to use these we simply do the following:

    exec sp_addextendedproperty 'Format', '(###)###-####',
        'user','dbo','table','Users','column','Phone'

    This will add a new extended property called "Format" to the column Phone in my Users table. This may be useful for me to know how to format and store the data in that column.

    To update that property I can do the following:

    exec sp_updateextendedproperty 'Format', '(410)###-####',
        'user','dbo','table','Users','column','Phone'

    Now the formatting will show that the area code should be 410.

    To remove this extended property, I simply call the following command:

    exec sp_dropextendedproperty 'Format', 
        'schema','dbo','table','Users','column','Phone'

     

    I think these stored procedures will be a lot easier for you to utilize that the query above, so I do recommend using them before building your own from the original query.

    Enjoy!

    Share this post: E-mail Retrieving+Column+Descriptions+from+MS+SQL | Submit Retrieving+Column+Descriptions+from+MS+SQL to Technorati | Submit Retrieving+Column+Descriptions+from+MS+SQL to del.icio.us | Submit Retrieving+Column+Descriptions+from+MS+SQL to digg.com | Submit Retrieving+Column+Descriptions+from+MS+SQL to reddit.com | Submit Retrieving+Column+Descriptions+from+MS+SQL to DotNetKicks | Add Retrieving+Column+Descriptions+from+MS+SQL to Live Bookmarks
  • Scaring pedestrians and drivers, just tuning a car honest...

    turbo I had the Trans-Am Firehawk out tonight testing out a new tune. All I can say is WOW. The car is insane now and breaks the tires loose in first and second with ease; drag radial tires mind you. I think I'm going to have to get my slicks for the dyno tune session. The car seems to be reacting well, no knock retard, AFR starts at 12.5 and gradually comes down to 11.1 at peak rpm. I'd prefer it to be a little leaner. Car also idles pretty rich and will need a little more tweaking. Overall though it really is starting to come back. I just have to figure out how to get it registered again since the emissions lateness has the plate suspended. The turbo is also starting to go, most likely due to the long period of time without oil, it got coroded and thus now has bad seals and shaft play. I have a spare PT67 sitting around and will throw that on until I can get money to rebuild the PT76... maybe even have it upgraded to an 88. smile_devil

     Developing...

    Share this post: E-mail Scaring+pedestrians+and+drivers%2c+just+tuning+a+car+honest... | Submit Scaring+pedestrians+and+drivers%2c+just+tuning+a+car+honest... to Technorati | Submit Scaring+pedestrians+and+drivers%2c+just+tuning+a+car+honest... to del.icio.us | Submit Scaring+pedestrians+and+drivers%2c+just+tuning+a+car+honest... to digg.com | Submit Scaring+pedestrians+and+drivers%2c+just+tuning+a+car+honest... to reddit.com | Submit Scaring+pedestrians+and+drivers%2c+just+tuning+a+car+honest... to DotNetKicks | Add Scaring+pedestrians+and+drivers%2c+just+tuning+a+car+honest... to Live Bookmarks
  • Seeing more of your code through Shift-Alt-Enter

    I just saw a nifty menu item referenced on the c# FAQ blog. I really wasn't ever aware of it either. Never really looked for it, but have had a need for it since forever. It's Shift-Alt-Enter, and it will hide just about everything in the visual studio environment except a menu and your code, opening up a ton of real estate to view your code. Check out the compare to see:

    Before: After:
    before_vs_screen after_vs_fullscreen

     

    As you can see, it's similar to pressing F11 in Internet Explorer for a large, full screen view of one's code. This certainly makes it easier than having to close and collapse all your side windows, potentially screwing up the layout of your environment. Def. a useful feature.

    Share this post: E-mail Seeing+more+of+your+code+through+Shift-Alt-Enter | Submit Seeing+more+of+your+code+through+Shift-Alt-Enter to Technorati | Submit Seeing+more+of+your+code+through+Shift-Alt-Enter to del.icio.us | Submit Seeing+more+of+your+code+through+Shift-Alt-Enter to digg.com | Submit Seeing+more+of+your+code+through+Shift-Alt-Enter to reddit.com | Submit Seeing+more+of+your+code+through+Shift-Alt-Enter to DotNetKicks | Add Seeing+more+of+your+code+through+Shift-Alt-Enter to Live Bookmarks
    Posted Sep 18 2007, 10:42 AM by RobK410 with no comments
    Filed under:
  • A simple SQL Express Backup

    Here is a very simple Batch file I have run backing up my database files every night. I figured it was so simple, I just had to share... no it's not a fancy Windows Script, or some other prose... simple command line commands... Using the free Info-Zip executable, I archive the data files into a single zip as well... just an added extra step to save some space. Enjoy

       1: @ECHO STOP SQL SERVICES
       2: NET STOP "MSSQL$SQLEXPRESS"
       3: @ECHO START MSSQL BACKUP
       4: cd c:\tools\
       5: c:\tools\zip -r -u -T -9 D:\Backups\MSSQL.zip C:\PROGRA~1\MICROS~1\MSSQL.1\MSSQL\Data\*.*
       6: @ECHO START SQL SERVICES
       7: NET START "MSSQL$SQLEXPRESS"
    Share this post: E-mail A+simple+SQL+Express+Backup | Submit A+simple+SQL+Express+Backup to Technorati | Submit A+simple+SQL+Express+Backup to del.icio.us | Submit A+simple+SQL+Express+Backup to digg.com | Submit A+simple+SQL+Express+Backup to reddit.com | Submit A+simple+SQL+Express+Backup to DotNetKicks | Add A+simple+SQL+Express+Backup to Live Bookmarks
    Posted Sep 18 2007, 12:37 AM by RobK410 with no comments
    Filed under:
  • How to suppress "beep" when pressing enter...

    I'm sitting here writing a chat application and needed a way to suppress the beep sound when the enter key was pressed on my text entry box. It's a single-line Rich Text control and I had thought it was just a matter of setting KeyChar to 0 on the key press event. In fact, this is exactly what Microsoft recommends here http://support.microsoft.com/default.aspx?scid=kb;en-us;Q140882

    But I found this not to work for the richtext control. In fact, I had to trap this key in the KeyDown event rather than the KeyPress event. Just an FYI in case you're attempting to do the same, and expect Microsoft to have the solution.

    Instead, we set SuppressKeyPress = true; and the beep will go away!

       1: private void rtEditor_KeyDown(object sender, KeyEventArgs e)
       2: {
       3:     if (e.KeyCode == Keys.Enter)
       4:     {
       5:         e.SuppressKeyPress = true;
       6:         btnSend_Click(sender, e);
       7:  
       8:     }
       9: }
    Share this post: E-mail How+to+suppress+%26quot%3bbeep%26quot%3b+when+pressing+enter... | Submit How+to+suppress+%26quot%3bbeep%26quot%3b+when+pressing+enter... to Technorati | Submit How+to+suppress+%26quot%3bbeep%26quot%3b+when+pressing+enter... to del.icio.us | Submit How+to+suppress+%26quot%3bbeep%26quot%3b+when+pressing+enter... to digg.com | Submit How+to+suppress+%26quot%3bbeep%26quot%3b+when+pressing+enter... to reddit.com | Submit How+to+suppress+%26quot%3bbeep%26quot%3b+when+pressing+enter... to DotNetKicks | Add How+to+suppress+%26quot%3bbeep%26quot%3b+when+pressing+enter... to Live Bookmarks
    Posted Sep 17 2007, 04:48 PM by RobK410 with no comments
    Filed under:
  • Joined Popfly

    Well, I finally got my invitation to try out Microsoft's Popfly. The concepts on their site are pretty interesting. It certainly is an easy to use designer allowing an individual to take information from other sites, link them together with interface components to render the mashup into a custom WYSIWYG designed page.

    Below is a picture of my mashup design:

    Comedy Carousel - Microsoft Popfly

    The designer allows you to choose content from a list on the side, a display component, and link the data provider to the display component. Automagically, the content is displayed.

    Check out the simple page I created below:

    http://www.popfly.ms/users/RobK410/Robs%20Home%20Page

    Should be interesting to see how successful this site becomes.

    Share this post: E-mail Joined+Popfly | Submit Joined+Popfly to Technorati | Submit Joined+Popfly to del.icio.us | Submit Joined+Popfly to digg.com | Submit Joined+Popfly to reddit.com | Submit Joined+Popfly to DotNetKicks | Add Joined+Popfly to Live Bookmarks
    Posted Sep 15 2007, 11:06 PM by RobK410 with no comments
    Filed under:
  • The Firehawk is Home!

    Finally went down today and picked up the Trans-Am Firehawk today. It drives a whole lot better now with the 6-speed in it. I'm going to spend this weekend cleaning it up, fixing a few loose ends, and just getting it back into a somewhat presentable shape. Some loose ends like a leaky fuel injector, some tuning, and reinstalling interior paneling is required... but the thing runs; going to perhaps swap the turbo out since the turbo on the car is failing. Pictures coming!

    Share this post: E-mail The+Firehawk+is+Home! | Submit The+Firehawk+is+Home! to Technorati | Submit The+Firehawk+is+Home! to del.icio.us | Submit The+Firehawk+is+Home! to digg.com | Submit The+Firehawk+is+Home! to reddit.com | Submit The+Firehawk+is+Home! to DotNetKicks | Add The+Firehawk+is+Home! to Live Bookmarks
  • Updating a form control from a worker thread

    Clear and to the point. This post will show you how to quickly do this. The scenario is you have a form with a control that must be updated from within a worker thread routine. If you try to update a form control from within a thread other than the one the control was created in (the primary main thread) you will have and exception thrown at you. To fix this one must create a delegate if a control must be invoked.

       1: ...
       2: {
       3:     // launch worker thread to process commands
       4:     ThreadStart clientThread = new ThreadStart(CommunicationsWorker);
       5:     _thread = new Thread(clientThread);
       6:     _thread.Start();
       7: }
       8:  
       9: // This is our primary worker routine
      10: private void CommunicationsWorker()
      11: {
      12:  
      13:     while (!bShuttingDown)
      14:     {
      15:         ....
      16:         // do some sort of work
      17:         ....
      18:         // Update a control
      19:         UpdateListView();
      20:     }
      21: }
      22:  
      23: // this is our delegate
      24: delegate void UpdateListViewDeligate();
      25:  
      26: private void UpdateListView()
      27: {
      28:     if(listView1.InvokeRequired)
      29:     {
      30:       UpdateListViewDeligate d = new UpdateListViewDeligate(UpdateListView);
      31:       Invoke(d);
      32:     }
      33:     else
      34:     {
      35:          // Actually interact with control here
      36:          listView1.Items.Clear();
      37:          // loop and add new list items or something
      38:          ....
      39:     }
      40: }
      41:  

    It's just a matter of creating a delegate, and adding some additional code to your control update/interaction routine in order to make this a possibility.

     

    Enjoy!

    Share this post: E-mail Updating+a+form+control+from+a+worker+thread | Submit Updating+a+form+control+from+a+worker+thread to Technorati | Submit Updating+a+form+control+from+a+worker+thread to del.icio.us | Submit Updating+a+form+control+from+a+worker+thread to digg.com | Submit Updating+a+form+control+from+a+worker+thread to reddit.com | Submit Updating+a+form+control+from+a+worker+thread to DotNetKicks | Add Updating+a+form+control+from+a+worker+thread to Live Bookmarks
  • 2007 Browns, Steelers, Both Suck

    Sitting here watching the Browns play the Steelers. Pathetic is the one word that comes to mind when I watch their starting quarterback. The guy seems like he doesn't want to be there playing, and on top of that, when he throws the ball, they've all been wobbly "dead ducks" that miss their target. His own receivers are looking at him like he's incompetent. Pittsburgh isn't all that impressive either. I was surprised the Browns had aquired Baltimore's Jamal Lewis. I guess we didn't give him the long term contract he wanted and for good reason since he really wasn't performing all that well the past few seasons (maybe due to his drug conviction?) Needless to say, he wasn't either smart, or dynamic enough to figure out that if there's a tackle in front of you, you should not continue to run directly into him... Jamal only knew "North-South" running and we needed someone who can roll around a defensive line... good riddance Jamal. But anyway, not impressed by any opening day teams right now. We'll see how well the ravens do tomorrow; hopefully they will trounce the Bengals. We'll see. On a side note, I think Bret Farve is doing a hell of a job coming back against the Eagles. He def. still has talent!

    Share this post: E-mail 2007+Browns%2c+Steelers%2c+Both+Suck | Submit 2007+Browns%2c+Steelers%2c+Both+Suck to Technorati | Submit 2007+Browns%2c+Steelers%2c+Both+Suck to del.icio.us | Submit 2007+Browns%2c+Steelers%2c+Both+Suck to digg.com | Submit 2007+Browns%2c+Steelers%2c+Both+Suck to reddit.com | Submit 2007+Browns%2c+Steelers%2c+Both+Suck to DotNetKicks | Add 2007+Browns%2c+Steelers%2c+Both+Suck to Live Bookmarks
    Posted Sep 09 2007, 03:19 PM by RobK410 with no comments
    Filed under:
  • Changing the default HTML viewer in Internet Explorer

    Sadly, even to this day, Internet Explorer relies on notepad for viewing HTML source code through the default view source menu item. There is no programmatic way to change their either; which completely blows. Luckily there is a registry setting one can add that will allow you to change the source viewer program for good. First off, I found a nifty notepad replacement called notepad++ that is fast, allows opening files in a familiar tabbed interface, and will do syntax highlighting, line numbering, etc. Definitely a good download to review... it has replaced notepad for good for me. Anyway, once it's installed, open regedit and add the following key:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\View Source Editor\Editor Name

    Set the (Default) value to the path to your new HTML viewer (in my case I entered the path to notepad++.exe) and save.

    changehtmlviewer_screen

    Now when you click the "View Source" menu item in Internet Explorer, the alternate program will open the source.

    Some caveats are that specifically with notepad++, it was unable to determine the file type of the cached source because IE passes the file without an extension. I had to manually specify the syntax parser to use... but for me this is alright.

    You can also see how it's done in Vista here as well.

    Enjoy!

    p.s. Microsoft, let's make this an option in the browser applications tab in the next release please!

    Share this post: E-mail Changing+the+default+HTML+viewer+in+Internet+Explorer | Submit Changing+the+default+HTML+viewer+in+Internet+Explorer to Technorati | Submit Changing+the+default+HTML+viewer+in+Internet+Explorer to del.icio.us | Submit Changing+the+default+HTML+viewer+in+Internet+Explorer to digg.com | Submit Changing+the+default+HTML+viewer+in+Internet+Explorer to reddit.com | Submit Changing+the+default+HTML+viewer+in+Internet+Explorer to DotNetKicks | Add Changing+the+default+HTML+viewer+in+Internet+Explorer to Live Bookmarks
  • New PC at work, but still left feeling stranded...

    So I've been dealing with a really dogged out computer at work for the past year now. 1GB of memory and plenty of disk space, you would think the P4 GX270 would be able to cope with every day developer tasks, but it really has become a pain in the ass dealing with it's slow load speeds and constant lack of memory. I really can't put my finger on the reasons why the PC went to hell, perhaps it's the 20 or so odd applications that my company installs on my computer so they can have complete control over everything that goes in or on the damn thing. Not much since it's rendered useless with just enough memory to load notepad.

    So anyway, the company's solution to upgrading memory is just give me a new PC since the current one was out of warranty. The new PC is a Optiplex 745 which thus far seems to be handling the work load well. I've spent the better part of today loading all my old files over, reinstalling and setting up applications, etc.

    So why am I not as happy as I should be? I guess it's the feeling of not being taken care of by my company. I mean, they gave me a new PC, but no monitor, keyboard, or mouse... I had two previous requests to get a new keyboard and I guess instead of saying we're out of them and too cheap to go buy a bunch from best buy down the street, they ignore the requests.

    Lastly, is the monitor situation. I have a dual screen setup, which is probably nicer than most devs (I doubt this, just being nice) and one monitor is a giant CRT. The other is a flat panel 19". Well apparently we're not allowed to have two flat screens  because that may make some people envious...and we can't have that here. Quite frankly flipping between this dull ass CRT and the LCD all day is killing my eyes, so I've put in a request for a new LCD to replace the CRT, and my request was met with a "we're out of those too"

    So now I'm using my keyboard from my workstation at home here at work (a nice wireless Microsoft multimedia keyboard/mouse) and if action isn't taken soon, will soon go buy myself the $200 Q9 I need to fix this monitor problem.

    It seems petty, but to be treated 2nd class, when you do as much as I do for the company, seems like I'm left stranded to fend for my self regarding the hardware and software.

    Is it this bad in company's like Microsoft? IBM? Does your job buy you the hardware you need in a timely manor; or at least reimburse you for your own hardware purchases?

    Share this post: E-mail New+PC+at+work%2c+but+still+left+feeling+stranded... | Submit New+PC+at+work%2c+but+still+left+feeling+stranded... to Technorati | Submit New+PC+at+work%2c+but+still+left+feeling+stranded... to del.icio.us | Submit New+PC+at+work%2c+but+still+left+feeling+stranded... to digg.com | Submit New+PC+at+work%2c+but+still+left+feeling+stranded... to reddit.com | Submit New+PC+at+work%2c+but+still+left+feeling+stranded... to DotNetKicks | Add New+PC+at+work%2c+but+still+left+feeling+stranded... to Live Bookmarks
Copyright © 2007, RobKennedy.com.
I reserve the right to beat yo arse if you steal sh!t.
Shat out at you via the CommunityServer.org Engine