Tuesday, September 29, 2009

Weird date format from FreeTDS with mssql.datetimeconvert = 0

Today I encountered a problem with date field format in MS SQL Server 2000. We are accessing the server through FreeTDS and for data abstraction we are using latest stable PEAR MDB2_Driver_mssql v 1.2.1.

We were migrating to newest daily FreeTDS. As soon as we recompiled FreeTDS, our PHP applications started acting weird, showing invalid dates. We narrowed down all problems to a change in date format we got from SQL server.

A simple query:
echo $mdb2->getOne("SELECT datefield FROM table");
now returned some weird data format:
2009-01-01 31695:06
However, when we used mssql_* functions, skipping MDB2 altogether the date format was OK. I noticed one bug report: mssql.datetimeconvert force set to 0 - generate wrong dates. It was correct - even though we used mssql.datetimeconvert = 1 in our php.ini, MDB2 driver sets it to 0 on connect().

But the same code used to work with older FreeTDS. It seems that FreeTDS changed its internal date format, some locale settings etc. And disabling datetimeconvert by MDB2 triggered the problem as we started getting this new weird format.

I didn't want to mess up with internal date handling by MDB2 and keep patches to apply on future MDB2 updates - luckily we found a simple solution: recompile PHP with the newest FreeTDS libraries and everything goes back to normal. The same script now outputs:

2009-09-29 18:11:00

Even though mssql.datetimeconvert = 0 thanks to MDB2, we are receiving standard Y-m-d H:i:s format we love so much. Hope that helps anyone with similar problem.

Thursday, September 24, 2009

Using shared SVN working copy on samba

Part of deployment procedure for PHP applications in company I work for is to update the code on a staging server through a samba share. The code is then replicated to production machines.

We use Subversion as our VCS of choice so we simply kept working copies on staging server and used TortoiseSVN to do an svn update. Later on we would e.g. migrate the database, update configuration files etc. This proved to be very simple and effective technique.

However,when our administration changed authentication procedures and gave every developer separate account (we used a single user name to log in to our samba share before, now we authorize through NT domain) - it suddenly stopped being so effective.

As soon as one developer updated the staging working copy, he started "owning it". Anyone else trying to update it later on got access denied errors. The reason? Subversion client created files in .svn that are read-only and these could not be deleted and recreated by anyone else (and Subversion client does this during svn update).

Luckily, there is an easy solution, found here and also mentioned in SVN FAQ. In our case, inserting:
[global]
delete readonly = yes
in smb.conf solved our problem. Any developer that is authenticated to use our staging share may now update the working copy.

Disclaimer: Although using working copy on samba share is not recommended by Subversion team, we use this technique for years now with different server and client versions and this was our first problem. However - we don't do development on this working copy, we only update it, so it's not a real full-blown multiuser working copy.

Thursday, September 17, 2009

HTTP File server released

Problem

Imagine a situation where your application has to store and retrieve files on the web (i.e. not on a local filesystem). You have many options - you may upload them to FTP server, e-mail them, use some file hosting services like Dropbox, upload files using a HTML form, use WebDAV server. Finally you may mount some remote filesystem like NFS.
All of these options are valid, but they all carry certain amount of requirements that may not always be met:
  • To use FTP, you need to set up a remote FTP server, have an implemented FTP client in your language of choice and the ability to open FTP connections on the system you're using.
  • To use e-mail you need to be able to handle POP3 and SMTP protocols and have a mail server set up.
  • WebDAV, although convenient, is hard to set up in the first place. The protocol itself takes some time to implement.
  • Using any other web application like Dropbox requires you to have a client for their services and you need to accept the licence restrictions.
  • HTML form - an excelent choice. If you're doing the uploads manually, you may write a simple script in minutes - but what if you want to upload files automatically (e.g. in a batch script)? You need to make a HTTP request with form and the file within encoded, you have to deal with mime-types, encoding file contents etc. Not really fast to implement.
  • Mounting remote filesystem is impossible on a shared Linux server, or Windows server.

Solution

HTTP File server to the rescue. This small little fellow, written in PHP5 is a simple REST-oriented file server with minimal requirements:
  • PHP 5 (5.2 I suppose)
  • web server (Apache will do)
  • writable directory (this is where your files will be stored)
This is for the server part. For the client part you only need to be able to do HTTP GET and HTTP POST requests, so you're good with just wget in a batch script (or .NET application, or Ruby, PHP, Java - pretty much anything nowadays can form HTTP requests).

Example

Example usage:
# store file on server - use HTTP POST
wget --post-file=file_to_send.txt http://server/index.php/path/to/store/file.txt -O -

# retrieve file - use HTTP GET
wget http://server/index.php/path/to/store/file.txt
That's pretty much it. The server is so simple, it doesn't (yet?) offer even the ability to list directory contents. All it does is store files and retrieve them.

Download

Download HTTPFileServer and take a look for yourself. Your comments are welcome. The project is BSD licensed.