Wednesday, September 23, 2009

HTML default buttons

I had been having a difficult time at work with a supposedly simple problem. I have a series of buttons in a web application, basically a "Previous", "Save & Exit", and "Next" button to guide the user of the web application through a wizard type application. The elements were declared as <>, not <>, because I wanted the customer to be able to customize the button layout and potentially use image buttons.

For the life of me, IE wanted to make the default button the first one and I couldn't override it to the "Next" button. At first what I had was a hack that I thought pretty much always worked.... Do a hidden <> tag with type=submit, then make that apply whatever button you wanted as the default... works great in Firefox but not in IE. So I tried making the "Next" an actual <> just to see if that functionality worked in IE. I set the type=submit, and the other buttons were still <>.... Still no dice and this time it broke Firefox, too! Google'ing around you get all sorts of weird suggestions like trying to trap the enter key and then firing an event. That borders on keylogger-ish behavior and some browsers and/or plugins might not allow that to work, just seemed like a big hack, too.

Final solution... specify type on BOTH buttons made through <> and <>... I was able to go back to making all 3 buttons a <> (therefore allowing image button support). On the default button, set type=submit. On ALL the other buttons (and this is the key), set type=button..... Now my rant...... why the heck would NORMAL non-attributed BUTTONS take precedence over anything that had a type=submit?!?!

phpBB forums -> Joomla's ccboard & auth integration

I've been working with LanOC ( http://www.lanoc.org ), a large gamer group from Van Wert, to help them convert their present website which runs mainly off of phpBB with several items like Wordpress integrated. Lately they've decided to migrate to the Joomla CMS ( preview of new site at ( http://test.lanocreviews.com/ ) ), and after looking at that for a while, I am giving serious consideration to moving FWGamers as well. LanOC's admin has been extremely fun to work with, he's getting a migration for free and I've been getting advice on running larger parties.

That aside, anyone who has used phpBB before knows that the only headache along the way is converting the users. LanOC had over 400 user accounts (only 370ish active from what I can see), and you can bet at that size, they didn't want to tell everyone to just go enroll again or come up with a password migration scheme.

I proposed developing a sort of bridge, but one they could eventually move off of, not something they would need to keep installed forever. Mostly the reason for that was I didn't want to have to change my code every time Joomla decided to update their core authentication. What I came up with is something that will first check and see when someone goes to log in if the user already has a Joomla password set up, if they do, it just skips my code & runs like normal. However, if the Joomla password field is blank, I take the password supplied (it's in clear text at this point since the user just typed it) and compute the phpBB hash using some functions I cobbled together and modified from the phpBB source code. I then connect to the old phpBB database and attempt to find the user record there. Assuming it exists, I just compare the computed hash with the database. If they match, I take the cleartext password and run it through the standard Joomla encrypter and update the Joomla user record. At that point I just re-read the Joomla user record & then fall through to the existing Joomla logic.

Other bridges out there for phpBB -> Joomla seem to go in a direction that doesn't really make sense to me, other than if you were trying to supply multiple UI choices to access your CMS environment (which still makes no sense... just choose 1 and provide good themes). Basically they disregard authenticating against the Joomla database and just go straight to phpBB. Any user updates that happen occur in phpBB, not Joomla (unless phpBB doesn't have the appropritate field being updated). Those integration packages are very nicely done, but I just feel it's better to do as close as possible to a 100% migration.

The result is, over the next 6 months or so, LanOC's users can seamlessly migrate themselves to their new site and then totally remove my custom modification as well as delete the phpbb_users table (that's the only table I need access to). Anyone who hasn't logged in for 6 months (password in Joomla user's table would be empty) could be given a random password and the next time they try to log in could go through the password reset procedure.

Additionally I helped with some UI enhancements to their new site. It looks & functions 100% like what they want it to, now. There are a few things I would change up personally but think overall it is worlds better than what they have now.

If anyone needs a phpBB -> Joomla conversion and is looking at using the ccboard forums, I can send you my conversion package. It converts users, categories, forums, topics, posts, attachments, private messages (assuming you have the "community" Joomla extension). It does not convert the groups currently because it's quick and easy to convert those manually. The conversion itself is database agnostic, just change the DSN string to whatever database you're using and it will work. The authentication piece I custom coded, however, is coded for MySQL. With only one query being done, though, it could easily be changed.

