PHP: Get Human Readable Time from Seconds

by Yang Yang on September 29, 2010

Linux timestamp is a number of seconds from the Epoch of Linux, large number of seconds. When you are counting the time interval between 2 times or 2 dates, the result is usually in seconds as well. Understandably, it’s everything but user friendly to just present the number of seconds to the users, e.g. 153297 s since last visit.

To display the time interval in a human readable format instead of in seconds, you can use the following function:

function getHumanTime($s) {
	$m = $s / 60;
	$h = $s / 3600;
	$d = $s / 86400;
	if ($m > 1) {
		if ($h > 1) {
			if ($d > 1) {
				return (int)$d.' d';
			} else {
				return (int)$h.' h';
			}
		} else {
			return (int)$m.' m';
		}
	} else {
		return (int)$s.' s';
	}
}

This is what I used for Usable Databases to display length of time since the user’s last visit to a certain page. d indicates day, h hour, m minute and s seconds. This function requires a number of seconds as input and convert it into human readable time periods such as x hours or x days.

{ Comments on this entry are closed }

Regular Expression for Date and Time Strings

by Yang Yang on September 29, 2010

Often we need the users to enter a valid string of date or time in the form. But how do you validate the strings with regular expressions? In PHP, you can use these functions and regular expressions.

RegExp and function to validate against date string:

// Default: YYYY-MM-DD
function isDate($subject, $separator = '-') {
	return preg_match('@^\d{4}'.$separator.'(0[1-9]|1[0-2])'.$separator.'(0[1-9]|1[0-9]|2[0-9]|3[0-1])$@', $subject);
}

RegExp and function to validate against time string:

// Default: HH:MM:SS
function isTime($subject, $separator = ':') {
	return preg_match('@^(0[1-9]|1[0-9]|2[0-4])'.$separator.'(0[1-9]|[1-5][0-9])'.$separator.'(0[1-9]|[1-5][0-9])$@', $subject);
}

If you need to validate against a different format, just change the $separator.

Now that you have the functions to validate date and time, you can combine them to verify date time strings such as 2016-04-30 18:19:05:

function isDateTime($subject) {
	$subject_array = explode(' ', $subject);
	if (count($subject_array) == 2) {
		return isDate($subject_array[0]) && :isTime($subject_array[1]) || $subject == '0000-00-00 00:00:00';
	}
	return false;
}

At Form Kid, these are functions I use for fields that need validation of the date and time.

{ Comments on this entry are closed }

When I’m developing the online form creator that enables the users to create form fields that accept only certain type of numbers, I need to verify if a given string is a valid natural number such as 1, 2, 3, 4, …. I’m writing the code / functions in PHP but you can literally use the regular expression in other programming languages as well. I use the following function to distinguish strings if they are natural numbers or positive integers.

function isNaturalNumber($subject) {
	return preg_match('|^[1-9][0-9]*$|', $subject);
}

You can add for a leading plus sign as well:

^+?[1-9][0-9]*$

Regular Expression for Negative Integers?

Negative integers are –1, –2, –3, …. Just add a minus sign before the regular expression for positive integers:

^-[1-9][0-9]*$

Regular Expression for Non-negative Integers?

That is, 0, 1, 2, 3, 4, …. By a little help of the isNaturalNumber function, you can use this function to check if a string is a legal non-negative integer:

function isNonNegativeInteger($subject) {
	// @^(0|[1-9][0-9]*)$@
	if ($subject == '0' || isNaturalNumber($subject)) {
		return true;
	}
}

Or if you insist on using a regular expression:

function isNonNegativeInteger($subject) {
	return preg_match('@^(0|[1-9][0-9]*)$@', $subject);
}

PHP functions to check if a string is a valid integer?

Just use the above functions in combination or the native is_integer() function of PHP.

function isInteger() {
	return isNegativeInteger($subject) || isNonNegativeInteger($subject);
}

{ Comments on this entry are closed }

The strange thing is that the native empty() function of PHP treats a string of ‘0’ as empty:

