Archive for September, 2009

Robot Roll Call

Sunday, September 27th, 2009

Just a quick followup to my last post – I originally wrote something a bit more generalized, but I realized that it was entirely too boring to show here and boiled it down to an ADD-compatible list of my Top 5 MST3k Episodes of All Time. But if you’re at all like me, then you have an unexplainable affinity for data plotted in graphical linear representations, aka graphs. I came up with this little illustrative piece that I might as well share here now that my affinity for Mystery Science has been revealed. It plots the hilarity quotient (or “HQ”) of MST3k episodes over time. As you can see, the series had a bit of a rough start, but it changed hosts halfway through the 5th season (from Joel Hodgson to Mike Nelson) and it was also around this time that Bill Corbet took over the role of Crow – and once this dream team came together the show really took off:

MST3k Over Time

Lets just all be thankful that Mike didn’t stick with TGI Fridays for long. And yeah I know, it’s just a lame graph … to some. But I like graphs, even pie ones:

-Andy

Top 5 MST3k Episodes of All Time

Friday, September 25th, 2009

In a very particular order, here are the Top 5 best episodes of Mystery Science Theater 3000 of ALL TIME! These episodes are my favorites to watch, and especially to show to people who are new to MST3k. Without further ado…

#5 – Final Sacrifice

910-3There is yet to be a better Canada-based movie about an ancient civilization that never actually existed. It’s almost difficult to explain the extreme appeal of a film like this – between the constant references to Super Bowl <insert nonsensical roman-numerals> MVP Larry Zonka (not pictured), the weaselly red-sweatered hero Mike Pipper, and the alcoholic hockey-hair sporting sidekick Zap Rowsdower. Yes, there is no name more Canadian than Zap Rowsdower – (presumably of the Saskatchewan Rowsdower’s). Special appearance by Gordon Lightfoot.

#4 – Time Chaserscastleton_official_2

The plots of time travel movies always make so much sense, and Time Chasers is no exception. It goes like this: basically, this guy creates a machine that lets him travel through time (the key was apparently to equip a Cessna with a flopy-drive-enabled computer), so he goes forward in time, then comes back to tell everyone but ends up selling the technology to some guy who turns out to be evil, only to go back forward in time and find out that everything has changed, so he has to go back before his time to stop his future-current self from going forward in time in the first place, but that makes the evil guy mad, so him and his future-current self end up having to escape way back to Paul Revere times, but the evil guy follows them (through time) and they end up having to kill him.

It makes a lot less sense than I probably gave it credit for…

#3 –  This Island Earthnew this island earth morrow THIS_ISLAND_EARTH-10

I know, this technically wasn’t an episode – it premiered in movie theaters as the first (and last) official MST3k movie. But don’t you dare get technical with me. It’s still a fantastic representation of their work, and one of the few Dr. Forester-era episodes that I wholeheartedly enjoyed. To this day I still use ‘nanu’ as a greeting, and hopefully someday soon I’ll complete construction of my first Interocit0r. The real question you’ll ask yourself while watching this movie is not why aliens capable of intergalactic travel couldn’t come up with some common (cosmically speaking) uranium or plutonium; or why they needed the help  of Earth-scientists’ with less than 10-20 years of experience to develop new nuclear technologies; or why their spaceships seemed to be powered by rotating lights one would expect to see in the center of any given carnival ride; or why such an advanced alien race would see the need to breed an army of super-strong insectoid slaves that mysteriously lack a cranial structure. No, you’ll ask yourself why oh why did the director think large foreheads and white hair was a good idea.

Memory#2 –  Overdrawn At The Memory Bank

The best thing about this episode (besides the wonderfully talented Raul Julia as star, the endless references to Casblanca, and the cheesy late-80′s style video effects) is the fact that it completely and unequivocally demonstrates how pathetically useless public television really is in modern context. Seriously, who green-lit this project? Did they really think that a movie about a man being “doppled” (think The Matrix, only much, much lamer) into the body of a baboon would be 1) entertaining, and 2) make any god damned sense?! And I don’t know all that much about Casablanca, but I’m pretty sure if the director and/or producer are dead they’re spinning in their respective graves. What really seals the deal here is the “I’M INTERFACED!” ending which logistically makes no real sense and furthermore whitewashes what little plot seeths to the surface in the whole hour in the half. I can’t ague against one point though – it does really sort of sandwich the whole terrible movie thing it’s got going on, what with starting the movie with such terrible concepts, and then coming full circle by finishing the movie with terrible concepts. Oh, and I’ve got nothing against the musical number during the intermission, “When Loving Lovers Love.” Good stuff.

#1 –  Space Mutiny

Even good movies usually poach ideas here and there from other area of popular culture. Bad movies, on the other hand, simply rip off scenes frame by frame. The movie is, as the title hints at, based in space, and as such the plot calls for the occational shot of the ships in space. Instead of filming new scenes, they just ripped scenes from Battlestar Galactica. 1970′s Battlestar Galactica. It’s a bit like taking a picture of a bad painting – the result is an even worse picture. To it’s credit, the movie does present a wonderfully entertaining tail of … uhm, what was this really about again? I’ve seen it a hundred times, and all I can find out is that some bad guy named Calgon wants to take over the ship …. to go … somewhere else? The plot’s really a moot point anyways – you’ll be too distracted by Big McLarge Huge prancing around and mumbling his lines and Santa’s Grandma-daughter (aka Spider Skank) skulking around in her unsettlingly revealing workout bikini. It’s hilarity factor is high enough that even SciFi haters will enjoy an opportunity to see the genre at it’s absolute worse, and SciFi fans can enjoy the opportunity to see … well, the genre at it’s absolute worse. There are so many opportunities for the MST3k gang to poke fun, and that’s really why I enjoy this movie above all else, especially when watching with folks that aren’t familiar with the genius that is Mystery Science Theater. It’s more than a movie – it’s a bad movie.

Best of all, you can watch it right here:

I leave you with these wonderful haiku:


