If there is one thing that bothers me about Dreamweaver’s default settings (other than its annoying habit of rewriting valid code as camelCase), it is that double-clicking .php and .asp files launches Dreamweaver in Design view. Who on earth thinks that people generally want to open these kinds of files in anything other than code view?

Well, thankfully, this ridiculous behavior can be changed with a quick registry tweak. Just add an extension to the “Open As Text” value to cause Dreamweaver to always open that file type in code view. The .reg file below assumes you’re running Dreamweaver CS5.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USERSoftwareAdobeDreamweaver CS5Helper Applications Preferences]
"Open As Text"=".js .asa .css .cs .config .inc .txt .as .asc .asr .vb .htaccess .htpasswd .php .asp .html"

It would be nice if Dreamweaver were smart enough to realize that, if your preferred layout is Coder, any file should be opened in Code view.

The link below explains how to do the same thing via Edit | Preferences.

Source: Open files in Code view by default

I was trying to create a bootable flash drive with Ubuntu 11.04 using the Universal USB Installer 1.8.6.3 utility from pendrivelinx.com on a Windows 7 64-bit machine with a 16 GB flash drive (mapped to G:), but I kept getting an error that the drive wouldn’t be bootable.

The message in the command line window read:

Execute: C:Users[username]AppDataLocalTemp[random].tmpsyslinuxnew.exe -maf G:
Syslinux Errors 1

A message box would then appear with the following warning:

Universal USB Installer 1.8.6.3 Setup

An error(1) occurred while executing syslinux.
Your USB drive won’t be bootable…
[OK]

When I opened a command prompt and ran syslinuxnew.exe -maf G:, the result was zero FAT sectors. When I ran syslinux.exe -maf G:, I got a much more informative message, or at least one that I could better understand: this doesn’t look like a valid FAT filesystem.

And of course, the flash drive wasn’t FAT32, it was NTFS. I had forgotten to format the drive as FAT32 before running the utility, but I also managed to not check the box next to “We will format G:Drive as FAT32.” in the utility itself.

No wonder Google wasn’t returning any results when I searched this – who’s going to have missed properly formatting the drive not once but twice?

In the event that a quick format as FAT32 doesn’t work for you, you can try running a few diskpart commands in Windows to really thoroughly format a flash drive, including the MBR and partition table.

Update 1:59 PM 9/19/2011: Tier 3 support at Virgin Mobile was able to change my Beyond Talk Plan back to $25/month, which was the resolution I was looking for. Nice work, Tier 3.

12:26 PM 9/17/2011

I bought a Virgin Mobile Android phone on July 15, 2011, back when the least expensive plan was $25/month (a terrific deal, IMO). Today, I ported my T-Mobile phone number, but as a result, I was put on the current least expensive plan, which is $35/month (the included minutes and unlimited text, messaging, and data levels of the service are all unchanged). The cost of porting my number, which was only revealed after the port was successful, will be $10/month, to be paid in perpetuity.

The customer service rep that handled the actual porting didn’t seem to know what was going on. At one point, because he seemed so confused, I stopped and asked him point blank if porting numbers was something that happened very often. After the number was ported, I received the text message confirming the change, which noted that my plan was $35/month. The phone, which was supposed to start working after the port, wasn’t able to receive calls. I couldn’t even log into my account at virginmobileusa.com because I had a $0 balance, reportedly because hadn’t paid my $35 monthly bill yet (even though I’d just paid for another month at $25 two days earlier).

I called back, but the rep I reached this time couldn’t change my account back to $25/month, and put me on hold to speak with her supervisor. When she came back, she said the supervisor couldn’t convert my account to the $25/month plan either, and all they could do was credit me the additional $10 that the new plan would cost me this month.

She said that, had the first rep noted in the call that I had been on the $25 plan, this wouldn’t have happened. But because there was no such note, the system wasn’t allowing her to change to the $25 plan.

I told the rep that I would like to keep pursuing a different resolution, and asked for an email address. She gave me fraudalerts@virginmobileusa.com (which seems like a strange address for a department that handles non-fraudulent billing problems, but OK), so I sent the following message.

Date: Sat, 17 Sep 2011 12:25:00 -0500
To: fraudalerts@virginmobileusa.com
Subject: Porting my phone number resulted in my $25/month plan being cancelled…

Hello, there.

I have been a Virgin Mobile customer under the now discontinued $25/month plan for a few months. Before becoming a Virgin Mobile customer, I had a T-Mobile Prepaid – Pay As You Go plan. At the time I bought the Virgin Mobile phone, I still had a few hundred minutes on the T-Mobile plan that I wanted to use before porting that number to Virgin Mobile.

Virgin Mobile changed the plan pricing structure after I became a customer, increasing the price on the $25 plan to $35/month. When I ported the T-Mobile number, my Virgin Mobile account changed to the $35 plan. I wasn’t told at the time that my plan would change, and honestly, I would have stuck with the original Virgin Mobile phone number if I had been told that it would cost me $120/year to port my number.

