Completed
Push — 1.1 ( c89835...51b260 )
by Johnny
02:00
created

Ftp::setPassiveMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 3
ccs 0
cts 3
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
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
        $this->transfer_mode = $transfer_mode;
62
    }
63
64
65
    /**
66
     * Set passive mode on or off. Please not that you can
67
     * only use this mode after you have authenticated the user.
68
     *
69
     * @param bool $status
70
     */
71
    public function setPassiveMode(bool $status) {
72
        ftp_pasv($this->handle, $status);
73
    }
74
75
    /**
76
     * Disable passive mode and switch to active mode.
77
     */
78
    public function setActiveMode() {
79
        return $this->setPassiveMode(false);
80
    }
81
82
83
    /**
84
     * We should be so nice to terminate the construction of we are done.
85
     */
86
    public function __destruct()
87
    {
88
        if ($this->handle) {
89
            ftp_close($this->handle);
90
        }
91
    }
92
93
    /**
94
     * Authenticate to the ftp server.
95
     *
96
     * @return bool
97
     */
98
    public function authenticate()
99
    {
100
101
        set_error_handler(
102
            function () {
103
            }
104
        );
105
106
        $this->handle  = ftp_connect($this->host, $this->port, $this->timeout);
107
        $authenticated = ftp_login($this->handle, $this->username, $this->password);
108
109
        restore_error_handler();
110
111
        if ($this->handle === false) {
112
            throw new Exception\RuntimeException('Could not connect to host: '.$this->host);
113
        }
114
115
        if ($authenticated === false) {
116
            throw new Exception\RuntimeException('Could not authenticate to: '.$this->host);
117
        }
118
        return true;
119
    }
120
121
    /**
122
     * Read the previous scan results from the file system.
123
     *
124
     * @return array
125
     */
126
    public function read()
127
    {
128
        if ($this->handle === false)
129
            return false;
130
131
        $stream = fopen('php://memory', 'w');
132
133
        if (!$stream)
134
            return false;
135
136
        $data   = '';
137
        if ($ret = ftp_nb_fget($this->handle, $stream, $this->filename, $this->transfer_mode)) {
138
            while ($ret === FTP_MOREDATA) {
139
                rewind($stream);
140
                $data .=  stream_get_contents($stream);
141
                $ret = ftp_nb_continue($this->handle);
142
            }
143
            if ($ret != FTP_FINISHED) {
144
               return false;
145
            } else {
146
                $data = Yaml::parse($data);
147
                return Report\Report::fromArray($data);
0 ignored issues
show
Bug introduced by
It seems like $data defined by \Symfony\Component\Yaml\Yaml::parse($data) on line 146 can also be of type string; however, Redbox\Scan\Report\Report::fromArray() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
148
            }
149
        }
150
        return false;
151
    }
152
153
    /**
154
     * Write the report to the filesystem so we can reuse it
155
     * at a later stace when we invoke Redbox\Scan\ScanService's scan() method.
156
     *
157
     * @param Report\Report|null $report
158
     * @return bool
159
     */
160
    public function write(Report\Report $report = null)
161
    {
162
        if ($this->handle === false)
163
            return false;
164
165
        if ($report) {
166
167
            $stream = fopen('php://memory', 'w+');
168
            if (!$stream) return false;
169
            $data = $report->toArray();
170
            $data = Yaml::dump($data, 99);
171
172
            fwrite($stream, $data);
173
            rewind($stream);
174
175
            if (ftp_fput($this->handle, $this->filename, $stream, $this->transfer_mode)) {
176
                return true;
177
            } else {
178
                return false;
179
            }
180
        }
181
        return false;
182
    }
183
}