Monday, February 9, 2009

Time to Get Serious About Programming

A long while back, I started learning how to program and create stand-alone applications. I really didn't wind up creating anything much, really. I had several projects I was working on in my learning such as "Hyponiq's Calculator", a customizable and fully-functional calculator with command logging and other nifty little features. None of those projects were ever really completed as I lost interest or moved onto other things. I also pretty much concentrated (and still do) mostly on Web development and all things related.

Well, recently I downloaded and installed Microsoft's Visual Studio 2008 Express Edition on both of my PCs -- my desktop and laptop. I decided that if I were going to have it, I need to use it. I've always had Visual Studio since it's 2003 release, but it really just collects dust as I hardly ever create ASP .NET applications anymore. Mostly, I utilize PHP as my server-side application interpreter. PHP is really so much better than ASP .NET, although ASP .NET does have its benefits such as the direct link to the Windows APIs and the .NET Framework. Both are strong and powerful and I hold no ill will towards Microsoft and their technologies. In point of fact, almost all of Microsoft's applications are my preferred tools and resources, with just a few exceptions ... such as the Expression tools line (yuck!).

Whatever the case, Visual Studio did nothing more for me anymore than simply sit on my hard drive looking pretty. Version 2008, however, does have major key benefits and improvements over the 2005 release and previous versions, as well. So, again I decided it was high time I started using my programming skills and put them to good use. The problem: finding the right thing to produce. With so many programmers, developers, and architects in the industry, it's really difficult to find that inspiration as almost all ideas are covered ... except for at least one.

So what's the issue? I use, primarily, Microsoft Internet Information Services 7 (IIS7) as my default Web service provider for my project(s) testing suite. I have no problems with IIS7. In point of fact, I love it! It is so very easy to install, use, and configure. Plus, it has a very low profile on my processor(s). Unfortunately, it only comes in Windows Vista and/or Windows Server 2008 or higher. My laptop has Windows Vista Home Premium which allows me to install IIS7 and run it as an advanced service platform. It is multi-threaded and allows me to utilize PHP to its max potential. The point of interest here is that PHP can utilize per-directory configuration settings as well as a master configuration settings file for default configurations. There are many other points here, as well, but the aforementioned is my number one concern. My desktop, on the other hand, runs Windows XP Media Center Edition (which is really Windows XP Professional with a few media-related tweaks and its own indigenous GUI theme). And, yes, my desktop PC is a little outdated. I have the ability to run IIS 5.1, but it is not a multi-threaded server and therefore does not allow for virtual hosts. It only allows for one Web site; not many. There-in lies the issue. I simply must have a multi-threaded environment. I could (and should) just buy Windows Vista, but it is very expensive and I'd rather spend my money on something else, really. That's not to say that Vista is bad; it's not and I do prefer it over XP. The simple fact remains that this PC (my desktop) isn't quite suitable for Vista, although it can handle it (and I have tested it). Sometime in the not-so-distant future, I'll be purchasing an MSDN subscription which will allow me to download all Microsoft Windows platforms, but that doesn't solve the problem now.

So, Apache HTTPD (Apache, for short), therefore, is the solution. It is highly configurable via the configuration files (i.e. http.conf, vhosts.conf, et cetera) and allows for a plethora of application extensions, code libraries, scripting engines, and so on. In other words, I can use PHP and have multiple Web sites! There are three problems I have with Apache, however.

Issue #1: Apache, on a Linux/Unix platform, has a stand-alone, visual configuration tool for manipulating the configuration files. Using this tool is easy and fairly light-weight on the processor and memory. Although it's a great tool, the open-source Apache Configuration Tool (which ships with most Linux/Unix ports) is a Linux/Unix only tool and I haven't found any successful and powerful-enough ports to the Win32 architecture. In other words, I haven't found any useful Apache configuration tools available for Windows. There are a few projects out there (Google returned 295,000 hits for "apache configuration tool") that I found, but not one of them does exactly what I would like. Plus, being as pedantic and OCD as I am, many of the said applications are ugly, over-bloated, and resource intense. Also, a lot of them are not free of charge which, to me, defeats the entire purpose of open-source software. So, returning back to the original topic -- programming -- I'm taking it upon myself to create a new visual tool for Apache, building upon IIS7's visual interface. What that means is that I'm basically going to emulate Microsoft's IIS7's configuration tool. Almost all the features found therein will be available in my Apache configuration tool. I haven't decided a name for it, but that'll come in time. Moreover, this project will be open-source and freely distributable. I believe in open-source technology, which is my only real gripe to Microsoft. Personally, I believe Microsoft should release a freely distributable version of the Windows platform, if only limited in abilities, along side of other technologies -- namely: IIS. Sure, they have their operating systems freely downloadable to MSDN and TechNet subscribers, but that's really not the same as those subscriptions cost more than the operating systems supplied. Imagine that. . o O ( Damn, I'm rambling! )

