One time passwords in PHP.

July 12, 2007

I have posted a kind of an article with accompanying (working) PHP code about generating and using one time passwords on a Web site. The technique can be useful to temporary logons on public computers to prevent disclosures of “real” passwords.

The whole thing it located at  http://www.kyusl.com/scr.php?mod=02

ReCAPTCHA against Spam.

June 28, 2007

In the last two weeks, spam engines finally have found their way to Kyusl signup page. In the Apache log it looks like getting to the form and firing the send button right away, all the data filled in correctly. As Kyusl is used to store site links, among other things, it’s a natural target for folks dumping the stinking stuff onto the Net.

My first idea was to find the most simple PHP script that will supposedly use GD library to generate some distorted text to be presented as CAPTCHA challenge. Just like everyone else does. But I have found an interesting link on Wikipedia. Carnegie Mellon University, known for its software-related research and software itself, has an interesting project that has developed a kind of Web service that does everything for you: RECAPTCHA.

Integrating the checks is very easy and they provide ready to use code in many languages including PHP. I have tested it with Firefox and IE, and after adding the new checks into the signup code, the spam signups have disappeared. Hmmmm…. as of today.

Backup a Web site and MySQL, sending backups by E-mail.

June 8, 2007

To do backups of Web sites, I have written a short shell script that creates backups including files and MySQL database. It creates a TAR/GZIP archive and sends it by e-mail (to myself of course). For more detail and script source code, please have a look at http://www.kyusl.com/scr.php?mod=01 .

Dangers of copying the code.

May 15, 2007

How many times have you seen something like this at the top of a PHP file?

