all entries in category 'web development'


Boring Development Post - sL lives

It’s been a long time since I got my dev on, but after a little prodding from good ol’ Wheatbread, we’ve decided to put Showlister, a project with truckloads of possibility, back on the road to fruition.

Yeap, I finally got my home network together enough to contribute more to the internet than snarky commentary and pictures of my feet.

Asshat Alert

It ain’t often in the open source community that you get to call out a fellow developer (being generous with that title there) for being a sneaky shit, but recently it was brought to my attention that one of the former team members on the Showlister project has decided to usurp the considerable audience sL has with his own meager and unstable offering. Nothing illegal, mind you – just a bit underhanded. It’s fairly obvious though, that the project's website ahem borrows liberally from this website, the latter being one that I spent weeks designing and coding. What an assclown. I’m just glad he never had access to the scripting.

Forgive me, Wheat, if you planned on roasting this guy on your blog, but after seeing that website… well, let’s just say I was inspired.

Anyway. On to the coding. Or the de-and-recoding. "He" was allowed into the sL project last year, and basically proceeded to take a dump on the codebase. This is what the to-do list looks like for the next few weeks:

.

==========================================
ShowLister – TODO.txt
==========================================

NEXT VERSION 1.0

#unfscking the codebase, round 3 (getting there)

#undoing freak2532’s changes

# unfsck user account settings editing

# Remove GET variable session handling and loggedout behavior is far too easily compromised and it looks like shit. All session variables should probably be passed via POST or COOKIE.

# Remove extranneous security level display. It is cluttery, and the premise is flimsy.

# protect the admin user so it can only be modified, never deleted.

==========================================

*** THIS ENDS GRIPING NERDNESS POST ***

Best Website Error Message Ever.

While planning a weekend in NYC, I came across this gem. Either this developer has a great sense of humor, or he’s overly concerned about covering his ass on a shit scripting job.

Error ! The current browser is either too old or too modern (usind DOM document structure).

Okay Goldilocks. I bet IE 5.5 is juuuuuust right.

Google Analytics

Google Analytics

Google announced yesterday that its web statistics service–formerly called Urchin for Google–will now be offered for free to the general public. The improved service, renamed Google Analytics, is purported to provide accurate, timely, and most importantly useful information to “everyone from senior executives and advertising and marketing professionals to site owners and content developers.”

Though not necessary to take advantage of the statistics, an active AdWords account provides hooks for all sorts of valuable information about a web site's traffic. These extended metrics are ostensibly targeted at Google's paying customers, but clearly have added appeal to those prospective AdWords users with dollars to spend and a vested interest in spending them wisely in a competitive web marketplace.

A blurb from the press release:

“We want to give all online marketers and publishers access to powerful web analytics to help them better understand what their customers want. With this knowledge, businesses can create more accurate advertising and build better websites,” said Paul Muret, Google engineering director, and one of the founders of Urchin. “By making this powerful service free, we aim to give all websites–large and small–the tools they need to better serve their customers, make more money, and improve the web experience for everyone.”

Combining the best bits of its Urchin acquisition with its competition-flogging mastery of the web interface, I think it's fair to say that Google has once again successfully applied its winning business strategy: catering to the web as it is, and not necessarily how they'd like it to be.

Editor's addendum: For those of you folks out there who are intruiged by the principals and methodology of advertising in the aformentioned web marketplace, you might want to check out the Google Analytics companion website, Conversion University, which has quite an interesting array of information for your marketing edification.

CloneSpy’s Official Widgethood

The fine folks over at Konfabulator have officially listed CloneSpy, and I couldn’t be happier with the response. (Yo Snay… check out the screenshot on the listing page… I’ll make you famous.)

I was asked to write up a howto on getting both BBclone and CloneSpy working with Wordpress, but that’ll have to be put off until I finish the WBA project.

Anyone who has specific questions about CloneSpy, feel free to drop me a line, or leave a comment on the CloneSpy page.

CloneSpy v1.0 Is a Go.

 

Without further ado, CloneSpy is here.

I feel like a proud parent of some sort. Only this development cycle didn’t take 20 years, and I don’t have to pay for college.

Check That. It’s CloneSpy Beta.

Update10/11/2005

CloneSpy, the BBClone Stats Widget for Konfabulator has a new home. You can read up on the little guy and download him there.
–––

After a lot of fiddling with the Konfabulator API and a general coming-to-terms with the feng-shui of widget design, I’ve retagged my widgeteering venture and sexed it up a bit. I also trimmed the width down to a conservative 183px, bringing it in line (so to speak) with the very popular and seemingly ubiquitous Weather widget. I'm sure I'm not the only one who likes to keep things square on their desktop.

The code is simple, but as it stands, I think the stats that are shown in the minimal state might be too detailed. Right now I am still debating what stats to put in and what to leave out (Total for the past year? Yeah, umm… I might hide that one for good).

Now all I have to do is prepare a little HOWTO on setting up the gateway, a little page to track downloads (can never have enough pointless stats) and then I’m off to foist it upon the Konfabulator people.

