MiscPodcast
Code: , ,
1 comment

I have some random episodes of podcasts laying around waiting to get listened to from podcasts I don’t (yet) care to subscribe to. Maybe they had an interesting guest or topic, or came recommended. These downloads will lay around on my computer for months because they’re not in my podcasting app, so they’re not really in my listening queue.

So I hacked up a PHP script to grab those mp3s and serve a valid (if spartan) podcast feed.

You can find the code on GitHub. It’s designed to be dropped into place rather than robustly deployed. Then I download mp3s to that folder and they’re delivered as my own personally-curated podcast feed.

Thanks to Shubham Jain for his PHP-ID3 library so the script can read some metadata into the feed.

SPWA Week 2: Funding and Forms
Games: , , ,
5 comments

So Play We All is partly a motivation hack, with teammates/competitors and penalties to make sure we each put in time towards our games. Luke’s job sent him to a conference for almost all of the week, so he didn’t get to do any of his hours. He’s paying us both $20. To keep anyone from falling behind, we’ve tweaked the rules to say that anyone who pays the penalty for missed hours can make them up when they have the time.

Meanwhile, Jim’s done great, getting code live for the first time. I took a screenshot:

Allabrilyn Exclusive First Screenshot!

The first page has a simple login form. There’s no way to register an account, and any login/password you enter gives you the above message. In his blog post, Jim wrote about the code

At that point, it was a fairly easy task to take the user object and add its data to the display for rendering. I chose to go with something like:

Hello %user%! Your account was created at %time% on %date% and you last logged in at %time% on %date%. Enjoy your stay!

STOP IT. You are writing a template language in a template language! Templates are the one thing PHP actually does pretty decently (well, it’s not Haml, but it’s way better than TAL)! Wrap PHP’s output buffering around include() and get on with your life before you find yourself implementing conditionals and loops.

This is part of a larger topic I have to respond to:

This is mostly because I had to rush myself just to even get this far and put in lots of sloppy code. So, I’ve decided that I don’t care how far ahead the others get, I am not going to worry about matching their pace.

Really, it was an unrealistic goal that I’m glad to be letting go of. They’re using a pre-built framework which means they have options to solve a lot of their issues right out of the box. I, on the other hand, have to implement even my low-level functionality. This means that I’m going to be slower to execute no matter what happens. That’s the price that I pay for wanting to use my own implementation. The positive upside is that once I manage to solve these issues, they’ll be solved for me in all of my future games and I’ll be able to skip this tedium the next time around. …

Sure, it slows me down in terms of this competition, however, I will have 100% control over every aspect of the process which is not something that I would have if I were to leverage Drupal to build the game.

I know you write good code, Jim, but satisfice, man. You’ve got the worst time demands of all of us. Luke and I aren’t barfing into our editors and making sure it passes a syntax check, we’re taking acceptable components from other people so we spend our time on the important bits.

Last week I bought and added a theme to Oaqn. I was hugely tempted to tear it apart and make sure everything was perfect, with semantic class names and no unused code and efficient selectors and and and… Instead I added achievements, a feature that will help inspire and retain players for the lifetime of my game. That code’s not perfect, either, I already know I’ll want to tweak it to add some kind of bronze/silver/gold upgrading medals — but now I’ve got something decent in place and I can get closer to a running game.

Finish a game. So Play We All.

PHP Hex Map Graphics
Code: , , ,
1 comment

This PHP code uses the GD functions to create hex map images (eg. for wargames).

Leland on GitHub

Features:

  • Shapes: rectangule, hexagonal (‘circle’), freeform (‘free’)
  • Variable hex sizes
  • shape() to calculate distance in hexes
  • highlight a hex
  • set a border on a hex
  • color a hex
  • add text to a hex
  • I swear it used to allow setting a background picture, but I don’t see that functionality so maybe I dreamed it or lost it when I misplaced this code for four years.

Known Issues

The code has ugly styling (tabs, odd spacing, no optional braces) – sorry, I was young(er) and stupid(er).

There’s a fair amount of temporal coupling in there – functions that you can’t call before other functions, etc. I hadn’t heard of the command pattern or closures yet.

There’s a bug in the ‘circle’ shape (that the following code exercises):

<?php
 
require 'class_hex_image.php';
 
$radius = 3;
$map = new Hex_image;
$map->set_color('bg', 255, 255, 255);
$map->set_l(20);
$map->set_shape('circle', $radius);
$map->start();
for($x = 1; $x <= $map->xsize; $x++) {
    for($y = 1; $y <= $map->ysize; $y++) {
        $map->text($x, $y, 'black', $map->steps($x, $y, $radius, $radius));
        // nice for getting a feel for coordinates
        //$map->text($x, $y, 'black', "$x,$y");
    }
}
 
header('Content-Type: image.png');
$map->finish();       // calls imagepng()
 
?>

Future

One of the guys in #bbg on irc,freenode.net is building a browser-based game with a hex map and I remembered this code was squirreled away somewhere on my hard drive. I have no plans to fix, improve, or in any way maintain this code. I figure I may as well release it so someone can do something with it.

