Issues (15)

src/FtpBridge.php (3 issues)

1
<?php
2
3
/**
4
 * This file is part of the Lazzard/ftp-bridge package.
5
 *
6
 * (c) El Amrani Chakir <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 */
12
13
namespace Lazzard\FtpBridge;
14
15
use Lazzard\FtpBridge\Logger\LoggerInterface;
16
use Lazzard\FtpBridge\Response\Response;
17
use Lazzard\FtpBridge\Stream\ActiveDataStream;
18
use Lazzard\FtpBridge\Stream\CommandStream;
19
use Lazzard\FtpBridge\Stream\DataStream;
20
use Lazzard\FtpBridge\Stream\PassiveDataStream;
21
use Lazzard\FtpBridge\Error\ErrorTrigger;
22
23
/**
24
 * @since  1.0
25
 * @author El Amrani Chakir <[email protected]>
26
 */
27
class FtpBridge
28
{
29
    /**
30
     * Transfer type representations.
31
     */
32
    const TR_TYPE_ASCII      = 'A';
33
    const TR_TYPE_BINARY     = 'I';
34
    const TR_TYPE_EBCDIC     = 'E';
35
    const TR_TYPE_LOCAL      = 'L';
36
    const TR_TYPE_NON_PRINT  = 'N';
37
    const TR_TYPE_TELNET     = 'T';
38
    const TR_TYPE_CR_CONTROL = 'C';
39
40
    /** @var LoggerInterface */
41
    public $logger;
42
43
    /** @var Response */
44
    public $response;
45
46
    /** @var CommandStream */
47
    protected $commandStream;
48
49
    /** @var DataStream */
50
    protected $dataStream;
51
52
    /**
53
     * FtpBridge constructor
54
     *
55
     * @param LoggerInterface|null $logger
56
     */
57
    public function __construct(LoggerInterface $logger = null)
58
    {
59
        $this->logger = $logger;
60
    }
61
62
    /**
63
     * Sends a command to the server thought the control channel.
64
     *
65
     * @param string $command
66
     *
67
     * @return bool
68
     */
69
    public function send($command)
70
    {
71
        if (!$this->commandStream || !is_resource($this->commandStream->stream)) {
72
            return !ErrorTrigger::raise("The FTP connection must be established first before try sending any commands.");
73
        }
74
75
        return $this->commandStream->write($command);
76
    }
77
78
    /**
79
     * Writes the string content to the data stream.
80
     *
81
     * @param string $string
82
     * 
83
     * @return bool
84
     */
85
    public function write($string)
86
    {
87
        if (!$this->dataStream || !is_resource($this->dataStream->stream)) {
88
            return !ErrorTrigger::raise("The FTP data connection must be established first 
89
                before try writing to the data stream.");
90
        }
91
92
        return $this->dataStream->write($string);
93
    }
94
95
    /**
96
     * Receives and gets the response from the command stream.
97
     * 
98
     * @return Response
99
     */
100
    public function receive()
101
    {
102
        if (!$this->commandStream || !is_resource($this->commandStream->stream)) {
103
            return !ErrorTrigger::raise("The FTP command connection not created yet.");
0 ignored issues
show
Bug Best Practice introduced by
The expression return ! Lazzard\FtpBrid...tion not created yet.') returns the type boolean which is incompatible with the documented return type Lazzard\FtpBridge\Response\Response.
Loading history...
104
        }
105
106
        return $this->response = new Response($this->commandStream->read());
107
    }
108
109
    /**
110
     * Receives and reads the data from the data stream.
111
     *
112
     * @return string
113
     */
114
    public function receiveData()
115
    {
116
        if (!$this->dataStream || !is_resource($this->dataStream->stream)) {
117
            return !ErrorTrigger::raise("The FTP data connection not created yet.");
0 ignored issues
show
Bug Best Practice introduced by
The expression return ! Lazzard\FtpBrid...tion not created yet.') returns the type boolean which is incompatible with the documented return type string.
Loading history...
118
        }
119
120
        return $this->dataStream->read();
121
    }
122
123
    /**
124
     * Opens an FTP connection.
125
     *
126
     * @param string $host     The remote host name or the IP address.
127
     * @param int    $port     [optional] The remote server port to connect to, if omitted the port 21 will be used.
128
     * @param int    $timeout  [optional] Specifies the connection timeout of all FTP transfer operations, default sets
129
     *                         to 90.
130
     * @param        $blocking $blocking [optional] The transfer mode, the blocking mode is the default.
0 ignored issues
show
Documentation Bug introduced by
The doc comment $blocking at position 0 could not be parsed: Unknown type name '$blocking' at position 0 in $blocking.
Loading history...
131
     *
132
     * @return bool Returns true on success, false on failure and an E_WARNING error raised.
133
     */
134
    public function connect($host, $port = 21, $timeout = 90, $blocking = true)
135
    {
136
        $this->commandStream = new CommandStream($this->logger, $host, $port, $timeout, $blocking);
137
        return $this->commandStream->open();
138
    }
139
140
    /**
141
     * Opens a passive data connection.    
142
     * 
143
     * @return bool
144
     */
145
    public function openPassive()
146
    {
147
        $this->dataStream = new PassiveDataStream($this->logger, $this->commandStream);
148
        return $this->dataStream->open();
149
    }
150
151
    /**
152
     * Opens an active data connection to the FTP server.
153
     *
154
     * @param string $activeIpAddress [optional] The IP address to send along with the PORT command, if omitted 
155
     *                                           the server IP address in the $_SERVER['SERVER_ADDR'] will be used.
156
     * 
157
     * @return bool
158
     */
159
    public function openActive($activeIpAddress = null)
160
    {
161
        $this->dataStream = new ActiveDataStream($this->logger, $this->commandStream, $activeIpAddress);
162
        return $this->dataStream->open();
163
    }
164
165
    /**
166
     * Logs into the FTP server.
167
     *
168
     * Note: this method must be called after a successful connection.
169
     *
170
     * @param string $username
171
     * @param string $password
172
     *
173
     * @return bool Returns true on success, false on failure and an E_WARNING error 
174
     *              will be raised.
175
     */
176
    public function login($username, $password)
177
    {
178
        $this->send("USER $username");
179
        $this->receive();
180
181
        if ($this->response->getCode() === 230) {
182
            return true;
183
        }
184
185
        if ($this->response->getCode() === 331) {
186
            $this->send("PASS $password");
187
            $this->receive();
188
189
            // TODO 202 code
190
            if ($this->response->hasCode(202, 230)) {
191
                return true;
192
            }
193
194
            return !ErrorTrigger::raise($this->response->getMessage());
195
        }
196
197
        return !ErrorTrigger::raise($this->response->getMessage());
198
    }
199
200
    /**
201
     * Sets the transfer type for the next transfer operation.
202
     *
203
     * @param string     $type        The transfer type can be either {@link FtpBridge::TR_TYPE_BINARY} or {@link FtpBridge::TR_TYPE_ASCII} 
204
     *                                or {@link FtpBridge::TR_TYPE_EBCDIC}.
205
     * @param string|int $secondParam Specifies how the text should be interpreted for the file types {@link FtpBridge::TR_TYPE_ASCII} 
206
     *                                and {@link FtpBridge::TR_TYPE_EBCDIC}, it can be either {@link FtpBridge::TR_TYPE_NON_PRINT},
207
     *                                {@link FtpBridge::TR_TYPE_TELNET} or {@link TR_TYPE_CONTROL}.
208
     *                                For the {@link FtpBridge::TR_TYPE_LOCAL} an integer must be specified to specify the 
209
     *                                number of bits per byte on the local system.
210
     *                     
211
     * @return bool
212
     */
213
    public function setTransferType($type, $secondParam = null)
214
    {
215
        $this->send(sprintf("TYPE %s%s", $type, $secondParam ? " $secondParam" : ''));
216
        $this->receive();
217
218
        return $this->response->getCode() === 200;
219
    }
220
}