CGI::Application::Util::Diff - Diff 2 directories or files, or run other commands


A classic CGI script:

        use strict; 
        use warnings;

        use CGI;
        use CGI::Application::Dispatch;

        # ---------------------

        my($cgi) = CGI -> new();

        CGI::Application::Dispatch -> dispatch
                args_to_new => {QUERY => $cgi},
                prefix      => 'CGI::Application::Util',
                table       =>
                ''      => {app => 'Diff', rm => 'initialize'},
                '/diff' => {app => 'Diff', rm => 'diff'},

A modern FCGI script:

        use strict;
        use warnings;

        use CGI::Application::Dispatch;
        use CGI::Fast;
        use FCGI::ProcManager;

        # ---------------------

        my($proc_manager) = FCGI::ProcManager -> new({processes => 2});

        $proc_manager -> pm_manage();


        while ($cgi = CGI::Fast -> new() )
                $proc_manager -> pm_pre_dispatch();

                CGI::Application::Dispatch -> dispatch
                 args_to_new => {QUERY => $cgi},
                 prefix      => 'CGI::Application::Util',
                 table       =>
                        ''      => {app => 'Diff', rm => 'initialize'},
                        '/diff' => {app => 'Diff', rm => 'diff'},

                $proc_manager -> pm_post_dispatch();


CGI::Application::Util::Diff diffs 2 directories or files, or runs other commands. on the web server's machine.

The output of a directory diff is a table, where the Match column contains a red 'x' if there is a mis-match in the sizes of a file or sub-directory in the 2 given directories.

You click on a file name, or any field in the row, and a menu appears (beside the Diff button) which contains the actions available.

The output of a file diff is the output of the shell's diff command.

Available actions are in the file lib/CGI/Application/Util/Diff/.htutil.diff.actions.conf. They are listed below.

There is an action confirmation option in this file, which you are strongly advised to leave as is.

The confirmation is effected by means of a call to the Javascript confirm() function.

I hope this will be the first in a set of such tools. I plan to release any of my own under the same namespace CGI::Application::Util::*.

Since I expect this set to grow, I've decided to immediately adopt a Javascript library, rather than struggle with a more ad hoc approach. And the Yahoo User Interface, YUI, is the one I like the most.

This module was developed using YUI V 2.7.0b.


This module does not incorporate any security protection whatsoever.

If you need any more convincing that this module is unsafe because it runs shell commands, there is plenty of info on the net about this topic. For instance:



The actions will actually be run under the user who is running the web server.

This is often a fake human called nobody or daemon.

Such special user accounts normally have deliberately restricted permissions, so you might find the commands don't appear to do anything.

How you solve that on your machine is a security issue you must deal with.


This is the contents of .htutil.diff.actions.conf:

        # This option, when 1, causes a Javascript confirm() message box
        # to pop-up before the action is sent to the server.
        # If not present, the value defaults to 1.
        confirm_action = 1
        # The option limits output of the file_diff action.
        # If not present, the value defaults to 100.
        max_diff_line_count = 100
        # Actions
        # -------
        # Format: Name = Shell command (except for 'cd') = Javascript menu text.
        # The duplication is deliberate. It allows 'action' to be validated, because the first token
        # on each line is sent to the client, and returned by the CGI form field 'action'
        # when the user selects an action from the menu.
        # Also, in CGI::Application::Util::Diff::Actions, all of these keys are stored in a single hash.
        # For Perl equivalents of these shell commands, see:
        # o File::Copy::Recursive
        # o File::Tools
        # o File::Util
        # The 'cd' commands don't actually use the shell's 'cd',
        # and neither do they use Perl's 'chdir'.
        # Rather, the CGI form fields 'left' and 'right'
        # have the chosen directory appended. This emulates 'cd'.
        dir_cd_both  = cd = Change directory on both sides
        dir_cd_left  = cd = Change directory on left side
        dir_cd_right = cd = Change directory on right side
        # For here on down, they are shell commands.
        # Warning: Don't use anything which prompts, e.g. mv -i,
        # or your app will hang, making you look r-e-a-l-l-y stupid!
        dir_cp_left2right = cp -fprv = Copy directory from left side to right
        dir_cp_right2left = cp -fprv = Copy directory from right side to left
        dir_mv_left2right = mv -fv   = Move directory from left side to right
        dir_mv_right2left = mv -fv   = Move directory from right side to left
        dir_rm_both       = rm -frv  = Remove directory from both sides
        dir_rm_left       = rm -frv  = Remove directory from left side
        dir_rm_right      = rm -frv  = Remove directory from right side
        file_cp_left2right = cp -fpv  = Copy file from left side to right
        file_cp_right2left = cp -fpv  = Copy file from right side to left
        file_diff          = diff     = Run 'diff' on left and right files
        file_mv_left2right = mv -fv   = Move file from left side to right
        file_mv_right2left = mv -fv   = Move file from right side to left
        file_rm_both       = rm -frv  = Remove file from both sides
        file_rm_left       = rm -frv  = Remove file from left side
        file_rm_right      = rm -frv  = Remove file from right side

A Note on Diff

The file_diff action, unlike the other actions, has the potential to output a great deal of text.