if (!($dbconnection = @mysql_connect(‘localhost’, ‘user’, ‘pwd’))) {
die ‘Could not connect to the database.’;

It’s so simple that it went to many scripts running on the Web. Mine were not exception. I never thought that it can hit me, but one day, after checking what kind of information Google has on Kyusl.com, I was shocked to see that message about the database problem in the Google cache. And that for the home page! I could never imagine that Google bot will reindex my site exactly at the same moment when the database is down or overloaded!

Getting Google site entry in a bad shape takes some time to recover. To have some protection for future problems, the first thing I did was to examine all PHP-based pages to decide what can run without the database and what needs it. If the database is not available, I can still display the home page, “about” and several other pages. Normally they check for an existing user session, using the database, but I adjusted them so that if there is no database connection, it is assumed that the user is not logged in, and general information is displayed.

The trick is very simple. At the top of each script for which the database is not vital I set a flag telling that in case of database problems, the script should not be stopped:

if (!($dbconnection = @mysql_connect(‘localhost’, ‘user’, ‘pwd))) {
if( !isset($no_db_error) ) {
print ‘<html><h3>Sorry, I could not connect to the database. Please try again later.</h3></html>’;
exit;

I hope that the database problems will not occur frequently, but even if they do, now Kyusl.com will show a better face in such cases.

Simple bookmark manager in 20 lines of PHP.

April 28, 2007

There are dozens of bookmarks managers on the Web, but for my most simple needs, I decided to make my own. I have bookmarks at Yahoo, but do use them efficiently, I have to install their Toolbar, and you can never know what does it do with your private infomation. Del.icio.us is good too, but the default setting is that your bookmarks are public (well, it’s the main idea of the service actually). So, there are no ideal services, and tired of keeping different sets of bookmarks on my home and office computers, I implemented a very rudimentary but my own bookmarks storage script. It takes less than twenty lines of PHP but it does what I need. To use it, you have to have your own PHP-capable site on the Web (even a free one should work). It’s important to note that there are no login checks and the only way to prevent the owner from troubles is to use some cryptic file names (instead of ones below). “Troubles” means not making your private bookmarks public (which is not good too), but allowing anyone to post there, which can be used to plant some nasty Javascript into your file to hack your browser.

The principle is very simple. If you supply at least the URL parameter, it adds a new bookmark and then displays the whole list. If no URL parameter is given – it’s just the display. To make things easier, you have to create a bookmark in your browser with the following Javascript instead of usual URL (note that there is no http:// stuff, and don’t forget to replace localhost and bm.php with your own host and file names):

javascript:location.href=’http://localhost/bm/bm.php?url=’+encodeURIComponent(location.href)+’&title=’+encodeURIComponent(document.title)

The PHP code is below. Normally, WordPress screws up the quote symbols (both single and double), so you have to retype them. To prevent warnings on the first use, either create the include file or try it right with adding a bookmark.


<?
print '<html><title>Bookmarks</title><body>Bookmarks<br><br><br>';

if( isset($_GET['url']) ) {
$url = $_GET['url'];
$title = ”;
if( isset($_GET['title']) ) $title = $_GET['title'];
if( $title == ” ) $title = $url;
$handle = fopen(“bm.inc”, “a”);
fwrite($handle, ‘<a href=”‘.$url.’”>’.$title.’<br>’);
fclose($handle);
}

include ‘bm.inc’;

print ‘</body></html>’;

?>

Obviously, it's not a full manager because there are no edit or delete features. But as I almost never to that, it's fine with me to edit the file directly when needed.

Webmaster notification functions in PHP

April 18, 2007

I wanted to add notification functionalities to Kyusl.com, so that I could be informed about certain events, but at the same time there will be a limit on how many notifications will I get on a given day. My cell phone plan at German Vodafone comes with an E-mail account, and every time I get an E-mail, Vodafone sends me an SMS that includes the subject of the E-mail. To read the message, you have to have an appropriate cell phone, but for short notifications you can pack most important things right into the subject line. That allows me to get the most important information for free almost anywhere in the world, which is important if I go on vacation (normally, SMS roaming doesn’t cost anything).

I called the concept “counted events”. One of the “events” would happen when someone uses the contact form, which sends a message (not E-mail!) to the administrative user. If that happens, I want to inform myself about that, but not more often than two times per day. Then I can login into Kyusl and check the message.

I have decided to keep the track of one “counted event” in one database record per user. Obviously, you have to reasonably limit the number of events per given period if you don’t want to have several records per event. I allow maximum five events per period, here’s MySQL declaration:

create table ceventlog (
    uid           integer,
    cevent        varchar(8) not null,
    alimit        integer,
    period        integer,
    t1            integer,
    t2            integer,
    t3            integer,
    t4            integer,
    t5            integer,
    primary key ceventlog_key (uid,cevent)
);

Period field measures the period in seconds, and t1 to t5 represent a rolling log of timestamps telling when has the event happened. Every time the event happens, I shift the values “down” and write the current UNIX timestamp into t1. Then if, say, I want to check whether I have reached four events in the given period, I check the time difference between now and t4, whether it exceeds the time limit in the “period” field.

Two functions can either init an event or reset it. First I had a reset in the init function (to count for the case when calling insert on existing record), but then decided that if I don’t reset the event in the init, I can safely call the init every time without zapping the log:

function InitCEvent($uid, $cevent, $limit, $period) {
  $query = "insert into ceventlog (uid,cevent,alimit,period,t1,t2,t3,t4,t5)".
               " values ($uid,'$cevent',$limit,$period,0,0,0,0,0)";
  $result = mysql_query($query);
  // if we don't call Reset - insert will fail if the record exists,
  // so Init can be called every time, and Reset can be called on demand.
  // ResetCEvent($uid, $cevent);  // just in case we had a record already
}

function ResetCEvent($uid, $cevent) {
  $query = "update ceventlog set t1=0 t2=0 t3=0 t4=0 t5=0".
                 " where uid=$uid and cevent='$cevent'";
  $result = mysql_query($query);
}

When the event happens, I shift the values in the event log with the following function:

function ShiftCEvent($uid, $cevent) {
  $query = "select alimit,t1,t2,t3,t4,t5 from ceventlog".
                      " where uid=$uid and cevent='$cevent'";
  $result = mysql_query($query);
  if (!$result) {
    return 0;
  }
  else {
    $num_rows = mysql_num_rows($result);
    if( $num_rows == 0 ) {
      return 0;
    }
    else {
      $row = mysql_fetch_row($result);
      list($limit,$t1,$t2,$t3,$t4,$t5) = $row;
      $t5 = $t4;
      $t4 = $t3;
      $t3 = $t2;
      $t2 = $t1;
      $t1 = time();
      $query = "update ceventlog set t1=$t1, t2=$t2, t3=$t3, t4=$t4, t5=$t5".
                         " where uid=$uid and cevent='$cevent'";
      $result = mysql_query($query);
    }
  }
}

And finally, to check whether the limit is reached, I have this:

function CEventLimitReached($uid, $cevent) {
  $query = "select alimit,period,t1,t2,t3,t4,t5 from ceventlog".
                       " where uid=$uid and cevent='$cevent'";
  $result = mysql_query($query);
  if (!$result) {
    return 0;
  }
  else {
    $num_rows = mysql_num_rows($result);
    if( $num_rows == 0 ) {
      return 0;
    }
    else {
      $row = mysql_fetch_row($result);
      list($limit,$period,$t1,$t2,$t3,$t4,$t5) = $row;
      $now = time();
      if( $limit == 1 ) {
	if( $t1 == 0 || $now - $t1 > $period ) return 0;
	else return 1;
      }
      elseif( $limit == 2 ) {
	if( $t2 == 0 || $now - $t2 > $period ) return 0;
	else return 1;
      }
      elseif( $limit == 3 ) {
	if( $t3 == 0 || $now - $t3 > $period ) return 0;
	else return 1;
      }
      elseif( $limit == 4 ) {
	if( $t4 == 0 || $now - $t4 > $period ) return 0;
	else return 1;
      }
      elseif( $limit == 5 ) {
	if( $t5 == 0 || $now - $t5 > $period ) return 0;
	else return 1;
      }
    }
  }
}

For each event, I have written a corresponding notification function. For notifications about admin messages mentioned above, I have the code similar to:

function AdminMessageNotify() {
  InitCEvent(1,'ADM_MSG',2,3600*24);
  if( !CEventLimitReached(1,'ADM_MSG') ) {
    $message = 'New message to admin!';
    $email = 'my_email_id_at@vodafone.de';
    $send = @mail("$email", "New adm msg", $message,
		 "From: myuser@mydomain.com\\r\\n"
		 ."Reply-To: myuser@mydomain.com\\r\\n" );
  }
  ShiftCEvent(1,'ADM_MSG');
}

The code in the contact.php, after sending a message to administrator, is simply the call of AdminMessageNotify.

That simple set of functions can be used easily to notify webmasters about data processing errors (database, for example), traffic and many others that may require webmaster’s attention. I will greatly appreciate any improvement ideas you may want to share.

Why HTML tables are good for you.

March 2, 2007

The topic is now at least decade old: “Never ever use HTML tables, especially for formatting purposes. You do everything in CSS”. The main reasons given are delays in page loading, incompatible or deprecated tags and the basic mistake of using something for formatting while it was dedicated to a different purpose. Kyusl.com is using a mixed style – both tables and CSS. CSS is used for positioning normally where tables really can’t do. Here’s why: since I am in no way an HTML or CSS expert like those folks on the Net advocating CSS, I had to run Google before doing many formatting tasks. The impression you get is that with anything beyond simple positioning, the page can easily go to hell. When you filter out the search results generated by HTML snippets of CSS machos (look! yet another way to do XYZ in CSS!), you start browsing some real life code, dealing with poor CSS support in general, with different levels of support in different browsers and with most unwanted limitations. Most of code that I tried to get rounded corners for page elements broke so easily that I have given up on the second evening, drawn those corners in Gimp and did everything using tables (just as many well-known Internet sites do). Then, after having fought off numerous smaller problems (okay, beginner problems! but aren’t new technologies supposed to be little bit more straightforward?), Internet Explorer hit me with the lack of support of “min-weight” property. Sure, it sounds childish, but aren’t those things simple and isn’t CSS a mature technology? I hope things will be getting easier – the new CSS promises the rounded corners for lazy types like me! But for now, shouldn’t HTML tables get some deserved tolerance?

Some obvious MySql tuning.

February 23, 2007

I was reading my hoster’s member forums recently and one topic there mentioned that normally the default installation of MySql database on our virtual servers doesn’t have cache enabled. As I didn’t look deep into those things yet, and on my home PC I just take the defaults and don’t care, I did a quick search on the Internet, which took me to the standard MySql documentation and a short article explaining the basics. Then, as suspected, the checks of MySql settings on the Kyusl.com server has shown that the cache is really not enabled. It looks like the hosting company provides a “minimum” install, assuming that folks who purchase virtual server hosting with almost root access will do the tuning on their own.

The whole thing doesn’t take long. I just had to ssh to my server and add three lines to /etc/my.cnf (it’s on RedHat, on Debian-based systems like Ubuntu it should be /etc/mysql/my.cnf). They have to be placed somewhere under [mysqld] section:

query_cache_limit = 1048576
query_cache_size = 16777216
query_cache_type = 1

After that, you need either restart MySql daemon (mysqld stop then mysqld start) or, if you don’t mind, the PC or VPS server. When you log into the mysql client after restart, do a quick check if your changes are active now:

mysql> SHOW VARIABLES LIKE ‘query_cache%’;

NOTE: both quotes in the statement above should be the same “normal” single quote. Don’t copy-paste – this won’t work. Just type it yourself.

The result should report something like:

+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 |
| query_cache_type             | ON       |
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

By the way, the default installation that you get with Ubuntu Linux has the cache enabled by default.

Choices – Part II. PHP.

February 17, 2007

Long before starting Kyusl, I was asked, during a job interview, what platform (or language) would I use for a project if I was free to choose? It sounded funny first because we are never free and that’s what I said first. I remember that then I finally answered “.NET” because at that time it was still new and I wanted to learn it. Microsoft provides the best documentation when compared to anyone else, but unfortunately, .NET locks you into one OS. Yes, I know what Mono is, but it’s not 1:1 port.

With Kyusl, I don’t remember having any problem to make up my mind. I didn’t use PHP and MySQL at the time for anything bigger than “Hello world”, and had to learn starting from basics. For simple scripts at work and at home, Python is my favourite, but to create a Web application, the choice of PHP was almost obvious.

One of the main questions that you have to answer is what kind of hosting plan can you afford. You can always find a niche company offering support for the most exotic software, for a reasonable price, but what if you are going to move? Actually, those days you can easily get a virtual private server and install any software you want. It’s how Kyusl.com is hosted, but doing things, say, in beautiful Python would be a pain because most of Web libraries it offers are developed and supported by small communities and most of them are moving too slow. So, unless you commit to the workload of maintaining the software on VPS all by yourself, you have to choose among “standard” offers. They are normally ASP.NET for Windows-based or Perl/PHP (plus MySQL) for Linux/UNIX/BSD-based hosting, plus Java. The latter has normally higher price tag, though, and even JSP, if you count all the works behind (the created servlets), looks too heavy. All of them, however, are widely and wildly supported, with huge communities and huge choice of libraries and tools.

So, after calming any political thoughts about choosing the language, I started with PHP. The first couple of months were hard because I never used those languages full of dollars. Now I can easily produce dollars when they needed, though I will probably never get the idea why using them in (originally) Perl and (in Perl’s descendant to some extent) PHP to indicate your intent and distinguish between different way of interpreting data is sooooo important in our life.

Another (less important) reason to choose PHP over overhyped things like Java was its “environment friendly” system requirements. Even if you don’t use any IDEs, running a heavy tool plus a Web server in background would bring my then four year old home computer to a complete halt. Forget the modern IDEs wasting 200 megs of memory right after start, even without doing anything useful! I coded the HTML layout myself simply to have more flexibility and control and without having to learn yet another library just to hit the wall of its bugs and limitations several months later. This way, all that you need is a decent editor (the choice is also almost obvious) and probably a couple of scripts to manage tasks like backups until you grow to the point where the real version control is needed.

Now, when the first version is running, it seems like I have made a right decision. The most important thing is that even if you are completely free in your choice, you have to take a pragmatic approach, even if it will result in starting from basics.

Mysterious progressive JPEG.

February 13, 2007

There is something new to learn every day. I have never paid any attention to the “progressive” checkbox in the JPEG options dialog of GIMP. It turned out that this special (see description here) JPEG is a kind of better known to me interlaced GIFs. Interesting is that it’s only Internet Explorer who marks JPEGs, probably all JPEGs, not only those that are really progressive, as MIME type “image/pjpeg”. The card upload script was not ready to accept those but it’s fixed now. And I’m waiting for something like “regressive PNG” MIME type from the “market leader”.


Follow

Get every new post delivered to your Inbox.