So, anyway, I'm definitely going to start that project immediately.

Issue #2: Using PHP on Apache isn't as successful as using it on IIS7. The foremost complaint I have is the simple fact that PHP's per-directory configuration settings don't work quite the same on Apache as it does on IIS7 (one of the many reasons for why I don't understand why everyone is so uptight about using Apache over IIS7). You can read more information in this blog post. So, what am I going to do about that? I'm going to write an Apache module that allows PHP to find and use separate configuration files per-directory as well as read the standard configuration settings from the master file. I haven't yet figured it out in my head how to go about this, but I'm sure I will.

Issue #3: Going back to the beginning parts of this discussion, I mentioned the fact that I utilize ASP .NET in some of my yester-year projects. As I said before, ASP .NET is a powerful and very-useful application platform. I have no problems with it (minus the major difference in overall development time vs. PHP). I'm sure sometime in the future that I'll be using ASP .NET for someone's site architecture and will/would definitely need the ability to run ASP .NET from my computer(s). Once again, my laptop can do this as it has IIS7; my desktop cannot, however, due to the operating system. So, the solution is to build an Apache extension that taps into the very powerful .NET framework and serve ASP .NET pages. There is/was an Apache module project already started (and probably many more) -- mod_aspdotnet. There is also a cross-platform (Windows included) .NET Framework port called Mono (as well as the corresponding Apache module (mod_mono)) which allows for .NET Framework development using some of the more common programming languages (including my favorite language (for programming, that is): C#). Bearing that in mind, Mono is still under development and will probably continue to be so as it seems to be a fairly popular project. mod_aspdotnet, however, isn't maintained properly (the last build date was in 2006!). Temporarily, until I release my first stable version of my own Apache module, I'll be using mod_aspdotnet. The concept here is to allow Apache to interpret and serve ASP .NET-related pages (particularly ASPX) and work from the System.Web sub-classes of said framework. This will probably be the most complicated of the three Apache projects I have in mind with it being the latter project tackled.

