Here is the code when run finds all the changed php files in the directory area tt stores file information of all php files and then compares with the subsequent run.
I've installed it in root crontab using the line below. It runs once in every two minutes. On my installation it take only 3-5 seconds to run. "*/2" refers to that. If you want once in an hour then change "*/2" to "59" ie., run every hour at 59 minutes.
*/2 * * * * /usr/bin/php /home/myuser/usefulscripts/locate-changed-php-files.php /home/myuser
define('LOC', '/home/myuser/usefulscripts/all-php-file-db.sr');
This is the file name of a database where it'll keep all info about file locations and sizes. This file need not be already existing. But change this path :"'/home/myuser/usefulscripts" to an existing path. Better it should be the directory in which this program will be placed by you.
Run Argument
It needs to be run with first argument of directory and all sub-directories will also be scanned for files. On linux it'd be like /home/username
Change it to your email id to get changed file notifications
Removing permission
Although not recommended, you can uncomment 3 lines beginning with chown - which will make all new files unreadable as soon as those are created/changed.
$ignoredFolders
Add the absolute path of directories which will be skipped if you're sure that no php hacks can get into it.
php_file_extensions
This is an array of php extensions which can contain php code. In Drupal those are *.php, *.inc and *.module. If you don't want then remove those or add others.
<?php $debug = false; define('LOC', '/home/myuser/usefulscripts/all-php-file-db.sr'); place_htaccess(); if ($argc != 2) { print "Usage $argv[0] <dir>\n"; exit; } if (!file_exists($argv[1])) { print "Usage $argv[0] <dir>\nDirectory does not exist!\n"; exit; } $warnings = array(); if (file_exists(LOC)) { $warnings["SR file:" . LOC . " exists!"] = ''; $filesarray = unserialize(file_get_contents(LOC)); } else { // name=>ctime,file if it is changed $filesarray = array(); $warnings["SR file:" . LOC . " NOT FOUND. will be created!"] = ''; } $newfiles = array(); $changedfiles = array(); $ignoredFolders = array( '/home/myuser/public/forum.mysite2.com/public/cache', '/home/myuser/public/forum.mysite1.org/public/cache'); $php_file_extensions = array("php" => 1, "inc" => 1, "module" => 1); $iter = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($argv[1], RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD // Ignore "Permission denied" ); $paths = array($argv[1]); foreach ($iter as $path => $dir) { if ($dir->isDir()) { @$warnings['Total directories found']++; if (isset($ignoredFolders[$path])) { if ($debug) { print "Skipped Directory: " . $dir->getPathname() . "\n"; } @$warnings['Total skipped directories']++; continue; } } else { if (!in_array_beginning_with($dir->getPathname(), $ignoredFolders)) { $filename = $dir->getBasename(); $extn = $dir->getExtension(); if (isset($php_file_extensions[strtolower($extn)])) { @$warnings['Total processed files']++; if ($debug) { print "Processed: " . $dir->getPathname() . "\n"; } process($dir); } } else { if ($debug) { print "Skipped File: " . $dir->getPathname() . "\n"; } } } } $warnings['Total new files found=' . count($newfiles)] = ''; $warnings['Total changed files found=' . count($changedfiles)] = ''; $msg = ' 7y782p3\r\n'; $sub = ''; $ALLSUCCESS = false; if (empty($newfiles) && empty($changedfiles)) { $sub = "Success; No files changed!"; $msg = "Success; No files changed!"; $ALLSUCCESS = true; } else { //overwrite file_put_contents(LOC, serialize($filesarray)); $warnings['Overwritten/created SR file:' . LOC] = ''; $sub = "PROBLEMS FOUND! " . count($newfiles) . " new files/" . count($changedfiles) . " changed files"; $i = 1; foreach (array_keys($newfiles) as $file) { if ($i == 1) { $msg .="New Files\r\n"; } $msg .= "\r\n" . ($i++) . ") $file"; //Just uncomment these three files if you don't want to change it's permission to 000 //chmod($file,000); //chown($file,'root'); //chgrp($file,'root'); } $i = 1; foreach (array_keys($changedfiles) as $file) { if ($i == 1) { $msg .="Changed Files\r\n"; } $msg .= "\r\n" . ($i++) . ") $file"; chmod($file, 000); } } if (!$ALLSUCCESS || checkFirsttimerun()) { mail('rag.myuser@gmail.com', $sub, substr($msg, 0, 800)); } $warnings['Sent email'] = ''; $dbg = "\n\n\n-------------------------------------------------\nStarted executing on :" . date('c'); foreach ($warnings as $key => $value) { if (empty($value)) { $dbg .= "$key\n"; } else { $dbg .= "$key => $value\n"; } } $dbg .= "\n\n*******$sub********\n\n$msg\n"; $fp = fopen(dirname(LOC) . "/all-php-file-debug.txt", "a"); fprintf($fp, "%s", $dbg); fclose($fp); exit(0); //$dir the file handle to file function process($dir) { global $filesarray; global $newfiles; global $changedfiles; $fullfile = $dir->getPathname(); if (isset($filesarray[$fullfile])) { //file already in the db if ($filesarray[$fullfile][0] == $dir->getCTime()) { //no change //skip it } else { //if the file size is changed then only consider it if ($dir->getSize() != $filesarray[$fullfile][1]) { $filesarray[$fullfile] = array($dir->getCTime(), $dir->getSize()); //store the new info $changedfiles[$fullfile] = 1; //mark it as changed } else { //else it is ignorable change $filesarray[$fullfile] = array($dir->getCTime(), $dir->getSize()); //store the new info //don't consider it changed. } } } else { $filesarray[$fullfile] = array($dir->getCTime(), $dir->getSize()); $newfiles[$fullfile] = 1; } } /* * Returns true if the path begins with any of the dirs passed */ function in_array_beginning_with($path, $array) { foreach ($array as $begin) { if (strncmp($path, $begin, strlen($begin)) == 0) { return true; } } return false; } function checkFirsttimerun() { define('CHECKFILE', dirname(LOC) . '/locate-changed-php-files-MONITOR'); if (file_exists(CHECKFILE)) { $stat = stat(CHECKFILE); } else { $stat[9] = 0; //consider it changed } //now write the file file_put_contents(CHECKFILE, "Empty"); if (date('j', $stat[9]) != date('j')) { //new day return true; } return false; } //Place htaccess file in tmp function place_htaccess() { if (!file_exists("/tmp/.htaccess")) { $str = " # Turn off all options we don't need. Options None Options +FollowSymLinks # Set the catch-all handler to prevent scripts from being executed. SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 <Files *> # Override the handler again if we're run later in the evaluation list. SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 </Files> # If we know how to do it safely, disable the PHP engine entirely. <IfModule mod_php5.c> php_flag engine off </IfModule> Deny from all "; file_put_contents("/tmp/.htaccess", $str); } }