<?php
class Kontakt {
    private 
$ip '';
    private 
$adminMail 'mail@example.com';
    private 
$tmpFile '/kontakt.tmp.php';
    private 
$requestZeiten = array();
    private 
$question 'Nenne eine Farbe aus der deutschen Fahne';
    private 
$answers = array('schwarz','rot','gold','gelb');
    private 
$posts = array();
    private 
$entryAdress '';
    private 
$postPrefix 'kontakt-';
    private 
$spammerMessages = array(
        
'time' => 'Ich kenne niemanden, der in 10 Sekunden ein solches Formular füllt!',
        
'question' => 'Sie haben meine Frage nicht korrekt beantwortet, bitte berichtigen Sie dieses!',
        
'incomplete' => 'Sie haben nicht alle notwendigen Felder ausgefüllt, bitte holen Sie dies nach!',
        
'too_many_submits' => 'Sie haben zu oft in kurzer Zeit versucht, mir eine Nachricht zu schicken!',
        
'too_short' => 'Ich bezweifel dass Sie wirklich mit mir in Kontakt treten wollen, ansonsten wäre Ihr Text länger!',
        
'wrong_email' => 'Ihre email wurde nicht korrekt validiert, bitte geben Sie eine andere Adresse an.',
        
'machine_suspicion' => 'Ich vermute, Sie haben diese Seite direkt mit POST-Parametern aufgerufen und schließe daraus auf Spam von Ihnen!<br />Ist dies nicht so, oder wissen Sie nicht wovon ich da überhaupt rede, so überlesen Sie bitte diesen Absatz und klicken einfach nochmal unten auf "Kontakt aufnehmen".'
    
);
    private 
$haveToSendFields = array('name''mail''frage''nachricht''url'); # url ist eine ablenkung für bots!
    
public $emptyFields = array();
    private 
$errors = array();
    private 
$minTimeToWrite 10;
    private 
$minTextLength 8# wordcount in message!
    
private $maxRssEntries 25;
    private 
$timeBeforeElapse 3600# in seconds
    
private $time;
    public function 
__construct(&$request false){
        
$this->tmpFile dirname(__FILE__) . $this->tmpFile;
        
$this->ip = isset($_SERVER["HTTP_X_FORWARDED_FOR"]) ? $_SERVER["HTTP_X_FORWARDED_FOR"] :
                    isset(
$_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '0.0.0.0';
        
$this->ip preg_replace("@:[a-f0-9]+$@"":0000"$this->ip);
        
$this->ip preg_replace("@\.\d+$@"".0"$this->ip);
        
$this->time time();
        if(!
is_file($this->tmpFile)){
            
$this->writeTmpData('');
        }
        require_once(
$this->tmpFile);
        
$this->requestTimes $requestTimes;
        if(
$_SERVER['REQUEST_METHOD'] === 'POST'){
            
$this->cachePosts();
            if(
$this->checkEntries()){
                
$this->saveAsRss();
                
$user $this->posts['url'];
                
# mail ist zwar schon fertig, aber ich brauche es nicht,
                # bevor nicht das komplette Script fertig ist.
            #    $this->mailToAdmin(); # if possible!
            
}
        }else{
            
$this->prepareUser();
            
$user false;
        }
        
$this->deleteOldRequests($user);
    }
    private function 
mailToAdmin(){
        
$to 'mail@example.com';
        
$subject 'Kontaktaufnahme auf http://'.$_SERVER['SERVER_NAME'];
        
$message "Ein Nutzer will mit Ihnen in kontakt treten.\n\n".$this->entryAdress;
        
$headers 'From: kontakt-formular@' $_SERVER['SERVER_NAME'] . "\r\n" .
                    
'Reply-To: webmaster@example.com' "\r\n" .
                    
'X-Mailer: PHP/' phpversion();
        if(
function_exists('mail'))
            
mail($to$subject$message$headers);
    }
    private function 
saveAsRss(){
        
$rsshead = <<<HERE
<?xml version="1.0" encoding="utf-8"?>
 
<rss version="2.0">
 
    <channel>
        <title>Kontaktanfragen</title>
        <link>http://nemoinho.lima-city.de</link>
        <description>Die letzten 
{$this->maxRssEntries} Kontaktanfragen von nemoinho.lima-city.de</description>
        <language>de-de</language>

HERE;
        
$rssfeed dirname(__FILE__).'/kontakt.rss';
        if(
is_file($rssfeed) === false){
            
$rss "\n\t</channel>\n\n</rss>";
        }else{
            
$max 3+$this->maxRssEntries*7;
            
$rss file($rssfeed);
            if(
count($rss) > $max){
                
$i count($rss)-4;
                while(
$i>=$max){
                    
$rss[$i--] = '';
                }
            }
            for(
$i=9;$i--;){
                
$rss[$i]='';
                echo 
$rss[$i];
            }
            
$rss implode($rss);
        }
        
$entries $this->posts;
        
$entries['nachricht'] = preg_replace("@\r\n|\n|\r@"''nl2br(addslashes(preg_replace("@<(.*?)>@""&lt;$1&gt;"$entries['nachricht']))));
        
$now date("D, d M o G:i:s +0200");
        
$newentry "\n\t\t<item>\n\t\t\t<title>".$entries['name'].' '.$entries['mail']."</title>\n\t\t\t<description><![CDATA[".$entries['nachricht']."<br />]]></description>\n\t\t\t<author>".$entries['name']."</author>\n\t\t\t<pubDate>".$now."</pubDate>\n\t\t</item>\n";
        
$rss $rsshead.$newentry.$rss;
        
file_put_contents($rssfeed$rss);
        
chmod($rssfeed0766);
    }
    private function 
cachePosts(){
            foreach(
$_POST as $k => $v){
                
$this->posts[str_replace($this->postPrefix''$k)] = $v;
            }
    }
    private function 
writeTmpData($str$new false){
        if(!
is_file($this->tmpFile) || $new){
            
file_put_contents($this->tmpFile"<?php\nif(@get_class() != '".__CLASS__."')return;\n\$requestTimes=array();\n");
        }
        
file_put_contents($this->tmpFile$strFILE_APPEND);
    }
    private function 
prepareUser(){
        
$str '$requestTimes[\''.$this->createIndividualNumber()."'] = {$this->time};\n";
        
$this->writeTmpData($str);
    }
    private function 
cacheErrors($error true){
        if(
$error === true)return;
        
$this->errors[] = $error;
    }
    private function 
checkEntries(){
        
$this->cacheErrors($this->checkForCompleteFields());
        
$this->cacheErrors($this->checkForPermission());
        
$this->cacheErrors($this->checkQuestion());
        
$this->cacheErrors($this->checkEMail());
        
$this->cacheErrors($this->checkWordCount());
        if(empty(
$this->errors))return true;
    }
    public function 
showMessages(){
        if(!empty(
$this->errors) || empty($_POST)){
    
#        echo '<p class="information">Es sind ein paar Fehler aufgetreten, während Sie mir eine Nachricht schreiben wollten.</p>'."\n";
            
foreach($this->errors as $v){
                echo 
"<p class=\"interactive-error\">$v</p>\n";
            }
            return 
false;
        }else{
            echo 
"<p>Danke für Ihre Nachricht, ich werde Ihnen so schnell wie möglich antworten!</p>\n";
            return 
true;
        }
        return 
false;
    }
    private function 
deleteOldRequests($knownEntry false){
        
$str '';
        
$redo false;
        foreach(
$this->requestTimes as $k => $v){
            
# Falls die Zeit noch nicht abgelaufen ist,
            # und $knownEntry !== $k ist
            
if($this->time $v $this->timeBeforeElapse && $k !== $knownEntry){
                
$str .= "\$requestTimes['$k'] = $v;\n";
            }else{
                
$redo true;
            }
        }
        if(
$redo)
            
$this->writeTmpData($str,true);
    }
    private function 
checkForPermission(){
        if(!isset(
$this->requestTimes[$this->posts['url']])){
            return 
$this->spammerMessages['machine_suspicion'];
        }elseif(
$this->time $this->requestTimes[$this->posts['url']] < $this->minTimeToWrite){
            return 
$this->spammerMessages['time'];
        }
        return 
true;
    }
    private function 
checkForCompleteFields(){
        foreach(
$this->haveToSendFields as $v){
            if(empty(
$this->posts[$v]) || trim($this->posts[$v]) == ''){
                
$this->emptyFields[$v] = true;
            }
        }
        if(!empty(
$this->emptyFields)){
            return 
$this->spammerMessages['incomplete'];
        }
        return 
true;
    }
    public function 
checkWordCount(){
        if(isset(
$this->emptyFields['nachricht']) || $_SERVER['REQUEST_METHOD'] !== 'POST')return true;
        if(
preg_match_all("/[^\s]\b/"$this->posts['nachricht'], $matches) <= $this->minTextLength){
            return 
$this->spammerMessages['too_short'];
        }
        return 
true;
    }
    public function 
checkQuestion(){
        if(isset(
$this->emptyFields['frage']) || $_SERVER['REQUEST_METHOD'] !== 'POST')return true;
        
$flipAnswers array_flip($this->answers);
        
$questionValue strtolower(trim($this->posts['frage']));
        if(empty(
$this->posts['frage']) || !$flipAnswers[$questionValue]){
            return 
$this->spammerMessages['question'];
        }
        return 
true;
    }
    public function 
checkEMail(){
        if(isset(
$this->emptyFields['mail']) || $_SERVER['REQUEST_METHOD'] !== 'POST')return true;
        if(!
preg_match("/^.+@.+\.\w{2,4}$/"$this->posts['mail'])){ # pie mal auge e-mail validation :)
            
return $this->spammerMessages['wrong_email'];
        }
        return 
true;
    }
    public function 
createIndividualNumber(){
        return 
md5(md5($_SERVER['HTTP_USER_AGENT']).$this->ip.$this->time);
    }
}
$kk = new Kontakt($request);
?>