Clonespy Interface - Two states.

FrankenStats beta

For the longest time I have wanted to be with the kewl kids, using Shaun Inman’s ShortStat and Keegan Jones' Dashboard widget to track visitors to this site, boosting my ego and fulfilling my stats jones without the laborious task that is opening a browser. Ahh, mainlined stats is the only way to fly.

Lots of folks swear by Shortstat, and it is a great piece of code to be sure—but after my long love affair with bbclone, I found the info one can glean from the ShortStat interface just doesn’t stack up. I know, I know, one might ask “But why not just have a mint?” To that I say “I need not pay for a mint if I already have this wad of gum.”

frankenstats interface

Enter FrankenStats.

Yep, I finally got around to fleshing out a long-planned BBclone widget for Konfabulator, which, much like the current Shortstat widget shows raw hits YTD, uniques YTD, and the last couple of referrers. It uses the BBclone data, which is replete with every bit of info you could want about a visitor, so I plan to add some more stuff, like hostnames, searches, IP addresses (network-dork-am-i) and such. Anyone who wants the widget before I polish it up and ship it off to the official Konfabulator repo, drop me a line and I'll send it along.

Konfabulatin’ is fun fun fun.

iRGA: Image Replacement Gone Apeshit

(Behold the clever lower-case i.)

iRGA is a new technique I’m thinking about pushing on all the floofy web design sites. You know—just like all good heroes should have theme music, all good web techniques should have a catchy acronym¹. Errr-Gah. Or maybe Ear-Gay. Marketing is still kickin’ it around.

Anyway—on to the thing.