I think it’s probably possible to activate a $25/month plan, even if the helpful phone support staff cannot do this. Someone, somewhere must have adminstrative access to do this.

Can you please provide contact information for the department that would be able to return my account to the $25/month plan, even if that means putting me back on a Virgin Mobile-assigned phone number?

If the porting of a number is going to cause a change to the account, and I’m not sure why this must be the case, it would be gracious to alert the customer.

Here’s my plan:
1. Try again to submit a ticket using the virginmobileusa.com web site (the first time, I got a page not found error: “The specified URL cannot be found”).
2. Call one more time.
3. Give Virgin Mobile 48 hours to respond to the email to fraudalerts email.
4. File a complaint with the BBB.

8:40 PM 9/17/2011

A few more thoughts:

Virgin Mobile seems to be treating this as a new account when it’s just a number port. I even got an “About Your Phone & Phone Number” email from Virgin Mobile that is identical to the email I received when I first became a customer back in July:

Hey OLIVER,

Thanks for joining Virgin Mobile! We know there are a lot of wireless options out there and we’re really glad you chose us.

Your Phone Number Is: (xxx) xxx-xxxx

Top-Up Now To Start Using Your Phone:
To start using your Virgin Mobile Service all you need to do is add money to your account. If you haven’t done that yet, click here to log in and do it now. Or, give us a call at 1-888-322-1122.

As soon as you’ve Topped-Up, you should be able to start using your phone. Access to Downloads and Voicemail can take up to 4 hours to come online, but usually it’s a lot sooner.

If you want to learn about your phone click here and then click on the Phone, Apps & More page to see additional information about your phone.

Stay Tuned:
We’ll be back in touch soon with some more info about your service. If you have any questions in the meantime, check out virginmobileusa.com or give us a call at 1-888-322-1122. Thanks again, and welcome aboard!
Virgin Mobile

At the bottom of the message is an email address that I hadn’t found when looking for ways to contact customer support: ourteam@virginmobileusa.com. I’ll be sending them a copy of my first email shortly.

Also, the FCC’s Guide to Portability doesn’t mention anything about whether a service provider can change your service on you during a port, but they do state that you can port your number at any time.

The FCC also has an online form for filing a complaint, so along with the BBB, this makes two avenues of recourse if Virgin Mobile won’t resolve this themselves.

11:53 PM 9/17/2011

Just for the record, before I became a customer, I wanted to be sure that the rates for existing customers wouldn’t increase on July 20, 2011. I emailed Virgin Mobile on 07/14/2011 at 10:02 PM, and this was their response (4 days later):

Response Via Email (Jennifer) 07/18/2011 12:54 AM
Hello Oliver,

Thanks for contacting Virgin Mobile Customer Care.

We are so glad to know that you want to become part of our Virgin Mobile family!

You have a great option to take advantage of, purchasing a Virgin Mobile phone that is compatible with our Beyond Talk plans because you cannot sign up for a monthly plan if you have not activated yet a phone, sorry about that! Remember that as of July 20th, 2011, new Virgin Mobile customers will be activated on the new plans while existing Beyond Talk customers will be able to stay on their current plans.

If you need additional assistance, feel free to respond to this email or contact us at 1-888-322-1122 (or *VM from your handset). You can reach us Monday through Sunday from 4am-9pm PST.

Thanks,

Kim
Virgin Mobile At Your Service
www.virginmobileusa.com

I’m pretty sure that I’ve got a good case here.

8:28 PM 9/18/2011

I received a response to my email to ourteam@virginmobileusa.com.

Response Via Email (Jose) 09/18/2011 02:22 PM
Hello Oliver,

Thanks for contacting Virgin Mobile Customer Care.

First let us extend our apologies for any inconvenience this has caused.

Virgin Mobile values each customer and is disappointed to know how you have stated your issue was handled.

Unfortunately, the $25 Beyond Talk Plan is no longer available and there is no way for us to get it active in your account. These rate changes affect new activations and plan changes in our system, and in order to process a Port In Request, the phone serial number needed to be free. That is the reason we needed to deactivate your old Virgin Mobile phone number.

Please accept our apologies for being unable to give you a different response, but this is the policy we are ruled by.

If you need additional assistance, feel free to let us know how we can assist further or contact us at 1-888-322-1122 (or *VM from your handset). You can reach us from Monday to Sunday from 4:00 am- 9:00 pm PST.

Thanks,

Heydi
Virgin Mobile At Your Service

Right off the bat, I think it’s unlikely that there isn’t some administrative override possible. While the $25 Beyond Talk Plan is no longer available, I suspect there is a way to charge my account $25/month. But let’s assume that changing the plan is not an option. Another resolution could be that Virgin Mobile credits me the difference between the $25 Beyond Talk Plan and whatever plan they want me to use. That can be as little as $10/month, or $120/year, for as long as I am a customer. This way I’m not incurring a cost for porting my number, and Virgin Mobile isn’t confronted with the hassle of making that administrative change to my account.

