Passed
Push — master ( 23b5cc...9353aa )
by Sébastien
04:46
created

SimpleHttpHandler::getChannel()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3.7536

Importance

Changes 0
Metric Value
cc 3
eloc 17
nc 3
nop 1
dl 0
loc 24
ccs 9
cts 16
cp 0.5625
crap 3.7536
rs 8.9713
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * soluble-japha / PHPJavaBridge driver client.
7
 *
8
 * Refactored version of phpjababridge's Java.inc file compatible
9
 * with php java bridge 6.2
10
 *
11
 *
12
 * @credits   http://php-java-bridge.sourceforge.net/pjb/
13
 *
14
 * @see      http://github.com/belgattitude/soluble-japha
15
 *
16
 * @author Jost Boekemeier
17
 * @author Vanvelthem Sébastien (refactoring and fixes from original implementation)
18
 * @license   MIT
19
 *
20
 * The MIT License (MIT)
21
 * Copyright (c) 2014-2017 Jost Boekemeier
22
 * Permission is hereby granted, free of charge, to any person obtaining a copy
23
 * of this software and associated documentation files (the "Software"), to deal
24
 * in the Software without restriction, including without limitation the rights
25
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26
 * copies of the Software, and to permit persons to whom the Software is
27
 * furnished to do so, subject to the following conditions:
28
 *
29
 * The above copyright notice and this permission notice shall be included in
30
 * all copies or substantial portions of the Software.
31
 *
32
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
38
 * THE SOFTWARE.
39
 */
40
41
namespace Soluble\Japha\Bridge\Driver\Pjb62;
42
43
use Soluble\Japha\Bridge\Exception\ConnectionException;
44
use Soluble\Japha\Bridge\Socket\StreamSocket;
45
46
class SimpleHttpHandler extends SocketHandler
47
{
48
    public $headers;
49
50
    /**
51
     * @var array
52
     */
53
    public $cookies;
54
55
    /**
56
     * @var string
57
     */
58
    public $context;
59
60
    /**
61
     * @var string
62
     */
63
    public $ssl;
64
65
    /**
66
     * @var int
67
     */
68
    public $port;
69
70
    /**
71
     * @var string
72
     */
73
    public $host;
74
75
    /**
76
     * @var array
77
     */
78
    protected $cachedValues = [];
79
80
    /**
81
     * @var string
82
     */
83
    protected $java_servlet;
84
85
    /**
86
     * @var int
87
     */
88
    protected $java_recv_size;
89
90
    /**
91
     * @var int
92
     */
93
    protected $java_send_size;
94
95
    /**
96
     * @throws Exception\IllegalStateException on channel creation error
97
     *
98
     * @param Protocol $protocol
99
     * @param string   $ssl
100
     * @param string   $host
101
     * @param int      $port
102
     * @param string   $java_servlet
103
     * @param int      $java_recv_size
104
     * @param int      $java_send_size
105
     */
106
    public function __construct(Protocol $protocol, $ssl, $host, $port, $java_servlet, $java_recv_size, $java_send_size)
107
    {
108 26
        $this->cookies = [];
109
        $this->protocol = $protocol;
110 26
        $this->ssl = $ssl;
111 26
        $this->host = $host;
112 26
        $this->port = $port;
113 26
        $this->java_servlet = $java_servlet;
114 26
115 26
        $this->java_send_size = $java_send_size;
116
        $this->java_recv_size = $java_recv_size;
117 26
118 26
        $this->cachedValues = [
119
            'getContext' => null
120 26
        ];
121
        $this->createChannel();
122
    }
123 26
124 26
    /**
125
     * @throws Exception\IllegalStateException     on channel creation error
126
     * @throws Exception\BrokenConnectionException if all goes wrong
127
     */
128
    protected function createChannel()
129
    {
130
        $channelName = Pjb62Driver::getJavaBridgeHeader('X_JAVABRIDGE_REDIRECT', $_SERVER);
131
        $context = Pjb62Driver::getJavaBridgeHeader('X_JAVABRIDGE_CONTEXT', $_SERVER);
132
        $len = strlen($context);
133
        $len0 = PjbProxyClient::getInstance()->getCompatibilityOption($this->protocol->client);
134
        $len1 = chr($len & 0xFF);
135
        $len >>= 8;
136
        $len2 = chr($len & 0xFF);
137
        $this->channel = $this->getChannel($channelName);
138
        $this->protocol->setSocketHandler(new SocketHandler($this->protocol, $this->channel));
139
        $this->protocol->write("\177${len0}${len1}${len2}${context}");
140
        $this->context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $context);
141
        $this->protocol->handler = $this->protocol->getSocketHandler();
142
143
        if ($this->protocol->client->sendBuffer !== null) {
0 ignored issues
show
introduced by
The condition $this->protocol->client->sendBuffer !== null can never be false.
Loading history...
144
            $ret = $this->protocol->handler->write($this->protocol->client->sendBuffer);
145
            if ($ret === null) {
146
                $this->protocol->handler->shutdownBrokenConnection('Broken local connection handle');
147
            }
148
            $this->protocol->client->sendBuffer = null;
149
            $this->protocol->handler->read(1);
150
        }
151
    }