This technique borrows completely from Malarkey’s Image Replacement Method (or MIR, see #1). In fact, it is the exact same method, [stolen] verbatim if you will, but used so extensively and in so many different imported, linked and inline style rules that it causes [through the magic of spaghetti CSS] [almost] all known browsers to forego any attempt at screwing up the design. I call this effect The cascade of last resort. I reckon that it's quite similar in notion to sympathy sex.

Ahh, but enough words. I know what you want. You want pictures. What follows is the first known successful implementation of iRGA:

IRGA is Born

39 images, 3 imported stylesheets, text-indentation to exceed -4999px, and a whole lotta lurve. Okay, so maybe the silly Swede still doesn’t get the joke, but I’m working on him.

The Writers Blog Alliance

Yesterday I was asked to help redesign and outfit The Writers Blog Alliance. This is my favorite type of project to work on: a solid idea, a dedicated usership, and a real opportunity to push myself to the limit when it comes to design and development.

The Writers Blog Alliance

Thanks a lot to Clive Allen for the kind words about this site, and for the vote of confidence from my good friend Mad. I hope to give the WBA website a good design footing to start on, as well as the fluid, sturdy, and refined management infrastructure that a website needs to maintain a standard of quality, accessibility, and interest.

Update Sunday, 08/14/2005

Goodness. This is becoming quite a project. The forum integration was for the most part seamless, though I am still trying to get my head around how I should link the sessions/DB tables for the user base. I think this is one of those projects where an outline of some sort can go a long way towards getting what you want from the code. Gotta write one of those.

The image above now links directly to the development domain, so if you wanna take a peek and even leave a comment (there) about something you see that's out of whack, please do. Oh, and if you are using IE, don't bother. Designing for IE first is exactly why the innerweb looked like shit for a decade or so. :P ◊

Showlister : From the Makers of Wheatblog

The creator of wheatblog, the web API at the heart of this website (and probably hundreds of others) has an equally popular open-source project to his credit: a lightweight CMS, called Showlister, which is designed to easily integrate a performance calendar into a website. Pretty cool, and if I was ever to take my mandolin wanking on the road, this would certainly be a tool I’d use.

Well, apparently Mr. Martin trusts my design sensibilities, as I am neck-deep in the newest version of wB, and I was recently asked to throw a little of my “moojoo” at Showlister’s sourceforge site. Here’s what I came up with; anyone stopping in is encouraged to leave a word about what strikes you as good, bad, or ugly. This is open-source web development, of course, but I still like to be pixel-perfect when I can swing it.

The text formatting, font, and other presentational details are still in the works, but any thoughts on the design are appreciated.

link to devpage/sl


Update Thursday, 07/21/05

The navigation is up, using Malarkey's Image Replacement technique. It seems to work fine on IE 5+, Firefox and Opera 7.54+, but I've yet to skin over to icapture and check it out with Safari. Anyone who might have IE5/Mac, I beg of you, check it out and tell me if and how badly it implodes.


Update Saturday, 07/23/05

Officially moved development tree to http://showlister.sourceforge.net/new/. Decided on three-column layout, as the content fits well. Lots of work on dynamic content with SF's (somewhat clunky) RSS feeds. Some fleshing out of Email form and processing for user-adder.

Update Monday, 07/25/05

Well, I finally got all the RSS shenanigans taken care of: The News feed, The Project Info feed, and the DL counter are now all synced with a CRON job (SF actually had wget installed, which is very nice). To get around their request to poll feeds as little as possible, I devised a scheme to cache the feeds every 8 hours, and then build the actual markup blocks with scripts that run immediately afterwards. I also started an Email campaign to ask permission for the spotlight doohickey, and 4 people have already given a thumbs-up (Fair Use has me out of any real danger, but its good to ask anyway). I'm not happy with the menu at all, and will probably scrap it for something more legible. Some cursory work on the management ui for the userlist–but I am still trying to picture the best scripting-flow in my head.

Update Saturday, 08/06/05

The site is live.

Turning Del.icio.us Feeds into Content: Part 1

Social Bookmarking Kicks Ass.

Anyone who has discovered the benefits of del.icio.us knows how easy it makes gathering up the good stuff you find on the web; It is one of those brilliant ideas along the lines of the paperclip. The simplicity of the system is its greatest asset, and the potential for even greater flexibility and ingenuity has been realized with doodads like the del.icio.us extension for Firefox, which makes taking advantage of the benefits of social bookmarking almost effortless.

Really?

Yep. The real beauty, though, lies in the RSS feeds created by del.icio.us. These feeds act like a personal doodlepad for power surfers, and with a little elbow grease, some organization, and some PHP, you can seamlessly integrate these links into your website—allowing you to manage and freshen your content from anywhere you might find a connection to the int'rweb.

So what are you on about here?

Well, I know this is not the newest idea, and many types of blogware include this sort of functionality, but I don't use Wordpress or Movable Type, so I had to figure it out on my own. I have decided to write down how I do it, putting the code in fancy colors so others who might be interested in a nifty source of content for their website might do the same.

Okay then, Giddyup.

Am I Ready?

To Begin!

This method has four distinct parts:

  1. A script that grabs remote RSS files from del.icio.us and caches them on the local web server
  2. A script to read these files and output them as proper HTML
  3. A method for easy and flexible inclusion into your existing pages
  4. A cron job to automate the RSS retrieval process.

I'm going to explain these steps individually, trying my best to keep them as coherent as possible.

First, In

1. As I mentioned, the first step in the process is setting up a script to retrieve your feeds over the web. There are practically thousands of ways to do this, but I am just gonna dump my version on you.

<?php


/* feed_puller.php(s) ************************ *** ** *

Simple RSS grabber, run with wget and a CRON job

CLI version : 
http://www.hinkybox.com/devpages/delish-ex3.phps

All code by JBE, 2004 hinkybox.com (GPL)
http://www.hinkybox.com  (sysadmin@hinkybox.com)

*/

// This is the name of the feed you
// want to capture and cache. In this
// example, it is called from a URL,
// like this:
//
// feed_puller.php?feed=http://otherserver.com/feed.rss
//

// make sure this script is only run locally, 
// or specify an IP that is trusted
//

if ($_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) {

// Lie to the scoundrels!
//

die("Illegal operation. This has been logged. "
    . $_SERVER['REMOTE_ADDR']);

}

$source = $_GET['feed'];

// path to cache directory
// make sure this directory is writeable
//

$path = "/path/to/feeds/cache";



// Your user name on the server. 
// This is used to automatically change the file 
// ownership of your cached feeds.
// You can probably leave this blank if you are 
// in a shared hosting environment, as your only 
// access will be within your user account.

$usr = "apache";

// Permissions.  I use 755, which works fine. 
// change this if you need to. 
//
$perm = 0755;


/* Establishes naming convention 
   for RSS cache file 
******************************************************/

// Choose a default file extension. 
// They are all XML after all, so this should do.
//
$ext = "xml";

// Feed prefix, can be anything 
//
$prefix = "feed_";

// rip out protocol prefix
//
$resource = str_replace("http://", "", $source);

// rip out forward slashes
//
$resource = strtolower(str_replace("/", "_", $resource));

// if the file is a directory, usually something mod_rewritten
// append an .xml for good recordkeeping
//
if(substr($resource, -4, 4) != ".".$ext ) {

$rssfile = $prefix.$resource.".xml";

} else {

$rssfile = $prefix.$resource;

}
// RFC 2822 Date format
//
$timestamp =  date("r");                        


// @ supresses PHP warnings, uses custom error messages.
// 
$feed_url = @file_get_contents($source);

/* file handling 
******************************************************/

// if the URL is accessible, open that puppy
if ($feed_url) {
  $feed = utf8_encode($feed_url); 
echo "Feed grab from ".$source." successful.\n\n";

} else {
// Output error, for debugging
 echo "Feed grab from ".$source." has failed.\n\n";    

 exit(0);

}

if (!file_exists($path.'/'.$rssfile)) {

    $rsswrite = fopen($path.'/'.$rssfile, "x+");
      fwrite($rsswrite, $feed);
  fclose($rsswrite);

// automagically change file permissions to $permissions
//
chmod($path.'/'.$rssfile, $perm);


// only change ownership if necessary
//
if(!empty($usr)) {

// assign ownership to apache
//
chown($path.'/'.$rssfile, $usr);
// assign group rights to apache
//
chgrp($path.'/'.$rssfile, $usr);

}

echo "New cache file is\n\n "
     .$path.'/'.$rssfile."\n\n"
     ."Created ".date('r')."\n\n";

} else {

    $rsswrite = fopen($path.'/'.$rssfile, "w+");
      fwrite($rsswrite, $feed);
  fclose($rsswrite);

echo "Putting newest version of feed:\n\n "
      .$path.'/'.$rssfile.".\n\n" 
      ."Created ".$timestamp."\n\n";
}



?>

This script is pretty much a skeletal implementation of PHP's filesystem manipulation capabilities. Here is a generalized idea of how the script works:

The script is called as if it was an HTML page, usually with a linux program called wget. By default, this script is prohibited from use by a user agent not located on the same server, but it is possible to specify a remote server IP that is allowed to process the feeds. I used this method for about a year, running a cron job from a protected server within my LAN. For safety's sake, you should not allow blanket access to this script, instead restricting it to a trusted server.

Using the URL passed as a $_GET['feed'] variable, it retrieves the file and writes it to the specified cache location. The RSS url is transmogrified with a little PHP string two-stepping; for example, a feed located at

http://www.foobar.baz/blog/foobar_rss.xml

would be cached as

feed_www.foobar.baz_blog_foobar_rss.xml

There is some text output associated with this file; its error states are useful for debugging. When using wget, a command-line switch redirects the standard hypertext output (what would normally show up in your browser window) to /dev/null—geekspeak for the void.

An alternative and much preffered method utilizes the PHP Command Line Interpreter, and bypasses the need for an http client such as wget altogether. Not a lot of folks are comfortable with the command line, and usually they don't have shell access in the traditional sense. I've provided a source file for this alternative script, and will explain the differences in greater detail in the section about cron jobs.

Note: Depending on your hosting setup, you might need to know your username and php include path for this to work correctly. The script is designed to automagically change file permissions, owner and group upon initial creation of the cached file. This can be bypassed and configured manually, but that is a headache in most cases.

Then, Out

2. The real workhorse of this method is the XML interpreter that reads, parses and formats the feeds for inclusion into your pages. Two such parsers, PEAR XML_RSS and MagpieRSS are ideal for this purpose; though in my experience, magpieRSS is a nice, lightweight way to get the results needed without a lot of fancy extras that only serve to slow script execution. XML_RSS is a great tool to have for more complex projects, but for now, I'll just assume we are working with Magpie.

Get MagpieRSS and install it a directory of your choosing–somewhere safe, but accessible by your scripts. There are multiple files in the package, but most of them are used as includes when needed by the main script, rss_parse.inc.php.

As soon as you have the parser where you want it, you can start sticking together the scripty bits. You'll need to have an RSS file handy for testing; if you don't already have a cached version of a del.icio.us feed, you can use this example page. Any well-formed RSS feed will do, but for the sake of continuity I supplied one from my del.icio.us account.

Now that the foundations are in place, you can begin to build the script to parse the XML in the feed. Here is a simple example script you can use as a framework or to get your paths and such in line:


<!-- 
We know this will be a definition list,
so we open the element here.
-->
<dl>
<?php


/* delish.php ************************ *** ** *

RSS parse-and-include script.
All code by JBE, 2004 hinkybox.com (GPL)
http://www.hinkybox.com  (sysadmin@hinkybox.com)

*/


// usually this is a server path,
// e.g., mine is /var/www/hb/public_html/feeds/scripts/
//
require_once('/path/to/rss_parse.inc.php');

// For now, the location of the test file. **
//
$rss_file = "/path/to/test/rss_file";

// PHP needs to "handle" the file and see what's in it
//
$rss_string = file_get_contents($rss_file);

// Magpie creates an XML Parser
//
$rss = new MagpieRSS( $rss_string );

// Proceed if the parser was created successfully 
// and there are no error states
//
if ( $rss and !$rss->ERROR) {

// The parser turns the feed into an array
//
$items = $rss->items;

// Loop through the array, pick out the 
// bits we want, and format them accordingly
//
foreach ($items as $item) {

// the link string from the feed
// that goes in the href=""
//
$href = $item['link'];

//  The title of the bookmark, used in the link
//
$title = $item['title'];

// the string representing the description 
// you've given the bookmark
//
$description = $item['description'];

// The markup we want for the links
// This can be as complex as you need, 
// but you should probably keep it flexible,
// so you can reuse it for multiple content sections    
//

echo '<dt><a href="'.$href.'">'.$title.'</a><dt>'."n".
     '<dd>'.$description.'</dd>'."n";    
    
// closes the foreach
//
}


// if there is any failure in the loop, exit 
// and issue an error message
//

    } else {

    echo $rss->ERROR;

    }

?>

<!-- 
"Close the definition list.
Aaaaaaaaaaaand SCENE!" 
-->
</dl> 

Now its time to test this script out and see if it works. The business end of the script is the HTML, and you can modify this to suit your needs; some people choose to use a list, like this:

<ul>
<li><a href="LINK">TITLE</a> – DESCRIPTION</li>
<li><a href="LINK">TITLE</a> – DESCRIPTION</li>
<li><a href="LINK">TITLE</a> – DESCRIPTION</li>
<li><a href="LINK">TITLE</a> – DESCRIPTION</li>
</ul>

which is perfectly fine. This is semantically correct, of course, but I choose to use a different markup method, the definition list, like so:

<dl>
<dt><a href="LINK">TITLE</a></dt>
<dd>DESCRIPTION</dd>
<dt><a href="LINK">TITLE</a></dt>
<dd>DESCRIPTION</dd>
<dt><a href="LINK">TITLE</a></dt>
<dd>DESCRIPTION</dd>
<dt><a href="LINK">TITLE</a></dt>
<dd>DESCRIPTION</dd>
</dl>

In practice, both are acceptable; it just comes down to a personal preference. Here is an example of this script in action – Both methods are shown. To see the innards of this example, check out the source.

If you have troubles with the PHP part of the script, check the paths to both rss_parse.inc.php and the test RSS file. If you have modified the markup, check to make sure all your quotes and parentheses are in the right places. If you get nothing at all when you run this script, chances are your host has error reporting turned off. Some web hosts restrict PHP's error reporting level to keep the size of log files in check, or to keep things tidy—to get around this, you can temporarily add

error_reporting(E_ALL);

at the very top of this script. This overrides that directive on a per-script basis, and is a great trick for debugging on stingy servers.

Now, Show Me

3.The basic usage of this script is fairly straightforward; it is deliberately vague in its variable definitions, which adds flexibility when it is called as an PHP include. For example, let's say you have a page that contains a sidebar, like hinkybox. Once you have an idea where you want these links to appear, you can just stick this code in the page:


<?php 

$rss_file = "/path/to/cached/file.rss"; 

include ("includes/delish.php"); 

?>

Take a look at the source of this page—the sidebar is contained in <div id="content2">. It is commented fairly well, and you will see where I've use this method.

Note: Make sure to remove the $rss_file variable I defined inside the script for testing purposes, otherwise you will get exactly the same links every time you use the script.

Nifty, right? Because PHP's variable scope is so flexible, you can use this bit of code as many times as you want; the $rss_file variable is simply overwritten each time you define it. There is another customization you can make that will limit the number of links displayed; I will get to that tweak in the next installment. I'll also explain how I use cron jobs to keep my feeds up to date, as well as a few customizations you can use to further personalize your content. ◊

Note on the code: I am a self-taught programmer; PHP is my favorite scripting environment, but I know better than anyone that I have some idiosyncrasies and some dark spots in my vocabulary that might make my code appear to the trained eye, well — shitty. I am not proud, and if you are reading this and see something amateurish or, god forbid, dangerous, please feel free to voice it or any other WTF?!? moments in the comment section.

Resources

Google's New Toy: Sitemaps

From Googleblog - 6/2/2005 05:29:00 PM
We're undertaking an experiment called Google Sitemaps that will either fail miserably, or succeed beyond our wildest dreams, in making the web better for webmasters and users alike. It's a beta "ecosystem" that may help webmasters with two current challenges: keeping Google informed about all of your new web pages or updates, and increasing the coverage of your web pages in the Google index.
...
Full article —>

Damned nifty; a bit like robots.txt on steroids. All submissions seem to be tracked based on a user account, in my case a gmail handle. I spent an hour or two working up an on-the-fly generator for the wB 1.0 cms, and will, if this rain persists, probably spend tomorrow working up a mod process for the 0.xb series.

Some links about Google Sitemaps:

I already have xmlrpc pings (technorati, ping-o-matic) integrated into HB, so I plan to throw that in as well. ◊

IE (Re)V(er)(i)sion(ist) Seven. Beta.

Yes, some people are fickle. But even more people are lazy.

Redmond, Wash., Feb. 15, 2005
We're very excited to announce at the RSA Conference today that this summer we'll release a beta of Internet Explorer 7.0 for Windows XP with Service Pack 2, which will have even more enhancements to security and privacy protections. These enhancements align very closely with the three core tenets of Microsoft's security approach that I mentioned earlier. Internet Explorer 7.0 will be the most secure browser we've ever released, building on and surpassing the success of the SP2-enhanced Internet Explorer 6.0. We don't plan to ship it until it meets our quality bar, which we've set pretty high. Full article —>

I know this is old news, but I have been thinking about the ramifications of this forthcoming release, especially as I read the mounds of negative feedback on the IEBlog. I am forced to ask myself a terrible question — Is the launch of IE 7 the beginning of the end for Firefox?

Yes, IE7 has tabs. Full article —>

I know I will probably continue to use Firefox, but I am not sure about people have recently switched. I have a distinct feeling that MS will come out with a "It's all clear, you can come back now!" campaign directed at the casual user, most likely accompanied by a smear campaign along the lines of the Alexis de Tocqueville Institution crock from back in 2002. I certainly know a couple of folks who will probably flee back to the comfort of the blue E as soon as it is released; in fact, I happen to have my suspicions about a couple of people who swear by Firefox now.

My question is: How many people do you know who will redefect? ◊

Regular Expressions Madness

This weekend I spent a few hours working on a php function (source) I plan to use (in posts like this one) that automagically turns a non-standard tag like

<css>
#accessform input {
display : inline;
font : normal .9em/1em Tahoma, Verdana, sans-serif;
margin : 2px 0 ;
border-top : 1px solid #A8A29C;
border-right : 1px solid #9F9F9F;
border-bottom : 1px solid #A8A29C;
border-left : 1px solid #9F9F9F;
background : #FFF url(input-unfocused.gif) 0 100% repeat-x;
}
</css>

