SFTP::is_file()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
namespace LibSSH2\Sessions;
3
4
use LibSSH2\Authentication\Authentication;
5
use LibSSH2\Configuration;
6
use LibSSH2\Connection;
7
8
/**
9
 * SFTP class.
10
 *
11
 * SFTP interface.
12
 *
13
 * @package LibSSH2\Sessions
14
 */
15
class SFTP extends Connection
16
{
17
18
    /**
19
     * SFTP connection resource.
20
     *
21
     * @var resource
22
     */
23
    private $sftp;
24
25
    /**
26
     * Constructor.
27
     *
28
     * @param  instance $configuration  Configuration instance
29
     * @param  instance $authentication Authentication instance
30
     * @return void
31
     */
32
    public function __construct(Configuration $configuration, Authentication $authentication)
33
    {
34
        parent::__construct($configuration, $authentication);
35
36
        $this->sftp = @ssh2_sftp($this->connection);
37
        if (!$this->sftp)
38
        {
39
            throw new \RuntimeException($this->get_error_message());
40
        }
41
    }
42
43
    /**
44
     * Copies file.
45
     *
46
     * @param  string $srcfile  path to the source file
47
     * @param  string $destfile path to the destination file
48
     * @return void
49
     */
50
    final public function copy($srcfile, $destfile)
51
    {
52
        if ($this->is_file($srcfile) === FALSE)
53
        {
54
            $this->set_error('Local file '.$srcfile.' does not exist.');
55
            $this->set_exitstatus(1);
56
            return;
57
        }
58
59
        if (@copy($this->sftp_url($srcfile), $this->sftp_url($destfile)) === FALSE)
60
        {
61
            $this->set_error($this->get_error_message());
62
            $this->set_exitstatus(1);
63
            return;
64
        }
65
        $this->set_output('Successfully copied file at: '.$srcfile.' to '.$destfile);
66
        $this->set_exitstatus(0);
67
    }
68
69
    /**
70
     * Removes files.
71
     *
72
     * Caveats:
73
     *		-	accepts one or more files (recursive)
74
     *
75
     * @param  mixed $files files to remove
76
     * @return void
77
     */
78
    final public function delete($files)
79
    {
80
        $files = !is_array($files) ? [$files] : $files;
81
        foreach ($files as $file)
82
        {
83
            if ($this->is_file($file))
84
            {
85
                if (@unlink($this->sftp_url($file)) === false)
86
                {
87
                    $this->set_error($this->get_error_message());
88
                    $this->set_exitstatus(1);
89
                    return;
90
                }
91
                continue;
92
            }
93
        }
94
        $this->set_output('Successfully deleted remote file(s) at: '.implode(', ', $files));
95
        $this->set_exitstatus(0);
96
    }
97
98
    /**
99
     * Tells whether the filename is a directory.
100
     *
101
     * @param  string $path directory path
102
     * @return boolean
103
     */
104
    final public function is_dir($path)
105
    {
106
        return is_dir($this->sftp_url($path));
107
    }
108
109
    /**
110
     * Tells whether the filename is a file.
111
     *
112
     * @param  string $path directory path
113
     * @return boolean
114
     */
115
    final public function is_file($path)
116
    {
117
        return is_file($this->sftp_url($path));
118
    }
119
120
    /**
121
     * Directory listing.
122
     *
123
     * @param  string $path directory path
124
     * @return void
125
     */
126
    final public function ls($path)
127
    {
128
        $files = [];
129
        if ($handle = @opendir($this->sftp_url($path)))
130
        {
131
            while (($file = @readdir($handle)) !== false)
132
            {
133
                if ($file != '.' && $file != '..')
134
                {
135
                    $filename = rtrim($path, '/').'/'.$file;
136
                    if ($this->is_dir($filename))
137
                    {
138
                        $files['directories'][] = $filename;
139
                    }
140
					
141
                    if ($this->is_dir($filename) === false)
142
                    {
143
                        $files['files'][] = $filename;
144
                    }
145
                }
146
            }
147
            closedir($handle);
148
        }
149
        $this->set_output($files);
150
        $this->set_exitstatus(0);
151
    }
152
153
    /**
154
     * Returns pathnames matching a pattern (for files only & hidden files).
155
     *
156
     * @param  string $directory directory
157
     * @param  mixed  $pattern   pattern (does not support tilde expansion)
158
     * @return mixed  matched files or null
159
     */
160
    final public function glob($directory, $pattern = '')
161
    {
162
        if ($this->is_dir($directory) == false)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
163
        {
164
            $this->set_error($this->get_error_message());
165
            $this->set_exitstatus(1);
166
            return;
167
        }
168
		
169
        $handle = opendir($this->sftp_url($directory));
170
        while (($file = readdir($handle)) !== false)
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $dir_handle of readdir() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

170
        while (($file = readdir(/** @scrutinizer ignore-type */ $handle)) !== false)
Loading history...
171
        {
172
            $files[] = preg_grep('/(^.*'.$pattern.'.*$)/', explode(PHP_EOL, $file));
173
        }
174
175
        if (empty($files))
176
        {
177
            $this->set_output([]);
178
            $this->set_exitstatus(0);
179
            return;
180
        }
181
182
        $files = array_reduce($files, 'array_merge', []);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $files does not seem to be defined for all execution paths leading up to this point.
Loading history...
183
        $files = array_diff($files, ['.', '..']);
184
185
        $_files = [];
186
        foreach ($files as $file)
187
        {
188
            $_files[] = rtrim($directory, '/').'/'.$file;
189
        }
190
        $this->set_output($_files);
191
        $this->set_exitstatus(0);
192
    }
193
194
    /**
195
     * Create new directory.
196
     *
197
     * @param  mizxed $directories path to the directory
0 ignored issues
show
Bug introduced by
The type LibSSH2\Sessions\mizxed was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
198
     * @param  int    $mode        directory permission mode value (octal)
199
     * @param  bool   $recursive   create directories as needed
200
     * @param  int    $chgrp       change gid for directory
201
     * @return bool
202
     */
203
    final public function mkdir($directories, $mode = 0777, $recursive = false)
204
    {
205
        $directories = !is_array($directories) ? [$directories] : $directories;
0 ignored issues
show
introduced by
The condition ! is_array($directories) can never be false.
Loading history...
206
        foreach ($directories as $directory)
207
        {
208
            if (@mkdir($this->sftp_url($directory), $mode, $recursive) === false)
209
            {
210
                $this->set_error($this->get_error_message());
211
                $this->set_exitstatus(1);
212
                return;
213
            }
214
        }
215
        $this->set_output('Successfully created remote directory(ies) at: '.implode(', ', $directories));
216
        $this->set_exitstatus(0);
217
    }
218
219
    /**
220
     * Moves file to different path (rename).
221
     *
222
     * @param  string $oldfile path to the old file
223
     * @param  string $newfile path to the new file
224
     * @return void
225
     */
226
    final public function rename($oldfile, $newfile)
227
    {
228
        if ($this->is_file($oldfile) === false)
229
        {
230
            $this->set_error('Local file '.$oldfile.' does not exist.');
231
            $this->set_exitstatus(1);
232
            return;
233
        }
234
235
        if (!@ssh2_sftp_rename($this->sftp, $oldfile, $newfile))
236
        {
237
            $this->set_error($this->get_error_message());
238
            $this->set_exitstatus(1);
239
            return;
240
        }
241
        $this->set_output('Successfully renamed remote file at: '.$oldfile.' to '.$newfile);
242
        $this->set_exitstatus(0);
243
    }
244
245
    /**
246
     * Removes directory.
247
     *
248
     * Caveats:
249
     *		-	directories that are not empty are emptied then deleted
250
     *		-	accepts one or more directories (recursive)
251
     *
252
     * @param  mixed   $directories directory or directories to remove
253
     * @return boolean
254
     */
255
    final public function rmdir($directories)
256
    {
257
        $directories = !is_array($directories) ? [$directories] : $directories;
258
        foreach ($directories as $directory)
259
        {
260
            if ($this->is_dir($directory))
261
            {
262
                start:
263
                $this->ls($directory)['files'];
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->ls($directory) targeting LibSSH2\Sessions\SFTP::ls() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
264
                $stdout = $this->get_output();
265
                $files = array_key_exists('files', $stdout) ? $stdout['files'] : [];
266
                if (count($files) == 0)
267
                {
268
                    if (@rmdir($this->sftp_url($directory)) === false)
269
                    {
270
                        $this->set_error($this->get_error_message());
271
                        $this->set_exitstatus(1);
272
                        return;
273
                    }
274
                    continue;
275
                }
276
277
                if (count($files) != 0)
278
                {
279
                    $this->delete($files);
280
                    goto start;
281
                }
282
            }
283
        }
284
        $this->set_output('Successfully removed remote directory(ies) at: '.implode(', ', $directories));
285
        $this->set_exitstatus(0);
286
    }
287
288
    /**
289
     * Sends a file via SCP.
290
     *
291
     * @param  mixed   $local  		source file(s) (local)
292
     * @param  string  $remote_dir  destination directory (remote)
293
     * @param  integer $mode   		permissions on the new file
294
     * @return void
295
     */
296
    final public function put($local_files, $remote_dir, $mode = 0750)
297
    {
298
        $local_files = !is_array($local_files) ? [$local_files] : $local_files;
299
        foreach ($local_files as $local_file)
300
        {
301
            if (!@ssh2_scp_send($this->connection, $local_file, rtrim($remote_dir, '/').'/'.basename($local_file), $mode))
302
            {
303
                $this->set_error($this->get_error_message());
304
                $this->set_exitstatus(1);
305
                return;
306
            }
307
        }
308
        $this->set_output('Successfully sent local files to remote host at: '.implode(', ', $local_files));
309
        $this->set_exitstatus(0);
310
    }
311
312
    /**
313
     * Recieves a file via SCP.
314
     *
315
     * @param  mixed   $local  		source file(s) (local)
316
     * @param  string  $remote_dir  destination directory (remote)
317
     * @return void
318
     */
319
    final public function get($remote_files, $local_dir)
320
    {
321
        $remote_files = !is_array($remote_files) ? [$remote_files] : $remote_files;
322
        foreach ($remote_files as $remote_file)
323
        {
324
            if (!@ssh2_scp_recv($this->connection, $remote_file, rtrim($local_dir, '/').'/'.basename($remote_file)))
325
            {
326
                $this->set_error($this->get_error_message());
327
                $this->set_exitstatus(1);
328
                return;
329
            }
330
        }
331
        $this->set_output('Successfully received remote files: '.implode(', ', $remote_files));
332
        $this->set_exitstatus(0);
333
    }
334
335
    /**
336
     * Returns stat a file on a remote filesystem.
337
     *
338
     * @param  string $path directory path
339
     * @return void
340
     */
341
    final public function stat($path)
342
    {
343
        $statinfo = ssh2_sftp_stat($this->sftp, $path);
344
345
        if ($statinfo === false)	
0 ignored issues
show
introduced by
The condition $statinfo === false can never be true.
Loading history...
346
        {
347
            $this->set_error($this->get_error_message());
348
            $this->set_exitstatus(0);
349
            return;
350
        }
351
352
        $statinfo = [
353
            'size' 		=> $statinfo['size'],
354
            'groupid'	=> $statinfo['gid'],
355
            'userid'	=> $statinfo['uid'],
356
            'atime'		=> date('c', $statinfo['atime']),
357
            'mtime'		=> date('c', $statinfo['mtime']),
358
            'mode'		=> $statinfo['mode'],
359
        ];
360
        $this->set_output($statinfo);
361
        $this->set_exitstatus(0);
362
    }
363
364
    /**
365
     * Create SFTP URL wrapper for unsupported commands.
366
     *
367
     * @param  string $path directory path
368
     * @return string SFTP connection wrapprer
369
     */
370
    final private function sftp_url($path = '')
371
    {
372
        return 'ssh2.sftp://'.$this->sftp.$path;
0 ignored issues
show
Bug introduced by
Are you sure $this->sftp of type resource can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

372
        return 'ssh2.sftp://'./** @scrutinizer ignore-type */ $this->sftp.$path;
Loading history...
373
    }
374
	
375
}
376