$str = '0';
echo empty($str) ? 'empty' : 'non-empty';

And it will output ’empty’. Therefore if you need to examine if a string is truly an empty string with zero length, you have to use:

echo strlen($str) == 0 ? 'empty' : 'non-empty';

Or you can use this function:

function isNonEmpty($subject) {
	return !empty($subject) || is_numeric($subject);
}

Which checks if the input string $subject is a numeric value (which makes it non-empty) or if it’s non-empty with empty() function when it’s not a numeric value.

{ Comments on this entry are closed }

Auto-generated content by user searches

by Yang Yang on September 29, 2010

A not-so-commonly employed content strategy is to automatically generate custom content by user searches. For example, if you’ve got a popular blog, there will be a lot of users searching for things they want to find on your blog. It’s an obvious sign that they want you to write about them. While you are recommended to keep an eye on what they are searching so as to provide content accordingly, you can also make the blog automatically generate search results pages by the searching terms.

I tried to find some WordPress plugins that do this for us but was unable to find any. Basically, the plugin would record all unique user search phrases and present them on a page as a list for the search engines to index the results pages with the custom page titles.

You should use the search term prominently in the page title and in the h1 tag. After the search engine has indexed the search results pages, you will have a lot of custom content pages AND best of all, they are exactly what users and potential visitors want to read. I have seen pretty exciting increase in searching traffic for my quotes site after I have implemented the strategy. The quotes search automatically generates a lot of custom pages by the searching phrase. What the user is searching is usually stuff that’s hard to come by in other sites or search engines so Google is pretty hungry in indexing these pages.

{ Comments on this entry are closed }

I created a free online web form builder a while back and since it went well in search engine rankings, spammers and phishers found it and started to use it creating forms to collect email account usernames and passwords through phishing attempts. I’ve got to do something before my host closes down my site because of all the complaints and alerts from security department of the universities. They’ve got good reasons. I’m hosting all the phishing forms.

Phishers tend to use URL slugs that include words such as ‘admin’, ‘webmail’ or ‘account’ so that the form seems authoritative at first glance. After they have signed up, they will create forms with fields labeled ‘Password’ or something. So what I’m going to do is to list all such words as reserved words and prohibit the users from doing anything with them.

A function will be needed to examine a subject string against an array of reserved words that will be censored when users use them as input. Listed is a my function:

public static function isStringLegal($subjectString = '', $disallowedWords = array()) {
	$alphabetSubject = preg_replace('|[^a-zA-Z]+|', '', $subjectString);
	foreach ($disallowedWords as $disallowedWord) {
		if (stripos($alphabetSubject, $disallowedWord) !== false) {
			return false;
		}
	}
	return true;
}

The PHP function stripos() returns a numeric value if it finds $disallowedWord in $alphabetSubject, case-insensitive. If it fails to find anything, it returns false.

A sample disallowed words list:

$slugDisallowedWords = array(
	'formkid', 
	'kavoir', 
	'mail', 
	'admin',
	'account',
	'password'
);

The disallowed words list can only contain alphabet letters. If you need a phrase such as ‘no way’, you have to add it in the array as ‘noway’. This is to prevent illegal attempts to add any word or phrase in manners such as ‘a-d-m-i-n’ or ‘Pa_ss Word’. All the non-alphabet letters / characters are first gotten rid of and then the deprived string which contains only alphabet letters are checked against each word in the disallowed words list.

{ Comments on this entry are closed }

Best renewal promo code for non .com domains at GoDaddy

by Yang Yang on September 26, 2010

Had a bunch of .info, .net and .org to be renewed yesterday and after searching for quite a while, I was unable to find any promo source code deals better than this one:

gdbb776

It places a 17% discount ($6.99 .info, $7.49 .org and .net) off your cart for domain renewals. I had 17 domains to be renewed yesterday and it saved me about $25. Just thought I’d share with you in case you are going to renew some names.

Good GoDaddy promo codes that are nicely discounted are harder and harder to come by these days, especially for renewals.