I don’t believe the average wireless customer could be expected to consider the porting of a phone number as a plan deactivation and a new plan activation.

I sent the following reply:

Hello there,

Thanks for writing back to me.

Unfortunately, the issue is not yet resolved to my satisfaction, as I still strongly feel that porting my number should not cost me $10/month for as long as I am a customer.

Now that the plan has been changed, however, there is still a way to resolve this to my satisfaction. Virgin Mobile can keep me on the $35 Beyond Talk Plan, and so avoid the problem of putting me back on the $25 Beyond Talk Plan, but then credit my account the difference each month.

I think that this is a fair and manageable way of handling the issue.

I’ll wait a day to hear back from my friends at ourteam@virginmobileusa.com and then go to the FCC and BBB.

12:30 PM 9/19/2011

I received a response from ourteam@virginmobileusa.com last night.

Response Via Email (Mariela Valenzuela) 09/18/2011 10:49 PM

Hello Oliver,

Thanks for contacting Virgin Mobile Customer Care.

Please accept my apologies on behalf of Virgin Mobile, our customers are highly valued and we are sorry to know that at this moment your experience has not been pleasant and easy.

Regarding your request, unfortunately we will not be able to process a $10 adjustment every month to cover your monthly charge. We are very sorry about that.

We understand your point of view and our main goal is your satisfaction, but our system cannot proceed against our terms of service. We are very sorry for any misunderstanding and inconvenience that you had regarding this issue.

If you need additional assistance, feel free to let us know how we cana ssist further or contact us at 1-888-322-1122 (or *86 from a Virgin Mobile handset). You can reach us Monday through Sunday from 4am-9pm PST.

Thanks & Best Regards,

Maryelah
Virgin Mobile At Your Service
www.virginmobileusa.com

So, it seems that it’s time to file a complaint with the FCC and the BBB. The FCC has a nifty online form for complaints (but it’s limited to 1000 characters), so I submitted the following.

Hello,

I became a Virgin Mobile USA mobile phone customer in July, 2011 under the $25/month plan (“$25 Beyond Talk”). Since then, the $25 Beyond Talk has been discontinued and a new plan, at $35/month, has replaced it for new customers. Existing customers remain on the $25/month plan.

I recently ported my T-Mobile number to my Virgin Mobile account. During the port, my $25/month account was cancelled and a new account was created on the $35/month plan. I was not told of this at the time by the CSR handling the porting and would have declined to port the number.

I have contacted Virgin Mobile in an attempt to resolve this problem, but they have only offered me a one-time $10 credit to my account. Virgin Mobile reports that they are unable to put me back on the $25/month plan, and are unwilling to credit me the difference of $10/month each month going forward.

Details of the correspondence are at http://www.ardamis.com/2011/09/17/virgin-mobile-usa/

Thank you for your assistance.

After submitting that complaint, I received a reply to my email to fraudalerts, sent by Stephanie M from the email address Tier3@virginmobileusa.com. I had only asked fraudalerts for the contact information of a department that could help, and so didn’t provide my phone number or PIN in that email. The reply from Stephanie M was just a request for that information. I replied to Tier3@virginmobileusa.com with the phone number and PIN.

I think I’ll wait to see what comes of the FCC complaint and the Tier 3 investigation before going to the BBB.

1:59 PM 9/19/2011

Well, that was fast. Tier 3 came through with the fix that all other contacts at Virgin Mobile claimed was impossible. Stephanie M set my account to $25/month. Her email to me:

YOUR ACCOUNT HAS BEEN CREDITED 35.00 SO THAT I COULD TAKE OUT 25 .00 FOR THE
25 BEYOND TALK PLAN YOUR ACCOUNT CASH BALANCE IS 10.00

Thank you,
STEPHANIE M
Virgin Mobile Tier 3

I logged into my account at Virgin Mobile and confirmed that the price for my Beyond Talk plan is $25.00/month. I sent Stephanie a thank you.

Stephanie!

Oh my goodness! Were you really able to put my account back to $25/month?

You have no idea how many people have told me this was not possible.

Thank you very, very much.

I think this is the end of the story. I’ll have to try to contact the FCC and cancel the complaint.

A moment ago, a new email arrived:

Hey OLIVER,

Thanks for switching to our $25 Beyond Talk Plan.

For worry-free monthly service, make sure you’ve registered a payment method with us. Or, buy Top-Up cards to cover the cost of your monthly charge.

Manage Your Account The Easy Way.
To Top-Up, get downloads, and check your balance, log in at virginmobileusa.com. Just enter your phone number and Account PIN.

With Virgin Mobile, you’re in control. It’s just that simple.

Thanks, bye.
Virgin Mobile

Why do I even play Modern Warfare 2: Black Ops? I’m awful at it. I have something like a .49 K/D ratio and I’m almost always the worst guy on the squad.