Mike-Era Joel-Era
In the not too-distant future
Somewhere in Time and Space
Mike Nelson and his robot pals
Were caught in and endless chase
Pursued by a woman whose name is Pearl
An evil Gal who wants to rule the world
She threw a few things in her purse
And in her rocket ship she hunts him all across the universe.
In the not-too-distant future
Next Sunday A.D.
There was a guy named Joel
Not too different from you or me
He worked at Gizmonic Institute
Just another face in a red jumpsuit
He did a good job cleaning up the place
But his bosses didn’t like him so they shot him into space.

-Andy

Followup on Fees

Wednesday, September 23rd, 2009

I noticed that even before Sen. Chris Dodd’s bill made it to a vote (you know, the one that would require banks ask permission to charge you overdraft fees) a few banks are already taking the hint. Both Chase and Bank of America announced today that they will be voluntarily restructuring their overdraft fee system, starting by asking their customers for permission to charge overdraft fees. Additionally, all accounts overdrawn less than $10 will no longer be assessed a fee at all, and they are limiting the number of total fees per day to 4. It’s apparently a complete reversal of policies recently instated earlier this year which raised the limit to 10. The banks must feel like this some kind of twisted charitable contribution, but like Dodd says, it’s merely “a step in the right direction.”

Imagine if the city’s parking system worked this way – you go to park your car on the street, a meter maid walks up, you pay to park, and the meter maid asks, “Would it be alright, if it weren’t too much trouble, if I gave you a $36 ticket if you’re here 10 minutes too long, then another $36 ticket for each additional 10 minute block, up to 40 minutes, after which you’ll no longer be able to park here?”

Do they really think that asking for permission makes their fee system any less ridiculous? Apparently they don’t - because Wells Fargo is also hopping on the bandwagon (get it? wagon?) by also pledging to not fee for less than $5 and ask for permission first. Well, I guess if it’s consensual

If you ask me, it sounds like they all got caught with their hand in the cookie jar. And by cookie jar I mean your wallet. If all of this wasn’t shady enough, Chase explains that they’ll be gracefully ending their con of reordering your transactions to maximize the amount they gouge you. These fees are already mean, but finding methods to maximize them is just cruel. You already gave them all your money, do they really think the best thing to do when you run low is to take even more out of the account? It doesn’t make sense!

ScroogeMcDuckEven when you do actually have the money, just not in the right account, the vultures circle. “Linking” accounts will automatically pull money out to cover your overdraft, but it’s more of a band-aid for a system that’s bleeding out your money. They still come at you with “Transfer Fees”, even when the money is transferred from an account at the same bank and is transferred at no cost via computerized systems. It’s not as if someone physically transfers the money between accounts – but they still feel justified in jabbing at you with the fee. Some banks even enforce maximum blocks, so that they can stab you repeatedly with transfer fees instead of mercifully lumping the money in a single transfer. In an effort to repeatedly kick you while you’re down, almost all of them continue to charge you every day, upwards of $35 per item. As if the number of items had some bearing on the costs to the bank of covering your overdraft. It’s incomprehensible.

So asking for permission and giving you $10 in ‘leeway’? I say no deal. They even have the balls to call these fees “Protection” – the only thing we need protection from is the bank.

Oh and P.S.  – ING is still feeless.

-Andy

A Bank You Can Bank On

Monday, September 21st, 2009

I’ve used a lot of space on this site talking about companies I don’t like, but I’m not that negative about everything and everyone. I am, however, appropriately critical. When I exchange money for services I expect them to be delivered. It’s not a complex equation to me. Frankly, if I don’t receive things I pay for, then I’m simply being cheated.

Banks convolute the process a bit, in that you’re not paying for a service in the traditional sense of the word. You give them money openly and freely, expecting only one thing in return: that you can get it back someday. If they want to give me interest, fine, I really don’t care one way or another. I just want to be able to spend a paycheck without having to step into a CheckIn2Cash-type establishment.

It should be simple, I think, to hold onto my money, then give it back to me when I ask. But banks these days aren’t making it so simple. One of my most generalized and long standing complaints I’ve had is simply their terrible hours. Most people have jobs from 9-5 M-F. Why on earth would every bank out there hold hours from exactly the same period. They basically require that to ever give them my money I have to take off time from work. This was particularly troublesome when I used to be paid on an hourly basis, when taking time off means earning less money. When that was the case, depositing money actually cost me money.

My second (and now very common) complaint is all these indomitable fees! My God, so many damn fees! I can understand wanting to cover their costs for things like overdrafts or checks, whatever it is – maybe even understand slightly profiting from it. But there is no logical reason to charge a minimum of $36 for 17¢ in overdraft. That isn’t covering their costs, it isn’t “making a living” – it’s gouging your customers.

Take this example: if you had $30, then unwittingly bought $30 in groceries, spent $7 at lunch, $3 on coffee, $2.50 on gum, $8 on dinner, $5 at a bar, took an $8 taxi home, you’d be in the hole $33.50:

calc

In the grand scheme of your multi-billion dollar banking institution, this measly thirty bucks shouldn’t be a big deal, especially if you were able to cover that in a couple of days. But if you were a customer of USBank, you’d be in the hole $249.50 the very next morning. Nothing but fees! They also won’t email you a “Low Balance Alert” until after you’ve overdrafted. At this point, it’s already too late, they’ve charged you almost $250 to cover $30 for a day.

Frankly, I find these excessive fees downright criminal. I’d rather they deny the charge and not let me buy something, then have them tack on $250 to a day’s worth of spending. I’m not the  only one that agrees, apparently the Dems are pushing for more regulation, requiring they at least ask for permission. It’s becoming a bigger issue as banks continue to make record profits from fining their own customer base to oblivion, totaling nearly $40 billion annually. According to the Washington post, the average cost of an overdraft fee “has  climbed by $10, to 35″ in just 10 years. As much as I’d like good-ol’ capitalism take over and watch a mass exodus away from these high-fee banks – they’re all charging the same fees anymore. There’s practically no where to run. From a quick survey online, it looks like USBank is somehow one of the cheapest mainstream banking institutions – Chase, for example, charges about the same fee as USBank, but on an exponential scale, instead of a linear one.

Enter a bank like INGDirect. It might seem odd to put your money in a bank that doesn’t actually have banks (they are 100% online and by phone), but in this day and age the brick-and-mortar stores are really just annoyances. If you still need cash (a situation which for me is becoming increasingly rare), you’re welcome to use an ATM. The beauty of ING is that they seem to genuinely care about your business, no matter how small. They don’t use fees as tools to sap money from you – in fact there practically feeless. They don’t even have overdraft fees – if you run over, they loan the money to you at a competitive rate (~17%, better than the average credit card). It gives you a couple of days to shift some funds, with the total end cost to you maybe a couple of pennies. That -$30 of overdraft from our example above? If you payed it off the next day you’d literally be down a cent. Not too shabby.

Plus, their website isn’t stuck in the dark ages, it’s actually a wonderfully useful tool. It even has mobile versions great for your iPhone (you do have an iPhone don’t you!?) when you’re stuck on AT&T’s Edge network. Since it’s online, they’re always open – even on Sundays. They give you tools to help automatically save money in linked accounts, even pull or send money from accounts to other banks free of charge. If you need to write a check, you do it online and they mail it out that day, no stamps, and they’ll keep the address on file in case you need to send out another one. You can even overnight a check by courier for a few bucks. Their customer service rocks too. I had a question about PIN numbers, called their line, and got a real-life American teller (not some overseas underpaid call center rep) which was so friendly I almost thought I was talking to an old friend.

Not only is their service quality excellent, but they pay interest on checking and savings at much better rates. My checking account alone has better rates than my USBank savings. I’m really getting paid to bank with them – the way it should be – unlike USBank which simply charged me for the “privilege” of letting them keep my money.

I’ve gloated about ING before to friends and family, it’s refreshing to actually enjoy doing business with a bank. Today I logged on and even saw this lovely message:Picture 2

Thanks INGDirect – best wishes to you as well.

-Andy

Conspiracy Theories

Sunday, September 13th, 2009

One can’t help but find it odd that after months of sub 3-5 Mbps connections, I suddenly am getting the best connection speeds of my life just days after writing about poor transfer rates.

I don’t keep my logs for long, but have a few recent test results available:
9/1/09 7:41 AM – 4.15 Down, 4.4 Up
9/7/09 6:58 PM – 4.6 Down, 6.06 Up
9/11/09 6:39 PM – 2.65 Down, 6.35 Up

Today, 9/13:

comparisonspeeds

Touché Comcast. It’s hard to make a formal complaint about my usually pigeon-poor connection speeds when they “suddenly” are faster than what I’m even paying for:

ispserviceoffering

I’m supposed to be getting “up to” 12 – not averaging 14. Heck these speeds aren’t simply not slow – they’re actually faster than the average:

resultssum

I couldn’t prove, mind you, that Comcast did improve my service just to spite me, but it’s a strong possibility. If it keeps up, my dreams of owning a pigeon-based ISP may be at end…

Update: Two days and rates are still in the 15′s! I’m giving it a week before I declare anything offical, but its clear that something has actually changed, and for once, it’s for the better.

-Andy

Comcast Responds!

Friday, September 11th, 2009

Wow, I honestly can say I didn’t expect to see someone from Comcast comment here on this backwoods little blog:

Melissa Mendoza says:
September 11, 2009 at 1:29 pm

Wow…that’s pretty bad. Considering that we can offer speeds up to 50mbps in some areas, this is unacceptable. Please email our team at the address below so we can look into the trouble.

Kind Regards,
Melissa Mendoza
Comcast Customer Connect
National Customer Operations
We_Can_Help@cable.comcast.com
@ComastMelissa

I’m not sure if I should be honored that I’ve grown popular enough to garner this attention in the first place (don’t worry, I won’t let it go to my head!), or simply disgusted that I’ve been wronged enough that eventually, from the sheer number posts on the subject of being screwed one way or another by the company, that one was bound to be noticed eventually.

To reply, let me first say thanks to Melissa for taking the time to read my post and send me a message. I do recognize that it would be unfair for me to make such claims about the poor quality of your service if I was unwilling to give you a chance to make things right. For that reason alone I will be contacting the ‘team’ by email and give them the benefit of the doubt on this matter.

That said, If by some miracle of science they can actually improve my service, I will be grateful for sure, but it’ll be a long way off from healing all the old scars I’ve been dealt over years of poor service – and worse, poor customer service.

It’s also not too difficult find out through a simple search that your job (and the job of several people like you) is in fact to find complaints of this nature on social networking sites, be them blogs, twitter, or customer complaint megasites. In general I find this practice dubious and best, and downright shady at worst. I’d rather see the company focus 100% on getting their services right rather than hire people to troll forums and blogs in a backwards attempt to repair their damaged reputation. Frankly I’d given up hope with ever fully resolving anything with Comcast customer service years ago, and even if your team can help – it’s a lot too little, a lot too late. I’ve already dumped TV from my life almost entirely, would jump to FIOS in a heartbeat (at double the cost if it was available in the slightest) and would switch to Qwest this afternoon if their maximum service offering wasn’t somehow even worse (1.5 Mbps in my area- municipal Boulder CO, pop. 293,161).

I’ll be sure to keep you all apprised of the situation as it develops

“Kind regards”

-Andy

Comcast “Bird for Brains” Internet

Thursday, September 10th, 2009

I saw on Gizmodo this morning a lovely article about a pigeon-that-could. The little guy took on the local broadband company in South Africa, and actually came out clean. Apparently, using a carrier pigeon and a 4 GB flash drive, tech-and-bird-enthusiasts sent a bird 50 miles to its destination while simultaneously attempting to transfer the file over the internet. The result, ironically, is that the pigeon was about 25 times faster. The point of the experiment was to demonstrate how terribly slow and unreliable S. Africa’s network really is. Apparently transfer rates are still in the Dark Ages over there.

But it might surprise you that here in the States we really couldn’t do better.

As my father pointed out on Facebook (“You think Comcast was bad…”) my Internet connection is no where near as slow as S. Africa’s. My internet is, however, Comcast bad.

