Diff: STRATO-apps/wordpress_03/app/wp-admin/includes/class-wp-filesystem-ftpsockets.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
/**
3
+
* WordPress FTP Sockets Filesystem.
4
+
*
5
+
* @package WordPress
6
+
* @subpackage Filesystem
7
+
*/
8
+
9
+
/**
10
+
* WordPress Filesystem Class for implementing FTP Sockets.
11
+
*
12
+
* @since 2.5.0
13
+
*
14
+
* @see WP_Filesystem_Base
15
+
*/
16
+
class WP_Filesystem_ftpsockets extends WP_Filesystem_Base {
17
+
18
+
/**
19
+
* @since 2.5.0
20
+
* @var ftp
21
+
*/
22
+
public $ftp;
23
+
24
+
/**
25
+
* Constructor.
26
+
*
27
+
* @since 2.5.0
28
+
*
29
+
* @param array $opt
30
+
*/
31
+
public function __construct( $opt = '' ) {
32
+
$this->method = 'ftpsockets';
33
+
$this->errors = new WP_Error();
34
+
35
+
// Check if possible to use ftp functions.
36
+
if ( ! require_once ABSPATH . 'wp-admin/includes/class-ftp.php' ) {
37
+
return;
38
+
}
39
+
40
+
$this->ftp = new ftp();
41
+
42
+
if ( empty( $opt['port'] ) ) {
43
+
$this->options['port'] = 21;
44
+
} else {
45
+
$this->options['port'] = (int) $opt['port'];
46
+
}
47
+
48
+
if ( empty( $opt['hostname'] ) ) {
49
+
$this->errors->add( 'empty_hostname', __( 'FTP hostname is required' ) );
50
+
} else {
51
+
$this->options['hostname'] = $opt['hostname'];
52
+
}
53
+
54
+
// Check if the options provided are OK.
55
+
if ( empty( $opt['username'] ) ) {
56
+
$this->errors->add( 'empty_username', __( 'FTP username is required' ) );
57
+
} else {
58
+
$this->options['username'] = $opt['username'];
59
+
}
60
+
61
+
if ( empty( $opt['password'] ) ) {
62
+
$this->errors->add( 'empty_password', __( 'FTP password is required' ) );
63
+
} else {
64
+
$this->options['password'] = $opt['password'];
65
+
}
66
+
}
67
+
68
+
/**
69
+
* Connects filesystem.
70
+
*
71
+
* @since 2.5.0
72
+
*
73
+
* @return bool True on success, false on failure.
74
+
*/
75
+
public function connect() {
76
+
if ( ! $this->ftp ) {
77
+
return false;
78
+
}
79
+
80
+
$this->ftp->SetTimeout( FS_CONNECT_TIMEOUT );
81
+
82
+
if ( ! $this->ftp->SetServer( $this->options['hostname'], $this->options['port'] ) ) {
83
+
$this->errors->add(
84
+
'connect',
85
+
sprintf(
86
+
/* translators: %s: hostname:port */
87
+
__( 'Failed to connect to FTP Server %s' ),
88
+
$this->options['hostname'] . ':' . $this->options['port']
89
+
)
90
+
);
91
+
92
+
return false;
93
+
}
94
+
95
+
if ( ! $this->ftp->connect() ) {
96
+
$this->errors->add(
97
+
'connect',
98
+
sprintf(
99
+
/* translators: %s: hostname:port */
100
+
__( 'Failed to connect to FTP Server %s' ),
101
+
$this->options['hostname'] . ':' . $this->options['port']
102
+
)
103
+
);
104
+
105
+
return false;
106
+
}
107
+
108
+
if ( ! $this->ftp->login( $this->options['username'], $this->options['password'] ) ) {
109
+
$this->errors->add(
110
+
'auth',
111
+
sprintf(
112
+
/* translators: %s: Username. */
113
+
__( 'Username/Password incorrect for %s' ),
114
+
$this->options['username']
115
+
)
116
+
);
117
+
118
+
return false;
119
+
}
120
+
121
+
$this->ftp->SetType( FTP_BINARY );
122
+
$this->ftp->Passive( true );
123
+
$this->ftp->SetTimeout( FS_TIMEOUT );
124
+
125
+
return true;
126
+
}
127
+
128
+
/**
129
+
* Reads entire file into a string.
130
+
*
131
+
* @since 2.5.0
132
+
*
133
+
* @param string $file Name of the file to read.
134
+
* @return string|false Read data on success, false if no temporary file could be opened,
135
+
* or if the file couldn't be retrieved.
136
+
*/
137
+
public function get_contents( $file ) {
138
+
if ( ! $this->exists( $file ) ) {
139
+
return false;
140
+
}
141
+
142
+
$tempfile = wp_tempnam( $file );
143
+
$temphandle = fopen( $tempfile, 'w+' );
144
+
145
+
if ( ! $temphandle ) {
146
+
unlink( $tempfile );
147
+
return false;
148
+
}
149
+
150
+
mbstring_binary_safe_encoding();
151
+
152
+
if ( ! $this->ftp->fget( $temphandle, $file ) ) {
153
+
fclose( $temphandle );
154
+
unlink( $tempfile );
155
+
156
+
reset_mbstring_encoding();
157
+
158
+
return ''; // Blank document. File does exist, it's just blank.
159
+
}
160
+
161
+
reset_mbstring_encoding();
162
+
163
+
fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
164
+
$contents = '';
165
+
166
+
while ( ! feof( $temphandle ) ) {
167
+
$contents .= fread( $temphandle, 8 * KB_IN_BYTES );
168
+
}
169
+
170
+
fclose( $temphandle );
171
+
unlink( $tempfile );
172
+
173
+
return $contents;
174
+
}
175
+
176
+
/**
177
+
* Reads entire file into an array.
178
+
*
179
+
* @since 2.5.0
180
+
*
181
+
* @param string $file Path to the file.
182
+
* @return array|false File contents in an array on success, false on failure.
183
+
*/
184
+
public function get_contents_array( $file ) {
185
+
return explode( "\n", $this->get_contents( $file ) );
186
+
}
187
+
188
+
/**
189
+
* Writes a string to a file.
190
+
*
191
+
* @since 2.5.0
192
+
*
193
+
* @param string $file Remote path to the file where to write the data.
194
+
* @param string $contents The data to write.
195
+
* @param int|false $mode Optional. The file permissions as octal number, usually 0644.
196
+
* Default false.
197
+
* @return bool True on success, false on failure.
198
+
*/
199
+
public function put_contents( $file, $contents, $mode = false ) {
200
+
$tempfile = wp_tempnam( $file );
201
+
$temphandle = @fopen( $tempfile, 'w+' );
202
+
203
+
if ( ! $temphandle ) {
204
+
unlink( $tempfile );
205
+
return false;
206
+
}
207
+
208
+
// The FTP class uses string functions internally during file download/upload.
209
+
mbstring_binary_safe_encoding();
210
+
211
+
$bytes_written = fwrite( $temphandle, $contents );
212
+
213
+
if ( false === $bytes_written || strlen( $contents ) !== $bytes_written ) {
214
+
fclose( $temphandle );
215
+
unlink( $tempfile );
216
+
217
+
reset_mbstring_encoding();
218
+
219
+
return false;
220
+
}
221
+
222
+
fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
223
+
224
+
$ret = $this->ftp->fput( $file, $temphandle );
225
+
226
+
reset_mbstring_encoding();
227
+
228
+
fclose( $temphandle );
229
+
unlink( $tempfile );
230
+
231
+
$this->chmod( $file, $mode );
232
+
233
+
return $ret;
234
+
}
235
+
236
+
/**
237
+
* Gets the current working directory.
238
+
*
239
+
* @since 2.5.0
240
+
*
241
+
* @return string|false The current working directory on success, false on failure.
242
+
*/
243
+
public function cwd() {
244
+
$cwd = $this->ftp->pwd();
245
+
246
+
if ( $cwd ) {
247
+
$cwd = trailingslashit( $cwd );
248
+
}
249
+
250
+
return $cwd;
251
+
}
252
+
253
+
/**
254
+
* Changes current directory.
255
+
*
256
+
* @since 2.5.0
257
+
*
258
+
* @param string $dir The new current directory.
259
+
* @return bool True on success, false on failure.
260
+
*/
261
+
public function chdir( $dir ) {
262
+
return $this->ftp->chdir( $dir );
263
+
}
264
+
265
+
/**
266
+
* Changes filesystem permissions.
267
+
*
268
+
* @since 2.5.0
269
+
*
270
+
* @param string $file Path to the file.
271
+
* @param int|false $mode Optional. The permissions as octal number, usually 0644 for files,
272
+
* 0755 for directories. Default false.
273
+
* @param bool $recursive Optional. If set to true, changes file permissions recursively.
274
+
* Default false.
275
+
* @return bool True on success, false on failure.
276
+
*/
277
+
public function chmod( $file, $mode = false, $recursive = false ) {
278
+
if ( ! $mode ) {
279
+
if ( $this->is_file( $file ) ) {
280
+
$mode = FS_CHMOD_FILE;
281
+
} elseif ( $this->is_dir( $file ) ) {
282
+
$mode = FS_CHMOD_DIR;
283
+
} else {
284
+
return false;
285
+
}
286
+
}
287
+
288
+
// chmod any sub-objects if recursive.
289
+
if ( $recursive && $this->is_dir( $file ) ) {
290
+
$filelist = $this->dirlist( $file );
291
+
292
+
foreach ( (array) $filelist as $filename => $filemeta ) {
293
+
$this->chmod( $file . '/' . $filename, $mode, $recursive );
294
+
}
295
+
}
296
+
297
+
// chmod the file or directory.
298
+
return $this->ftp->chmod( $file, $mode );
299
+
}
300
+
301
+
/**
302
+
* Gets the file owner.
303
+
*
304
+
* @since 2.5.0
305
+
*
306
+
* @param string $file Path to the file.
307
+
* @return string|false Username of the owner on success, false on failure.
308
+
*/
309
+
public function owner( $file ) {
310
+
$dir = $this->dirlist( $file );
311
+
312
+
return $dir[ $file ]['owner'];
313
+
}
314
+
315
+
/**
316
+
* Gets the permissions of the specified file or filepath in their octal format.
317
+
*
318
+
* @since 2.5.0
319
+
*
320
+
* @param string $file Path to the file.
321
+
* @return string Mode of the file (the last 3 digits).
322
+
*/
323
+
public function getchmod( $file ) {
324
+
$dir = $this->dirlist( $file );
325
+
326
+
return $dir[ $file ]['permsn'];
327
+
}
328
+
329
+
/**
330
+
* Gets the file's group.
331
+
*
332
+
* @since 2.5.0
333
+
*
334
+
* @param string $file Path to the file.
335
+
* @return string|false The group on success, false on failure.
336
+
*/
337
+
public function group( $file ) {
338
+
$dir = $this->dirlist( $file );
339
+
340
+
return $dir[ $file ]['group'];
341
+
}
342
+
343
+
/**
344
+
* Copies a file.
345
+
*
346
+
* @since 2.5.0
347
+
*
348
+
* @param string $source Path to the source file.
349
+
* @param string $destination Path to the destination file.
350
+
* @param bool $overwrite Optional. Whether to overwrite the destination file if it exists.
351
+
* Default false.
352
+
* @param int|false $mode Optional. The permissions as octal number, usually 0644 for files,
353
+
* 0755 for dirs. Default false.
354
+
* @return bool True on success, false on failure.
355
+
*/
356
+
public function copy( $source, $destination, $overwrite = false, $mode = false ) {
357
+
if ( ! $overwrite && $this->exists( $destination ) ) {
358
+
return false;
359
+
}
360
+
361
+
$content = $this->get_contents( $source );
362
+
363
+
if ( false === $content ) {
364
+
return false;
365
+
}
366
+
367
+
return $this->put_contents( $destination, $content, $mode );
368
+
}
369
+
370
+
/**
371
+
* Moves a file or directory.
372
+
*
373
+
* After moving files or directories, OPcache will need to be invalidated.
374
+
*
375
+
* If moving a directory fails, `copy_dir()` can be used for a recursive copy.
376
+
*
377
+
* Use `move_dir()` for moving directories with OPcache invalidation and a
378
+
* fallback to `copy_dir()`.
379
+
*
380
+
* @since 2.5.0
381
+
*
382
+
* @param string $source Path to the source file or directory.
383
+
* @param string $destination Path to the destination file or directory.
384
+
* @param bool $overwrite Optional. Whether to overwrite the destination if it exists.
385
+
* Default false.
386
+
* @return bool True on success, false on failure.
387
+
*/
388
+
public function move( $source, $destination, $overwrite = false ) {
389
+
return $this->ftp->rename( $source, $destination );
390
+
}
391
+
392
+
/**
393
+
* Deletes a file or directory.
394
+
*
395
+
* @since 2.5.0
396
+
*
397
+
* @param string $file Path to the file or directory.
398
+
* @param bool $recursive Optional. If set to true, deletes files and folders recursively.
399
+
* Default false.
400
+
* @param string|false $type Type of resource. 'f' for file, 'd' for directory.
401
+
* Default false.
402
+
* @return bool True on success, false on failure.
403
+
*/
404
+
public function delete( $file, $recursive = false, $type = false ) {
405
+
if ( empty( $file ) ) {
406
+
return false;
407
+
}
408
+
409
+
if ( 'f' === $type || $this->is_file( $file ) ) {
410
+
return $this->ftp->delete( $file );
411
+
}
412
+
413
+
if ( ! $recursive ) {
414
+
return $this->ftp->rmdir( $file );
415
+
}
416
+
417
+
return $this->ftp->mdel( $file );
418
+
}
419
+
420
+
/**
421
+
* Checks if a file or directory exists.
422
+
*
423
+
* @since 2.5.0
424
+
* @since 6.3.0 Returns false for an empty path.
425
+
*
426
+
* @param string $path Path to file or directory.
427
+
* @return bool Whether $path exists or not.
428
+
*/
429
+
public function exists( $path ) {
430
+
/*
431
+
* Check for empty path. If ftp::nlist() receives an empty path,
432
+
* it checks the current working directory and may return true.
433
+
*
434
+
* See https://core.trac.wordpress.org/ticket/33058.
435
+
*/
436
+
if ( '' === $path ) {
437
+
return false;
438
+
}
439
+
440
+
$list = $this->ftp->nlist( $path );
441
+
442
+
if ( empty( $list ) && $this->is_dir( $path ) ) {
443
+
return true; // File is an empty directory.
444
+
}
445
+
446
+
return ! empty( $list ); // Empty list = no file, so invert.
447
+
// Return $this->ftp->is_exists($file); has issues with ABOR+426 responses on the ncFTPd server.
448
+
}
449
+
450
+
/**
451
+
* Checks if resource is a file.
452
+
*
453
+
* @since 2.5.0
454
+
*
455
+
* @param string $file File path.
456
+
* @return bool Whether $file is a file.
457
+
*/
458
+
public function is_file( $file ) {
459
+
if ( $this->is_dir( $file ) ) {
460
+
return false;
461
+
}
462
+
463
+
if ( $this->exists( $file ) ) {
464
+
return true;
465
+
}
466
+
467
+
return false;
468
+
}
469
+
470
+
/**
471
+
* Checks if resource is a directory.
472
+
*
473
+
* @since 2.5.0
474
+
*
475
+
* @param string $path Directory path.
476
+
* @return bool Whether $path is a directory.
477
+
*/
478
+
public function is_dir( $path ) {
479
+
$cwd = $this->cwd();
480
+
481
+
if ( $this->chdir( $path ) ) {
482
+
$this->chdir( $cwd );
483
+
return true;
484
+
}
485
+
486
+
return false;
487
+
}
488
+
489
+
/**
490
+
* Checks if a file is readable.
491
+
*
492
+
* @since 2.5.0
493
+
*
494
+
* @param string $file Path to file.
495
+
* @return bool Whether $file is readable.
496
+
*/
497
+
public function is_readable( $file ) {
498
+
return true;
499
+
}
500
+
501
+
/**
502
+
* Checks if a file or directory is writable.
503
+
*
504
+
* @since 2.5.0
505
+
*
506
+
* @param string $path Path to file or directory.
507
+
* @return bool Whether $path is writable.
508
+
*/
509
+
public function is_writable( $path ) {
510
+
return true;
511
+
}
512
+
513
+
/**
514
+
* Gets the file's last access time.
515
+
*
516
+
* @since 2.5.0
517
+
*
518
+
* @param string $file Path to file.
519
+
* @return int|false Unix timestamp representing last access time, false on failure.
520
+
*/
521
+
public function atime( $file ) {
522
+
return false;
523
+
}
524
+
525
+
/**
526
+
* Gets the file modification time.
527
+
*
528
+
* @since 2.5.0
529
+
*
530
+
* @param string $file Path to file.
531
+
* @return int|false Unix timestamp representing modification time, false on failure.
532
+
*/
533
+
public function mtime( $file ) {
534
+
return $this->ftp->mdtm( $file );
535
+
}
536
+
537
+
/**
538
+
* Gets the file size (in bytes).
539
+
*
540
+
* @since 2.5.0
541
+
*
542
+
* @param string $file Path to file.
543
+
* @return int|false Size of the file in bytes on success, false on failure.
544
+
*/
545
+
public function size( $file ) {
546
+
return $this->ftp->filesize( $file );
547
+
}
548
+
549
+
/**
550
+
* Sets the access and modification times of a file.
551
+
*
552
+
* Note: If $file doesn't exist, it will be created.
553
+
*
554
+
* @since 2.5.0
555
+
*
556
+
* @param string $file Path to file.
557
+
* @param int $time Optional. Modified time to set for file.
558
+
* Default 0.
559
+
* @param int $atime Optional. Access time to set for file.
560
+
* Default 0.
561
+
* @return bool True on success, false on failure.
562
+
*/
563
+
public function touch( $file, $time = 0, $atime = 0 ) {
564
+
return false;
565
+
}
566
+
567
+
/**
568
+
* Creates a directory.
569
+
*
570
+
* @since 2.5.0
571
+
*
572
+
* @param string $path Path for new directory.
573
+
* @param int|false $chmod Optional. The permissions as octal number (or false to skip chmod).
574
+
* Default false.
575
+
* @param string|int|false $chown Optional. A user name or number (or false to skip chown).
576
+
* Default false.
577
+
* @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
578
+
* Default false.
579
+
* @return bool True on success, false on failure.
580
+
*/
581
+
public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
582
+
$path = untrailingslashit( $path );
583
+
584
+
if ( empty( $path ) ) {
585
+
return false;
586
+
}
587
+
588
+
if ( ! $this->ftp->mkdir( $path ) ) {
589
+
return false;
590
+
}
591
+
592
+
if ( ! $chmod ) {
593
+
$chmod = FS_CHMOD_DIR;
594
+
}
595
+
596
+
$this->chmod( $path, $chmod );
597
+
598
+
return true;
599
+
}
600
+
601
+
/**
602
+
* Deletes a directory.
603
+
*
604
+
* @since 2.5.0
605
+
*
606
+
* @param string $path Path to directory.
607
+
* @param bool $recursive Optional. Whether to recursively remove files/directories.
608
+
* Default false.
609
+
* @return bool True on success, false on failure.
610
+
*/
611
+
public function rmdir( $path, $recursive = false ) {
612
+
return $this->delete( $path, $recursive );
613
+
}
614
+
615
+
/**
616
+
* Gets details for files in a directory or a specific file.
617
+
*
618
+
* @since 2.5.0
619
+
*
620
+
* @param string $path Path to directory or file.
621
+
* @param bool $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
622
+
* Default true.
623
+
* @param bool $recursive Optional. Whether to recursively include file details in nested directories.
624
+
* Default false.
625
+
* @return array|false {
626
+
* Array of arrays containing file information. False if unable to list directory contents.
627
+
*
628
+
* @type array ...$0 {
629
+
* Array of file information. Note that some elements may not be available on all filesystems.
630
+
*
631
+
* @type string $name Name of the file or directory.
632
+
* @type string $perms *nix representation of permissions.
633
+
* @type string $permsn Octal representation of permissions.
634
+
* @type int|string|false $number File number. May be a numeric string. False if not available.
635
+
* @type string|false $owner Owner name or ID, or false if not available.
636
+
* @type string|false $group File permissions group, or false if not available.
637
+
* @type int|string|false $size Size of file in bytes. May be a numeric string.
638
+
* False if not available.
639
+
* @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string.
640
+
* False if not available.
641
+
* @type string|false $lastmod Last modified month (3 letters) and day (without leading 0), or
642
+
* false if not available.
643
+
* @type string|false $time Last modified time, or false if not available.
644
+
* @type string $type Type of resource. 'f' for file, 'd' for directory, 'l' for link.
645
+
* @type array|false $files If a directory and `$recursive` is true, contains another array of
646
+
* files. False if unable to list directory contents.
647
+
* }
648
+
* }
649
+
*/
650
+
public function dirlist( $path = '.', $include_hidden = true, $recursive = false ) {
651
+
if ( $this->is_file( $path ) ) {
652
+
$limit_file = basename( $path );
653
+
$path = dirname( $path ) . '/';
654
+
} else {
655
+
$limit_file = false;
656
+
}
657
+
658
+
mbstring_binary_safe_encoding();
659
+
660
+
$list = $this->ftp->dirlist( $path );
661
+
662
+
if ( empty( $list ) && ! $this->exists( $path ) ) {
663
+
664
+
reset_mbstring_encoding();
665
+
666
+
return false;
667
+
}
668
+
669
+
$path = trailingslashit( $path );
670
+
$ret = array();
671
+
672
+
foreach ( $list as $struc ) {
673
+
674
+
if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
675
+
continue;
676
+
}
677
+
678
+
if ( ! $include_hidden && '.' === $struc['name'][0] ) {
679
+
continue;
680
+
}
681
+
682
+
if ( $limit_file && $struc['name'] !== $limit_file ) {
683
+
continue;
684
+
}
685
+
686
+
if ( 'd' === $struc['type'] ) {
687
+
if ( $recursive ) {
688
+
$struc['files'] = $this->dirlist( $path . $struc['name'], $include_hidden, $recursive );
689
+
} else {
690
+
$struc['files'] = array();
691
+
}
692
+
}
693
+
694
+
// Replace symlinks formatted as "source -> target" with just the source name.
695
+
if ( $struc['islink'] ) {
696
+
$struc['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $struc['name'] );
697
+
}
698
+
699
+
// Add the octal representation of the file permissions.
700
+
$struc['permsn'] = $this->getnumchmodfromh( $struc['perms'] );
701
+
702
+
$ret[ $struc['name'] ] = $struc;
703
+
}
704
+
705
+
reset_mbstring_encoding();
706
+
707
+
return $ret;
708
+
}
709
+
710
+
/**
711
+
* Destructor.
712
+
*
713
+
* @since 2.5.0
714
+
*/
715
+
public function __destruct() {
716
+
$this->ftp->quit();
717
+
}
718
+
}
719
+