into


#accessform input  {
display : inline;
font : normal .9em/1em Tahoma, Verdana, sans-serif;
margin : 2px 0 ;
border-top : 1px solid #A8A29C;
border-right : 1px solid #9F9F9F;
border-bottom : 1px solid #A8A29C;
border-left : 1px solid #9F9F9F;
background : #FFF url(input-unfocused.gif) 0 100% repeat-x;
}

The trick is regular expressions, but more specifically the PCRE version that PHP uses. A week or so back I got in over my head with regexp's and mod_rewrite, So I picked out a project that would challenge me into learning the basics of this very powerful pattern-matching syntax. I am still working out some of the kinks, but a final revision is forthcoming, and though I know there are other, probably much better versions of this script, I have adapted it specifically to wheatblog, and I plan to eventually write it up as a hack to extend the post interface.

I'm also thinking about some sort of autolinker for comments, though I already use PhotoMatt's Extended autop function, so I will have to make sure nothing implodes, as is often the case with regexp replaces. ◊

"Schadenfreude!" "Gesundheit."

Oh no, it can't be.

Yes, all is not well in MacSnootyville. It seems Apple has run afoul of some *nix heavyweights, and the drive to incorporate (pun intended) the best parts of open-source dev with the the best parts of making money hand over fist is finally showing some cracks. I bet Redmond is having a good snort over this.