152
153
    public function getContextFromCgiEnvironment(): string
154
    {
155
        return Pjb62Driver::getJavaBridgeHeader('X_JAVABRIDGE_CONTEXT', $_SERVER);
156
    }
157
158
    /**
159
     * @return string
160
     */
161
    public function getContext()
162
    {
163
        if (!array_key_exists('getContext', $this->cachedValues)) {
164 24
            $ctx = $this->getContextFromCgiEnvironment();
165
            if ($ctx) {
166
                $this->cachedValues['getContext'] = sprintf('X_JAVABRIDGE_CONTEXT: %s', $ctx);
167
            }
168
        }
169
170
        return $this->cachedValues['getContext'];
171 24
    }
172
173
    public function getWebAppInternal()
174
    {
175
        $context = $this->protocol->webContext;
176 24
        if (isset($context)) {
177 24
            return $context;
178
        }
179
180
        return ($this->java_servlet == 'User' &&
181 24
                array_key_exists('PHP_SELF', $_SERVER) &&
182 24
                array_key_exists('HTTP_HOST', $_SERVER)) ? $_SERVER['PHP_SELF'].'javabridge' : null;
183 24
    }
184
185
    public function getWebApp(): string
186
    {
187
        $context = $this->getWebAppInternal();
188 24
        if (null === $context) {
189 24
            $context = $this->java_servlet;
190 24
        }
191
192
        return $context;
193 24
    }
194
195
    /**
196
     * @throws Exception\BrokenConnectionException
197
     */
198
    public function write(string $data): ?int
199
    {
200
        return $this->protocol->getSocketHandler()->write($data);
201
    }
202
203
    public function doSetCookie($key, $val, $path)
204
    {
205
        $path = trim($path);
206
        $webapp = $this->getWebAppInternal();
207
        if (!$webapp) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $webapp of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
208
            $path = '/';
209
        }
210
        setcookie($key, $val, 0, $path);
211
    }
212
213
    /**
214
     * @throws Exception\BrokenConnectionException
215
     */
216
    public function read(int $size): string
217
    {
218
        return $this->protocol->getSocketHandler()->read($size);
219
    }
220
221
    /**
222
     * @param string $channelName generally the tcp port on which to connect
223
     *
224
     * @return SocketChannelP
225
     *
226
     * @throws Exception\ConnectException
227
     */
228
    public function getChannel(string $channelName): SocketChannelP
229 8
    {
230 8
        $persistent = $this->protocol->client->getParam(Client::PARAM_USE_PERSISTENT_CONNECTION);
231 8
        try {
232 8
            $streamSocket = new StreamSocket(
233 8
                $this->ssl === 'ssl://' ? StreamSocket::TRANSPORT_SSL : StreamSocket::TRANSPORT_TCP,
234 8
                $this->host.':'.$channelName,
235
                null,
236 8
                [],
237
                $persistent
238
            );
239
            $socket = $streamSocket->getSocket();
240
        } catch (\Throwable $e) {
241
            $logger = $this->protocol->getClient()->getLogger();
242
            $logger->critical(sprintf(
243
                '[soluble-japha] %s (%s)',
244
                $e->getMessage(),
245
                __METHOD__
246 8
            ));
247
            throw new ConnectionException($e->getMessage(), $e->getCode());
248 8
        }
249
        stream_set_timeout($socket, -1);
250
251
        return new SocketChannelP($socket, $this->host, $this->java_recv_size, $this->java_send_size);
252
    }
253 14
254
    public function keepAlive(): void
255
    {
256
        parent::keepAlive();
257
    }
258
259
    public function redirect(): void
260
    {
261
    }
262
}
263