main page content
Snippets
Code Counter
Code line counting tool for website files.
» download CodeCounter 1.0 (Windows and Linux; 63kB ZIP)
Count code and comment lines in the following website-related files: .html, .htm, .css, .php, .inc, .js, .sql
This command line program recursively searches sub-directories.
DISCLAIMER: This software is supplied as is. It simply opens, reads, and closes the file types listed above. Nevertheless, the author accepts no liability for damages, direct or consequential, which may result from the use of this software.
Lottery Demo
A simple demonstration of how unlikely it might be to win the jackpot of the UK National Lottery.
» download
Lottie 1.1 (Win 98/2k/XP/Vista/7; 60kB ZIP)
» download
Lottie 1.1 (Linux; 89kB ZIP)
Generates more than a million 'draws' per second on most PCs over 2GHz.
Developed in FreeBASIC utilising a C library (thanks to Simon Nash for the fast integer sort function).
Uses the Mersenne Twister algorithm to generate less predictable pseudo-random numbers.
Type 'Q' to exit the program at the start or the end of a lottery draw cycle, and use the close icon (Windows: also Alt-F4) to exit during the cycle.
DISCLAIMER: This software is supplied as is. The author accepts no liability for damages, direct or consequential, which may result from the use of this software.
'Daily Backup' Batch Script
A backup script for Windows PCs with the 7-Zip open source application installed.
Losing just 25% of a hard drive's contents in 2002 impressed upon me the need for consistent backup methods. PowerArchiver possesses a nice utility to create a password-protected .zip archive of the day's created/changed files. However, PowerArchiver is commercial software and I have only a single licence.
The replacement solution for me was to use the command line options of the open source 7-Zip application, and create superior .7z files. The Windows batch script below copies all files residing in two directories that have changed on the current day, compresses them into a single password-protected .7z file, copies this file to an external drive, and deletes all the temporary files.
This of course is not a complete backup solution — merely an assistive one e.g. run just before the end of a day's work. Important files should also be regularly saved to CDs, secure webspace etc. — never depend on one method.
REM from copysense.co.uk/snippets.php
SET dates="db_%date:~6,6%-%date:~3,2%-%date:~0,2%"
SET dates2=%date:~3,2%-%date:~0,2%-%date:~6,6%
SET dates3=db_%date:~6,6%-%date:~3,2%-%date:~0,2%
IF EXIST "c:\t-backup\%dates%" (RD /s /q "c:\t-backup\%dates%")
XCOPY "c:\temp" "c:\t-backup\%dates%" /s /i /D:%dates2%
XCOPY "c:\documents and settings\joe.bloggs\my documents\reference" "c:\t-backup\%dates%" /s /i /D:%dates2%
CD c:\program files\7-Zip
7z a %dates%.7z -t7z -mx=7 -ms=off -pPa55Word "C:\t-backup\%dates%\*"
MOVE %dates3%.7z \\ServerName\users\joe.bloggs\dbs
RD c:\t-backup\%dates3% /s /q
- Download and install 7-Zip from 7-Zip.org.
- Copy the batch script above into a text editor.
- Change the password (Pa55Word) to something more secure (line 9).
- If you have not installed 7-Zip into its default installation directory (c:\program files\7-Zip) on your PC, change this path (line 8).
- Create a temporary directory on your hard drive for copied files: c:\t-backup\
- Change the path(s) of the directories that require backing up (at present, the script copies all files changed in two locations: c:\temp and c:\documents and settings\joe.bloggs\my documents\reference).
- Change the backup location directory path (\\ServerName\users\joe.bloggs\dbs) — ideally this should be an external drive/network location (line 10). If the external drive is mapped, the path may be as simple as e.g. H:\backup.
- Save the file in your text editor as 'dailybackup.bat'. Move this file to your chosen directory location, then add it to Windows Scheduled Tasks (in Control Panel) and set the time you wish the script to run (e.g. 17:25 every day).
- Thoroughly test your batch file (for testing, you need at least one file that has been created/changed today in the scanned directories; double click on the batch file in Windows Explorer to execute it) to make sure it runs without errors (test in command prompt window) and a .7z file appears in your backup location.
- When finalised, @echo off added at the start of the script will suppress the output of the command line window at run time (if you find the output distracting).
- Large files placed in the scanned directories may result in a large .7z file in the backup location — some file types such as PNGs hardly compress at all.
- If you are running Win 2000, XP Pro, or higher Vista versions, encrypt the .bat file (right click > Properties > Advanced > Encrypt Contents... > OK) to make it more difficult for snoopers to view the password of your .7z backup files.
- On Windows Vista this script will need to be run as administrator, else access will not be permitted to the 7-Zip directory within Program Files. (Vista without SP1 seems to have a bug in Scheduled Tasks which causes a basic task to fail on the second instance. This bug has been fixed in SP1.)
(The script searches for UK format file stamps. If US file stamps (mm/dd/yyyy) are required, you will need to change the date format in lines 2, 3, and 4 of the script.)
Twitter RSS PHP Class
A PHP class to read, cache, and display Twitter RSS feeds.
Class TwitterFeed {
/**
* @name TwitterFeed
* @description Twitter Feed RSS Displayer
* @author Martin Latter
* @url copysense.co.uk
* @created 02/08/2011
* @license Creative Commons: Attribution-ShareAlike
* @version release 1.00
* @return string HTML/text
* @example:
*
* first create 'tweets' directory (with suitable permissions) in the directory where this class is placed
*
* create TwitterFeed:
* $o = new TwitterFeed(n);
* (n = number of tweets to display (int))
*
* output TwitterFeed:
* $o->outputTweets(enclosing tag, title enclosing tag, timestamp enclosing tag);
* (all strings; HTML tags used can have attributes)
*/
#########################################################################################
## configuration
#########################################################################################
private $sAccountID = '236378761'; # Twitter account number
private $sCacheDirectory = 'tweets';
private $sCacheFile = 'twitter_rss.xml';
private $sPrefix = 'Tweeter X: '; # Twitter name - removed if $bPrefixRemove=TRUE
private $bPrefixRemove = TRUE;
private $bUseCURL = FALSE; # use cURL library to grab feed
private $sFeedError = '<p>Twitter feed not available.</p>';
private $iCacheTime = 3600; # cache expiry, seconds
private $bDebug = FALSE; # toggle cache messages
#########################################################################################
private $sTwitterURL;
private $sCacheTime;
private $iMaxTweets;
private $oXML;
private $aTweets = array();
private $aOutputTweets = array();
public function __construct($iMaxTweets = 0) {
$this->sTwitterURL = 'http://twitter.com/statuses/user_timeline/' . $this->sAccountID . '.rss';
$this->sCacheFile = $this->sCacheDirectory . '/' . $this->sCacheFile;
$this->iMaxTweets = $iMaxTweets;
$this->initFeed();
$this->createTweets();
}
private function initFeed() {
$iTimeDiff = @(time() - filemtime($this->sCacheFile));
if (file_exists($this->sCacheFile) && $iTimeDiff < $this->iCacheTime) {
$sFileContents = file_get_contents($this->sCacheFile);
if ($this->bDebug) {
echo 'cache file exists, parsing file<br>';
}
}
else {
if ($this->bDebug) {
echo 'cache file expired - acquiring RSS feed<br>';
}
if (!$this->bUseCURL) {
$sFileContents = file_get_contents($this->sTwitterURL);
}
else {
# if Twitter is picky about lack of user agent, the following can be enabled with $bUseCURL flag
$rCh = curl_init($this->sTwitterURL);
curl_setopt($rCh, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($rCh, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
$sFileContents = curl_exec($rCh);
curl_close($rCh);
}
if (!$sFileContents) { # boolean on error
echo $this->sFeedError;
}
else {
file_put_contents($this->sCacheFile, $sFileContents);
}
}
$this->oXml = simplexml_load_string($sFileContents);
} # end initFeed()
private function createTweets() {
$iCounter = 0;
foreach ($this->oXml->channel->item as $oItem) { # create array of objects from XML
$oTemp = new stdClass;
$oTemp->title = $oItem->title;
$oTemp->date = $oItem->pubDate;
$this->aTweets[] = $oTemp;
$iCounter++;
}
if ($this->iMaxTweets > $iCounter) {
$this->iMaxTweets = $iCounter; # catch too many Tweets requested vs actual
}
$iCounter = 0; # reset
# only process the tweets that are actually output
# LIFO list
while ($iCounter < $this->iMaxTweets) {
$sTitleTemp = $this->aTweets[$iCounter]->title;
if ($this->bPrefixRemove) {
$sTitleTemp = str_replace($this->sPrefix, '', $sTitleTemp);
}
if (stripos($sTitleTemp, '#') || stripos($sTitleTemp, '@') || stripos($sTitleTemp, 'http:')) {
$sTitleTemp = $this->linkifyTweet($sTitleTemp);
}
$oTemp = new stdClass;
$oTemp->title = $sTitleTemp;
$oTemp->date = @date('F j, Y - g:ia', strtotime($this->aTweets[$iCounter]->date));
$this->aOutputTweets[] = $oTemp;
$iCounter++;
}
} # end createTweets()
private function linkifyTweet($sText) {
$sText = ' ' . $sText;
$sText = preg_replace('/(^|\s)@(\w+)/', '\1@<a href="http://www.twitter.com/\2">\2</a>', $sText);
$sText = preg_replace('/(^|\s)#(\w+)/', '\1#<a href="http://search.twitter.com/search?q=%23\2">\2</a>', $sText);
$sText = preg_replace("#(^|[\n ])([\w]+?://[\w]+[^ \"\n\r\t<]*)#ise", "'\\1<a href=\"\\2\" >\\2</a>'", $sText);
$sText = preg_replace("#(^|[\n ])((www|ftp)\.[^ \"\t\n\r<]*)#ise", "'\\1<a href=\"http://\\2\" >\\2</a>'", $sText);
$sText = preg_replace("#(^|[\n ])([a-z0-9&\-_\.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i", "\\1<a href=\"mailto:\\2@\\3\">\\2@\\3</a>", $sText);
$sText = mb_convert_encoding($sText, 'ISO-8859-1', 'UTF-8'); # for converting UTF-8 into ISO-8859-1
return trim($sText);
} # end linkifyTweet()
private function createEndTag($sTag) {
# create end tags from start tags, despite any attributes
if (stripos($sTag, ' ')) { # space should mean an attribute is present
$sTag = substr($sTag, 0, stripos($sTag, ' '));
$sTag .= '>';
}
return str_ireplace('<', '</', $sTag);
} # end createEndTag()
public function outputTweets($sContTag = '', $sTitleContTag = '', $sTimeContTag = '') {
$aOut = array();
$sContTagEnd = self::createEndTag($sContTag);
$sTitleContTagEnd = self::createEndTag($sTitleContTag);
$sTimeContTagEnd = self::createEndTag($sTimeContTag);
foreach ($this->aOutputTweets as $oTweet) {
$aOut[] = $sContTag;
$aOut[] = $sTitleContTag . $oTweet->title . $sTitleContTagEnd . ' ';
$aOut[] = $sTimeContTag . $oTweet->date . $sTimeContTagEnd;
$aOut[] = $sContTagEnd;
}
echo join("\n", $aOut);
} # end outputTweets()
public function __destruct() {
unset(
$this->aTweets,
$this->aOutputTweets
);
}
}
?>
<ul>
<?php
$oTweets = new TwitterFeed(3);
$oTweets->outputTweets('<li>', '<span>', '<span class="time">');
?>
</ul>
