Passed
Push — master ( 56ddb3...e5f494 )
by Nikita
02:15
created

GdaemonFiles::listFiles()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 4
nop 1
dl 0
loc 33
ccs 19
cts 19
cp 1
crap 6
rs 9.0777
c 0
b 0
f 0
1
<?php
2
3
namespace Knik\Gameap;
4
5
use Knik\Binn\BinnList;
6
use RuntimeException;
7
use InvalidArgumentException;
8
9
class GdaemonFiles extends Gdaemon
10
{
11
    const FSERV_AUTH            = 1;
12
    const FSERV_FILESEND        = 3;
13
    const FSERV_READDIR         = 4;
14
    const FSERV_MKDIR           = 5;
15
    const FSERV_MOVE            = 6;
16
    const FSERV_REMOVE          = 7;
17
    const FSERV_FILEINFO        = 8;
18
    const FSERV_CHMOD           = 9;
19
20
    const FSERV_UPLOAD_TO_SERVER        = 1;
21
    const FSERV_DOWNLOAD_FR_SERVER      = 2;
22
23
    const FSERV_STATUS_ERROR                = 1;
24
    const FSERV_STATUS_UNKNOWN_COMMAND      = 3;
25
    const FSERV_STATUS_OK                   = 100;
26
    const FSERV_STATUS_FILE_TRANSFER_READY  = 101;
27
28
    /**
29
     * Upload file to server
30
     *
31
     * @param string|resource $locFile path to local file or file stream
32
     * @param string $remFile path to remote file
33
     * @param int $permission
34
     *
35
     * @return boolean
36
     */
37 21
    public function put($locFile, $remFile, $permission = 0644)
38
    {
39 21
        if (is_string($locFile)) {
40
            set_error_handler(function () {});
41 15
            $fileHandle = fopen($locFile, 'r');
42 15
            restore_error_handler();
43 11
        } else if (is_resource($locFile)) {
44 3
            $fileHandle = $locFile;
45 1
        } else {
46 3
            throw new InvalidArgumentException('Invalid local file');
47
        }
48
49 18
        if ($fileHandle === false) {
50 3
            throw new RuntimeException('File open error');
51
        }
52
53 15
        $stat = fstat($fileHandle);
54 15
        $filesize = $stat['size'];
55 15
        unset($stat);
56
57 15
        $writeBinn = new BinnList;
58
59 15
        $writeBinn->addUint8(self::FSERV_FILESEND);
60 15
        $writeBinn->addUint8(self::FSERV_UPLOAD_TO_SERVER);
61 15
        $writeBinn->addStr($remFile);
62 15
        $writeBinn->addUint64($filesize);
63 15
        $writeBinn->addBool(true); // Make dirs
64 15
        $writeBinn->addUint8($permission);
65
66 15
        $read = $this->writeAndReadSocket($writeBinn->serialize());
67
68 15
        $readBinn = new BinnList;
69 15
        $readBinn->binnOpen($read);
70 15
        $results = $readBinn->unserialize();
71
72 15
        if ($results[0] == self::FSERV_STATUS_OK) {
73 3
            throw new RuntimeException('Unexpected `OK` status. Expected `ready to transfer`');
74 12
        } else if ($results[0] != self::FSERV_STATUS_FILE_TRANSFER_READY) {
75 3
            throw new RuntimeException('Couldn\'t upload file: ' . isset($results[1]) ? $results[1] : 'Unknown');
76
        }
77
78 9
        while(!feof($fileHandle)) {
79 9
            $this->writeSocket(fread($fileHandle, $this->maxBufsize));
80 3
        }
81
82 9
        $read = $this->readSocket();
83
84 9
        $readBinn = new BinnList;
85 9
        $readBinn->binnOpen($read);
86 9
        $results = $readBinn->unserialize();
87
88 9
        if ($results[0] != self::FSERV_STATUS_OK) {
89 3
            throw new RuntimeException('Couldn\'t send file: ' . isset($results[1]) ? $results[1] : 'Unknown');
90
        }
91
92 6
        if (is_resource($locFile)) {
93 3
            rewind($fileHandle);
94 3
            return $fileHandle;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $fileHandle returns the type resource which is incompatible with the documented return type boolean.
Loading history...
95
        } else {
96 3
            fclose($fileHandle);
97 3
            return true;
98
        }
99
    }
100
101
    /**
102
     * Download file
103
     *
104
     * @param string $remFile path to remote file
105
     * @param string|resource $locFile path to local file or file stream
106
     *
107
     * @return boolean|resource
108
     */
109 21
    public function get($remFile, $locFile)
110
    {
111 21
        if (is_string($locFile)) {
112
            set_error_handler(function () {});
113 15
            $fileHandle = fopen($locFile, 'w+b');
114 15
            restore_error_handler();
115 11
        } else if (is_resource($locFile)) {
116 3
            $fileHandle = $locFile;
117 1
        } else {
118 3
            throw new InvalidArgumentException('Invalid local file');
119
        }
120
121 18
        if ($fileHandle === false) {
122 3
            throw new RuntimeException('File open error');
123
        }
124
125 15
        $writeBinn = new BinnList;
126
127 15
        $writeBinn->addUint8(self::FSERV_FILESEND);
128 15
        $writeBinn->addUint8(self::FSERV_DOWNLOAD_FR_SERVER);
129 15
        $writeBinn->addStr($remFile);
130
131 15
        $read = $this->writeAndReadSocket($writeBinn->serialize());
132
133 15
        $readBinn = new BinnList;
134 15
        $readBinn->binnOpen($read);
135 15
        $results = $readBinn->unserialize();
136
137 15
        if ($results[0] == self::FSERV_STATUS_OK) {
138 3
            throw new RuntimeException('Unexpected `OK` status. Expected `ready to transfer`');
139 12
        } else if ($results[0] != self::FSERV_STATUS_FILE_TRANSFER_READY) {
140 3
            throw new RuntimeException('Couldn\'t upload file: ' . isset($results[1]) ? $results[1] : 'Unknown');
141
        }
142
143 9
        $this->writeSocket(self::SOCKET_MSG_ENDL);
144
145 9
        $filesize = $results[2];
146 9
        $writed = 0;
147
148 9
        while($writed < $filesize) {
149 9
            if ($filesize - $writed > $this->maxBufsize) {
150 3
                $readlen = $this->maxBufsize;
151 1
            }
152
            else {
153 9
                $readlen = $filesize - $writed;
154
            }
155
156 9
            $socketRead = $this->readSocket($readlen, true);
157
158 9
            $writed += fwrite($fileHandle, $socketRead, $readlen);
159 3
        }
160
161 9
        if (is_resource($locFile)) {
162 3
            rewind($fileHandle);
163 3
            return $fileHandle;
164
        } else {
165 6
            fclose($fileHandle);
166 6
            return true;
167
        }
168
    }
169
170
    /**
171
     * List files
172
     *
173
     * @param string $directory
174
     *
175
     * @return array Files names list
176
     */
177 12
    public function listFiles($directory)
178
    {
179 12
        $writeBinn= new BinnList;
180
181 12
        $writeBinn->addUint8(self::FSERV_READDIR);
182 12
        $writeBinn->addStr($directory);     // Dir path
183 12
        $writeBinn->addUint8(0);       // Mode
184
185 12
        $read = $this->writeAndReadSocket($writeBinn->serialize());
186
187 12
        $readBinn = new BinnList;
188
189 12
        $readBinn->binnOpen($read);
190 12
        $results = $readBinn->unserialize();
191
192 12
        if ($results[0] != self::FSERV_STATUS_OK) {
193
            // Error
194 3
            throw new RuntimeException('GDaemon List files error:' . isset($results[1]) ? $results[1] : 'Unknown');
195
        }
196
197 9
        $filesList = $results[2];
198 9
        $returnList = [];
199
200 9
        foreach($filesList as &$file) {
201
202 9
            if (basename($file[0]) == '.' OR basename($file[0]) == '..') {
203 3
                continue;
204
            }
205
206 9
            $returnList[] = basename($file[0]);
207 3
        }
208
209 9
        return $returnList;
210
    }
211
212
    /**
213
     * @param string $directory
214
     * @return array
215
     */
216 9
    public function directoryContents($directory)
217
    {
218 9
        $writeBinn= new BinnList;
219
220 9
        $writeBinn->addUint8(self::FSERV_READDIR);
221 9
        $writeBinn->addStr($directory);     // Dir path
222 9
        $writeBinn->addUint8(1);       // Mode
223
224 9
        $read = $this->writeAndReadSocket($writeBinn->serialize());
225
226 9
        $readBinn = new BinnList;
227
228 9
        $readBinn->binnOpen($read);
229 9
        $results = $readBinn->unserialize();
230
231 9
        if ($results[0] != self::FSERV_STATUS_OK) {
232
            // Error
233 3
            throw new RuntimeException('GDaemon List files error:' . isset($results[1]) ? $results[1] : 'Unknown');
234
        }
235
236 6
        $filesList = $results[2];
237 6
        $returnList = [];
238
239 6
        foreach($filesList as &$file) {
240 3
            if (basename($file[0]) == '.' OR basename($file[0]) == '..') {
241 3
                continue;
242
            }
243
244 3
            $returnList[] = array(
245 3
                'name' => basename($file[0]),
246 3
                'size' => $file[1],
247 3
                'mtime' => $file[2],
248 3
                'type' => ($file[3] == 1) ? 'dir' : 'file',
249 3
                'permission' => $file[4],
250
            );
251 2
        }
252
253 6
        return $returnList;
254
    }
255
256
    /**
257
     * Make directory
258
     *
259
     * @param string $path
260
     * @param int $permissions
261
     * @return bool
262
     */
263 6
    public function mkdir($path, $permissions = 0755)
264
    {
265 6
        $writeBinn = new BinnList;
266
267 6
        $writeBinn->addUint8(self::FSERV_MKDIR);
268 6
        $writeBinn->addStr($path);
269 6
        $writeBinn->addStr($permissions);
270
271 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
272
273 6
        $readBinn = new BinnList;
274 6
        $readBinn->binnOpen($read);
275 6
        $results = $readBinn->unserialize();
276
277 6
        if ($results[0] != self::FSERV_STATUS_OK) {
278 3
            throw new RuntimeException('Couldn\'t make directory: ' . isset($results[1]) ? $results[1] : 'Unknown');
279
        }
280
281 3
        return true;
282
    }
283
284
    /**
285
     * Rename file
286
     *
287
     * @param string $oldPath
288
     * @param string $newPath
289
     * @return bool
290
     */
291 9
    public function rename($oldPath, $newPath)
292
    {
293 9
        return $this->move($oldPath, $newPath);
294
    }
295
296
    /**
297
     * Move file
298
     *
299
     * @param string $oldPath
300
     * @param string $newPath
301
     * @return bool
302
     */
303 9
    public function move($oldPath, $newPath)
304
    {
305 9
        $writeBinn = new BinnList;
306
307 9
        $writeBinn->addUint8(self::FSERV_MOVE);
308 9
        $writeBinn->addStr($oldPath);
309 9
        $writeBinn->addStr($newPath);
310 9
        $writeBinn->addBool(false);
311
312 9
        $binn = $writeBinn->serialize();
313
314 9
        $read = $this->writeAndReadSocket($binn);
315
316 9
        $readBinn = new BinnList;
317 9
        $readBinn->binnOpen($read);
318 9
        $results = $readBinn->unserialize();
319
320 9
        if ($results[0] != self::FSERV_STATUS_OK) {
321 3
            throw new RuntimeException('Couldn\'t move file: ' . isset($results[1]) ? $results[1] : 'Unknown');
322
        }
323
324 6
        return true;
325
    }
326
327
    /**
328
     * Copy file
329
     *
330
     * @param string $oldPath
331
     * @param string $newPath
332
     * @return bool
333
     */
334 6
    public function copy($oldPath, $newPath)
335
    {
336 6
        $writeBinn = new BinnList;
337
338 6
        $writeBinn->addUint8(self::FSERV_MOVE);
339 6
        $writeBinn->addStr($oldPath);
340 6
        $writeBinn->addStr($newPath);
341 6
        $writeBinn->addBool(true);            // Copy
342
343 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
344
345 6
        $readBinn = new BinnList;
346 6
        $readBinn->binnOpen($read);
347 6
        $results = $readBinn->unserialize();
348
349 6
        if ($results[0] != self::FSERV_STATUS_OK) {
350 3
            throw new RuntimeException('Couldn\'t copy file: ' . isset($results[1]) ? $results[1] : 'Unknown');
351
        }
352
353 3
        return true;
354
    }
355
356
    /**
357
     * Delete file/directory
358
     *
359
     * @param string $path
360
     * @param bool $recursive
361
     * @return bool
362
     */
363 6
    public function delete($path, $recursive = false)
364
    {
365 6
        $writeBinn = new BinnList;
366
367 6
        $writeBinn->addUint8(self::FSERV_REMOVE);
368 6
        $writeBinn->addStr($path);
369 6
        $writeBinn->addBool($recursive);
370
371 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
372
373 6
        $readBinn = new BinnList;
374 6
        $readBinn->binnOpen($read);
375 6
        $results = $readBinn->unserialize();
376
377 6
        if ($results[0] != self::FSERV_STATUS_OK) {
378 3
            throw new RuntimeException('Couldn\'t delete: ' . isset($results[1]) ? $results[1] : 'Unknown');
379
        }
380
381 3
        return true;
382
    }
383
384
    /**
385
     * Get file metadata
386
     *
387
     * @param string $path
388
     * @return array
389
     */
390 6
    public function metadata($path)
391
    {
392 6
        $writeBinn= new BinnList;
393
394 6
        $writeBinn->addUint8(self::FSERV_FILEINFO);
395 6
        $writeBinn->addStr($path);
396
397 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
398
399 6
        $readBinn = new BinnList;
400
401 6
        $readBinn->binnOpen($read);
402 6
        $results = $readBinn->unserialize();
403
404 6
        if ($results[0] != self::FSERV_STATUS_OK) {
405 3
            throw new RuntimeException('GDaemon metadata error:' . isset($results[1]) ? $results[1] : 'Unknown');
406
        }
407
408 3
        $fileInfo = $results[2];
409
410
        return [
411 3
            'name' => basename($fileInfo[0]),
412 3
            'size' => $fileInfo[1],
413 3
            'type' => ($fileInfo[2] == 1) ? 'dir' : 'file',
414 3
            'mtime' => $fileInfo[3],
415 3
            'atime' => $fileInfo[4],
416 3
            'ctime' => $fileInfo[5],
417 3
            'permissions' => $fileInfo[6],
418 3
            'mimetype' => $fileInfo[7],
419 1
        ];
420
    }
421
422
    /**
423
     * Change file mode
424
     *
425
     * @param integer $mode
426
     * @param string $path
427
     * @return bool
428
     */
429 6
    public function chmod($mode, $path)
430
    {
431 6
        $writeBinn = new BinnList;
432
433 6
        $writeBinn->addUint8(self::FSERV_CHMOD);
434 6
        $writeBinn->addStr($path);
435 6
        $writeBinn->addUint16($mode);
436
437 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
438
439 6
        $readBinn = new BinnList;
440 6
        $readBinn->binnOpen($read);
441 6
        $results = $readBinn->unserialize();
442
443 6
        if ($results[0] != self::FSERV_STATUS_OK) {
444 3
            throw new RuntimeException('Couldn\'t chmod: ' . isset($results[1]) ? $results[1] : 'Unknown');
445
        }
446
447 3
        return true;
448
    }
449
450
    /**
451
     * Check file exist
452
     *
453
     * @param $path
454
     * @return bool
455
     */
456 6
    public function exist($path)
457
    {
458 6
        return in_array(basename($path), $this->listFiles(dirname($path)));
459
    }
460
}