Issues (18)

php-src/Protocols/Fsp/Answer.php (1 issue)

1
<?php
2
3
namespace kalanis\RemoteRequest\Protocols\Fsp;
4
5
6
use kalanis\RemoteRequest\Interfaces\IRRTranslations;
7
use kalanis\RemoteRequest\Protocols;
8
use kalanis\RemoteRequest\RequestException;
9
use kalanis\RemoteRequest\Traits\TLang;
10
11
12
/**
13
 * Class Answer
14
 * @package RemoteRequest\Protocols\Fsp
15
 * Process server's answer - FSP packet
16
 */
17
class Answer extends Protocols\Dummy\Answer
18
{
19
    use TLang;
20
    use Traits\THeader;
21
    use Traits\TChecksum;
22
23
    protected int $headChecksum = 0;
24
    protected int $headCommand = 0;
25
    protected int $headServerKey = 0;
26
    protected int $headSequence = 0;
27
    protected int $headDataLength = 0;
28
    protected int $headFilePosition = 0;
29
    protected string $header = '';
30
    protected string $content = '';
31
    protected string $extra = '';
32
33
    public bool $canDump = false; // for dump info about checksums
34
35 20
    public function __construct(?IRRTranslations $lang = null)
36
    {
37 20
        $this->setRRLang($lang);
38
    }
39
40
    /**
41
     * @throws RequestException
42
     * @return Answer
43
     */
44 18
    public function process(): Answer
45
    {
46 18
        $this->checkSize();
47 16
        $this->getHeader();
48 16
        $this->processHeader();
49 16
        $this->processContent();
50 16
        $this->checkResponse();
51 15
        return $this;
52
    }
53
54
    /**
55
     * @throws RequestException
56
     */
57 18
    protected function checkSize(): void
58
    {
59
        // @phpstan-ignore-next-line
60 18
        $loadSize = is_resource($this->body) ? fstat($this->body)['size'] : strlen(strval($this->body));
61 18
        if (Protocols\Fsp::HEADER_SIZE > $loadSize) {
62 1
            throw new RequestException($this->getRRLang()->rrFspResponseShort($loadSize));
63
        }
64 17
        if (Protocols\Fsp::MAX_PACKET_SIZE < $loadSize) {
65 1
            throw new RequestException($this->getRRLang()->rrFspResponseLarge($loadSize));
66
        }
67
    }
68
69 16
    protected function getHeader(): void
70
    {
71 16
        $this->header = is_resource($this->body)
72 15
            ? strval(stream_get_contents($this->body, Protocols\Fsp::HEADER_SIZE, 0))
73 1
            : strval(substr(strval($this->body), 0, Protocols\Fsp::HEADER_SIZE))
74 16
        ;
75
    }
76
77 16
    protected function processHeader(): void
78
    {
79 16
        $this->headCommand = Strings::cutter($this->header, 0, 1);
80 16
        $this->headChecksum = Strings::cutter($this->header, 1, 1);
81 16
        $this->headServerKey = Strings::cutter($this->header, 2, 2);
82 16
        $this->headSequence = Strings::cutter($this->header, 4, 2);
83 16
        $this->headDataLength = Strings::cutter($this->header, 6, 2);
84 16
        $this->headFilePosition = Strings::cutter($this->header, 8, 4);
85
    }
86
87 16
    protected function processContent(): void
88
    {
89 16
        $content = is_resource($this->body)
90 15
            ? strval(stream_get_contents($this->body, -1, Protocols\Fsp::HEADER_SIZE))
91 16
            : strval(substr(strval($this->body), Protocols\Fsp::HEADER_SIZE))
92 16
        ;
93 16
        $this->content = strval(substr($content, 0, $this->getDataLength()));
94 16
        $this->extra = strval(substr($content, $this->getDataLength()));
95
    }
96
97
    /**
98
     * Generate server checksum from data and compare them
99
     * @throws RequestException
100
     */
101 16
    protected function checkResponse(): void
102
    {
103 16
        $checksum = $this->computeCheckSum();
104
        // @codeCoverageIgnoreStart
105
        // necessary dumper - who can calculate checksums from their head?
106
        if ($this->canDump) {
107
            var_dump(['chksums',
0 ignored issues
show
Security Debugging Code introduced by
var_dump(array('chksums'...($this->headChecksum))) looks like debug code. Are you sure you do not want to remove it?
Loading history...
108
                'calc_raw' => $checksum, 'calc_hex' => dechex($checksum), 'calc_bin' => decbin($checksum),
109
                'got_raw' => $this->headChecksum, 'got_hex' => dechex($this->headChecksum), 'got_bin' => decbin($this->headChecksum)
110
            ]);
111
        }
112
        // @codeCoverageIgnoreEnd
113 16
        if ($checksum != $this->headChecksum ) {
114 1
            throw new RequestException($this->getRRLang()->rrFspInvalidChecksum($checksum, $this->headChecksum));
115
        }
116
    }
117
118 16
    public function getInitialSumChunk(): int
119
    {
120 16
        return 0;
121
    }
122
123 16
    public function getChecksumPacket(): string
124
    {
125 16
        $content = $this->header . $this->content . $this->extra ;
126 16
        $content[1] = chr(0); // null checksum
127 16
        return $content;
128
    }
129
130 15
    public function getCommand(): int
131
    {
132 15
        return intval($this->headCommand);
133
    }
134
135 3
    public function getKey(): int
136
    {
137 3
        return intval($this->headServerKey);
138
    }
139
140 3
    public function getSequence(): int
141
    {
142 3
        return intval($this->headSequence);
143
    }
144
145 16
    public function getDataLength(): int
146
    {
147 16
        return intval($this->headDataLength);
148
    }
149
150 8
    public function getFilePosition(): int
151
    {
152 8
        return intval($this->headFilePosition);
153
    }
154
155 12
    public function getContent(): string
156
    {
157 12
        return strval($this->content);
158
    }
159
160 6
    public function getExtraData(): string
161
    {
162 6
        return strval($this->extra);
163
    }
164
}
165