So, all in all it seems I have my work cut-out for me. It'll probably be several months before the first official release of any of the above projects, but it will keep me company and occupied so I'm not doing other, potentially harmful things (but that's another discussion).

Sunday, February 8, 2009

Apache & PHP: Multiple PHP.ini Configuration Files

I just thought I'd add my little tid-bits of information here as I searched and searched for possible solutions to a formidable problem: How can I use per-directory PHP configuration settings in Apache?

I read through several different work-arounds and tested them thoroughly. I've come to one possible and viable solution.

Solution #1: The information listed here in this documentation section seemed to be the best possible solution. The php_value, php_flag, php_admin_value, and php_admin_flag (settings available in httpd.conf, vhosts.conf, or per-directory .htaccess files) seemed to do the job nicely in each and all of my virtual hosts. It takes a LOT of editing -- and possibly a lot of files -- but the results are efficient and less CPU taxing.

So, if you wanted to set a virtual host's doc_root directive, you'd use something like:
# vhosts.conf
NameVirtualHost *:81
<VirtualHost *:81>
ServerAdmin admin@example.com
ServerName vhost.example.com
DocumentRoot "C:/path/to/doc/root"
ErrorLog "logs/vhost.example.com-errors.log"

# Set the PHP "doc_root" directive
php_value doc_root "C:/path/to/doc/root"

<Directory "C:/path/to/doc/root">
# ... yadda, yadda, yadda ...
# you get the point!
</Directory>
</VirtualHost>
I used the doc_root directive example due to the fact that if you want to use relative paths to include files (i.e. <?php require_once "Classes/MyClass.php"; ?>) in files several folders deep in the tree, you need to tell PHP where to look. By default, if this is not set, or if the include_path directive is not set, PHP only looks in it's own directory (i.e. C:/PHP). However, setting the master PHP configuration file's include_path directive to all the virtual hosts' directories can cause problems, especially if you're including files with the same name in several different virtual hosts (as is in my case where I use my own framework for each of my Web site projects). It also taxes PHP as far as efficiency is concerned. It is for this I started using per-directory PHP.ini configuration files in all of my virtual hosts under IIS. I found that Apache ignores these files. Meanwhile, I found this solution to be the most efficient resource-wise, although time consuming as far as personally.

NOTE: This solution doesn't quite have the effect I had originally intended. For some reason, the per-directory php.ini file is not being loaded per-request to a given virtual host. I'm currently searching for another possibility for solving this issue. In the mean time, I'll leave this up for legacy purposes and to remind myself how quick to conclusion I can be. ;)

Solution #2: The second work-around is to use the PHPRC environment variable configurable in Apache using the SetEnv directive. This directive allows you to set an environment variable that is then passed to any CGI script and/or Server Side Include (SSI) set in any static (x)HTML page (or other document type). In this instance, you'd be telling each PHP-CGI instance where to find its configuration settings. The example would be (coinciding with the previous one):
# vhosts.conf
NameVirtualHost *:81
<VirtualHost *:81>
ServerAdmin admin@example.com
ServerName vhost.example.com
DocumentRoot "C:/path/to/doc/root"
ErrorLog "logs/vhost.example.com-errors.log"

# Set the PHPRC environment variable
SetEnv PHPRC "C:/path/to/doc/root/php.ini"

<Directory "C:/path/to/doc/root">
# ... yadda, yadda, yadda ...
# you get the point!
</Directory>
</VirtualHost>
There are two very good reasons why I don't believe this to be the better solution, although it does work. The first reason is that it requires you to have a php.ini file per directory. As I said before, I don't have much of a problem with this under IIS, but that is simply because in IIS, PHP reads the master php.ini file as well as per-directory configuration files. Apache, however, does not. The issue here is that each and every per-directory configuration file must contain all directives previously set in the master PHP configuration file. In other words, if you have a common include_path directive (for example) set that includes common file locations that you plan to use in conjunction with the current working directory's files accross your virtual hosts, you would have to also implicitly express the already set paths in EVERY php.ini file. Again, this is not the case in IIS. In IIS, you can set all the generalized configuration settings for PHP that remain true accross all of your Web sites and only set the pertinent ones in the per-directory configuration files. In that sense, you could have your include_path directive in your master file set to include common PHP scripts and includes and set your doc_root setting in the per-directory file to include scripts from anywhere in that site's current working directory. Here's an example:

Master php.ini Configuration File:
include_path = ".;C:/PHP/PHP5/pear;C:/Users/Hyponiq/Sites/Framework"

Per-Directory php.ini Configuration File (IIS):
; include_path already implied and settings used under IIS
doc_root = "C:/Users/Hyponiq/Sites/hyponiqs.com"

Per-Directory php.ini Configuration File (Apache):
; include_path is ignored from the master file; in fact, it wasn't even read!
include_path = ".;C:/PHP/PHP5/pear;C:/Users/Hyponiq/Sites/Framework"
doc_root = "C:/Users/Hyponiq/Sites/hyponiqs.com"

Conversely, if you specify an already implicitly set configuration variable in a per-directory file, it is overwritten. This also comes in handy in IIS. Sometimes, you may not need or wish to include a directive set in the master file in all of your virtual hosts, especially one that is more limited than the other. To keep this as short as possible (and it's already lengthy), I'll not go into that. Considering that, however, there are times I could see this solution coming in handy.

The other problem I have with this solution is that in order to use it, you must set the AllowOverride FileInfo directive in the httpd.conf file in order to allow the SetEnv directive to be parsed and utilized in each virtual host. What this means is that Apache then also allows the use of other -- and potentially harmful -- directives as well. What does this mean for server administrators? If you're working in a multi-user environment, such as a Web hosting service, a user may include allowed FileInfo overridden directives that could cause unwanted problems, if used correctly -- or even incorrectly by a novice. To my knowledge (correct me if I'm wrong), there are no Apache configuration directives that allow server administrators to allow or deny specific configuration directives. AllowOverride only limits categories which encompass many directives. Thus, an expert user who knows what they are doing could potentially cause serious damage to a server. In that case, a seriously inexperienced user without any knowledge could accidently mess things up as well.

Well, I hope this helps all of you -- novices and professionals alike.