To help protect against that, the file .htutil.diff.actions.conf has a [global] section containing the line:

        max_diff_line_count = 100

This is the maximum number of lines of output from diff which are transferred from this module to the web client.

It's set large enough to give you a clear indicator that the 2 files being diffed are indeed different, without being so large as to overwhelm the web client.


CGI::Application::Util::Diff ships with:

Two instance scripts: util.diff.cgi and util.diff

util.diff.cgi is a trivial CGI script, while util.diff is a fancy script which uses FCGI::ProcManager.

Both use CGI::Application::Dispatch.

Trivial here refers to using a classic CGI-style script, while fancy refers to using a modern FCGID-style script.

The word fancy was chosen because it allows you to use fancier URLs. For samples, see Start Testing, below.

The scripts are shipped as httpd/cgi-bin/util.diff.cgi and htdocs/local/util.diff.

These directory names were chosen because you'll be installing util.diff.cgi in your web server's cgi-bin/ directory, whereas you'll install util.diff in a directory under your web server's doc root.

For home-grown modules, I use the namespace Local::*, and for local web server scripts I use the directory local/ under Apache's doc root.

For FCGID, see

FCGID is a replacement for the older FastCGI. For FastCGI, see

Also, edit util.diff.cgi and util.diff to fix the 'use lib' line. See the Note in those files for details.

A set of HTML::Template templates: *.tmpl

See htdocs/assets/templates/cgi/application/util/diff/*.

A config file for CGI::Application::Util::Diff

See lib/CGI/Application/Util/Diff/.htutil.diff.conf.

A config file for CGI::Application::Util::Diff::Actions

See lib/CGI/Application/Util/Diff/.htutil.diff.actions.conf.

A config file for CGI::Application::Util::Logger

See lib/CGI/Application/Util/.htutil.logger.conf.

A patch to httpd.conf, if you run Apache and FCGID.

See httpd/conf/httpd.conf.

Yes, I realise that if you run FCGID you already have this patch installed, but there's nothing wrong with having such information documented in various places.

Lastly, the config files .htutil.*.conf are installed by both Build.PL and Makefile.PL.

Bells and Whistles

For a huge range of features, in a package developed over many years, see Webmin:

However, I could not see anything in Webmin's standard packages which offered the same features as this module. And that's probably because of security concerns.


CGI::Application::Util::Diff ships with a default logging module, CGI::Application::Util::Logger.

The option to activate logging is 'logging', in .htutil.diff.conf.

If this line is missing, no attempt is made to log.

Note: The logger's own config file, .htutil.logger.conf by default, might also turn logging off.

The default 'logging' line looks something like:


You'll notice it refers to the Util/ directory, not the Util/Diff/ directory.

This is because this logging mechanism is meant to be shared among all modules in the CGI::Application::Util::* namespace.

This version of CGI::Application::Util::Diff does not contain a menuing system for such utilities, because there is as yet only this 1 module, but later versions will.

If the logging class cannot be loaded (with 'require'), the error is ignored, and no logging takes place, but a message is written to the web-server's log with Carp::carp.


This module is available as a Unix-style distro (*.tgz).

See for help on unpacking and installing distros.


At the very least, you will need to patch .htutil.diff.conf, since that's where HTML::Template's tmpl_path is stored, if using another path.

Config file options are documented in the config file itself.

Also, you may want to edit .htutil.logger.conf and .htutil.diff.actions.conf.

Install the module

Note: Build.PL and Makefile.PL refer to FCGI::ProcManager. If you are not going to use the fancy script, you don't need FCGI::ProcManager.

Install CGI::Application::Util::Diff as you would for any Perl module:

Run cpan: shell>sudo cpan CGI::Application::Util::Diff

or unpack the distro, and then either:

        perl Build.PL
        ./Build test
        sudo ./Build install


        perl Makefile.PL
        make (or dmake)
        make test
        make install

Install the HTML::Template files.

Copy the distro's htdocs/assets/ directory to your doc root.

Install the trivial instance script

Copy the distro's httpd/cgi-bin/util.diff.cgi to your cgi-bin/ directory, and make util.diff.cgi executable.

Install the fancy instance script

Copy the distro's htdocs/local/ directory to your doc root, and make util.diff executable.

Configure Apache to use /local/util.diff

If in fancy mode, add these to Apache's httpd.conf:

        LoadModule fcgid_module modules/


        <Location /local>
                SetHandler fcgid-script
                Options ExecCGI
                Order deny,allow
                Deny from all
                Allow from

Of course, use of '/local' is not mandatory; you could use any URL fragment there.

And don't forget to restart Apache after editing it's httpd.conf.

Start testing

Point your broswer at (trivial script), or (fancy script).


The command did nothing!

What you mean is that it did not perform according to your false expectations, and/or you did not read the section called Actions.

The user running the web server is the user who runs these actions, and hence their limited permissions means the actions are limited in what they are allowed to do.

The log always contains the word 'message'!

Right! The log is a database table, and the column heading you refer to should be there.


CGI::Application::Util::Diff was written by Ron Savage <> in 2009.

Home page:


Australian copyright (c) 2009, Ron Savage. All Programs of mine are 'OSI Certified Open Source Software'; you can redistribute them and/or modify them under the terms of The Artistic License, a copy of which is available at: