Completed
Push — 1.1 ( 8e8af0...63c0ae )
by Johnny
04:43 queued 16s
created

Ftp::getTransferMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
namespace Redbox\Scan\Adapter;
3
use Redbox\Scan\Exception;
4
use Redbox\Scan\Report;
5
use Symfony\Component\Yaml\Yaml;
6
7
/**
8
 * Read and write files from a given ftp location.
9
 * see examples/ftp.php for a demonstration.
10
 *
11
 * @package Redbox\Scan\Adapter
12
 */
13
class Ftp implements AdapterInterface
14
{
15
    const FTP_MODE_ASCII  = FTP_ASCII;
16
    const FTP_MODE_BINARY = FTP_BINARY;
17
18
19
    protected $transfer_mode = self::FTP_MODE_ASCII;
20
    protected $host          = '';
21
    protected $username      = '';
22
    protected $password      = '';
23
    protected $filename      = '';
24
    protected $port          = 21;
25
26
    protected $timeout       = 90;
27
    protected $handle        = null;
28
29
    /**
30
     * You might think just connect to the ftp server from the constructor
31
     * but psr-4 dictates that autoloadable classes MUST NOT...
32
     *
33
     * Quote:
34
     * Autoloader implementations MUST NOT throw exceptions, MUST NOT raise errors of any level, and SHOULD NOT return a value.
35
     *
36
     * So we need to use authenticate() after we construct.
37
     *
38
     * @param string $host
39
     * @param string $username
40
     * @param string $password
41
     * @param string $filename
42
     * @param int $port
43
     * @param int $timeout
44
     */
45
    public function __construct($host = "", $username = "", $password = "", $filename = "", $port = 21, $timeout = 90)
46
    {
47
        $this->host     = $host;
48
        $this->username = $username;
49
        $this->password = $password;
50
        $this->filename = $filename;
51
        $this->timeout  = $timeout;
52
        $this->port     = $port;
53
    }
54
55
    /**
56
     * Set the connection transfermode to FTP_MODE_ASCII or FTP_MODE_BINARY.
57
     *
58
     * @param $transfer_mode
59
     */
60
    public function setTransferMode($transfer_mode)
61
    {
62
        $this->transfer_mode = $transfer_mode;
63
    }
64
65
    /**
66
     * Return the current TransferMode.
67
     *
68
     * @return int
69
     */
70
    public function getTransferMode()
71
    {
72
        return $this->transfer_mode;
73
    }
74
75
    /**
76
     * Set passive mode on or off. Please not that you can
77
     * only use this mode after you have authenticated the user.
78
     *
79
     * @param bool $status
80
     * @return mixed
81
     */
82
    public function setPassiveMode(bool $status)
83
    {
84
        return ftp_pasv($this->handle, $status);
85
    }
86
87
    /**
88
     * Disable passive mode and switch to active mode.
89
     */
90
    public function setActiveMode()
91
    {
92
        return $this->setPassiveMode(false);
93
    }
94
95
    /**
96
     * We should be so nice to terminate the construction of we are done.
97
     */
98
    public function __destruct()
99
    {
100
        if ($this->handle) {
101
            ftp_close($this->handle);
102
        }
103
    }
104
105
    /**
106
     * Authenticate to the ftp server.
107
     *
108
     * @return bool
109
     */
110
    public function authenticate()
111
    {
112
113
        set_error_handler(
114
            function () {
115
            }
116
        );
117
118
        $this->handle  = ftp_connect($this->host, $this->port, $this->timeout);
119
        $authenticated = ftp_login($this->handle, $this->username, $this->password);
120
121
        restore_error_handler();
122
123
        if ($this->handle === false) {
124
            throw new Exception\RuntimeException('Could not connect to host: '.$this->host);
125
        }
126
127
        if ($authenticated === false) {
128
            throw new Exception\RuntimeException('Could not authenticate to: '.$this->host);
129
        }
130
        return true;
131
    }
132
133
    /**
134
     * Read the previous scan results from the file system.
135
     *
136
     * @return array
137
     */
138
    public function read()
139
    {
140
        if ($this->handle === false)
141
            return false;
142
143
        $stream = fopen('php://memory', 'w');
144
145
        if (!$stream)
146
            return false;
147
148
        $data   = '';
149
        if ($ret = ftp_nb_fget($this->handle, $stream, $this->filename, $this->transfer_mode)) {
150
            while ($ret === FTP_MOREDATA) {
151
                rewind($stream);
152
                $data .=  stream_get_contents($stream);
153
                $ret = ftp_nb_continue($this->handle);
154
            }
155
            if ($ret != FTP_FINISHED) {
156
               return false;
157
            } else {
158
                $data = (array)Yaml::parse($data);
159
                return Report\Report::fromArray($data);
160
            }
161
        }
162
        return false;
163
    }
164
165
    /**
166
     * Write the report to the filesystem so we can reuse it
167
     * at a later stace when we invoke Redbox\Scan\ScanService's scan() method.
168
     *
169
     * @param Report\Report|null $report
170
     * @return bool
171
     */
172
    public function write(Report\Report $report = null)
173
    {
174
        if ($this->handle === false)
175
            return false;
176
177
        if ($report) {
178
179
            $stream = fopen('php://memory', 'w+');
180
            if (!$stream) return false;
181
            $data = $report->toArray();
182
            $data = Yaml::dump($data, 99);
183
184
            fwrite($stream, $data);
185
            rewind($stream);
186
187
            if (ftp_fput($this->handle, $this->filename, $stream, $this->transfer_mode)) {
188
                return true;
189
            } else {
190
                return false;
191
            }
192
        }
193
        return false;
194
    }
195
}