How to clean up Contact Form 7 temporary captcha files on IIS web servers

Published on Monday, 28 April 2014

Contact Form 7 (CF7) is a WordPress plugin that provides a simple but flexible contact form. On IIS, Contact Form 7 captcha has one HUGE disadvantage: temporary captcha files placed in wp-content/uploads/wpcf7_captcha, are not automatically removed. The files are made read only. Here is how to remove Contact Form 7 temporary captcha files on IIS...


In a short amount of time, the number of temporary captcha files created in wp-content/uploads/wpcf7_captcha by Contact Form 7, increases to enormous numbers. Slowing down your WordPress website.

Why Contact Form 7 temporary captcha files aren't cleaned up

The reason for Contact Form 7's temporary captcha files not being deleted is that all files are made read only, using the PHP function chmod().

The default folder in which these files are saved is wp-content/uploads/wpcf7_captcha. In a short amount of time this folder will be filled up with tens of thousands files...

Too many files for PHP and WordPress to process, so that your WordPress site becomes slow.

I've already described how to set or remove the read only attribute assigned to files. In this post we'll take it one step further to semi-automatically delete Contact Form 7's temporary captcha files.

Contact Form 7 can manage multiple contact forms, plus you can customize the form and the mail contents flexibly with simple markup. The form supports Ajax-powered submitting, CAPTCHA, Akismet spam filtering and so on.

Delete Contact Form 7's temporary captcha files

There are two ways to delete Contact Form 7's temporary captcha files.

#1: The first method involves editing a Contact Form 7 file called file.php, that is located in the /modules folder. Going through the file.php source there are two chmod() calls:

line 175 - 176:

// Make sure the uploaded file is only readable for the owner process
@chmod( $new_file, 0400 );

line 297:

@chmod( $dir, 0733 );

The actual cleaning up and deleting of those temporary files happens in the function wpcf7_cleanup_upload_files, starting at line 316. We look further to lines 331 - 333:

$stat = stat( $dir . $file );
if ( $stat['mtime'] + 60 < time() ) // 60 secs
    @unlink( $dir . $file );

On Windows Server IIS it's required to make the files normally accessible before deleting them with unlink(). So we need to add an extra chmod() call, just before the unlink() function.

These three lines now become four lines:

$stat = stat( $dir . $file );
if ( $stat['mtime'] + 60 < time() ) // 60 secs
    chmod($dir . $file, '0755');
    @unlink( $dir . $file );

Unfortunately this is a file modification to file.php you have to make after each and every plugin update. In Contact Form 7 5.1.1 with Really Simple Captcha, I had to make the change in the file contact-form-7/modules/really-simple-captcha.php, on line 553.

The second method is to write a PHP script / function that deletes files older than 'n' seconds, for instance 1800 (30 minutes).

Unfortunately you'd have to request the URL to this script manually for the files to be deleted. Or someone has to make a hook into wp_cron, a function or plugin.

You can always try to hook this function into WordPress' Cron utilizing the information from my post Optimize WordPress MySQL tables through Cron. As a Must-Use Plugin.

I'll provide you with a function for you to use and expand. Provided "AS-IS" of course.

PHP function to remove Contact Form 7's temporary captcha files

Create a new file and name it wp-maintenance.php for instance. Copy and past the code below:

<?php
/**
 * Function to delete all temporary files older 
 * than 30 minutes created by Contact Form 7 Captcha
 * reference on Stackoverflow:
 *   http://stackoverflow.com/questions/2205738/how-to-delete-files-from-directory-based-on-creation-date-in-php
 * 
 * Follow me on Twitter: @Jan_Reilink
 * Please donate: https://www.paypal.me/jreilink
 * 
 **/

//flmt: file last modified time
function delSessionFiles( $dir, $flmt ) {
	if( $handle = opendir( $dir ) ) {
		while( false !== ( $file = readdir( $handle ) ) ) {
			if( $file != "." && $file != ".." ) {
				$filelastmodified = filemtime( $dir .'/'.$file );
				if( ( time() - $filelastmodified ) > $flmt && is_file( $dir .'/'.$file ) ) {
					chmod( $dir .'/'.$file, '0755' );
					unlink( $dir .'/'.$file );
				}
				clearstatcache();
			}
		}
		closedir( $handle );
		return TRUE;
	}
}

if ( delSessionFiles( 'wp-content/uploads/wpcf7_captcha', '1800' ) === TRUE ) {
	echo "Contact Form 7 temp files deleted.";
}
?>

Upload this file to the root of your web site.

Now every time you request www.example.com/wp-maintenance.php all temporary files older than 1800 seconds (or 30 minutes) are deleted.

Psst, want to know how to validate MIME types in PHP?