Tuesday, April 26, 2005
Interesting concept, though I'm still waiting for my results... waiting... waiting...
Monday, April 25, 2005
NPR Online
What a lovely website. Perfect background noise -- or intelligent informative news broadcasting -- while working at my computer. And just discovered this:
NPR Most Emailed Stories
Very sweet with Firefox. I just find the stories that interest me, open them in a new tab, and then listen to them in turn.
NPR Most Emailed Stories
Very sweet with Firefox. I just find the stories that interest me, open them in a new tab, and then listen to them in turn.
Markdown
I've often wondered why something like this wasn't more readily available on the web. Guess I wasn't looking for it in the right place.
Found it here on a very neatly designed site.
Found it here on a very neatly designed site.
Sunday, April 24, 2005
Last Known Google Result
Been helping out with this project lately. Not quite sure what it means, but it's been a worthwhile sort of proof of concept.
Thursday, April 14, 2005
Feeling Slightly Paranoid
Which inspired to look into scripts that limit login attempts:
Google Search
Forum Thread
See also this:
OWASP
Google Search
Forum Thread
See also this:
OWASP
Tuesday, April 12, 2005
Query to get a key value from one table that will serve as the search index in another table:
$foreign_key_query = "select `$join_key_col` FROM $key_table WHERE `$search_col` = '$search_value'";
open_db($db);
$foreign_key_result = mysql_query($foreign_key_query) or mysql_trigger_error('foreign_key_query error');
$foreign_key = mysql_result($foreign_key_result, 0, 0);
mysql_free_result($foreign_key_result);
open_db($db);
$foreign_key_result = mysql_query($foreign_key_query) or mysql_trigger_error('foreign_key_query error');
$foreign_key = mysql_result($foreign_key_result, 0, 0);
mysql_free_result($foreign_key_result);
Monday, April 11, 2005
The Postmodernism Generator
As a Lit Ph.D manqué, I find this really interesting. A subject near and queer to my heart:
http://www.elsewhere.org/cgi-bin/postmodern/
Interesting in that it's entirely automated using "recursive
transition network" code (that you can download here):
http://dev.null.org/dadaengine/
I think this was created before the internet really got going. With
the web and the ability to grab web pages, I imagine one could do some
even more interesting things with this. (With a few tweaks, maybe
even generate his entire Ph.D thesis.)
http://www.elsewhere.org/cgi-bin/postmodern/
Interesting in that it's entirely automated using "recursive
transition network" code (that you can download here):
http://dev.null.org/dadaengine/
I think this was created before the internet really got going. With
the web and the ability to grab web pages, I imagine one could do some
even more interesting things with this. (With a few tweaks, maybe
even generate his entire Ph.D thesis.)
Sunday, April 10, 2005
PHP Graveyard: fw_substage($stage_name, $skip_flag)
Figured out a much more sensible way to implement optional stages in a form wizard.
/* fw_substage
ARGS: stage_name (name of optional stage)
skip_flag (post value from previous stage that dictates whether to skip stage
RETURN: global array SUB_MEMO to which fw_backend reacts
add this to main root wizard page before fw_constructor
******************************/
function fw_substage($stage_name, $skip_flag) {
// global variables
global $SUB_MEMO, $STAGES;
// verify $STAGES array
if ( !is_array($STAGES) ) {
trigger_error("STAGES not array", E_USER_ERROR);
}
// if $stage_name not current stage, go no further
if ( $stage_name != $_SESSION['form_wizard']['current_stage'] ) {
return;
}
// naturalize POST
$skip = $_POST[$skip_flag];
// process skip_flag
if ( strtolower($skip) == 'y' ) { $skip = TRUE; }
if ( strtolower($skip) == 'n' ) { $skip = FALSE; }
// id 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 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 */
/******************************/
ARGS: stage_name (name of optional stage)
skip_flag (post value from previous stage that dictates whether to skip stage
RETURN: global array SUB_MEMO to which fw_backend reacts
add this to main root wizard page before fw_constructor
******************************/
function fw_substage($stage_name, $skip_flag) {
// global variables
global $SUB_MEMO, $STAGES;
// verify $STAGES array
if ( !is_array($STAGES) ) {
trigger_error("STAGES not array", E_USER_ERROR);
}
// if $stage_name not current stage, go no further
if ( $stage_name != $_SESSION['form_wizard']['current_stage'] ) {
return;
}
// naturalize POST
$skip = $_POST[$skip_flag];
// process skip_flag
if ( strtolower($skip) == 'y' ) { $skip = TRUE; }
if ( strtolower($skip) == 'n' ) { $skip = FALSE; }
// id 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 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 */
/******************************/
Saturday, April 09, 2005
The Junkyard of Abandoned Php Code
If such a thing existed, this would end up there:
Also this:
// id 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 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;
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 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;
Also this:
// SUB_MEMO (from Fx fw_substage() for optional wizard stages)
if ( $SUB_MEMO['action'] == 'redirect' ) {
if ( $SUB_MEMO['target'] == 'self' ) {
$_SESSION['form_wizard']['prev_stage'] = $STAGES[$stage_count]; /* update prev stage name */
$_SESSION['form_wizard']['counter'] = $_SESSION['form_wizard']['counter'] + $SUB_MEMO['stage']; /* update counter */
header("Location:{$_SERVER['PHP_SELF']}"); /* redirect */
} else { /* should never fire -- should always target self */
trigger_error('Backend firing non-self target from SUB_MEMO', E_USER_NOTICE);
$_SESSION['form_wizard']['prev_stage'] = $STAGES[$stage_count];
header("Location:{$SUB_MEMO['target']}");
}
}
if ( $SUB_MEMO['action'] == 'redirect' ) {
if ( $SUB_MEMO['target'] == 'self' ) {
$_SESSION['form_wizard']['prev_stage'] = $STAGES[$stage_count]; /* update prev stage name */
$_SESSION['form_wizard']['counter'] = $_SESSION['form_wizard']['counter'] + $SUB_MEMO['stage']; /* update counter */
header("Location:{$_SERVER['PHP_SELF']}"); /* redirect */
} else { /* should never fire -- should always target self */
trigger_error('Backend firing non-self target from SUB_MEMO', E_USER_NOTICE);
$_SESSION['form_wizard']['prev_stage'] = $STAGES[$stage_count];
header("Location:{$SUB_MEMO['target']}");
}
}
Thursday, April 07, 2005
PHP: get_user_time_js()
Finally put together a function that uses javascript to grab the time offset from a user's browser and feed that back to the php script. Still need to add some conditional handling for browsers with javascript turned off.
/* Fx get_user_time_js()
author:tatwell AT gmail DOT com
******************************/
function get_user_time_js($add_clear_button=FALSE) {
// handle reset button
if ( isset($_POST['reset_tz']) ) {
$_SESSION['got_tz'] = '';
$_SESSION['user_tz'] = '';
}
// avoid infinite loops
if ( empty($_SESSION['got_tz']) ) {
$_SESSION['got_tz'] = FALSE;
}
// JAVASCRIPT PART
// if tz already determined, don't post
if ( isset($_POST['tz']) ) {
$hr_offset = $_POST['tz'] / 60; /* convert from minutes to hours */
$user_tz = $hr_offset;
$_SESSION['user_tz_offset'] = $user_tz;
$_SESSION['got_tz'] = TRUE;
}
// if session value already set, get that
elseif ( $_SESSION['got_tz'] == TRUE ) {
$user_tz = $_SESSION['user_tz'];
}
// else post and submit javascript
else {
// get timezoneoffset value (JS)
// put tz value in hidden field
// auto-self-submit hidden field
$js_script = <<<JSH
<SCRIPT LANGUAGE="Javascript">
<!--
user_date = new Date();
user_offset = user_date.getTimezoneOffset();
form_str="<form name='tz_form' action='{$_SERVER['PHP_SELF']}' method='post'>";
input_str = "<input type='hidden' name='tz' id='tz' value='" + user_offset + "'></form>";
document.write(form_str);
document.write(input_str);
document.tz_form.submit();
//-->
</SCRIPT>
JSH;
// be sure to echo it to the browser
echo $js_script;
} /* end JS part */
// add clear button?
if ( $add_clear_button ) {
$clear_button = <<<CBHERE
<!-- clear button -->
<form action="{$_SERVER['PHP_SELF']}" method="post" name="reset">
<input type="submit" name="reset_tz" value="resubmit your timezone offset" />
</form>
CBHERE;
echo $clear_button;
}
$user_time = mktime(gmdate("G, i, s, n, d, Y")) - $_SESSION['user_tz_offset'];
return $user_time;
} /* end Fx */
/******************************/
author:tatwell AT gmail DOT com
******************************/
function get_user_time_js($add_clear_button=FALSE) {
// handle reset button
if ( isset($_POST['reset_tz']) ) {
$_SESSION['got_tz'] = '';
$_SESSION['user_tz'] = '';
}
// avoid infinite loops
if ( empty($_SESSION['got_tz']) ) {
$_SESSION['got_tz'] = FALSE;
}
// JAVASCRIPT PART
// if tz already determined, don't post
if ( isset($_POST['tz']) ) {
$hr_offset = $_POST['tz'] / 60; /* convert from minutes to hours */
$user_tz = $hr_offset;
$_SESSION['user_tz_offset'] = $user_tz;
$_SESSION['got_tz'] = TRUE;
}
// if session value already set, get that
elseif ( $_SESSION['got_tz'] == TRUE ) {
$user_tz = $_SESSION['user_tz'];
}
// else post and submit javascript
else {
// get timezoneoffset value (JS)
// put tz value in hidden field
// auto-self-submit hidden field
$js_script = <<<JSH
<SCRIPT LANGUAGE="Javascript">
<!--
user_date = new Date();
user_offset = user_date.getTimezoneOffset();
form_str="<form name='tz_form' action='{$_SERVER['PHP_SELF']}' method='post'>";
input_str = "<input type='hidden' name='tz' id='tz' value='" + user_offset + "'></form>";
document.write(form_str);
document.write(input_str);
document.tz_form.submit();
//-->
</SCRIPT>
JSH;
// be sure to echo it to the browser
echo $js_script;
} /* end JS part */
// add clear button?
if ( $add_clear_button ) {
$clear_button = <<<CBHERE
<!-- clear button -->
<form action="{$_SERVER['PHP_SELF']}" method="post" name="reset">
<input type="submit" name="reset_tz" value="resubmit your timezone offset" />
</form>
CBHERE;
echo $clear_button;
}
$user_time = mktime(gmdate("G, i, s, n, d, Y")) - $_SESSION['user_tz_offset'];
return $user_time;
} /* end Fx */
/******************************/
Monday, April 04, 2005
Word to HTML/XML
Surprised there isn't some kind of web-based utility for converting Word documents to XML or HTML. When I have time, I really have to figure out how to do this. It looks eminently doable with open source stuff, but appears to involve rebuilding or recompiling the server, an operation further complicated by the fact that my servers are on Windows machines. Anyway, some key resources:
"From Word to XML" (xml.com)
wvWare
antiword
cygwin
"From Word to XML" (xml.com)
wvWare
antiword
cygwin
The Gmail G-Drive
Gmail's first birthday, and the fact that the storage limit was doubling to 2GB, got a lot of coverage last week. The Gmail home page included a nifty little running tally timed to count up through the day from 1000MB to 2000MB.
What is really interesting -- and what I haven't seen reported yet -- is that the counter didn't stop. It's still running -- though not as fast -- and is now at 2057.810643 and counting...
Put this ever growing storage capacity together with scripts like these, and you get something really novel -- a paradigm shift. It's no longer simply another free email account. What you have is a de facto virtual hard drive. All the pieces of the Google puzzle are falling into place and this is perhaps the biggest yet. A desktop on the internet. A serious model of the slim client approach to personal computing is finally beginning to be realized.
What is really interesting -- and what I haven't seen reported yet -- is that the counter didn't stop. It's still running -- though not as fast -- and is now at 2057.810643 and counting...
Put this ever growing storage capacity together with scripts like these, and you get something really novel -- a paradigm shift. It's no longer simply another free email account. What you have is a de facto virtual hard drive. All the pieces of the Google puzzle are falling into place and this is perhaps the biggest yet. A desktop on the internet. A serious model of the slim client approach to personal computing is finally beginning to be realized.
Friday, April 01, 2005
PHP IDE
This is getting out of hand with the PHP stuff -- should really create a dull-as-dishwater PHP blog and put all this there. But I'm a little too busy right now for that. And PHP, alas, is more or less my life at the moment.
Anyway, I've been looking for a decent free PHP IDE for a while. PHP Coder looks pretty good. And it's free. I'll stick with HTML-Kit for the time being, but keep this around for more serious problems.
Anyway, I've been looking for a decent free PHP IDE for a while. PHP Coder looks pretty good. And it's free. I'll stick with HTML-Kit for the time being, but keep this around for more serious problems.