License

I release this code to the public domain. You may use it for any purpose with or without attribution. It would be polite to mention my name and let me know you come up with, but it’s not at all required.

Investigating Theme Spam
Code: , , , , ,
1 comment

If you’re interested in what spammers are up to these days, check out Snarky’s blog post Evil Eval() investigating the obfuscated spam code hidden in the new WordPress theme he downloaded.

I’d be really interested to see how many of the themes on various WordPress sites include function calls like eval, call_user_func, base64_decode, unpack, ord, chr, etc. as an indicator of hidden spam.

Building Clean URLs Into a Site
Code: , ,
5 comments

I wrote about building a site with clean URLs, but that’s useless to you. No, you’ve got a creaking hulking monster of a site that coughs up URLs like “render.php?action=list_mailbox&id=42189”, was built “to meet an accelerated schedule”, and eats summer interns whole.

This article tells you how to put clean and human-usable URLs on top of the site without even editing your underlying scripts. All these examples mention PHP but it doesn’t matter what you coded the site in, you just have to be running Apache and have a little familiarity with regular expressions.

So we have two goals. First, requests for the new URL are internally rewritten to call the existing scripts without users ever knowing they exist. Second, requests for the old URLs get a 301 redirect to the new URLs so that search engines and good bookmarks immediately switch to the new URLs.

Let’s work through an example .htaccess file. We take apart the new URLs and map them internally to the old URLs:

RewriteEngine on

RewriteRule ^new/(.*)/(.*)$ /old.php?action=$1&id=$2 [L]

This works great, so we dive into the 301 redirects:

RewriteEngine On

RewriteRule ^new/(.*)/(.*)$ /old.php?action=$1&id=$2 [L]
RewriteCond %{QUERY_STRING} ^action=([a-z]+)&id=([0-9]+)
RewriteRule ^old\.php$ /new/%1/%2? [R=301,L]

Arrrgh! We test this and find a problem: all requests for new are getting 301 redirected back to new. Apache is rewriting new to old fine, but then it sends the new URL back through mod_rewrite again so we’re stuck in an infinite loop of redirects (even though the [L] option is supposed to tell Apache to stop applying rules). We need to turn it up to 11 and tell Apache “No, really, stop rewriting URLs now” by setting a flag that it already rewrote the URL.

RewriteEngine on
# This rule just keeps DirectoryIndex working (so requests for / go to /index.php or whatever)
RewriteRule ^$ - [L]
# Set an environment variable REWROTE that we haven't done any rewriting
RewriteRule ^(.*)$ $1 [E=REWROTE:0]

# Flag that the new URL rewrote
RewriteRule ^new/(.*)/(.*)$ /old.php?action=$1&id=$2 [L,E=REWROTE:1]
# Only rewrote the old url if we didn't rewrite
RewriteCond %{ENV:REWROTE} !^1$
RewriteCond %{QUERY_STRING} ^action=([a-z]+)&id=([0-9]+)
RewriteRule ^old\.php$ /new/%1/%2? [R=301,L]

This set of rewrite rules accomplishes both our goals and the new URLs are all we’ll ever see in the address bar. You can set up any number of rewritten URLs (there’s no need to repeat the code turning on rewriting and REWROTE flag), editing them for your particular GET variables and layout.

Proudly displaying our shiny new URLs, we can send in surgical teams into the site’s source code file-by-file, slowly and carefully replacing instances of the old URLs with the new ones. Once all the URLs are replaced, you can watch your server logs to see usage of the old URLs fall off. The way is now prepared for you to further beautify your site inside and out.

Developing With Evil
Code: , , , ,
No comments

allaryin: whee…
allaryin: i’ve been given a job to put a simple email address subscription form on a site
Harkins: sounds pretty easy
allaryin: and… as far as i can tell, the server has neither php nor perl :P
allaryin: i’m running out of options :P
Harkins: cgi, baby
allaryin: for db access?
Harkins: Or change the target of the form to a server you control running PHP/perl that saves the data and redirects back to the other server.
allaryin: yeah…
allaryin: but i really don’t want to commit any of our server resources to their site :P
BSDCat: I think a ‘simplicity’ fairy just lost its wings
Harkins: Or make the form GET and write a cron job to scrape access.log.
allaryin: …
allaryin: wow.
Harkins: Yes, I’m evil.
allaryin: it’s beautiful really
Harkins: bwa
allaryin: but yes, evil

Building a Site With Clean URLs
Code: , , ,
6 comments

As an aside in my post about Cambrian House I posted some code for making pretty URLs. A few people (no, not CH) have asked for a little more info, so I’ve written up an explanation of that code.

PHP makes it very easy to create bad URLs like /member.php?id=8. Those are bad because web spiders don’t like to crawl URLs with GET variables, some browsers don’t cache any GET URLs, they expose that you use PHP (when the visitor should never even know), and they’re just downright ugly and hard to remember. I’m going to present a way to build a PHP/Apache site with clean URLs.