To prove this, let’s replicate this wonderful experiment using my connection instead of S. Africa’s 3rd-world connection speeds. Using the same 4 GB flash drive (presumably glued) to the pigeon, and the same 50 miles distance to, say, my parents house in Highlands Ranch, and then assuming it’s a ‘average day’ and I’m getting a solid ~4 Mbps connection, I could realistically expect (taking into account latency, packet loss, etc) about 300 kb/s average transfer rate between my apartment and their house, and then assuming we’re using an “average” homing pigeon with a flight speed of about 30 MPH. The result?

Picture 2

Comcast: 4 Gb / 300 kb/s = 2.4 Hours
Pigeon: 50 miles / 30 MPH = 1.6 Hours

The pigeon still beats Comcast by almost 50 minutes.

Comcast proves not just 50 minutes slower over 50 miles – but about 10 MPH slower overall. Given pigeons can easily travel hundreds of miles (over mountain ranges and through storms mind you), you would probably be better off sending a pigeon across the country with a 10GB flash drive than ever using my Comcast connection.

Hmm, I smell an untapped business opportunity – the world’s first dedicated pigeon-based data transfer service! I mean, the wizards at Hogwarts have realized this for years:

While disadvantages of pigeon-based ISP’s are probably numerous, for even moderately-sized files — this one’s for the birds.

-Andy

DOM You Safari!

Thursday, September 10th, 2009

I was checking on my post yesterday, the one about preventing Spam comments in WordPress - and happened to use Safari instead of my normal Firefox. In general I almost always use Firefox since, as a web developer, it’s just easier to code with. It’s more forgiving in general, and more accurate in its interpretation of HTML, CSS, and JavaScript (in my experience) than Safari (and especially more accurately than IE).

When things do seem to go wrong, it is more often in the complicated pieces where I’m trying to use some neat code trick or something. Quite frequently, a trick will work just fine in Browser A but not work at all (or worse, simply work differently) in Browser B. I’m not accustomed to is seeing, however, simple plan-text vanilla-flavored HTML just not be parsed correctly in the first place.

Take, for example, this code:

<div id="quickSummaryfull">
     <p class="p6">
          <span>&nbsp
               <div class="alignleft">&laquo; <a href="http://andyhoffner.com/?p=130">
                   (Re)Building A Blog-based Website From (Near) Scratch – Part 2</a>
                </div>
                <div class="alignright"></div>
           </span>
     </p>
</div>

This sample is taken from the little backwards/forwards links at the top of each post on this site (the ones with the dotted underline). If you looked at this site in Safari prior to this post, you’d have noticed the formatting of this was off. The links rendered below the dotted line, instead of above it. Why? Safari couldn’t parse the </span> or </p> tags correctly, so it closed the “class p6” item prematurely and threw away my spans entirely.

For the sake of conversation, I’ll simplify the problem down to this (which still causes the bug):

<div id="quickSummaryfull">
     <p>
          <div>Link to the older post!</div>
          <div>Link to the newer post!</div>
     </p>
</div>

For the layman, this structure is a “div” (just a containing element, think of it as a box of some size), a “p” (or paragraph element) which contains two more “divs”. In the DOM, it should look like this:

  • div #quickSumamryFull
    • p
      • div – Link to the older post!
      • div – Link to the newer post!

This is how it renders in good ol’ Firefox! But in Safari, it renders like:

  • div #quickSumamryFull
    • p
    • div – Link to the older post!
    • div – Link to the newer post!

See how the div’s are at the same level as the p? This is why they render below the dotted line, not above it. Safari isn’t doing this without reason, however, if you use Safari’s nifty “Resources” Panel (right click on the offending item, and select “Inspect Element”, you’ll then click Resources, and then the button to Enable it) – you’ll notice two errors:

Safari DOM Errors

From the real code at the start (the one with the spans)  it can’t seem to figure out why there is a closing span </span> or closing p </p> element in the code. But there should be – I opened a p and a span just two lines up.

Even if you delete the spans (like in the simplified example) it still can’t make heads or tails of the closing p tag. Why? No idea. It’s not logically complex code – maybe it isn’t perfectly “to spec” (it might be, the million page HTML specification document is only readable, I think, by those who posses some kind of ancient, lost cryptex)  but honestly if it not valid, then it should be. There is no logical reason these simple elements should be ‘nestable’. You can nest divs in divs, why not divs in p’s?  It also works just fine in Firefox. It also works fine if you change the code to simply use spans instead of divs:

<div id="quickSummaryfull">
     <p>
          <span>Link to the older post!</span>
          <span>Link to the newer post!</span>
     </p>
</div>

Now Safari can figure this code out. It’s barely different – and frankly I’m now just left unimpressed by the DOM parser built into Webkit.

I’m not the only one to notice some unexpected behavior in how browsers render DOM elements – take this post from Hixie Natural who also noticed some lovely cross-browser inconsistencies when writing the HTML 5 Specification. The conclusion – they pretty much do whatever the hell they feel like, and generally regardless of the specifications. And sometimes, they get lucky.

-Andy

SPAM – The Other Grey Meat

Wednesday, September 9th, 2009

A quick follow up note in regards to my last post, where I described in gory detail how to convert a customized layout into a WordPress-powered blog. WordPress does open up a very rich feature base for both you and your readers, but it also opens up your blog to a lot of spammers and bots which have evolved to take advantage of the comments and registration systems that are common to all WordPress-enabled sites. What this means is that eventually your blog will be found out, and bots will start trying to insert all kinds of crap into your comments area on each post. There are several ways to combat these Decepticons, and by combining multiple methods you can prevent spam with just a few minutes of work.

The first and most simple way is to ensure your WordPress moderation settings are adequately restrictive. Check out the Settings-> Discussion page in the Admin panel.

Check at minimum:

  • Comment author must fill out name and e-mail
  • Comment author must have a previously approved comment