If I was this bad at any other game, I would’t play it. But for some reason, I keep going back for more humiliation. I can’t figure it out. By all accounts, I should hate this game. I should put it away and never play it again. So why do I pick it up again, over and over?

I die alot

I’m too slow on the melee attack, which results in people appearing to run past me and then I get knifed. This is particularly weird, because I was awesome at melee in Halo.

I never win a face-to-face quick-draw contest. Maybe I sprint too much, or something, because it seems that the other guy can always raise his gun and shoot faster than I can.

The game likes to spawn me in front of more than one guy, too. Particularly on Crisis. Sometimes in the path of three guys.

My technique is weak

I really try to study the kill cams to find out how each guy beat me, but much of the time they’re shooting me in the foot or whatever. Hell, I can usually unload an entire clip into someone’s feet before they just casually finish reloading or whatever and then off me. It is frustrating, though, when the kill cam doesn’t quite jive with my recollection of the encounter. Like when I’m pretty sure I shot first, but the kill cam shows the other guy very obviously getting the jump on me.

I also can’t figure out how these guys finish a game with ridiculous stats, like 38/3. Guys like that look like they always know exactly where I am, from the Kill Cam. Maybe they just know the maps extremely well and can anticipate where someone ought to be? I saw one shared video of a guy who got 100 kills in a game, and he spent much of the time standing in the open, turning from side to side, shooting guys as they rounded a corner and ran up a hill.

Maybe I’m doing it all wrong. Maybe standing in the open is a genius strategy, but my gut tells me to find a place where I can protect my back with a claymore and shoot down a hallway or something. Or, if I decide to just always keep moving, I run the perimeter so that there is less opportunity to be ambushed. But neither of these tactics is going to get me 20 kills per game.

Like one dog waiting on another

Instead of going all lone-wolf all the time, I sometimes try to follow someone on my team in an attempt to combine our firepower. This seems to be a decent strategy on paper (and I sure get mowed down by multiple enemies enough to think that it’s effective), but more often than not, we’re both taken out by a grenade within about 15 seconds.

If I enter a room and see a teammate crouched down, gun pointed at the door, I typically figure he’ll be standing guard long enough for me to look out a window. The guy’s got my back, I figure. But no, I’ll get knifed in the kidney the moment I start looking down the street. It happens every time. Where’s the camaraderie, fellas?

Impossible

I get killed by these physics-defying grenade tosses that bounce in impossible ways, or fly half-way across the map and through the window to land at my feet, but I couldn’t get a grenade through a barn door. Chances are, my grenade will just bounce off a wall and come back to get me. At least the grenade physics part of the game is consistent with MW2. I probably have a 1 in 20 chance of successfully avoiding a grenade. I’d like to see stats on that.

A single napalm strike typically gets me more than once. I feel certain that I’ve actually spawned in the napalm.

Cover

I am forever trying to be sneaky and realistic, moving from cover to cover before looking around a wall or something. Usually, I’ll be seen before I locate my enemy and the cover will appear to be at least partly effective. I’ll get knicked a few times, but feel that I was very smart to have cover so close, then gracefully move back into the cover, then fall down and die. Are they shooting me through the wall each time? Because it sure feels like the game is just lagging and it’s decided that I’m already dead before I move behind the wall.

Even so, even with all the frustration and suckiness, I’m really looking forward to Modern Warfare 3. Plus, I heard they improved the completely lame and irritating slow-motion final kill cam stuff. Maybe now the guy doesn’t run past the cross hairs half a second before the blood splatter materializes out of thin air.

Update: I am just as bad at Modern Warfare 3.

I’ve had some problems with JustHost.com in the past, but over the last two days, I’ve been really struggling to get a database-heavy site to perform correctly.

Typically, the MySQL server is blazing fast and absolutely smokes my local workstation. But this weekend, on average, it’s taking the justhost.com MySQL server 5.42 times longer to run a query than my lousy $400, Core 2 Duo Dell laptop. Below are the results of four different ALTER TABLE table ADD INDEX (column) operations that were run in phpMyAdmin on both the justhost.com server and on my local machine, and the differences in time between the two.

Adding an index to a table in MySQL (1):

justhost: Query took 10.8276 sec
laptop: Query took 1.7399 sec

It took justhost 6.22 times longer to run this query.

Adding an index to a table in MySQL (2):

justhost: Query took 16.3461 sec
laptop: Query took 3.0225 sec

It took justhost 5.40 times longer to run this query.

Adding an index to a table in MySQL (3):

justhost: Query took 2.0694 sec
laptop: Query took 0.4179 sec

It took justhost 4.95 times longer to run this query.

Adding an index to a table in MySQL (4):

justhost: Query took 2.1861 sec
laptop: Query took 0.4266 sec

It took justhost 5.12 times longer to run this query.

This wasn’t always the case. The last time I needed to run some time-consuming processes, the justhost.com server chewed through in seconds what it took my laptop minutes to accomplish. Something is wrong.

Update: Within two hours, the problem was fixed, and the database was back to being amazingly fast.