One thing I have to give Apple credit for is Safari itself. I had a chance to use it over this weekend and I really took a shine to it, mostly because it didn't do anything drastic to my recent designs. It was pretty cool, for instance, that it managed to pass the Acid2 test , a feat Firefox is incapable of at present. Nifty would be the word for it, but in reality, the recent merger of Macradobomedee might signal a move away from standards as a whole. No wonder the flasheads everywhere were cheering. C'est la guerre. ◊

Postscript: That tiny mac keyboard still sucks.

CSS Craziness

This might be a little esoteric, but fsck it, its my website, I will say what I want. ;-)

If you happen to have the Web Developer Extension for Mozilla Firefox, and you also have a Gmail account, Try this.

Open your inbox, right-click, and select Web Developer > Information > Display ID & Class Details. Give it a second, it has a lot to chew on.

If you are like me, you will be amazed at what the developers over at Google have done with our beloved CSS. Pay particular attention to the ID's for most of the elements.

Stumbling across old development projects

RG-Gallery Generator, a.k.a. "Quickbuild"

I found this "thing" buried in my bookmarks -- I think started working on this sometime in early 2003, and after about a month of toil, I completely forgot about it. As you might see, I put most of my energy into designing the interface. . . it is quite complex, actually, I did manage to get most of the JS to behave -- alas, it is but another orphan of mine. Funny idea, though -- some day when I am bored (as hell) I might have to revive it.