Let’s look, line-by-line, at the contents of .htaccess. While writing this article I found a more elegant equivalent in the WordPress code, so I’ll present that here:

# Tell Apache to load mod_rewrite.
RewriteEngine On
# Rewrite URLs for the location starting at /
# Note this is URL location, not a path to your web root.
RewriteBase /
# If the request asks for a file or directory that doesn't exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# send the request to index.php.
RewriteRule . /index.php [L]

The hard part about this change is the shift in thinking. A URL isn’t just a path to a file you FTP’d to a web server, it’s a Universal Resource Locator, an address for information. It doesn’t matter whether your site presents data taken from files, a database, or a random number generator — a web browser requests a URL and knows nothing about where the website gets it from.

With that in mind, let’s look at how your PHP site can take apart the URL to route the request to the right PHP script. Create an index.php that looks like:

function url_parse($url) {
        // strip off get vars and anchor tags
        if (strpos($url, '?'))
                $url = substr($url, 0, strpos($url, '?'));
        if (strpos($url, '#'))
                $url = substr($url, 0, strpos($url, '#'));
 
        //remove leading slash and possible trailing slash, store in $url
        if (substr($url, 0, 1) == '/')
                $url = substr($url, 1);
        if (substr($url, -1) == '/')
                $url = substr($url, 0, -1);
        if ($url == '/')
                $url = '';
        $url = explode('/', $url);
 
        return($url);
}
 
$actions = Array(
    "" => "front_page.php",
    "mail" => "mail.php",
    "member" => "profile.php",
    "messageboard" => "boards.php",
);
 
$url = url_parse($_SERVER['REQUEST_URI']);
$action = array_shift($url);
if (array_key_exists($action, $actions)) {
    require($actions[$action]);
} else {
    require("404.php");
}

So index.php takes the first element off the array, and probably uses it to require() specific templates or scripts that do the work with the rest of the $url array. Think of it like a switchboard operator — it sends requests where they need to go.

Your individual pages can array_shift() their arguments from the $url array. In the example above, profile.php would expect a username or ID number, and it can require("404.php"); if there’s nothing there or no user by that id.

More complex nested URLs (say, /messageboard/chat/new_thread) work much the same way index.php works: the base script examines $url and passes it on to the scripts it knows about. In the example above, boards.php can load the requested board or the pages used to create a new post or a new board.

In my next post, I’ll provide a clean URL solution for existing sites that can’t afford to redesign their PHP scripts.

Pre-Cambrian House
Biz: , , , , ,
6 comments

I was poking around reddit and followed a link to CambrianCode.com, an all-Flash (ugh!) puzzle game. There’s a few of these “guess how to get to next level” games online and they all just annoy me. Yes, you’re so clever. No, I find patronization alluring. Yes, I’ll spend my time on this for no discernable reward.

The puzzle is run by Cambrian House, a mysteeeeerious stealth startup that has only a teaser page online. If there’s one thing that annoys me more than Flash puzzle-level games, it’s stealth startups.

So I went poking around some more and found a development copy of their website. And much to my surprise, it’s actually a darn cool business idea. So cool that after I wrote a whole “Mwaha, I’m raising the curtain early!” post I thought better of it and am only going to post this for now. It was clever and fun, there’s going to be a ridiculous amount of buzz around this company when it launches. And I got to register as user #9, which was damn funny when I noticed their “About Us” page lists 17 employees.

Confidential to CH in Calgary: it’s really tacky to litter your URLs with “.php” and get variables. Put the following in your .htaccess file and have index.php take apart the URL with the PHP code below and route to your different pages. URLs like “/community/member/Harkins” look much nicer than “/community/member-profile.php?users_id=9”. (Or ask me about mod_rewrite.)

<Location /secret_development_environment>
    Order Deny,Allow
    Deny from all
    Allow from 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 .cambrianhouse.com
</Location>

RewriteEngine On
RewriteCond    %{REQUEST_FILENAME}  -d [OR]
RewriteCond    %{REQUEST_FILENAME}  -f
RewriteRule     ^(.*)$  - [L]

RewriteRule ^(index.*) - [QSA,L]
RewriteRule ^([^.]*)$ /index.php [QSA,L]
function url_parse() {
        $url = $_SERVER['REQUEST_URI'];
 
        // we don't want to pass get vars or anchor tags on to the script
        if (strpos($url, '?'))
                $url = substr($url, 0, strpos($url, '?'));
        if (strpos($url, '#'))
                $url = substr($url, 0, strpos($url, '#'));
 
        //remove leading slash and possible trailing slash, store in $url
        if (substr($url, 0, 1) == '/')
                $url = substr($url, 1);
        if (substr($url, -1) == '/')
                $url = substr($url, 0, -1);
        if ($url == '/')
                $url = '';
        $url = explode('/', $url);
 
        return($url);
}
Cambrian House house responded to me.

Fatal error: Call to undefined function twentyseventeen_get_svg() in /home/malaprop/push.cx/wp-content/themes/pushcx/archive.php on line 45