Thursday, March 31, 2005

Yahoo! Creative Commons Search

Came across this on Lawrence Lessig's blog. Intriguing idea.

Tuesday, March 29, 2005

PHP: fw_substage()

A function that makes a stage in my form wizard optional. A bit convoluted. But after hours of mental anguish that pushed my mind to the very brink, I got it to operate:

/* fw_substage
ARGS: stage_name (name of optional stage)
skip_flag (post value from previous stage that dictates
whether to skip stage)
Call before fw_constructor
RETURN: global array SUB_MEMO to which fw_backend reacts
******************************/
// ARGS: $stage_name, $skip_flag = Y/N, T/F
function fw_substage($stage_name, $skip_flag) {

// global variables
global $SUB_MEMO, $STAGES;

// check $STAGES array
if ( !is_array($STAGES) ) {
trigger_error("STAGES not array", E_USER_ERROR);
}

// naturalize POST
$skip = $_POST[$skip_flag];

// conform skip_flag
if ( strtolower($skip) == 'y' ) { $skip = TRUE; };
if ( strtolower($skip) == 'n' ) { $skip = FALSE; };

// id previous stage and next stage
reset($STAGES);
while ( current($STAGES) != $stage_name ) {
if ( !next($STAGES) ) {
trigger_error(__FUNCTION__."stage name '$stage_name' not
matched
", E_USER_ERROR);
}
}
$next_stage = next($STAGES);

// determine whether to skip this stage
/* going forward */
if ( $skip === TRUE ) { /* skip flag set, SUB_MEMO to
fw_backend: skip the next stage */

$_SESSION['skip_stage'][$stage_name] = TRUE;
$SUB_MEMO = array('action' => 'redirect', 'target' => 'self',
'stage' => 1);
return $SUB_MEMO;

} elseif ( $skip === FALSE ) { /* if isset and !TRUE */

$_SESSION['skip_stage'][$stage_name] = FALSE; /* SESSION
skip_stage {$name} to FALSE */
return $SUB_MEMO;

}

/* going backward (from subsequent stage) */
if ( $_SESSION['form_wizard']['prev_stage'] == $next_stage &&
$_SESSION['skip_stage'][$stage_name] ) {

$_SESSION['form_wizard']['prev_stage'] = 'null';
$SUB_MEMO = array('action' => 'redirect', 'target' => 'self',
'stage' => -1);
return $SUB_MEMO;
}

return $SUB_MEMO;

} /* end Fx */

Monday, March 28, 2005

PHP: mysql_select_array

A function that accepts an array listing columns in a MySQL database table along with a reference and value and extracts

Engineered specifically for use with a user table that will list only those properties of the user that I specify in the passed array.

Passes array by reference (as opposed to value) so that the passed array (providing the category names for the various user properties) can be synchronized with array of values selected from the database.

/* Fx mysql_select_array
author: tatwell AT gmail DOT com
$ARRAY is a list of columns specifying which info to pull from database
Passed by reference so that the headers may be synchronized with the
values pulled form DB
1 result, returns 1 row; More than 1 result, returns an array of rows
(as arrays)
******************************/
function mysql_select_array(&$ARRAY, $ref_column, $value, $table='default',
$db_name='default', $limit_one=TRUE) {

// check database
if ( $db_name == 'default' ) {
if ( defined('DB_NAME') ) {
$db_name = DB_NAME;
} else {
trigger_error("db_name not defined for __FUNCTION__", E_USER_WARNING);
return FALSE;
}
}

// check table
if ( $table == 'default' ) {
if ( defined('TABLE') ) {
$table = TABLE;
} else {
trigger_error("table not defined for __FUNCTION__", E_USER_ERROR);
return FALSE;
}
}


// initialize values for building select phrase from array
$select_phrase = ''; /* initialize string */
$drop_offset = 0; /* index marker for tracking array */

// build select phrase and unset any array values which do not match
up with a TABLE COLUMN
foreach ( $ARRAY as $listed_col ) {
if ( mysql_fetch_row(mysql_query("SHOW COLUMNS FROM `$table`
LIKE '$listed_col'")) ) {
$select_phrase .= "`$listed_col`, "; /* array value match TABLE COLUMN */
} else {
unset($ARRAY[$drop_offset]); /* array value does not match TABLE COLUMN */
}
$drop_offset++;
} /* end column check */

// clean up query phrase
$select_phrase = trim(substr($select_phrase, 0,
strrpos($select_phrase, ',')));

// if no columns matched, warn and return
if ( !strlen($select_phrase) ) {
$report = "0 columns not found in table '$table'";
trigger_error($report, E_USER_WARNING);
return FALSE;
}

// build query
$select_query = "SELECT $select_phrase FROM `$table`
WHERE `$ref_column` = '$value'";

if ($limit_one) {
$select_query .= 'LIMIT 1';
}

// open db
open_db($db_name);

// execute query
$result = mysql_query($select_query)
or mysql_trigger_error($select_query);

// fetch result
if ( mysql_num_rows($result) > 0 && $limit_one ) {
$output = mysql_fetch_row($result);
}
elseif ( mysql_num_rows($result) > 0 ) {
$i = 0; /* array index */
while ($row = mysql_fetch_row($result)) {
$rows[$i] = $row;
$i++;
}
$output = $rows;
} else { /* no results */
$report = "0 rows found in table '$table'";
trigger_error($report, E_USER_NOTICE);
mysql_free_result($result);
return $report;
}

// return results
mysql_free_result($result);
return $output;

} /* end Fx */
/*****************************/

Sunday, March 27, 2005

Office Theme

Watching The Office marathon this weekend. Much more funny and irreverent than the new American one.

I think the credits say the theme song -- "Handbags and Gladrags" -- is performed by Fin. (Fin?) No mention of the fact on the complete history page. Sounds like Rod Stewart.

Cygwin

To wit:
  • Cygwin is a Linux-like environment for Windows. It consists of two parts: A DLL (cygwin1.dll) which acts as a Linux API emulation layer providing substantial Linux API functionality.

  • A collection of tools, which provide Linux look and feel.

Don't have time to play with this presently, but should give it a shot when I have a chance.

Saturday, March 26, 2005

Friendster Blog

This is truly becoming a tangled web of deception.

Finally succeeded in setting up a blog on Friendster. Now appears I have two? This one crashed during the set up process, but appears to still have been created, though I have no means to update or change it:

Stillborn Friendster Blog

This is the one I can update:

Active Friendster Blog

Don't have any real plans to use it.

The interface is pretty slick, but they put some pretty strict limits on what you can do with your blog. At least the free one. And why the hell would anyone pay to publish their blog?

Friday, March 25, 2005

Firefox Webdev Toolbar

Just discovered this. Pretty nifty.

Font Browser-Share

When it comes to font browser-share, courier is king.

Thursday, March 24, 2005

PHP cwd_to_url()

A revision to the code earlier posted -- added strtolower filtering. As a function:

/* fx cwd_to_url
converts current directory to URL path
author: tatwell_AT_gmail_DOT_com
******************************/

$slash = '/';

// standardize paths
$self = $_SERVER['PHP_SELF'];
$self = strtolower(str_replace('\\', $slash, $self));
$phys_path = getcwd();
$phys_path = strtolower(str_replace('\\', $slash, $phys_path));

// convert path strings to arrays
$file_path_array = explode ($slash, $self);
$cwd_path_array = explode ($slash, $phys_path);

// intersect arrays to get path trail
$self_dir_path_array = array_values (array_intersect ($file_path_array,
$cwd_path_array));
$self_dir_path = implode("/", $self_dir_path_array)."/";

// append path trail to url root
$url_path = 'http://' . $_SERVER['HTTP_HOST'] . '/' . $self_dir_path;

// return
return $url_path;

} // end fx
/******************************/

PHP Exploits

Security: the first obsession of the paranoiac. Unfortunately, it appears warranted in this case.

Security Corner: Shared Hosting

Not even going to try to make sense of this right now. But I imagine I will before too long -- especially as I'm not that vigilant about protecting passwords and don't put session data in the database. (How the hell would I do that anyway?)

Wednesday, March 23, 2005

PHP: clock_code()

My take on the PHP script timer. First time I've found an ideal use for the STATIC variable type:

/* clock_code()
author: Tom Atwell (tatwell at jee mail dot com)
description: a neatly packaged script-timing function
reference: http://www.php.net/manual/en/function.microtime.php (Notes)
credit: edwardzyang at thewritingpot dot com, 14-Mar-2005 09:31
/************************************************************/
function clock_code($leader='clock_code()', $echo=TRUE, $unit='ms')
{

// personal version check -- disables in live server environment
if ( defined('VERSION') && (VERSION == 'live') ) {
return;
}

// current time
$cc_now = microtime(TRUE); /* float, in _seconds_ */

// declare static vars
static $CC_SPLIT, $CC_CALLS;

// define original start time
if ( !defined('CC_START') ) {
define('CC_START', $cc_now );
}

// declare internal variables
$cc_last = $CC_SPLIT; /* to calculate split time between calls */
$CC_CALLS++; /* increment counter */

// declare output variables
$output = '';
$div = '<div style="border:thin solid lime; margin:4px;">';
$p_calls = ' [clock_code() Call #' . $CC_CALLS . '] : ';


// vary according to unit selected
if ($unit === 's') {
$cc_now = $cc_now + time();
$malt = 1;
$round = 7;
} elseif ($unit === 'ms') {
$malt = 1000;
$round = 3;
} else {
trigger_error('Unsupported $unit value');
}


/* Stop the chronometer : return the amount of time since it was started,
in ms with a precision of 3 decimal places, and reset the start time.
We could factor the multiplication by 1000 (which converts seconds
into milliseconds) to save memory, but considering that floats can
reach e+308 but only carry 14 decimals, this is certainly more precise */

$cc_elapsed = round($cc_now * $malt - CC_START * $malt, $round);
$CC_SPLIT = $cc_elapsed;
$cc_stage = $CC_SPLIT - $cc_last;
$p_split = ' [SPLIT: ' . $cc_stage . ' ' . $unit . '] ';

// build output string
$output = $div . $leader . $p_calls . $cc_elapsed . ' ' . $unit;
$output .= '$p_split . '</div>';

// output
if ( ($CC_CALLS > 1) && $echo ) {
echo $output;
return;
} else {
return $output;
}

} /* end Fx clock_code */
/*******************************/


How to use:

<?php

clock_code();

// Do stuff;

clock_code('Do Stuff'); /* will return the time taken to "Do stuff" */

// Do more stuff

clock_code('Do More Stuff'); /* returns time taken to "Do more stuff" */

?>


How it looks:

Do Stuff [clock_code() Call #2] : 4.869 ms [SPLIT: 4.869 ms]
Do More Stuff [clock_code() Call #3] : 47.446 ms [SPLIT: 42.577 ms]


(Maybe I should rename this blog "A Flimsy PHPretext")

Complete Works Now in RSS

More on Feedburner and Friendster

Ok, got it fixed -- wrong URL. Should have used this one:

http://feeds.feedburner.com/AFlimsyPretext

I entered my RSS link in my profile, but I still don't see my entries. Why?

Answer

In order to keep your RSS entries from delaying your page from loading, there is a time-out built into the loading of your RSS feed. If the time-out expires before loading the feed, the page will finish loading without the feed info. If you reload the page it may show up then, or you might have to wait until your RSS feed provider is serving data faster.


Smooth. But then how do I know if it's actually working?

Friendster Feed

Another proof of concept -- trying to get this to feed my friendster account. Not sure if I have the right RSS URL. This is the one I'm using:

http://feeds.feedburner.com/~u/tatwell

But there's also this:

http://feeds.feedburner.com/AFlimsyPretext

Now which one is the RSS feed?

Feedburner RSS Podcast Page

Not that anyone's really paying attention. Just a proof of concept.

Style Div: Old Monitor Screen

.code {
border: 1px solid lime;
background:#666;
padding:1em;
font:.9em monospace;
color:lime;
font-weight: bold;
white-space: pre;
}

Sample

Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat.

Tuesday, March 22, 2005

Google Print

Even if this doesn't really have much practical value for me any longer, it's still super sweet.

demo: The Merchant of Venice

Monday, March 21, 2005

Unit Testing

Came across this here. Sounds like what I need. Now I'll just figure out how to implement it. Looks like it require OOP.

Wednesday, March 16, 2005

PHP: Converting Filepath to URL Path for Current Directory

Finally sat down and put this together. Based on this:

junk at plaino dot com

The idea is that it will export seamlessly. But I haven't thoroughly checked the logic or tested it yet.

// URL path for current directory
$slash = '/';
$url_root = "http://".$_SERVER['HTTP_HOST'];
$self = $_SERVER['PHP_SELF'];
$self = str_replace('\\', $slash, $self);
$phys_path = getcwd();
$phys_path = str_replace('\\', $slash, $phys_path);

$file_path_array = explode ($slash, $self);
$file_name = array_pop($file_path_array);
$cwd_path_array = explode ($slash, $phys_path);
$self_dir_path_array = array_values (array_intersect ($file_path_array, $cwd_path_array));
$self_dir_path = implode("/", $self_dir_path_array)."/";

$cwd_url = $url_root . '/' . $self_dir_path;

Tuesday, March 15, 2005

Searching MySQL

Will need to do this shortly. Some references:

MySQL Documentation

Google Groups Thread

Sitepoint Forum

Saturday, March 12, 2005

Dilemmas of the Obsessive Accumulative

I'm looking again at this little Starbucks BLACK APRON Exclusives brochure thing I picked up last time I was at Starbucks. It's been sitting on my desk for a month. I've done nothing with it, but it's so elegantly designed I'm reluctant to throw it away. I suppose I could scan it, but it's two-sided and I really don't want to go to all that trouble. I need to get rid of it, dammit.

Found an image online here: Be A Design Group

Not the whole brochure, but gives you the idea. It's gone.

(I will become/I will become/silhouettes when/I get rid of all this crap/on my desk.)

Friday, March 11, 2005

Googlejacking

Just saw this note here:

WebmasterWorld: Site Risks and Hijackers (PHPDeveloper.org)

which references a forum here:

Google News (webmasterworld.com)

I get the gist but still can't grasp the cataclysmic implications being bruited in the forum.

Here's a more general-audience-friendly attempt to describe the problem:

tracker2.php Pagejacking via HTTP 302 Redirect Google Bug (tonyspencer.com)

Tax Cut Questions

How much have the cut enacted by the Bush Administration cost thus far (as opposed to future projections)?

* Through fiscal year 2005, the Bush tax cuts enacted since 2001 have cost $819 billion. Before they expire, they will cost another $1 trillion, for a total cost of $1.9 trillion.

* Because these tax cuts have not been paid for, their cost represents a permanent increase in the debt. The associated interest payments will continue even after the time when the enacted tax cuts are scheduled to expire. That is why the graph on the previous page shows a cost associated with the enacted tax cuts of more than $100 billion a year even after they have expired in 2010. In total, the interest costs associated with the enacted tax cuts will be $1.1 trillion through 2015.

* The combined cost of the tax cuts enacted since 2001 and the cost of extending the tax cuts would be $5.1 trillion through 2015, when interest costs are included. Of that total, $4.2 trillion would occur in the period between 2006 and 2015

Source: Center on Budget and Policy Priorities

Other Sources:

Brookings Institute: Tax Cuts and Budget Policy

The Cost of Tax Cuts (Brookings Institute)

Bush Administration Tax Policy: Short-Term Stimulus
(Brookings Institute)

Especially relevant in the context of this:

Congested highways, overflowing sewers and corroding bridges are constant reminders of the looming crisis that jeopardizes our nation's prosperity and our quality of life. With new grades for the first time since 2001, our nation's infrastructure has shown little to no improvement since receiving a collective D+ in 2001, with some areas sliding toward failing grades. The American Society of Civil Engineers' 2005 Report Card for America's Infrastructure assessed the same 12 infrastructure categories as in 2001, and added three new categories. Access the complete Report Card with details on each infrastructure category and state infrastructure information.

Total Investment Needs = $1.6 Trillion
(estimated 5-year need--does not include security investment needs)

Source: ACSE Report Card for America's Infrastructure

Wednesday, March 09, 2005

PHP: Add access protocol to domain name

Trying to find a script that does this. Not to difficult, I suppose, to roll my own, but I'd guess that it's common enough that I can cherry-pick one. Some references:

URL (answers.com)
preg_replace (php.net)
eregi_replace (php.net)
koders code (Google cache)

The result:

/* Fx add_http (1.1)
******************************/
function add_http($url) {

/* Get rid of any extra white space */
$url = trim($url);

/* Get rid of any preceding whitespace (fix for odd browsers like konqueror) */
$url = eregi_replace("^[[:space:]]+", "", $url);

/* If the URI doesn't start with a scheme, prepend 'http://' */
if (!empty($url)) {
if (!ereg("^(http)", $url)) {
$url = "http://$url";
}
}

return $url;

} /* end Fx */
/******************************/

Sunday, March 06, 2005

Fx add_link

/* Fx ADD_LINK
Add a link
******************************/
function add_link($text, $link="#", $new_page=FALSE) {

// _blank target?
$target = "";
if ( $new_page ) {
$target = " target=\"_blank\"";
}

$link = "<a href=\"$link\"$target>$text</a>";

echo $link;

return OK;

} /* end Fx */
/******************************/

Friday, March 04, 2005

Phorm

A fully loaded PHP-based html form processor. A little overloaded for my needs. But nice to know that there's a free, super-duper wheel already invented by somebody out there.

Thursday, March 03, 2005

Printing Browser Window (Javascript)

<a href="javascript:window.print();">Print This Page</a>

answers.com

Just read a short Washington Post review of this site and decided to check it out. Really like it. Clean, attractive layout and neat, efficient presentation of info. Answered my inquiry about ODBC rather tidily.

Web Marketers Fearful of Fraud in Pay-Per-Click (NY Times)

Second article I've seen on this topic in recent weeks. From the articles, I get the impression that it's a manageable technical problem. But the fact that the article is in the New York Times suggests a growing image problem.

Tuesday, March 01, 2005

class or id?

I've known this for some time but still use id for styling where I should use classes. Don't think it makes a huge difference but I should probably break the habit.

Just the Article I Was Looking For

In the process of learning all this by fire.