Yeah, I am posting this because I am out of ideas, you got me.

Cheers,

The Management

Ahh, amen.

http://www.hinkybox.com/goindex.php?page=feeds/feed_gen_parsed.php

Finished up this little project last night. It is designed to increase decrease the load time of my index page by at least a second or so.


Update Monday, 6/20/2005

I have since moved all of my feed generator scripting and associated source files to either dev.hinkybox.com or integrated them into the newest version of Wheatblog.

Thanks for visiting. ◊

Rss syndication is a GO! (kinda)

Oh, dear lord.

I finally got my RSS feed working, for the most part. It took me better part of 6 hours to do it, but I suppose it is worth it - I am not naive enough to think that anyone will ever syndicsate my ramblings, but the XML output is quite useful for on-site things, like title-based lists and such.

It took 6 hours because the original code for this site, although it has now been hacked into something completely different, called for output in the RSS 0.91 specification, which is ancient. Well, I spiced it up a tad. Within that 6 hours of coding, I realized that I had a relatively serious issue with dating posts that carries over from a decision I made at the outset; I then did what any other novice might do -- I kludged the hell out of it. I also spent a good portion of that time (sort-of) solvign one of my pet-peeves -- rss feeds that are not customizable by number of items on the server end. I have yet ot pound out the code for the form to allow this customization, but as you can see, the count variable (currently in the URL) does the work.

Minus some semi-crucial formatting details, here it is.

update hinkybox.com RSS feed

Don't let's all rush to syndicate me, people. ;)


Update Monday, 6/20/2005

