Tuesday, November 03, 2009

compiling apache 2.2.14 on CentOS 5

wrangled with this a bit today. One of our clients needed the upgrade for PCI compliance, and CentOS still has 2.2.8 as the latest version in YUM.

I couldn't find any decent RPMs, so I decided to compile from scratch by first downloading & extracting the source from apache.org.

The ./configure command for installing apache 2.2.14 on CentOS is below. The --disable lines you see are there because CentOS installs the default modules separately, which is probably a good thing. The rest of the options I found by reverse engineering the directory structure of the existing apache install.

To compile from source, you may need to first run: yum groupinstall 'Development Tools'

./configure \
--prefix=/etc/httpd \
--exec-prefix=/usr \
--bindir=/usr/bin \
--sbindir=/usr/sbin \
--mandir=/usr/share/man \
--libdir=/usr/lib64 \
--sysconfdir=/etc/httpd/conf \
--includedir=/usr/local/include/httpd \
--libexecdir=/etc/httpd/modules \
--datadir=/var/www \
--with-mpm=prefork \
--with-devrandom \
--disable-auth \
--disable-cgi \
--disable-cgid \
--disable-mime \
--disable-env \
--disable-setenvif \
--disable-negotiation \
--disable-alias \
--disable-actions \
--disable-autoindex \
--disable-include \
--disable-dir \
--disable-userdir \
--disable-status \
--disable-authn-file \
--disable-authn-default \
--disable-authz-default \
--disable-authz-user \
--disable-authz-host \
--disable-authz-groupfile \
--disable-auth-basic \
--disable-asis \

Note that I also had to then comment out the following lines, possibly because I didn't --enable-ldap during the compile. I don't need LDAP though, so I just commented out:

#LoadModule ldap_module modules/mod_ldap.so
#LoadModule authnz_ldap_module modules/mod_authnz_ldap.so

Tuesday, April 21, 2009

installing ruby, rails, and redmine on Apache & FreeBSD 6

I will elaborate on this if anyone needs it, but for now I just wanted to post my notes from this evening when I got ruby, rails, and redmine running on FreeBSD 6 with Apache 2.2:

1. install ruby

#cd /usr/ports/lang/ruby18/
#make && make install

2. install rails 2.2.2
#cd /usr/ports/www/rubygem-rails
#make && make install