All the settings in this section are pretty self-explanatory, but these two are particularly important first steps to securing your comment system. This will, at the very least, let you set up spam lists (by tracking emails) and prevent new users’ comments from automatically appearing on your posts. This way, guests that frequently comment are assumed to be “Approved” and don’t need to wait for moderation, but new people, which might be spammers, must first have their comment moderated.

This is a good start – but it produces a new problem. When spammers start trying to comment, you will be required to mark all their responses as spam. This can become particularly annoying when you get 5 or more spam comments a day – and it gets downright frustrating when that number starts to spike to 10 or 20 or 30…

What the hell is a 'smwm'?

One of the most common ways to reduce this number is to install a plugin like CAPTCHA. This will place one of those little images with a difficult-to-read phase in it. This will instantly defeat any automated bot – but I generally dislike these for the simple reason that, by design, they’re difficult to read. For a casual blog, it’s going to be hard to get anonymous commenters to say something if they can’t read the little CAPTCHA image on the first try. Maybe if your blog gets some serious traffic, then a plugin like this would be more warranted, but honestly for a mom-and-pop operation like this one, CAPTCHA is just downright annoying.

There are a lot of alternatives to CAPTCHA systems, however. One of the most popular and lightweight is the aptly-named Anti-Captcha. This plugin won’t change the look-and-feel of your comments system at all – its magic is completely invisible. It plugin basically inserts a unique invisible token in your comment system. Since most automated bots don’t usually bother to check for it, they will usually neglect to send it along with their comment. If the token doesn’t get sent, this plugin automatically marks the post as spam. You’ll never have to even bother moderating it.

Anti-Captcha is a nice, lightweight solution for lightweight blogs, but for ones with heavier or even moderate traffic, I’d try something like WP-Spam-Free. Some bots are designed to look for tokens hidden by plugins like Anti-Captcha, since these tokens are very easy for smarter bots to find. WP-Spam-Free uses a similar concept (hidden tokens) but in a much more advanced way. Instead of just one hidden token the HTML form, where it can be easily scraped,  it actually hides them in JavaScript and Cookies, where bots have a hard time digging them out. The result is even fewer spam posts for your to moderate.

Wp_spam_free_screencapWP-Spam-Free also has some additional settings, letting you blacklist certain IP’s, URL’s, or e-mails from ever commenting again. It also has some more advanced logging features to help you fine-tune your settings or even recover auto-blocked comments. It can also be used to easily disable proxy-based comments, a tactic frequently used by spammers to block their IP but almost never used by readers of small blogs. I should note that by default it places a link to their site under your comment field. If you feel like supporting them, you can leave it, but you can turn it off in the settings if you’d like to keep your comment box clean.

If you feel compelled, you could even install both of these plugins, they can run side-by-side without conflicts, and will work overtime to keep out spammers.

The easiest way to install WordPress plugins is by logging into the Admin interface, and clicking Plugins from the menu on the left. Select Add New, then search for the plugin by name. Click the little Install link on the left, and enter in your site’s domain name and login credentials. If you don’t want to give out your creds so freely, you can install it manually by downloading the contents from their site, copying it to your remote web server, and placing it in the wp-conent/plugins/ folder. It will automatically show up in the Admin interface in the Plugins section, all you have to do is click the Activate link to turn it on.

With just minimal install effort up front, you can save a lot of time in the long run by keeping spam out of your blog entirely.

Happy hunting!

-Andy

(Re)Building A Blog-based Website From (Near) Scratch – Part 2

Sunday, September 6th, 2009

Building A Blog

Back in the early days of this blog, I didn’t have the luxury of programming languages like PHP to do a lot of the heavy lifting. I simply didn’t have the knowledge to use them – and even if I did, I was also severely limited by the servers that were hosting the content. They didn’t support server-side scripting or have databases for storing information. I had to maintain each page by hand, manually editing the content and shifting posts around as I wrote new ones. The process was tedious and required an inordinate amount of maintenance. The best thing to happen to this blog was to switch from static-content models, where I hand-crafted each page entry, to a dynamic model, that loads content stored from a database into pre-made shells. The advantages are numerous. Besides eliminating the need to meticulously manage content on every page, I can also automatically categorize, cross-link, and tag posts. End-users such as yourself benefit from features like searching across entries, a rich comment system, and a consistent user interface.

Unlike the “old days”, where server-side scripting was scarce, you’d be crazy in this day and age not to utilize some kind of blogging framework, or at minimum a scripting language with an underlying database. One thing I’ve learned, however, is that there is a fairly good gap between understanding a markup language (like HTML) and a programing language like PHP or JavaScript. If you’re relatively new to programming – and more used to drag-and-drop what-you-see-is-what-you-get (WYSIWYG) environments (like Dreamweaver)- then using these kinds of technologies can be a little intimidating at first. While I’m not going to give you a crash course in computer programming (at least not right now) – you don’t really need to have an extremely in-depth knowledge of the programming language just to get something put together. If you know HTML, then you probably already know more than you might think you know. You know?

If you already have a good layout  in HTML and CSS ready, then converting it from a static page of text into an interactive blog system is really not too difficult. Programming the system from complete scratch – starting with a blank page and an empty database is, however, a daunting task – even for a seasoned programmer. Taking advantage of a system like WordPress is far more practical, and it takes all the complicated pieces out of the equation. You don’t need to know how to program – you just need to know how to put all the pieces together.

Before I start the tutorial, let me briefly explain the big picture. WordPress is a PHP-based system. PHP code is executed on the server, pulls data from a database, and outputs HTML-formatted text. This HTML is then sent to your browser, which renders the page.

phptohtml

It can also output pieces of JavaScript, which run in your browser, and let you do things like connect to Facebook, or just validate a form. The goal, then, is to modify existing WordPress code to output HTML in you’re pre-designed format instead of their default format. These ‘formats’ are simply called Themes in WordPress. With just an hour or so of work, you can take your layout and a default WordPress Theme, and turn it into a highly-customized website.

It’s probably easier than you might assume. If you’re interested, just follow along below:

