I had the need today to be able to set the current time zone for an application in multiple computer languages by the hourly offset from GMT/UTC, which turned out to be a lot harder than I expected. It seems most time zone related functions, at least in Linux, expect you to use full location strings to set the current time zone offset (i.e. America/Chicago).
After a lot of research and experimenting, I came up with the following results. All of these are confirmed working in Linux, and most or all of them should work in Windows too.
Language
Format Note
Format for GMT+5
Format for GMT-5
C
Negate
GMT-5
GMT5
Perl
Negate
GMT-5
GMT5
SQL
Requires Sign
+5:00
-5:00
PHP
Negate, Requires Sign
Etc/GMT-5
Etc/GMT+5
And here are examples of using this in each language. The “TimeZone” string variable should be a 1-2 digit integer with an optional preceding negative sign:
One thing I always really miss when working in other dynamic languages that aren’t JavaScript is the ability to access known (non dynamic) members of an associative array/object/hash (called a hash from here on out) through just a single dot. This matches C’s syntax of accessing struct members, as opposed to being forced into using array syntax which is harder to read IMO in languages like PHP and Perl. For example...
Creating a hash in:
JavaScript:
var Hash={foo:1, bar:2};
Perl:
my %Hash=(foo=>1, bar=>2);
PHP:
$Hash=Array('foo'=>1, 'bar'=>2);
Accessing a Hash’s member:
JavaScript:
Hash.foo or Hash['foo']
Perl:
$Hash{foo};
PHP:
$Hash['foo']
The reason this is preferable to me is it can make code like the following
When a good idea is still considered too much by some
While UTF-8 has almost universally been accepted as the de-facto standard for Unicode character encoding in most non-Windows systems (mmmmmm Plan 9 ^_^), the BOM (Byte Order Marker) still has large adoption problems. While I have been allowing my text editors to add the UTF8 BOM to the beginning of all my text files for years, I have finally decided to rescind this practice for compatibility reasons.
While the UTF8 BOM is useful so that editors know for sure what the character encoding of a file is, and don’t have to guess, they are not really supported, for their reasons, in Unixland. Having to code solutions around this was becoming cumbersome. Programs like vi and pico/nano seem to ignore a file’s character encoding anyways and adopt the character encoding of the current terminal session.
The main culprit in which I was running into this problem a lot with is PHP. The funny thing about it too was that I had a solution for it working properly in Linux, but not Windows :-).
Web browsers do not expect to receive the BOM marker at the beginning of files, and if they encounter it, may have serious problems. For example, in a certain browser (*cough*IE*cough*) having a BOM on a file will cause the browser to not properly read the DOCTYPE, which can cause all sorts of nasty compatibility issues.
Something in my LAMP setup on my cPanel systems was removing the initial BOM at the beginning of outputted PHP contents, but through some preliminary research I could not find out why this was not occurring in Windows. However, both systems were receiving multiple BOMs at the beginning of the output due to PHP’s include/require functions not stripping the BOM from those included files. My solution to this was a simple overload of these include functions as follows (only required when called from any directly opened [non-included] PHP file):
<?
/*Safe include/require functions that make sure UTF8 BOM is not output
Use like: eval(safe_INCLUDETYPE($INCLUDE_FILE_NAME));
where INCLUDETYPE is one of the following: include, require, include_once, require_once
An eval statement is used to maintain current scope
*/
//The different include type functions
function safe_include($FileName) { return real_safe_include($FileName, 'include'); }
function safe_require($FileName) { return real_safe_include($FileName, 'require'); }
function safe_include_once($FileName) { return real_safe_include($FileName, 'include_once'); }
function safe_require_once($FileName) { return real_safe_include($FileName, 'require_once'); }
//Start the processing and return the eval statement
function real_safe_include($FileName, $IncludeType)
{
ob_start();
return "$IncludeType('".strtr($FileName, Array("\\"=>"\\\\", "'", "\\'"))."'); safe_output_handler();";
}
//Do the actual processing and return the include data
function safe_output_handler()
{
$Output=ob_get_clean();
while(substr($Output, 0, 3)=='?') //Remove all instances of UTF8 BOM at the beginning of the output
$Output=substr($Output, 3);
print $Output;
}
?>
I would have like to have used PHP’s output_handlerini setting to catch even the root file’s BOM and not require include function overloads, but, as php.net puts it “Only built-in functions can be used with this directive. For user defined functions, use ob_start().”.
As a bonus, the following bash command can be used to find all PHP files in the current directory tree with a UTF8 BOM:
The one time I decide to look online before trying it out myself
A client of mine wanted their website to have an applet that played streaming music from a SHOUTcast server. The easy solution would have been to just embed a Windows Media Player applet into the page, but that would only work for IE.
I thoroughly searched the web and was unable to find a Flash applet (or other solution) that already did this (and actually worked). Most of the information I was finding was people having problems getting this kind of thing working in Flash with no answer provided. After giving up on finding a resolution online, I decided to load up Flash and see what I could find from some tinkering.
Quite frankly, I’m shocked people were having so many problems with this. I started an ActionScript 2.0 project and put in the following code, and it worked right away in Flash CS3 (v9.0) with no problem:
var URL="http://example.shoutcast.castledragmire.com:1234/" //The URL to the SHOUTcast server
var MySound:Sound=new Sound(this);
MySound.loadSound(URL,true);
Unfortunately, once I exported the Flash applet and loaded it up in my browsers, it was no longer working. After a few minutes of poking around, I had a hunch that the SHOUTcast host might be sending different data depending on the [Browser’s] User Agent. I changed Firefox’s User Agent to “Flash” through a Firefox add-on (User Agent Switcher), and it worked :-D.
Once again, unfortunately, this was not a viable solution because I couldn’t have every user who visited the client’s web page change their browser User Agent string :-). The quickest solution at this point to the problem was to just create a passthrough script that grabbed the live stream on their server and passed it to the client. The following is the PHP script I used for this:
Setting the Flash Applet’s URL variable to the PHP file
Turning off PHP output buffering for the file. This can only be done through Apache or the php.ini depending on the server setup. This is very important, as if it’s on, the data will never get sent to the user.
The only problem with this method is that it taxes the server that is passing the data through, especially since it uses PHP... This kind of thing could very easily be done in C though (as a matter of fact, I will be writing a post on something very close to that very soon).
After discovering the Alamo Draft House’scoolness a few months ago, I’ve been trying to watch what they’re playing to make sure I catch anything I might want to see on the big screen. Unfortunately, it is not easy to get a good quick idea of all the movies playing from their calendar because it shows movies per day with showtimes, making the list repetitive and crowded with extra information.
I decided to throw together a real quick PHP script that would parse their data so I could organize it however I wanted. The final result can be viewed here. The code is as follows:
//The list of calendar pages in format TheaterName=>URL
$PagesToGrab=Array(
'Ritz'=>'http://www.originalalamo.com/Calendar.aspx?l=2',
'Village'=>'http://www.originalalamo.com/Calendar.aspx?l=3',
'South Lamar'=>'http://www.originalalamo.com/Calendar.aspx?l=4'
);
foreach($PagesToGrab as $Name => $URL) //Grab the movies for each theater
{
print "<b>$Name</b><br>"; //Output the theater name
$TheHTML=file_get_contents($URL); //Grab the HTML
$ShowList=Array(); //This will contain the final list of shows and what days they are on
preg_match_all('/<td class="day">.*?<\/td>/', $TheHTML, $DayMatches); //Extract all table cells containing a day's info
foreach($DayMatches[0] as $DayInfo) //Loop over each day's info
{
//Determine the day of month
preg_match('/<a class=\"daynumber\" title=".*?, (.*?),/', $DayInfo, $DayOfMonth);
$DayOfMonth=$DayOfMonth[1];
//Determine all the shows for the day
preg_match_all('/<span class="show"><a href=".*?">(.*?)<\/a>/', $DayInfo, $AllShows);
foreach($AllShows[1] as $Show)
{
$Show=preg_replace('/^\s+|\s+$/', '', $Show); //Remove start and end of line whitespace
if(!isset($ShowList[$Show])) //If show has not yet been added to overall list, add it
$ShowList[$Show]=Array();
$ShowList[$Show][]=$DayOfMonth; //Add this day as a time for the show
}
}
//Output the shows and their days
print '<table>';
foreach($ShowList as $ShowName => $Days)
print "<tr><td>$ShowName</td><td>".implode(', ', $Days).'</td></tr>';
print '</table><br><br>';
}
<? PageFooter(); ?>
</body></html>
In PHP, you cannot include files in parent directories “../” from a file that has already been included from another file in a different directory. This has been a nuisance for a long time.
Here is a test case: (Files followed by their code)
/test1.php (This is the file that is called directly by the browser/apache)
<?
//This all works fine
print 'test1'_start;
require('foo/bar/test2.php');
print 'test1_end';
?>
/foo/bar/test2.php
<?
print 'test2_start';
require('blah/test3.php'); //This works fine because the include file it is in a subdirectory, not a parent directory of test2.php
require('../test4.php'); //This does not call fine (an error is thrown by php) because it is in a parent directory relative to test2.php, which was already included from the parent file (test1.php) in another directory (/). To fix this, use 'foo/test4.php'
print 'test2_end';
?>
/foo/bar/blah/test3.php
<? print 'test3'; ?>
/foo/test4.php (This file is not reached by this example without the fixes mentioned in either the comment in test2.php, or below)
<? print 'test4'; ?>
The obvious method to fix this whole conundrum is to always set all includes relative to one root path, and then make sure that path is always used with the set_include_path function if your parent file is not in the root directory. For example:
Another method would be to write a require/include wrapper that calculates paths from the current directory whenever a parent path “../” is used. Here is an example of this:
function _require($IncludeFile, $CurrentFile)
{
$CurrentPath=preg_replace('/[^\/]+$/', '', $CurrentFile); //Remove the filename to get the current path
require(realpath("$CurrentPath$IncludeFile"));
}
This method is called with 2 parameters: the relative path from the current include file to the file you want to include, and __FILE__
For example, line 4 of “/foo/bar/test2.php” above would now be:
_require('../test4.php', __FILE__);
The first line of the _require function could also be removed by using the __DIR__ constant (instead of __FILE__) which was added in PHP 5.3.0.
We recently moved one of our important web server clients to a newly acquired server (our 12th server at ThePlanetThePlanet [Used to be called EV1Servers, and before that RackShack], one of, if not the largest, server-farm hosting company in the states). A bad problem cropped up on his site in the form of a PHP script (CaRP) that deals with parsing XML.
The problem was that whenever the XML was parsed and then returned, all XML entities (escaped XML characters like “>” “<” and “"”) were removed/deleted. I figured the problem had to do with a bad library, as the code worked perfectly on our old server, and the PHP settings on both were almost identical, but I wasn’t sure which one. After an hour or two of manipulating the code and debugging, I narrowed it down to which XML function calls had the problem, and that it was definitely not the scripts themselves. The following code demonstrates the problem.
On the server with the problem, the following was outputted:
img test=a
while it should have outputted the following:
<img test="a"
I went with a hunch at this point and figured that it might be the system’s LibXML libraries, so I repointed them away from version 2.7.1, which appears to be buggy, to an older version that was also on the system, 2.6.32. And low and behold, things were working again, yay :-D.
Technical data (This is a cPanel install): In “/opt/xml2/lib/” delete the symbolic links “libxml2.so” & “libxml2.so.2” and redirect them as symbolic links to “libxml2.so.2.6.32” instead of “libxml2.so.2.7.1”.
I am often asked to transfer data sets into MySQL databases, or other formats. In this case, I’ll use a Microsoft Excel file without line breaks in the fields to MySQL as an example. While there are many programs out there to do this kind of thing, this method doesn’t take too long and is a good example use of regular expressions.
First, select all the data in Excel (ctrl+a) and copy (ctrl+c) it to a text editor with regular expression support. I recommend EditPad Pro as a very versatile and powerful text editor.
Next, we need to turn each row into the format “('FIELD1','FIELD2','FIELD3',...),”. Four regular expressions are needed to format the data:
Search
Replace
Explanation
'
\\'
Escape single quotes
\t
','
Separate fields and quote as strings
^
('
Start of row
$
'),
End of row
From there, there are only 2 more steps to complete the query.
Add the start of the query: “INSERT INTO TABLENAME VALUES”
End the query by changing the last row's comma “,” at the very end of the line to a semi-colon “;”.
For example:
a b c
d e f
g h i
would be converted to
INSERT INTO MyTable VALUES
('a','b','c'),
('d','e','f'),
('h','h','i');
Sometimes queries may get too long and you will need to separate them by performing the “2 more steps to complete the query” from above.
After doing one of these conversions recently, I was also asked to make the data searchable, so I made a very simple PHP script for this.
This script lets you search through all the fields and lists all matches. The fields are listed on the 2nd line in an array as "SQL_FieldName"=>"Viewable Name". If the “Viewable Name” contains a pound sign “#” it is matched exactly, otherwise, only part of the search string needs to be found.
<?
$Fields=Array('ClientNumber'=>'Client #', 'FirstName'=>'First Name', 'LastName'=>'Last Name', ...); //Field list
print '<form method=post action=index.php><table>'; //Form action needs to point to the current file
foreach($Fields as $Name => $Value) //Output search text boxes
print "<tr><td>$Value</td><td><input name=\"$Name\" style='width:200px;' value=\"".
(isset($_POST[$Name]) ? htmlentities($_POST[$Name], ENT_QUOTES) : '').'"></td></tr>';//Text boxes w/ POSTed values,if set
print '</table><input type=submit value=Search></form>';
if(!isset($_POST[key($Fields)])) //If search data has not been POSTed, stop here
return;
$SearchArray=Array('1=1'); //Search parameters are stored here. 1=1 is passed in case no POSTed search parameter are ...
//... requested so there is at least 1 WHERE parameter, and is optimized out with the MySQL preprocessor anyways.
foreach($Fields as $Name => $Value) //Check each POSTed search parameter
if(trim($_POST[$Name])!='') //If the POSTed search parameter is empty, do not use it as a search parameter
{
$V=mysql_escape_string($_POST[$Name]); //Prepare for SQL insertion
$SearchArray[]=$Name.(strpos($Value, '#')===FALSE ? " LIKE '%$V%'" : "='$V'"); //Pound sign in the Viewable Name=exact ...
//... value, otherwise, just a partial patch
}
//Get data from MySQL
mysql_connect('SQL_HOST', 'SQL_USERNAME', 'SQL_PASSWORD');
mysql_select_db('SQL_DATABASE');
$q=mysql_query('SELECT * FROM TABLENAME WHERE '.implode(' AND ', $SearchArray));
//Output retrieved data
$i=0;
while($d=mysql_fetch_assoc($q)) //Iterate through found rows
{
if(!($i++)) //If this is the first row found, output header
{
print '<table border=1 cellpadding=0 cellspacing=0><tr><td>Num</td>'; //Start table and output first column header (row #)
foreach($Fields as $Name => $Value) //Output the rest of the column headers (Viewable Names)
print "<td>$Value</td>";
print '</tr>'; //Finish header row
}
print '<tr bgcolor='.($i&1 ? 'white' : 'gray')."><td>$i</td>"; //Start the data field's row. Row's colors are alternating white and gray.
foreach($Fields as $Name => $Value) //Output row data
print '<td>'.$d[$Name].'</td>';
print '</tr>'; //End data row
}
print ($i==0 ? 'No records found.' : '</table>'); //If no records are found, output an error message, otherwise, end the data table
?>
A friend just asked me to write a PHP function to list all the contents of a directory and its sub-directories.
Nothing special here... just a simple example piece of code and boredom...
It wouldn’t be a bad idea to turn off PHP’s “output buffering” and on “implicit flush” when running something like this for larger directories. Example output for “ListContents('c:\\temp');”:
A.BMP [230]
Dir1 [D]
codeblocks-1.0rc2_mingw.exe [13,597,181]
Dir1a [D]
DEBUGUI.C [25,546]
Dir2 [D]
Dir3 [D]
HW.C [12,009]
INIFILE.C [9,436]
NTDETECT.COM [47,564]
I decided to make it a little nicer afterwards by bolding the directories, adding their total size, and changing sizes to a human readable format. This function is a lot more memory intensive because it holds data in strings instead of immediately outputting.
function HumanReadableSize($Size)
{
$MetricSizes=Array('Bytes', 'KB', 'MB', 'GB', 'TB');
for($SizeOn=0;$Size>=1024 && $SizeOn<count($MetricSizes)-1;$SizeOn++) //Loops until Size is < a binary thousand (1,024) or we have run out of listed Metric Sizes
$Size/=1024;
return preg_replace('/\\.?0+$/', '', number_format($Size, 2, '.', ',')).' '.$MetricSizes[$SizeOn]; //Forces to a maximum of 2 decimal places, adds comma at thousands place, appends metric size
}
function ListContents2($DirName, &$RetSize)
{
$Output='<ul>';
$dir=opendir($DirName);
$TotalSize=0;
while($file=readdir($dir))
if($file!='.' && $file!='..')
{
$FilePath="$DirName/$file";
if(is_dir($FilePath)) //Is directory
{
$DirContents=ListContents2($FilePath, $DirSize);
$Output.="<li><b>$file</b> [".HumanReadableSize($DirSize)."]$DirContents</li>";
$TotalSize+=$DirSize;
}
else //Is file
{
$FileSize=filesize($FilePath);
$Output.="<li>$file [".HumanReadableSize($FileSize).']</li>';
$TotalSize+=$FileSize;
}
}
closedir($dir);
$RetSize=$TotalSize;
$Output.='</ul>';
return $Output;
}
Example output for “print ListContents2('c:\\temp', $Dummy);”:
A.BMP [230 Bytes]
Dir1 [12.99 MB]
codeblocks-1.0rc2_mingw.exe [12.97 MB]
Dir1a [24.95 KB]
DEBUGUI.C [24.95 KB]
Dir2 [0 Bytes]
Dir3 [20.94 KB]
HW.C [11.73 KB]
INIFILE.C [9.21 KB]
NTDETECT.COM [46.45 KB]
The memory problem can be rectified through a little extra IO by calculating the size of a directory before its contents is listed, thereby not needing to keep everything in a string.
Of course, after all this, my friend took the original advice I gave him before writing any of this code, which was that using bash commands might get him to his original goal much easier.