Now 1 more project to complete, then back to working on my game .... :-)

Friday, August 14, 2009

Add strikethrough capabilities to Dragonfly CMS

I use Dragonfly CMS (version 9.1.2.1) for the gamer site I run. One feature it lacks is the BBCode strikethrough tag, which is normally [s] , and I wanted this to cross off items in a list that were no longer an option for an upcoming LAN party, so decided to add the functionality, it was very very simple and maybe there are already posts out there on how to do it, but if not here goes. Now, I didn't go as far as updting the editor GUI since those change based on the theme selected, but I did give the ability for my users to type in the raw tag and have it work great.

Steps to add [s] ... [/s] to Dragonfly's version of BBCode:
1. Open up nbbcode.php in the includes directory.
2. Search for "function decode". About 25 below that, you'll see where the [b], [u], and [i] tags are handled - they are commented. Each section is 3 lines with the comment.
3. Copy and paste the 3 lines. Change to look like the following:

# [s] and [/s] for striking out text
$patterns[] = '#\[s\](.*?)[/s\]#si';
$replacements[] = '< style="text-decoration:line-through"> \\1 < /span > ';

** Note ** The $replacements[] line may have wrapped to a new line and shouldn't. Also, I had to add spaces to the span tag for it to get approved to publish.

As far as what this does... The $patterns[]... line simply adds a search pattern that looks for any characters between [s] and [/s] - case insensitive. The $replacements[] line adds the complimenting replacement string to surround the text that was between [s] and [/s] with a tag (the "(.*?)" from the patterns line = "\\1" in the replacements line). Later in the same function, preg_replace is called to actually make the find/replace happen.

Wednesday, July 22, 2009

Utility to flood Contact list in Thunderbird E-Mail client to rich/plain text preferred format

The largest complaint I've heard from people switching to Thunderbird from another E-mail client (and one I've had myself) is that during the address book import process, the contact's preferred message format is set to "Unknown", which means when you compose mail to this user, no matter what your global setting is, it will always send plain text. This is a bummer if you've spent a lot of time formatting the e-mail to include header sections and other richtext content. Finally it bugged me enough that I did something about it.

This is a free utility to flood all contacts to either allow HTML mail or plain text only. It's not quite automatic because I didn't want to take the time to learn the Mozilla address book file format, but all you have to do is export your address book to a common format (LDIF), delete all the address in your book, run my program, then re-import the files. My program renames the LDIF file to place a ".orig" extension on it, so if there are any problems, you can always re-import directly from that original backup.