What You’ll Need

  • WordPress (http://wordpress.org/download/), v.2.8.4 or higher
  • Pre-made layout (See #3 for a good sample)
  • MySQL & PHP-Enabled web-server (I use MAMP locally, http://www.mamp.info/en/downloads/index.html. If you’re using Windows, you could use WAMP, but I’d recommend that instead you just stop right now and do what any right minded web-professional would do – go buy a damn Mac already. Seriously. Go ahead and run to the store – I’ll wait here until you get back.)

What To Do:

1. Download and install MAMP by dragging it to your Applications folder. Just double click it – and your done setting up a local website. The files are stored by default at ~/Sites/, and the website address is http://localhost:8080/. You also need to download and install WordPress, follow it’s instructions, as follows:

Original Ray’s “Famous 5-minute install”
1. Unzip the package in an empty directory.
Put this in your MAMP directory, like ~/Sites/wordpress
2. Open up wp-config-sample.php with a text editor like WordPad or similar and fill in your database connection details.
WordPad? Surely, they jest. If you like free, trying TextWrangler. If you’re serious about coding, Eclipse will do in a pinch, but it’ll pinch back. Recommended: Coda or BBEdit.
As for the Mysql DB credentials – the MAMP Homepage (http://localhost/MAMP/?language=English) will tell you what your credentials are.
3. Save the file as wp-config.php
4. Upload everything.
Actually, just do this locally first. Open up the page in a browser, aka http://localhost/wordpress and follow along. You’ll do this again on the webserver once we’re all finished. At a later point in time, consider adding version control systems like Git or SVN. I’ll cover each in a later tutorial.
5. Open /wp-admin/install.php in your browser. This should setup the tables needed for your blog. If there is an error, double check your wp-config.php file, and try again. If it fails again, please go to the support forums with as much data as you can gather.
6. Note the password given to you.
Did you ‘note’ it?
7. The install script should then send you to the login page. Sign in with the username admin and the password generated during the installation. You can then click on ‘Profile’ to change the password.
Please change the password to something good and secure, letters, numbers, symbols and all, and something you’ll actually remember.

2. Locate the Default theme: ~/Sites/wordpress/wp-content/themes/default. Make a copy of it, and rename it default_original.

3. We’ll edit the existing default theme. For reference, here is the layout I started with. I’ve highlighted how each section is going to be cut up, so you can see how the original code breaks down into the separate header, body, footer, and sidebar sections in WordPress.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
 <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
 <meta name="author" content="Andy Hoffner" />
 <meta name="keywords" content="andy hofner, hoffner, javascript, code, tech, apple, php, mysql, code samples, ramblings" />
 <meta name="description" content="The homepage of Andy Hoffner, programmer from Boulder Colorado. Focuses on coding, tech
  & video game news, and ramblings." />
 <meta name="robots" content="all" />

 <title>AndyHoffner.com - Home</title>

 <style type="text/css" media="all">
 @import "main.css";
 </style>

</head>

<body onload="window.defaultStatus='AndyHoffner.com';" id="andyhoffner">

<div id="container">
 <div id="linkList">
 <div id="linkList2">
 <div id="lselect">
 <h2>Articles</h2>
 <ul>
 <li><a href="/">Article 1</a></li>
 </ul> 

 <h2>Post Categories</h2>
 <ul>
 <li><a href="/">Category 1</a></li>
 </ul>

 <h2>Post Archives</h2>
 <ul>
 <li><a href="/">Archive 1</a></li>
 </ul>

 </div>
 </div>
 </div>

 <div id="intro">
 <div id="pageHeader">
 <h1>
 <li><div id='leftbkg'></div><div id='rightbkg'></div><div id='centerbar'></div>
 <div id='logotext'></div><span>AndyHoffner.com</span></li>
 <li><div id='tab1'></div><div id='tab2'></div></li>
 </h1>
 <h2><span>The Place You Go For Things</span></h2>
 </div>

 <div id="quickSummary">
 <p><span>There but for the grace of god...</span></p>
 </div>

 <div id="preamble">
 <h3 id='article1'><span>Building A Blog-based Website From Scratch</span></h3>
 <p>This is where the body text goes!</p>

 <h3 id='article2'><span>Basic Layered Layouts</span></h3>
 <p>This is also where body text goes!</p>
 <p><h4><span> -Andy</span></h4></p>
 </div>
 </div>

 <div id="footer">
 <a href="http://andyhoffner.com" title="Temp Link!">Home</a> &nbsp;
 <a href="http://andyhoffner.com" title="Temp Link!">Home away from home</a> &nbsp;
 <a href="http://andyhoffner.com" title="Temp Link!">no place like home</a> &nbsp;
 </div>

</div>
</body>
</html>

4. If you take a look at the default theme’s contents, you’ll see these pieces match up to files in there almost exactly, header.php, footer.php, sidebar.php and the body goes in index.php. The following steps will tell you how to take the code above and integrate it into each of these files.

5. First, open header.php. Remove all the lines in red. Add in the pieces from your header, which are in blue.

<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>

<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />

<title><?php wp_title('&laquo;', true, 'right'); ?> <?php bloginfo('name'); ?></title>
<title>AndyHoffner.com - Home</title>
<link rel="stylesheet" href="<?php ">php php ">bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />
<link rel="stylesheet" href="wp-content/themes/default/main.css" type="text/css" media="screen" />

<style type="text/css" media="screen">

<?php
// Checks to see whether it needs a sidebar or not
if ( empty($withcomments) && !is_single() ) {
?>
#page { background: url("<?php bloginfo('stylesheet_directory'); ?>
/images/kubrickbg-<?php bloginfo('text_direction'); ?>.jpg") repeat-y top; border: none; }
<?php } else { // No sidebar ?>
#page { background: url("<?php bloginfo('stylesheet_directory'); ?>
/images/kubrickbgwide.jpg") repeat-y top; border: none; }
<?php } ?>

</style>

<?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?>

<?php wp_head(); ?>
</head>
<body <?php body_class(); ?> onload="window.defaultStatus='AndyHoffner.com';" id="andyhoffner">
<div id="page">

<div id="header" role="banner">
<div id="headerimg">
<h1><a href="<?php echo get_option('home'); ?>/"><?php bloginfo('name'); ?></a></h1>
<div><?php bloginfo('description'); ?></div>
</div>
</div>
<hr />
<div id="container">
<div id="intro">
<div id="pageHeader">
<h1>
<li><div id='leftbkg'></div><div id='rightbkg'></div><div id='centerbar'></div>
<div id='logotext'></div><span>AndyHoffner.com</span></li>
<li><div id='tab1'></div><div id='tab2'></div></li>
</h1>
<h2><span>The Place You Go For Things</span></h2>

</div>

6. Now open up footer.php. Same deal, delete red, add your custom content in the blue. Little footnote here (pun intended) – removing the “Powered By WordPress” thing is optional – I just wanted to display it in a different place, and didn’t want the extra content mucking up the layout just yet. Please include it in your design wherever you feel warranted!

<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
?>

<hr />
<div id="footer" role="contentinfo">
<!-- If you'd like to support WordPress, having the "powered by" link somewhere on your blog
is the best way; it's our only promotion or advertising. -->
<p>
<?php bloginfo('name'); ?> is proudly powered by
<a href="http://wordpress.org/">WordPress</a>
<br /><a href="<?php bloginfo('rss2_url'); ?>">Entries (RSS)</a>
and <a href="<?php bloginfo('comments_rss2_url'); ?>">Comments (RSS)</a>.
<!-- <?php echo get_num_queries(); ?> queries. <?php timer_stop(1); ?> seconds. -->
</p>
</div>
</div>

<div id="footery">
<a href="http://andyhoffner.com" title="Temp Link!">Home</a> &nbsp;
<a href="http://andyhoffner.com" title="Temp Link!">Home away from home</a> &nbsp;
<a href="http://andyhoffner.com" title="Temp Link!">no place like home</a> &nbsp;
</div>

</div>
<?php wp_footer(); ?>
</body>
</html>

7. Sidebar.php – red = bad, blue = good, black = neutral. I pretty much have blown this whole file out, took a lot of content/features out with it – feel free to keep them if you like their look in your sidebar.

<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
?>
<div id="sidebar" role="complementary">
<ul>
<?php     /* Widgetized sidebar, if you have the plugin installed. */
if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar() ) : ?>
<li>
<?php get_search_form(); ?>
</li>

<!-- Author information is disabled per default. Uncomment and fill in your details if you want to use it.
<li><h2>Author</h2>
<p>A little something about you, the author. Nothing lengthy, just an overview.</p>
</li>
-->

<?php if ( is_404() || is_category() || is_day() || is_month() ||
is_year() || is_search() || is_paged() ) {
?> <li>

<?php /* If this is a 404 page */ if (is_404()) { ?>
<?php /* If this is a category archive */ } elseif (is_category()) { ?>
<p>You are currently browsing the archives for the <?php single_cat_title(''); ?> category.</p>

<?php /* If this is a yearly archive */ } elseif (is_day()) { ?>
<p>You are currently browsing the <a href="<?php bloginfo('url'); ?>/"><?php echo bloginfo('name'); ?></a> blog archives
for the day <?php the_time('l, F jS, Y'); ?>.</p>

<?php /* If this is a monthly archive */ } elseif (is_month()) { ?>
<p>You are currently browsing the <a href="<?php bloginfo('url'); ?>/"><?php echo bloginfo('name'); ?></a> blog archives
for <?php the_time('F, Y'); ?>.</p>

<?php /* If this is a yearly archive */ } elseif (is_year()) { ?>
<p>You are currently browsing the <a href="<?php bloginfo('url'); ?>/"><?php echo bloginfo('name'); ?></a> blog archives
for the year <?php the_time('Y'); ?>.</p>

<?php /* If this is a monthly archive */ } elseif (is_search()) { ?>
<p>You have searched the <a href="<?php echo bloginfo('url'); ?>/"><?php echo bloginfo('name'); ?></a> blog archives
for <strong>'<?php the_search_query(); ?>'</strong>.
 If you are unable to find anything in these search results, you can try one of these links.</p>

<?php /* If this is a monthly archive */ } elseif (isset($_GET['paged']) && !empty($_GET['paged'])) { ?>
<p>You are currently browsing the <a href="<?php echo bloginfo('url'); ?>/">
<?php echo bloginfo('name'); ?></a> blog archives.</p>

<?php } ?>

</li>
<?php }?>
</ul>
<ul role="navigation">
<?php wp_list_pages('title_li=<h2>Pages</h2>' ); ?>

<li><h2>Archives</h2>
<ul>
<?php wp_get_archives('type=monthly'); ?>
</ul>
</li>

<?php wp_list_categories('show_count=1&title_li=<h2>Categories</h2>'); ?>
</ul>
<ul>
<?php /* If this is the frontpage */ if ( is_home() || is_page() ) { ?>
<?php wp_list_bookmarks(); ?>

<li><h2>Meta</h2>
<ul>
<?php wp_register(); ?>
<li><?php wp_loginout(); ?></li>
<li><a href="http://validator.w3.org/check/referer" title="This page validates as XHTML 1.0 Transitional">
Valid <abbr title="eXtensible HyperText Markup Language">XHTML</abbr></a></li>
<li><a href="http://gmpg.org/xfn/"><abbr title="XHTML Friends Network">XFN</abbr></a></li>
<li><a href="http://wordpress.org/" title="Powered by WordPress, state-of-the-art
 semantic personal publishing platform.">WordPress</a></li>
<?php wp_meta(); ?>
</ul>
</li>
<?php } ?>

<?php endif; ?>
</ul>
</div>
<div id="linkList">
<div id="linkList2">
<div id="lselect">
<h2>Articles</h2>
<ul>
<?php wp_list_pages('title_li='); ?> <!-- This fetches a list of pages with an <;;li> tag without a headline -->
</ul>

<h2>Post Categories</h2>
<ul>
<?php wp_list_categories('show_count=1&title_li='); ?> <!-- This does the same -->
</ul>

<h2>Post Archives</h2>
<ul>
<?php wp_get_archives('type=monthly'); ?>
</ul>

</div>
</div>
</div>

8. Finally, the body:

<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
<?php get_header(); ?>
<div id="content" class="narrowcolumn" role="main">
<div id="quickSummary">
<p><span>There but for the grace of god...</span></p>
</div>
<div id="preamble">
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
<div <?php post_class() ?> id="post-<?php the_ID(); ?>">
<h23><a href="<?php the_permalink() ?>" rel="bookmark"
title="Permanent Link to <?php the_title_attribute(); ?>"><span><?php the_title(); ?></span></a></h23>
<small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small>
<p>
<div class="entry">
<?php the_content('Read the rest of this entry &raquo;'); ?>
</div>
<p class="postmetadata"><?php the_tags('Tags: ', ', ', '<br />'); ?> Posted in <?php the_category(', ') ?> |
<?php edit_post_link('Edit', '', ' | '); ?>
<?php comments_popup_link('No Comments &#187;', '1 Comment &#187;', '% Comments &#187;'); ?></p>
</p>
</div>
<?php endwhile; ?>
<div class="navigation">
<div class="alignleft" ><?php next_posts_link('&laquo; Older Entries') ?></div>
<div class=alignleft"><?php previous_posts_link('Newer Entries &raquo;') ?></div>
</div>
<?php else : ?>
<h2 class="center">Not Found</h2>
<p class="center">Sorry, but you are looking for something that isn't here.</p>
<?php get_search_form(); ?>
<?php endif; ?>
</div>
<?php get_sidebar(); ?>
<?php get_footer(); ?>

9. You should also check out single.php. This page will be used to show an entry all by itself on a single page, if someone does a search, or is browsing the archives. It is also where people will add comments.

<?php
/**
 * @package WordPress
 * @subpackage Default_Theme
 */

<?php get_header();?>
<div id="quickSummaryfull">
 <p class="p6"><span>&nbsp
 <div class="alignleft"><?php previous_post_link('&laquo; %link') ?></div>
 <div class="alignleft"><?php next_post_link('%link &raquo;') ?></div>
 </span></p>
</div>
<br />
 <div id="content" class="widecolumn" role="main">

 <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

 <div class="navigation">
 <div class="alignleft"><?php previous_post_link('&laquo; %link') ?></div>
 <div class="alignleft"><?php next_post_link('%link &raquo;') ?></div>
 </div>

 <div <?php post_class() ?> id="post-<?php the_ID(); ?>">
 <h2><?php the_title(); ?></h2>

 <div class="entry">
 <?php the_content('<p>Read the rest of this entry &raquo;</p>'); ?>

 <?php wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>',
 'next_or_number' => 'number')); ?>
 <?php the_tags( '<p>Tags: ', ', ', '</p>'); ?>

 <p class="postmetadata alt">
 <small>
 This entry was posted
 <?php /* This is commented, because it requires a little adjusting sometimes.
 You'll need to download this plugin, and follow the instructions:
 http://binarybonsai.com/wordpress/time-since/ */
 /* $entry_datetime = abs(strtotime($post->post_date) - (60*120)); echo time_since($entry_datetime);
 echo ' ago'; */ ?>
 on <?php the_time('l, F jS, Y') ?> at <?php the_time() ?>
 and is filed under <?php the_category(', ') ?>.
 You can follow any responses to this entry through the
<?php post_comments_feed_link('RSS 2.0'); ?> feed.

 <?php if ( comments_open() && pings_open() ) {
 // Both Comments and Pings are open ?>
 You can <a href="#respond">leave a response</a>, or <a href="<?php trackback_url(); ?>"
 rel="trackback">trackback</a> from your own site.

 <?php } elseif ( !comments_open() && pings_open() ) {
 // Only Pings are Open ?>
 Responses are currently closed, but you can <a href="<?php trackback_url(); ?> "
 rel="trackback">trackback</a> from your own site.

 <?php } elseif ( comments_open() && !pings_open() ) {
 // Comments are open, Pings are not ?>
 You can skip to the end and leave a response. Pinging is currently not allowed.

 <?php } elseif ( !comments_open() && !pings_open() ) {
 // Neither Comments, nor Pings are open ?>
 Both comments and pings are currently closed.

 <?php } edit_post_link('Edit this entry','','.'); ?>
 </small>
 </p>
 </div>
 </div>
 <?php comments_template(); ?>
 <?php endwhile; else: ?>
 <p>Sorry, no posts matched your criteria.</p>
<?php endif; ?>
 </div>
<?php get_footer(); ?>

10. Go ahead and check out your changes, http://localhost/wordpress/. You might have to tweak the layout or the main.css file, especially if any of your custom CSS names match the names in WordPress. Remember that CSS is a last-come, last-serve language – whichever declaration is read last will be the one that counts. I had you order you’re CSS file after the WordPress ones for just this reason, anything in your CSS file will overwrite the settings in WordPress. If you’d like, you can merge the two files and clean up any re-declarations. In the long run it’ll be easier to manage, but in the short run it’ll be a pain to sort out all the correct pieces. I’ll show you a short cut on how to do this in another post.

11. Once it looks right, you should make a new thumbnail picture for it. Open the site in a web-browser, take a picture (Cmd-Shift-4), open it in Preview, and resize it (Tools->Adjust Size) to no larger than 300 wide and 225 tall. You should also give your theme a name & author (that’s you). Open style.css and edit Theme Name, Description, and Author. In the Theme URI, put your web address (ex. http://andyhoffner.com), and Version should just be 1.0.

12. Now its time to get it running on your web server. The easiest way is to install a clean WordPress instance, following their “5 Minute Install” all over again. Then, copy your customized “default” template to the server, and just rename it to something unique. This way, you can keep the default template on file for emergency cleanups, or just simple reference.

13. To switch to and activate your new template, log into WordPress (htttp://yourremotewebserveraddress.com/wp-login.php), Click Appearance from the menu on the left, and you should see your new theme, with name and custom thumbnail. Click Activate.

14. You’re done! Congratulations!

Keep checking in for Part 3 of the series!

-Andy