<?php

class parser_ftp extends parser {
    private $host;
    private $user;
    private $pw;
    private $port;
    private $passive;
    private $localLogFile;
    private $remoteLogFile;
    private $con;
    private $logging;
    private $connected = 0;

    public function __construct($logfile, &$success, $host, $user, $pw, $port, $passive = true) {
        $this->logging = &$GLOBALS['logging'];
        $this->host = $host;
        $this->user = $user;
        $this->pw = $pw;
        $this->port = $port;
        $this->passive = $passive;
        $this->remoteLogFile["dir"] = dirname($logfile);
        $this->remoteLogFile["file"] = basename($logfile);

        $this->localLogFile = LOGDIR . "/ftplog.tmp";


        if (!$this->connect($errmsg)) {
            $success = false;
            $this->logging->write(MOD_ERROR, "FTP error: $errmsg");
        }
        else {
            $this->logging->write(MOD_NOTICE, "Successfully connected to FTP server: '$this->host' on port $this->port as '$this->user'");
        }

        parent::__construct($this->localLogFile, $success);
    }

    private function connect(&$errmsg = "") {
        $this->con = ftp_connect($this->host, $this->port, 5);
        if (!$this->con) {
            $errmsg = "Connection to $this->host on port $this->port failed";
            //No connection
            return false;
        }
        if (!ftp_login($this->con, $this->user, $this->pw)) {
            $errmsg = "Login failed with user $this->user";
            //Dir does not exist
            return false;
        }
        if (!ftp_pasv($this->con, $this->passive)) {
            $errmsg = "Passive mode not available at this server";
            //Passive mode not available
            return false;
        }
        if (!ftp_chdir($this->con, $this->remoteLogFile["dir"])) {
           $errmsg = "Dir does not exist: {$this->remoteLogFile['dir']}";
            //Dir does not exist
            return false;
        }

        $size = ftp_size($this->con, $this->remoteLogFile["file"]);
        if ($size == -1) {
            $errmsg = "File {$this->remoteLogFile["file"]} does not exist or server does not support SIZE";
            //Server does not support "size"
            return false;
        }
        if ($this->logpos === false) {
            $this->logpos = $size;
        }
        $fp = fopen($this->localLogFile, "w");
        if (!$fp) {
            $errmsg = "Error writing to LOCAL file $this->localLogFile, maybe not enough permissions";
            return false;
        }
        fseek($fp, $this->logpos -1, SEEK_SET);
        fwrite($fp, "\0", 1);
        fclose($fp);
        $this->connected = time();
        return true;
    }

    public function getNewLines() {
        if (!is_resource($this->con)) {
            $this->error(1);
            return array();
        }

        /*
        //Reconnect after 12h
        if (time() - $this->connected > 12 * 60 * 60) {
            $this->disconnect();
            sleep(2);
            if ($this->connect($errmsg)) {
                $this->logging->write(MOD_NOTICE, "Successfully reconnected after 12hrs");
            }
            else {
                $this->error(4);
            }
        }
        */

        $status = ftp_get($this->con, $this->localLogFile, $this->remoteLogFile["file"], FTP_BINARY, $this->logpos);

        if (!$status) {
            $this->error(2);
            return array();
        }

        clearstatcache();
        if (filesize($this->localLogFile) - $this->logpos > 140 * 300) { //140 Zeichen Durchnitt pro Zeile, 500 Zeilen maximal!!
            $this->error(3);
            return array();
        }

        $lines = parent::getNewLines();

        return $lines;
    }

    public function __destruct() {
        $this->disconnect();
    }

    private function disconnect() {
        file_put_contents($this->localLogFile, "");
        if (is_resource($this->con)) {
            ftp_quit($this->con);
        }
    }

    private function error($code = 0) {
        $this->logging->write(MOD_WARNING, "Error getting new loglines by FTP (code: $code), trying to reconnect...");
        $this->disconnect();

        $logpos = $this->logpos;

        for ($i = 1; $i <= 5; $i ++) {
            $this->logging->write(MOD_NOTICE, "waiting ".pow(2, $i)." seconds until next try...");
            sleep(pow(2, $i));
            if ($this->connect($errmsg)) {
                $this->logging->write(MOD_NOTICE, "Successfully reconnected to FTP server: '$this->host' on port $this->port as '$this->user'");
                $this->logpos = $logpos;
                return;
            }

            $this->logging->write(MOD_WARNING, "Reconnect ($i) failed: '$errmsg'");
        }

        $this->logging->write(MOD_ERROR, "FTP-Connection failed after 5 retries, quitting mod");

    }

}