Screenshot:
Program exec (sorry, no installer!): Download
Program source code (Visual C# 2008 Express Edition Solution): Download

Wednesday, July 15, 2009

Visual Studio 2008 SVN (Subversion) Plugin

I found this handy plugin someone else wrote to integrate Subversion source control into MS Visual Studio 2008. The beauty is it works for the Express Edition, too!

http://blog.programmerslog.com/?p=4

Wednesday, June 24, 2009

This gets a friggin plug

I am back on game development (sort of). I just finished my alpha version of the first space station for this game, I wanted to see how huge objects worked and what sort of performance hit I was going to see. I ran into 3 problems that had not been a problem when dealing with smaller objects. This was also my first stab at rendering something near 100,000 polygons on the screen.
  1. The 3D model was made in Maya and consisted of several NURBS items I converted to polys. Some of these objects at the polygon level had their normals reversed. The problem wasn't very apparent at first until I started orbiting the camera around certain parts and realized I was seeing through them to the other side. The trickiest part was to identify in the modeler which parts were messed up since I am dealing with a symmetrical model.
  2. While facing the station, if I went in reverse, eventually the back polys of the station would pop out of view. This was because my far Z clipping plane was too close to the camera. I'm dealing with an object that is roughly 13km wide and 8km tall, but my camera clip was configured for only 30 km total view distance. Along with this....
  3. Z-Fighting!! YUCK! I just knew if I ever encountered this it would be a beast to fight. Z-fighting is possible whenever intersections occur on an object and the camera is moving. What happens is the depth buffer which determines which vertices are rendered and which are culled is translated to be in the range of 0.0 - 1.0. Because of the math that occurs (a non-linear formula) sometimes the values get evaluated incorrectly, of course this is slightly compounded by the fact that floating point numbers are not precise.
Fixing the 2nd problem usually makes the 3rd one worse... The larger of a region you define to be visible, the more likely you are to experience Z-fighting... so I had to come up with a solution to #3 or just bite the bullet and try scaling everything down in the world by a factor of 10 or so (in my game, 1 unit = 1 meter). I decided more research was in order before just giving in.

After doing some research as to how others solve the problem, I found this ingenious solution: http://www.mvps.org/directx/articles/linear_z/linearz.htm

It works by taking the original view matrix you construct and scaling the parameters that hold information pertinent to the near & far clip planes by the far clip plane value. Then in the vertex shader, the output Z position is multiplied by the output W value (calculated by taking the input position multiplied by the world-view-projection matrices). The result is that when the pixel goes through the rest of the rendering pipeline transformation, when its W value is divided, it basically undoes the multiply done by the shader, leaving you with the original value. Absolutely smart.

This solution is elegant on so many levels. First off, it leverages the power of the GPU and uses a vertex shader-based solution. Second, well, it obviously fixes the problem! Third, it makes my 2nd problem a non-issue: you can basically set the far clip plane as far away as you want (yes there needs to be some reasonableness of course).

I was able to increase my far clip plane to 100,000km and have no popping, and no Z-fighting! Also, several km back from the station (enough that it still filled about 75% of my view) I'm running at > 1000fps... That is with a fully wrapping star skydome background, just under 100k polys, a basic UI, and the camera code. By comparison, with a 10k poly count fighter on the screen, I was running at 2700fps, I'm very happy with how the performance is!

Thursday, May 14, 2009

C# Service to start and stop a process at system boot

As anyone who's used Linux before knows, there's an incredibly easy way to start a server program up (even if it's not coded as a daemon) during system startup, just drop a line in /etc/rc.d/rc.local that starts the process nohup and throw an ampersand on the end of the command line (optionally redirect stdout/stderr) and you're good to go.

Windows systems don't have this. Sure there is the Autexec.nt file but this is sure to get deprecated in future releases of the OS... plus the fact that it runs before the major subsystems are initialized. What does that leave for Windows systems? You could put the program you want to start in a user's "Startup" folder but that requires a user to login, and would get killed when that user logged out. No good for a server application. In Microsoft's infinite wisdom, the only reliable way of doing this is to write a Windows service to start the program up and shut it down.

At work, one of my coworkers needed to do something like this, he had written a Progress program that just reads a DB table every so often and performs an action as needed, and he had a .BAT file to start the program up to test /run it, but no way of making the program run automatically when the server started up. I assisted him with this today. Due to copyright I can't include all the code, but the steps are simple.

  1. Startup a new Windows Service project in Visual Studio (we use 2008).
  2. In the service1.cs file in the "public partial class" section that is generated for you, define a class level variable:

    protected System.Diagnostics.Process m_process;
  3. In the OnStart() method, start up the program you want to startup along with any parameters. Note that you'll probably want to do what we did and read all of this in from a configuration file. In the long run this is what you'll have:

    string strProgram, strParameters;
    ...
    // Set strProgram & strParameters accordingly...
    ...
    m_process = System.Diagnostics.Process.Start(strProgram, strParameters);
  4. You should probably add exception handling and logging if you've got time. We needed something quick & dirty. Basically, if the process fails to start, your service won't start up anyhow... we thought that was just fine for our needs.
  5. In the OnStop() method, you need to gracefully shut down whatever process you started up. In this case, there was no graceful shutdown method (CTRL-C), so we just did:

    m_process.Kill();
  6. You'll then need to build an Install / Setup application to install your service.
It's a huge pain in the ass for something you can do in 30 seconds in Linux, but it's the "right" way for Windows...