{ Comments on this entry are closed }

The easy way to add a username and password pair in the .htpasswd file is to use an online password generator tool that converts the clear text password into its hash, a.k.a. the encrypted password. The problem with this approach is that you have to manually create the pair and append it to .htpasswd. Is there a way to dynamically generate encrypted passwords for .htpasswd in PHP?

According to http://httpd.apache.org/docs/2.2/misc/password_encryptions.html, we have come up with the following solution:

$pass = 'YourClearTextPasswordString';
$hash = base64_encode(sha1($pass, true));
$encoded = '{SHA}'.$hash;
echo $encoded;

And $encoded is the result we need, which would look something like:

{SHA}hNz9UE9WLiMlzYI+LRtwr0U+DHY=

Suppose the username is ‘manager’ and you can add the following line at the end of your .htpasswd file to make the credentials in effect:

manager:{SHA}hNz9UE9WLiMlzYI+LRtwr0U+DHY=

You can also write / append this to the file by PHP but that’s not covered here.

What’s better, the SHA1 algorithm is much more advanced than DES which most of the online .htpasswd generation tool still uses to generate the hash string of the clear password for you. DES supports only 8 digits and that’s where lengthy passwords fail.

{ Comments on this entry are closed }

Depending on the web server software you use, your PHP script will be consuming significantly different amount of memory (RAM). If you are using Apache without proper optimization, the simplest request that does nothing but returns a status code will need 150kB of memory. Multiply this by 2000 visits per day and by 10 sites in a single Linux VPS box, you will have some serious OOM (Out Of Memory) problems.

However if you are using simplistic web server software such as Lighttpd, the situation will get a lot better. But you would still like some improvements to your PHP script itself. So does one first know how much memory a PHP script consumes at run time?

The answer is the memory_get_peak_usage() function. At the end of your PHP script (footer script for a PHP site, you get the idea), put this line:

echo memory_get_peak_usage();

Or you can write the data down in a text file:

file_put_contents('mu.txt', memory_get_peak_usage());

The output is in bytes. Better yet, you can record down the URL request, HTTP request type and memory usage in the mu.txt file so that you can examine it regularly to make adjustments to your server and PHP scripts:

$mu = fopen('mu.txt', 'a');
fwrite($mu, $_SERVER['REQUEST_URI'].', '.$_SERVER['REQUEST_METHOD'].', '.memory_get_peak_usage()."\n");

{ Comments on this entry are closed }

If you accepted GoDaddy’s offer of the first-year-free private registration service for your domain, you would not be so happy when you are renewing the domain for more years because you will find the private registration is bound to that domain. You can either renew the domain WITH the private registration which costs an extra $9 per year or you can remove the domain from the shopping cart. You are forced to renew it with private registration at $9 per year plus the registration fee ($10 or so) or you cannot renew it at all. Very shady.

No, they don’t have any options to exclude private registrations (Domains By Proxy) when you are renewing the domains that were registered with the free private registration for the first year. The trick is, they don’t have that option on GoDaddy.com. You will have to do it on DomainsByProxy.com.

So how to turn off private domain registrations for renewals at GoDaddy?

For every order of domain registrations with first-year-free private registration services, you will be sent an email containing the login details of DomainsByProxy.com. I found them by searching my email inbox by the phrase "domains by proxy". Chances are you can find a few messages sent from domainsbyproxy.com by the title "Welcome to Domains By Proxy".

Each of the messages is an order of private registrations for one or multiple domains. Open them one by one and look for "User Id" which is a lengthy number that you will use as Customer # or Login Name at https://www.domainsbyproxy.com.

The password is the same with that of your GoDaddy.com account.

When you are logged in, you can see the list of domains that you opted for private registrations by clicking “Domains”. Check the domains you intend to renew (or rather, all of them) and click “Continue”. Select “Yes” and click the Done button or whatever to finish the process.

Now you can get back to GoDaddy and renew your domains without being bothered to purchase additional years of private registration services.

Shame on Godaddy.

{ Comments on this entry are closed }