In the endless battle against WordPress comment spam, I’ve developed and then refined a few different methods for preventing spam from getting to the database to begin with. My philosophy has always been that a human visitor and a spam bot behave differently (after all, we’re not dealing with Nexus-6 model androids here), and an effective spam-prevention method should be able to recognize the differences. I also have a dislike for CAPTCHA methods that require a human visitor to prove, via an intentionally difficult test, that they aren’t a bot. The ideal method, I feel, would be invisible to a human visitor, but still accurately identify comments submitted by bots.

Spam on ardamis.com - before and after

Spam on ardamis.com - before and after

A history of spam fighting

The most successful and simple method I found was a server-side system for reducing comment spam by using a handshake method involving timestamps on hidden form fields. The general idea was that a bot would submit a comment more quickly than a human visitor, so if the comment was submitted too soon after the page was loaded, it was rejected. A human caught in this trap would be able to click the Back button on the browser to resubmit. This had proven to be very effective on ardamis.com, cutting the number of spam comments intercepted by Akismet per day to nearly zero. For a long time, the only problem was that it required modifying a core WordPress file, wp-comments-post.php. Each time WordPress was updated, the core file was replaced. If I didn’t then go back and make my modifications again, I would lose the spam protection until I made the changes. As it became easier to update WordPress (via the admin panel) and I updated it more frequently, editing the core file became more of a nuisance.

A huge facepalm

When Google began weighting page load times as part of its ranking algorithm, I implemented the WP Super Cache caching plugin on ardamis.com and configured it to use .htaccess and mod_rewrite to serve cache files. Page load times certainly decreased, but the amount of spam detected by Akismet increased. After a while, I realized that this was because the spam bots were submitting comments from static, cached pages, and the timestamps on those pages, which had been generated server-side with PHP, were already minutes old when the page was requested. The form processing script, which normally rejects comments that are submitted too quickly to be written by a human visitor, happily accepted the timestamps. Even worse, a second function of my anti-spam method also rejected comments that were submitted 10 minutes or more after the page was loaded. Of course, most of the visitors were being served cached pages that were already more than 10 minutes old, so even legitimate comments were being rejected. Using PHP to generate my timestamps obviously was not going to work if I wanted to keep serving cached pages.

JavaScript to the rescue

Generating real-time timestamps on cached pages requires JavaScript. But instead of a reliable server clock setting the timestamp, the time is coming from the visitor’s system, which can’t be trusted to be accurate. Merely changing the comment form to use JavaScript to generate the first timestamp wouldn’t work, because verifying a timestamp generated on the client-side against one generated with a server-side language would be disastrous.

Replacing the PHP-generated timestamps with JavaScript-generated timestamps would require substantial changes to the system.

Traditional client-side form validation using JavaScript happens when the form is submitted. If the validation fails, the form is not submitted, and the visitor typically gets an alert with suggestions on how to make the form acceptable. If the validation passes, the form submission continues without bothering the visitor. To get our two timestamps, we can generate a first timestamp when the page loads and compare it to a second timestamp generated when the form is submitted. If the visitor submits the form too quickly, we can display an alert showing the number of seconds remaining until the form can be successfully submitted. This should hopefully be invisible to most visitors who choose to leave comments, but at the very least, far less irritating than a CAPTCHA system.

It took me two tries to get it right, but I’m going to discuss the less successful method first to point out its flaws.

Method One (not good enough)

Here’s how the original system flowed.

  1. Generate a first JS timestamp when the page is loaded.
  2. Generate a second JS timestamp when the form is submitted.
  3. Before the form is submitted, compare the two, and if enough time has passed, write a pre-determined passcode to a hidden INPUT element, then submit the form.
  4. On the form processing page, use server-side logic to verify that the passcode is present and valid.

The problem was that it seemed that certain bots could parse JavaScript enough to drop the pre-determined passcode into the hidden form field before submitting the form, circumventing the timestamps completely and defeating the system.

It also failed to adhere to one of the basic tenants of form validation – that the input must be checked on both the client-side and the server-side.

Method Two (better)

Rather than having the server-side validation be merely a check to confirm that the passcode is present, method two goes back to comparing the timestamps a second time on the server side. Instead of a single hidden input, we now have two – one for each timestamp. This is intended to prevent a bot from figuring out the ultimate validation mechanism by simply parsing the JavaScript. Finally, the hidden fields are added to the form via jQuery, which makes it easier to implement and may act as another layer of obfuscation.

  1. Generate a first JS timestamp when the page is loaded and write it to a hidden form field.
  2. Generate a second JS timestamp when the form is submitted and write it to a hidden form field.
  3. Before the form is submitted, compare the two, and if enough time has passed, submit the form (client-side validation).
  4. On the form processing page, use server-side logic to compare the timestamps a second time (server-side validation).

The timestamp handshake works more like it did in the server-side-only method. We still have to pass something from the comment form to the processing script, but it’s not too obvious from the HTML what is being done with it.

The same downside plagues me

