Sysadmins of the North

Technical blog, where topics include: computer, server, web, sysadmin, MySQL, database, virtualization, optimization and security

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

Contact Form 7 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 own 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:

This may interest you:   How to optimize your WordPress hosting - 9+ practical tips

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.

#2: 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: @HertogJanR
 * 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.

This may interest you:   Add a delay to your WordPress login form

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?

4 Comments

  1. Great article and the only article I found to solve my problems of deleting the temporary files. I just added some more lines to cleanup the uploads of CSF7, i.e.,

    if (delSessionFiles(‘wp-content/uploads/wpcf7_uploads’, ‘1800’) === TRUE) {
    echo “Contact Form 7 uploaded files deleted.”;
    }

    • Hi Imtiaz, thank you for your comment. Great to hear my post provided you with a solution for this problem.

      Deleting the contents of the wpcf7_uploads file is a nice addition!

      • Hi Jan,

        I came accross this solution and it worked great for me by uploading it to the root and calling the file.
        However, it’s still a manual process. Is there any way that this could be automated? as in have it periodically call that script to delete the temp files?

        Thanks,

        • Hi Wade Lim,

          Great to hear it worked great, and yes, out of the box it’s a manual process. But you can schedule a cURL or wget request as a cron job, or come to think about it: you can try to hook the clean-up function into a WordPress Cron through a Must Use Plugin. You can find some more information about this in my post Optimize WordPress MySQL tables through Cron.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

shares