I have since moved all of my feed generator scripting and associated source files to either dev.hinkybox.com or integrated them into the newest version of Wheatblog Thanks for visiting.

For Bubs


You might consider outputting a little blurb at the top of the page like Comment Posted, Danke Schoen! so's we know that the call went through, so to speak. smartass

<!-- This little thing is an option, too, it scrolls to the bottom of the document onload. -->

<body onload="window.scrollTo(0, document.height ? document.height : document.body.scrollHeight)">

<!-- Works in IE and Firefox, as well as Gecko back to 4.0 -->



ex.scroller.php

RFC Repo Planning

Well, here is the concept I have so far. The formatting is vague, of course, but it is just a framework for content display and distributed linking. The sections outlined in GREEN will be accomplished on a local LAN interior server; that is, a computer stashed in a closet who's job it is to crunch the code that would probably lag the web server terribly, if I had the poor thing do it all in its head. Those outlined in RED will involve the final parsing of the data on the web server itself, which resides in the DMZ of the LAN. This should be low-impact enough to not spike load, but the heavier bits will be accomplished in the wee hours, so it should be good.



The Outline

  1. Backend raw data management
    • secured rysnc transfer from ietf.org
    • crontab sort
  2. Dynamic update of RFC master list (XML document) with CLI PHP
    • crontab staggered, FiFo
    • crontab sort
    • txt2xhtml CLI scripting
  3. Final background parse to chunked source files for fastest possible indexing
  4. Dynamic generation of SSI's, indexed in second-tier XML tree
  5. Integration into functional interface (multiple output formats (CSS1) for printer-friendliness)


Ideas for the actual frontend are too numerous and gloppy to elaborate on. One such experiment: clicking the link below will issue a random RFC in ASCII format. It will eventually be part of a form that allows a user to select threads (of interest to them) within the RFC history to track -- such as, say, XML, or IP routing, and have these topical datasheets posted (randomly) on the index page when they pop into hinkybox.

CLICK ME, I AM A POORLY WORDED LINK

Hinkybox as RFC Repo?

In the everlasting struggle for content, I might have hit upon something worthwhile. I am gonna mirror all of the IETF's RFC's. Mostly for my own benefit, but being as some nice person (read that poor bastard) has already built an XML tree, I might be able to do all sorts of nifty things with the content as it exists. Who knows?

dyn_info.php: Dynamic Image Placement for Counters, Etc.

This little script was an experimental foray into using images to replace available fonts; It is the long way 'round, but it looks pretty cool when you tweak it just so.

<?php
/*
Dynamic Date for hinkybox.com
written by Joshua Estell
hbadmin@gmail.com
*/
/* Variable Settings *******************/

$datestr = date("mdYw");
//$imgDayPrefix = "elements/gif/date/rg3_day_";
$imgPath= "/devpages/elem/alpha/";

$imgExt = ".gif";
//$banPrefix = "elements/gif/rg3_banner_";

/******************************/
// string output -->  01242004
// array construct
/*
$dateArray[0] = substr($datestr, 0,2);
$dateArray[1] = substr($datestr, 2,1);
$dateArray[2] = substr($datestr, 3,1);
$dateArray[3] = substr($datestr, 4,1);
$dateArray[4] = substr($datestr, 5,1);
$dateArray[5] = substr($datestr, 6,1);
$dateArray[6] = substr($datestr, 7,1);
$dateArray[7] = substr($datestr, 8,1);
"elements/gif/rg3_banner_";
/******************************/

function linuxUptime() {
  $ut = strtok( exec( "cat /proc/uptime" ), "." );
  $days = sprintf( "%02d", ($ut/(3600*24)) );
  $hours = sprintf( "%02d", ( ($ut % (3600*24)) / 3600) );
  $min = sprintf( "%02d", ($ut % (3600*24) % 3600)/60  );
  $sec = sprintf( "%02d", ($ut % (3600*24) % 3600)%60  );
  return array( $days, $hours, $min, $sec );

}
$ut = linuxUptime();
// If you would like to show the 
// seconds as well just add 
// [ , $ut[3] seconds ] after minutes.

//echo "$ut[0]$ut[1]$ut[2]$ut[3]"; 


$upTimeRaw = "$ut[0]$ut[1]$ut[2]$ut[3]";


// 04061249

$uTime[0] = substr($upTimeRaw, 0, 1);
$uTime[1] = substr($upTimeRaw, 1, 1);

$uTime[2] = substr($upTimeRaw, 2, 1);
$uTime[3] = substr($upTimeRaw, 3, 1);

$uTime[4] = substr($upTimeRaw, 4, 1);
$uTime[6] = substr($upTimeRaw, 5, 1);

$uTime[7] = substr($upTimeRaw, 6, 1);
$uTime[8] = substr($upTimeRaw, 7, 1);


//<!-- /* Server Load */ -->
$loadavg_array = explode(" ", exec("cat /proc/loadavg"));
$loadavg = $loadavg_array[2];

// print("Server load: " . $loadavg . "%");