Unfortunately, if we want to have any server-side validation at all, and we do, the core file wp-comments-post.php will still have to be modified. In my experience, the system is only modestly effective using just client-side validation.

The code

Two files must be modified to implement the validation.

File 1: The theme’s comments.php file (older themes) or wp-includescomment-template.php (newer themes)

Your comment form lives somewhere. My theme is based on Kubrick, the old default WordPress theme, and my comment form is in my theme folder, in a file named comments.php. If your theme is newer and based on the current default theme, twentyeleven, the form is in wp-includescomment-template.php. If your theme isn’t based on either of these, all bets are off. I know it’s confusing. Sorry.

Add the JavaScript that creates and populates the timestamp fields. Be sure to confirm that your comment form has an ID of commentform. I’m using jQuery to help fire functions when the page loads.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
	ardGenTS1();
});

function ardGenTS1() {
	// prepare the form
	$('#commentform').append('<input type="hidden" name="ardTS1" id="ardTS1" value="1" />');
	$('#commentform').append('<input type="hidden" name="ardTS2" id="ardTS2" value="1" />');
	$('#commentform').attr('onsubmit', 'return validate()');
	// set a first timestamp when the page loads
	var ardTS1 = (new Date).getTime();
	document.getElementById("ardTS1").value = ardTS1;
}

function validate() {
	// read the first timestamp
	var ardTS1 = document.getElementById("ardTS1").value;
//	alert ('ardTS1: ' + ardTS1);
	// generate the second timestamp
	var ardTS2 = (new Date).getTime();
	document.getElementById("ardTS2").value = ardTS2;
//	alert ('ardTS2: ' + document.getElementById("ardTS2").value);
	// find the difference
	var diff = ardTS2 - ardTS1;
	var elapsed = Math.round(diff / 1000);
	var remaining = 10 - elapsed;
//	alert ('diff: ' + diff + 'nnelapsed:' + elapsed);
	// check whether enough time has elapsed
	if (diff > 10000) {
		// submit the form
		return true;
	}else{
		// display an alert if the form is submitted within 10 seconds
		alert("This site is protected by an anti-spam feature that requires 10 seconds to have elapsed between the page load and the form submission.nnPlease close this alert window.  The form may be resubmitted successfully in " + remaining + " seconds.");
		// prevent the form from being submitted
		return false;
	}
}
</script>

File 2: The wp-comments-post.php file

The wp-comments-post.php file lives in the root of WordPress and handles the form processing. We need to add a few lines that check the contents of our new validation input field.

Somewhere after line 53 or so (where $comment_content is defined), insert the following code.

$ardTS1 = ( isset($_POST['ardTS1']) ) ? trim($_POST['ardTS1']) : 1;
$ardTS2 = ( isset($_POST['ardTS2']) ) ? trim($_POST['ardTS2']) : 2;
$ardTS = $ardTS2 - $ardTS1;

if ( $ardTS < 10000 ) {
// If the difference of the timestamps is not more than 10 seconds, exit
    wp_die( __('<strong>ERROR</strong>:  This site uses JavaScript validation to reduce comment spam.  Either your browser has JavaScript disabled, or the comment was not legitimately submitted.') );
}

That’s it. Not so bad, right?

Final thoughts

One advantage to this method over the old PHP-only method is that even if the core file is replaced and the server-side validation is lost, the client-side validation continues to work, providing some measure of protection. The screen-shot at the beginning of the post shows the number of spam comments submitted to ardamis.com and detected by Akismet each day from the end of January, 2012, to the beginning of March, 2012. The dramatic drop-off around Jan 20 was when I implemented the method described in this post. The flare-up around Feb 20 was when I updated WordPress and forgot to replace the modified core file for about a week.

Now, for a little extra protection, you can rename the wp-comments-post.php file and change the path in the comment form’s action attribute. I’ve posted logs showing that some bots just try to post spam directly to the wp-comments-post.php file, so renaming that file is an easy way to cut down on spam. Just remember to come back and delete the wp-comments-post.php file each time you update WordPress.

We have been using I-GO car sharing for a few months now, since we sold the Volvo Cross Country (which I loved) to cut down on our monthly expenses. With the car loan, parking, gas, maintenance, and insurance, we were paying around $400 a month, and because we both take public transportation whenever possible, we were using it only on the weekends for shopping or trips to the zoo or whatever. It just didn’t make sense, financially or practically, to own a car.

We were sure that I-GO would save us money, but we weren’t sure we could give up the freedom and independence that comes with ownership. As it turns out, we could, and with a combination of renting from Budget or Hertz for the longer trips and I-GO for the quicker ones, we found we could save some money without too much sacrifice.

But, we were basing our expectations for I-GO on our experiences with renting from businesses like Enterprise, and a shared car is not the same as a rented car. I-GO would do well to close some of these gaps.