3. install ruby-iconv (rake script for redmine won't run without this)
cd /usr/ports/converters/ruby-iconv/
#make && make install

4. install mysql gem
#/usr/local/bin/gem install mysql

5. install passenger
#cd /usr/ports/www/rubygem-passenger
#make && make install

6. add these lines to your httpd.conf:

LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/gems/passenger-2.1.3/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-2.1.3
PassengerRuby /usr/local/bin/ruby18

7. install SVN (we'll need it to export the redmine trunk)
#cd /usr/ports/devel/subversion
#make && make install

8. export redmine trunk (note: since we have ruby 2.2.2, we'll need the trunk, not the stable version of redmine.) ** see note below

svn export http://redmine.rubyforge.org/svn/trunk/ redmine

9. follow instructions at: http://www.redmine.org/wiki/redmine/RedmineInstall
10. copy redmine/public/dispatch.fcgi.example to redmine/public/dispatch.fcgi
11. -set up redmine vhost:

# redmine.example.com
ServerName redmine.example.com
DocumentRoot /home/www/redmine/public


Now you should be good to go at redmine.example.com!

The version of trunk I exported seemed to have some bugs, so I ended up installing rails 2.1.2 and going with the stable version of redmine by doing:

#gem install rails --version='=2.1.2'
#svn export http://redmine.rubyforge.org/svn/branches/0.8-stable redmine

Thanks to Mat Schaffer for the help on that one

Tuesday, January 06, 2009

sIFR flash is in front of dropdown menus

While using sIFR to get nice, clean, scalable fonts on the web, I noticed that because sIFR uses flash replacement, the replaced text was appearing on top of (e.g. z-index) the dropdown navigation menus the site had, which was not the desired behavior. The simple fix was adding: sWmode: "opaque" as one of the options to the sIFR.replaceElement method.

Friday, October 24, 2008

Stop undeliverable spoofed spam using maildrop and PHP

A common problem among email providers is the growing practice of spammers using legitimate email addresses in the From: header of their messages, which means that unsuspecting users get flooded with potentially thousands of undeliverable messages due to the fact that many of the To: addresses on the spammers' lists are no longer valid.
A few of our customers had this issue, so I devised a quick way to filter out the undeliverable messages via Maildrop and php.

1. Set Postfix to pass mail through Maildrop

After installing maildrop (it should be readily available in your *nix distro's packaging system) Make sure Postfix is set up to pass mail to Maildrop by putting the following line in your master.cf file:

maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient} ${recipient}

(Note: adjust maildrop according to your environment - see http://www.postfix.org/MAILDROP_README.html)

2. Place the following code in /usr/local/etc/mail/maildrop_filters.php

ini_set('display_errors', 'off');


$recipients = array(

$bad_subjects = array(
'Undelivered Mail',
'Delivery Status Notification',
'Undeliverable mail',
'Returned Mail',
'Delayed Mail',
'Delivery Failure',
'Warning: could not send message',
'Warning: message'

// Don't edit below here
$sender_address = $argv[1];
$recipient_address = $argv[2];

$stdin = fopen('php://stdin', 'r');
$msg = '';
$header = '';

while ( $buf = fread($stdin, 500) ) {
$msg .= $buf;

$msg_lines = explode("\n", $msg);

if ( is_array($msg_lines) ) {
foreach( $msg_lines as $cur_line ) {

$cur_line = trim($cur_line);

if ( $cur_line == '' ) {

$header .= $cur_line . "\n";


foreach( $recipients as $recipient ) {

if ( preg_match('/^To\:\s*\

foreach( $bad_subjects as $subj ) {

if ( preg_match("/^Subject:\s*" . preg_quote($subj) . "/im", $header) ) {

echo $msg;


3. Add the following to your maildroprc file, which will probably be in /etc, /etc/mail, or /usr/local/etc/:


exception {
xfilter "/usr/local/bin/php /usr/local/etc/mail/maildrop_filters.php \"${SENDER}\" \"${RECIPIENT_ADDRESS}\""

if ( $RETURNCODE == 1 )
log "${OUTER_INDENT} Message for ${RECIPIENT_ADDRESS} discarded. Returncode was ${RETURNCODE}"

4. Edit the $recipients array

Go back into /usr/local/etc/mail/maildrop_filters.php and edit the $recipients array as necessary - this is where you put the addresses that are being bombarded with the undeliverable mail messages:

$recipients = array(

Additionally, you can add or remove subjects from the $bad_subjects array as required. Note that the filter matches subjects that *start* with the items listed in $bad_subjects, so "Undeliverable:" will match "Undeliverable: Mailbox not found" and "Undeliverable: Mailbox is full", and so on.

Wednesday, October 22, 2008

SwiftFile - Send files securely on the web

As the latest in a series of webtools that Context is launching, we've decided to offer an extremely easy, free, secure solution for uploading and sending files. SwiftFile.net offers a simple interface to upload and password protect files, making them unreadable even to the site administrator. Our goal was not to compete with filesharing giants like sendspace, mediafire, or rapidshare, but rather to offer a way to send sensitive documents very quickly and very securely. You can read the SwiftFile FAQ for information about how the data is stored and encrypted. Give it a try - it's fast, easy, and free. Additionally, thanks to the Fuse PHP framework, the site was put together from start to finish in 2 modest work days. We're hoping that a side effect of these tools will be to showcase the versatility and ease of use of the framework, which is now gaining ground in the PHP MVC community.

Sunday, October 19, 2008

suphp directory not owned by user

Installing suPHP on Apache 2 tonight, I was surprised that it was complaining about the parent directory for my document root not being owned by the specific user who owned the scripts. I had it owned by the apache user, www, and it turns out it (the parent directory which, for me, was /home/www) has to be owned by root in order for suPHP to traverse it.

Thursday, September 04, 2008

Why you should do your PHP development in FUSE

Let's face it - there are a lot of development frameworks out there, especially for PHP. CodeIgnitor and CakePHP come to mind immediately as leading PHP frameworks, but in this article I'm going to give some compelling reasons as to why you should be doing your PHP development with the Fuse Framework.

Fuse is a Model/View/Controller framework for PHP. If you're not familiar with MVC architecture, you may want to start with my other post, MVC and you: Partners in Freedom

1. FUSE is easy to get running

The installation scripts included with Fuse guarantee that you'll have a working install a few minutes after downloading. To get an idea of just how easy it is to get started with a Fuse project, have a look at the video I've posted here .
Fuse was built so that PHP developers don't have to feel like they were learning an entirely different language in order to make use of the framework. The syntax and structure follow normal PHP conventions, and everything from the method names to parameter order was designed to be as intuitive as possible.
Let's face it - everyone wants to use the newest, best, and most appropriate tool for the job. However, developers will often shy away from doing things differently because of the learning curve. They fear that introducing new technologies or methodologies will increase their project timeframe and decrease productivity. Fuse was built with a deadline-oriented mentality in mind: you can get started quickly, and you don't have to know every in and out of the framework to start building your project.

2. Data access has never been easier

Fuse's data modeling makes accessing your data easier than you ever thought possible. The management scripts will give you create, read, update, and delete access right off the bat, and customizing your queries is as simple as can be. Let's say you want to list your products, but also include their category_name, which lives in the product_categories table. In Fuse, all you have to do is open your ProductController and add this line:

public $list_options = array( 'include' => 'product_categories' );

That's it. Now when you iterate through your products, you can use the variable <{category_name}> in your template to display the category name for your product. Let's say we only want to display 20 categories? Try this:

public $list_options = array( 'include' => 'product_categories', 'limit' => 20 );

Fuse offers a whole slew of data methods just like these, and your queries can be as simple or as complicated as you need them to be. You will rarely have to write a query, but if you want to, Fuse even offers an object to take the headache out of writing queries . And, as always, if you just want to hand code a query the old fashioned way, Fuse will never stop you. A core principal of Fuse is that it's designed to aid the programmer, not force him or her into the methodologies that we've deemed best.

3. A simple but extremely powerful templating engine

Fuse contains its own robust, intuitive templating engine that allows you to truly separate your code from your presentation. As with everything else, the templating system was designed to be intuitive, and "designer friendly". Want to loop through the products we fetched above? Try this:

<{ITERATOR products}>
name: <{name}><br />
category: <{category_name}><br />
<br />

Want to apply a function to one of your fields? How about we only display the first 200 characters of our description:
<{ITERATOR products}>
name: <{name}><br />
category: <{category_name}><br />
description: <{ print(substr(description, 0, 200)) }>
<br />

Maybe our products can be in more than one category, and we want to fetch them?

After adding a one line method to our Product model that looks like this:

public function get_categories() {
return $this->product_categories->fetch_all();

We can do:

<{ITERATOR products}>
Name: <{name}>
<{ITERATOR get_categories()}>

Yes, <{name}> will know that when you're in the products loop, you want the product name and when you're in the product categories loop, you want the category name.

4. Searching your data has definitely never been easier.

Your client tells you that they want to be able to search records with any combination of title, date, description, id, and author. You know this is going to be an annoying task of using if/then statements to build a search query. Unless you're using Fuse, where you can do it all with a few lines of code.

The FuseDataController object, which handles all of the wheeling and dealing your app does with the database, has builtin search capabilities that will automatically sanitize data, generate the search query, and maintain the search session across pages. All you have to do is tell it which fields a user can search on, and it's ready to go. You can search fields values directly, with wildcards on either side, between two date intervals, or even have Fuse automatically parse strings like "restaurant AND (mexican OR Thai)" simply by setting your 'filter_type' to 'parsed_boolean'. The search capabilities are discussed here

5. Builtin management of photos for albums, user profiles, etc.

Let's say you're building a site that allows users to create a profile, add photo albums, then add photos to those albums. You're going to want several different sizes - a full sized image, a thumbnail for browsing, and a tiny thumbnail for a contact sheet type of display. You also want to watermark each image with your site's logo. This can be a pretty tedious task if you're not using the FusePhotoController, which should have you up and running in about a half hour if you're slow.

6. Simple but fully featured, scalable user management and ACL

A lot of sites need user authentication. I've seen a lot of custom implementation in my time, and because of the complexity of doing it right, mostly they rely on a very basic user scheme that allows little or no granularity or scalability when it comes to setting permissions. Fuse has a simple to implement, but fully granular and scalable user authentication and permissions scheme built right in. Need to associate users with groups that all have different permissions? No problem. Have a user who's in the "editors" group, but shouldn't have access to delete an article? Just add a restriction for that user. Need to set it up so that when a user tries to access a restricted page, they are asked to login, then redirected back to the original page on success? It's already done. Password encryption? SHA-1, MD5, and crypt() are all supported. I could go on. You can read about it on your own here

7. Integration with existing non-Fused projects

I mentioned above that Fuse endeavors to never prevent the developer from doing what he or she needs to do. If you have a project that's already done in standard, inline PHP, Fuse can go right alongside your existing code without upsetting any of the existing functionality. In fact, if you include the Fuse bootstrap in one of your existing php scripts, you can add Fuse functionality to that script without having to edit any of the existing code.

I have several projects right now that were handed to me as inline PHP, and I put Fuse right on top of it without having to re-code a single line of the existing project. However, I can now use Fuse moving forward for new features and updated functionality.


There you have it. Just a selected list of reasons you should switch to Fuse. Today. For the project you're working on. Right now. Make things easier on yourself. I've introduced a lot of people to MVC development and Fuse and, without fail, every single one has said, after just one project, that they could never possibly go back to their old methodologies of inline scripting and manually writing every query.

Comments welcome.