// Linux server1.hinkybox.local 
// 2.4.22-1.2199.nptl #1 Wed Aug 
// 4 12:21:48 EDT 2004 i686 i686 i386 GNU/Linux

$uname_array = explode(" ", exec("uname -a"));

$platform = strtolower($uname_array[0]);
$hostname = strtolower($uname_array[1]);

$kernelver = strtolower($uname_array[2]);

//Display hostname 

 $nodeName = exec("uname -n"); 


$hostName[0] = substr($nodeName, 0, 1);
$hostName[1] = substr($nodeName, 1, 1);

$hostName[2] = substr($nodeName, 2, 1);
$hostName[3] = substr($nodeName, 3, 1);

$hostName[4] = substr($nodeName, 4, 1);
$hostName[5] = substr($nodeName, 5, 1);

$hostName[6] = substr($nodeName, 6, 1);
$hostName[7] = substr($nodeName, 7, 1);

$hostName[8] = substr($nodeName, 8, 1);
$hostName[9] = substr($nodeName, 9, 1);

$hostName[10] = substr($nodeName, 10, 1);
$hostName[11] = substr($nodeName, 11, 1);

$hostName[12] = substr($nodeName, 12, 1);
$hostName[13] = substr($nodeName, 13, 1);

$hostName[14] = substr($nodeName, 14, 1);
$hostName[15] = substr($nodeName, 15, 1);

$hostName[16] = substr($nodeName, 16, 1);
$hostName[17] = substr($nodeName, 17, 1);

$hostName[18] = substr($nodeName, 18, 1);
$hostName[19] = substr($nodeName, 19, 1);

$hostName[20] = substr($nodeName, 20, 1);
$hostName[21] = substr($nodeName, 21, 1);



// character translation

function getChar($char) {

global $imgPath;
global $imgExt;

switch($char) {

//--numbers------------------------------

  case "1";
     echo($imgPath."1".$imgExt);   break;
  case "2";
     echo($imgPath."2".$imgExt);   break;
  case "3";
     echo($imgPath."3".$imgExt);   break;
  case "4";
     echo($imgPath."4".$imgExt);   break;
  case "5";
     echo($imgPath."5".$imgExt);   break;
  case "6";
     echo($imgPath."6".$imgExt);   break;
  case "7";
     echo($imgPath."7".$imgExt);   break;
  case "8";
     echo($imgPath."8".$imgExt);   break;
  case "9";
     echo($imgPath."9".$imgExt);   break;
  case "0";
     echo($imgPath."0".$imgExt);   break;


//--letters------------------------------

  case "a";
     echo($imgPath."a".$imgExt);   break;
  case "b";
     echo($imgPath."b".$imgExt);   break;
  case "c";
     echo($imgPath."c".$imgExt);   break;
  case "d";
     echo($imgPath."d".$imgExt);   break;
  case "e";
     echo($imgPath."e".$imgExt);   break;
  case "f";
     echo($imgPath."f".$imgExt);   break;
  case "g";
     echo($imgPath."g".$imgExt);   break;
  case "h";
     echo($imgPath."h".$imgExt);   break;
  case "i";
     echo($imgPath."i".$imgExt);   break;
  case "j";
     echo($imgPath."j".$imgExt);   break;
  case "k";
     echo($imgPath."k".$imgExt);   break;
  case "l";
     echo($imgPath."l".$imgExt);   break;
  case "m";
     echo($imgPath."m".$imgExt);   break;
  case "n";
     echo($imgPath."n".$imgExt);   break;
  case "o";
     echo($imgPath."o".$imgExt);   break;
  case "p";
     echo($imgPath."p".$imgExt);   break;
  case "q";
     echo($imgPath."q".$imgExt);   break;
  case "r";
     echo($imgPath."r".$imgExt);   break;
  case "s";
     echo($imgPath."s".$imgExt);   break;
  case "t";
     echo($imgPath."t".$imgExt);   break;
  case "u";
     echo($imgPath."u".$imgExt);   break;
  case "v";
     echo($imgPath."v".$imgExt);   break;
  case "w";
     echo($imgPath."w".$imgExt);   break;
  case "x";
     echo($imgPath."x".$imgExt);   break;
  case "y";
     echo($imgPath."y".$imgExt);   break;
  case "z";
     echo($imgPath."z".$imgExt);   break;

//--chars----------------------------------
  case "+";
     echo($imgPath."+".$imgExt);   break;
  case "-";
     echo($imgPath."-".$imgExt);   break;
  case "!";
     echo($imgPath."!".$imgExt);   break;
  case "@";
     echo($imgPath."@".$imgExt);   break;
  case "#";
     echo($imgPath."#".$imgExt);   break;
  case "$";
     echo($imgPath."$".$imgExt);   break;
  case "%";
     echo($imgPath."percent".$imgExt);   break;
  case "^";
     echo($imgPath."^".$imgExt);   break;
  case "%";
     echo($imgPath."%".$imgExt);   break;
  case "^";
     echo($imgPath."^".$imgExt);   break;
  case "&";
     echo($imgPath."&".$imgExt);