For one, when you rent from a company like Enterprise, you can expect that the car has been recently cleaned, inside and out, and the tank is full. The regular maintenance, like tire pressure, has been taken care of, and you won’t get in to discover the check engine light on. You can also expect to find the owner’s manual in the glove compartment. This is not the case for car sharing. You are basically borrowing a stranger’s car for a few hours, and very few people are going to care to wash it and fill it up when they are under no obligation to do so. So you tend to find yourself climbing into a car that has someone else’s crumbs in the back seat and is nearly out of gas. Just how to turn on the AC, or the headlights, or figuring out what that light on the dashboard means, is left to your ingenuity and curiosity, as so far none of the car’s I’ve used have come with an owner’s manual.

Both the I-GO and the rental cars are generally quite new or only a few years old, which is nice. The last I-GO car I drove had only 500 miles on it, while the last rental had 2000.

I-GO cars come with a fleet gas card, so you don’t have to pay for gas yourself. But, because you are generally paying by the hour, you pay for the time it takes to gas up.

You also don’t have to wait in line to pick up or drop off the car, and there is no paperwork after the initial sign-up. This, to me, is a huge advantage, as the process of renting a car, even if you reserve it online, still seems to take half-an-hour or more and involves signing papers. Scheduling a time to borrow an I-GO car takes about 4 minutes and is done entirely online. It’s totally self-serve and the cars are available 24-7, so you’re not stuck waiting until an office opens on Monday morning to return a car.

Insurance is included in the I-GO cost; not so for rentals. With rentals, you can waive the insurance if you carry it yourself, but I-GO means you can cancel your insurance policy (with the understanding that you’ll have to then buy insurance when renting).

Because you’re typically paying by the hour (or half-hour) for I-GO, vs by the day or weekend with a rental, you do have a sense that you’re not getting your money’s worth when the car is sitting in the lot. So it’s not ideal for trips to the zoo, or other places where you park and leave the car for an extended amount of time. It’s best when you need to get some place, grab something, and zip back.

All-in-all, I-GO is pretty great. If they could come up with a small incentive to encourage people to wash and gas up, so that it felt like the cars were just-for-you and ready to go, it would be even better.

I would like to be asked to complete a survey after each rental that encourages me to report on the condition of the vehicle.

The only other thing that bothers me, and it’s not a big deal, is the bumper stickers on the cars identifying them as I-GO vehicles. I realize that it’s helpful advertising, and I’m not embarrassed or ashamed to be driving one, but the stickers are tacky-looking. More professional-looking signage, maybe a tasteful and understated sticker like you would see on a Mercedes courtesy car, or what they show on the I-GO home page, would be nice.

Oh, and we chose I-GO over Zipcar because I-GO is a Chicago non-profit, and we like to support the little guy when we can.

I have an Android 2.2.1 device, and I keep noticing what may be a glitch in the scrolling. This happens in all applications in which scrolling occurs, but most frequently in Twitter. I’ll be slowly scrolling along, swipe… swipe… swipe… trying to catch up with dozens of tweets, when all of a sudden the scrolling takes off lightning fast.

When it takes off, it goes much faster than I’m ever able to make it go, which leaves me with the impression that I’m invoking a feature. But I can’t purposefully recreate this accidental fast scrolling. The closest I could come was when I lifted my finger at the end of the swipe, and my finger was near the top of the application. But I can’t swear that this is where my finger is each time it happens.

Others before me have wondered whether this is a bug or a feature.

The thing is, I’m not even trying to go fast, I’m actually doing slow, short swipes while trying to scan a screen’s worth of content at a time, so when it starts scrolling quickly, I have to mash my finger down to put on the brakes, then scroll back to wherever I was.

Update 08.27.11: Could the fast scrolling happen when I scroll at the same time extra data is being lazy-loaded by the browser or app? So, I scroll a little bit, and the page starts loading some images, and before it’s done rendering, I scroll again. The page then finishes loading the images and processes the scroll event, but due to some glitch, goes berserk.

Overview of classes and objects

Objects are the building blocks of the application (ie: the workers in a factory)
Classes can be thought of as blueprints for the objects. Classes describe the objects, which are created in memory.
So, the programmer writes the classes and the PHP interpreter creates the objects from the classes.

A class may contain both variables and functions.
A variable inside a class is called a property.
A function inside a class is called a method.

Instantiation

To create an object, you instantiate a class (you create an instance of the class as an object).
For example, if we have a class named ‘person’ and want to instantiate it as the variable $oliver:

$oliver = new person();

The variable $oliver is referred to as the ‘handle’.

Accessing properties and methods

To access the properties and methods of a class, we use the object’s handle, followed by the arrow operator “->”.
For example, if our class has a method ‘get_name’, we can echo that to the page with:

echo $oliver->get_name();

Note that there are no single or double quotes used in instantiating a class or accessing properties and methods of a class.

Constructors

A class may have a special method called a constructor. The constructor method is called automatically when the object is instantiated.
The constructor method begins with two underscores and the word ‘construct’:

function __construct($variable) { }

One can pass values to the constructor method by providing arguments after the class name.
For example, to pass the name “John Doe” to the constructor method in the ‘person’ class:

$john = new person("John Doe");

! If a constructor exists and expects arguments, you must instantiate the class with the arguments expected by the constructor.

Access modifiers and visibility declarations

Properties must, and methods may, have one of three access modifiers (visibility declarations): public, protected, and private.
Public: can be accessed from outside the class, eg: $myclass->secret_variable;
Protected: can be accessed within the class and by classes derived from the class
Private: can be accessed only within the class

Declaring a property with var makes the property public.

Methods declared without an explicit access modifier are considered public.

! If you call a protected method from outside the class, any PHP output before the call is still processed, but you get an error message when the interpreter gets to that call:

Fatal error: Call to protected method...

Inheritance

Inheritance allows a child class to be created from a parent class, whereby the child has all of the public and protected properties and methods of the parent.

A child class extends a parent class:

class employee extends person {
}

A child class can redefine/override/replace a method in the parent class by reusing the method name.

! A child class’s method’s access modifier can not be more restrictive than that of the parent class. For example, if the parent class has a public set_name() method and the child class’s set_name() method is protected, the class itself will generate a fatal error, and no prior PHP output will be rendered. (In the error below, employee is the child class to person):

Fatal error: Access level to employee::set_name() must be public (as in class person) in E:xampphtdocstesteroopclass_lib.php on line 38

To differentiate between a method in a parent class vs the method as redefined in a child class, one must specifically name the class that contains the method you want to call using the scope resolution operator (::):

person::set_name($new_name);

The scope resolution operator allows access to static, constant, and overridden properties or methods of a class, generally, a parent class. This would be done inside the child class, after redefining a parent’s method of the same name.

It’s also possible to use ‘parent’ to refer to the child’s parent class:

parent::set_name($new_name);

(I’m still a bit vague on this and am looking for examples of situations in which this would be used.)

Classes inside classes

Just as it’s possible to instantiate a class and use the object in a view file, it’s possible to instantiate an object and call its methods from inside another class.

Static properties and methods

Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static can not be accessed with an instantiated class object (though a static method can).

Resources
http://us2.php.net/manual/en/language.oop5.php
http://net.tutsplus.com/tutorials/php/oop-in-php/
http://www.phpfreaks.com/tutorial/oo-php-part-1-oop-in-full-effect
http://www.killerphp.com/tutorials/object-oriented-php/

The other day, I needed to extract a 7 GB zip file containing a VMware virtual machine onto the hard drive of a nearly stock 64-bit Windows 7 Professional machine. Because this machine did not have a third-party compression utility installed, I tried to extract it using Windows’ native zip utility, called Compressed Folders.

This failed with a pretty neat error.

You need an additional 5.99 PB to copy these files.

As you can see in the screenshot above, Windows reported that…

Copy Folder

There is not enough space on Local Disk. You need an additional 5.99 PB to copy these files.

Local Disk
Space free: 125 GB
Total size: 232 GB

[Try Again] [Cancel]

I found the 5.99 petabyte requirement pretty amusing, but I was in a hurry, so I downloaded the excellent 7-Zip, unpacked the file, and set about building the vm.

I had meant to write a post about the error message, but some time passed and I forgot all about it. Then, about three weeks later, someone else in the department tried to extract a copy of the file on a 32-bit Windows XP Professional machine and got the same error. At that point, I had to investigate.

The Compressed Folders native Windows utility seemed to be unable to accurately calculate the free space needed to extract the file. The file was admittedly pretty large, but was size the only reason?

According to the Wikipedia page on ZIP files, there are a number of known limitations of Compressed Folders.

ZIP64, AES Encryption, split or spanned archives, and Unicode entry encoding are not known to be readable or writable by the Compressed Folders feature in Windows XP or Windows Vista.

http://en.wikipedia.org/wiki/ZIP_(file_format)#Windows_compressed_folders

None of these things applied to my file, but I found a rather telling and simultaneously ambiguous (go figure) KB article at Microsoft Support: Compressed folder becomes corrupted when larger than 2 gigabytes.

According to various threads, the popular theory is that the problem stems from size limitations on compressed files. Windows Vista and later have a 4 GB limit (compressed and uncompressed size), while XP has a 2 GB limit.

Strangely, the same error appears before a copy process when the OS encounters a file that exceeds its maximum individual file size, which I can understand, but find a bit confusing in the context of a zip file. Certainly, both Windows 7 and XP (NTFS) were able to handle the file to begin with, and only had a problem when decompressing it.

My best guess is that the file was created using the Compressed Folders feature on XP. The file exceeded the maximum size limit for that version of Windows, but due to the bug described in MS KB article 301325, the file was created anyway using 32-bit headers. When the file was later opened by Compressed Folders, the 64-bit headers were read (as a file of that size would naturally use 64-bit headers), but that information was garbage, preventing Windows from accurately calculating the space required to extract.

If anyone has a more complete understanding of the cause of this error, please leave me a comment.