Skip to content

Commit d836595

Browse files
committed
Fixed issue where JavaPHP is stuck in a while loop when running a PHP script after another
1 parent b8b10e7 commit d836595

File tree

16 files changed

+200
-191
lines changed

16 files changed

+200
-191
lines changed

.gitignore

100644100755
File mode changed.

.idea/.gitignore

100644100755
File mode changed.

.idea/discord.xml

100644100755
Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/encodings.xml

100644100755
File mode changed.

.idea/misc.xml

100644100755
File mode changed.

.idea/vcs.xml

100644100755
File mode changed.

LICENSE

100644100755
File mode changed.

README.md

100644100755
File mode changed.

pom.xml

100644100755
File mode changed.
Lines changed: 115 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,115 @@
1-
package fr.breadeater.javaphp;
2-
3-
import java.io.ByteArrayOutputStream;
4-
import java.io.InputStream;
5-
import java.nio.ByteBuffer;
6-
import java.nio.charset.StandardCharsets;
7-
import java.util.Map;
8-
9-
class FastCGIUtils {
10-
public static byte[] buildRecord(Status type, int requestId, byte[] content){
11-
int length = content.length;
12-
int padding = (8 - (length % 8)) % 8;
13-
14-
ByteBuffer buffer = ByteBuffer.allocate(8 + length + padding);
15-
16-
buffer.put((byte) Status.FCGI_VERSION.getRequestStatusCode());
17-
buffer.put((byte) type.getRequestStatusCode());
18-
19-
buffer.putShort((short) requestId);
20-
buffer.putShort((short) length);
21-
22-
buffer.put((byte) padding);
23-
buffer.put((byte) 0);
24-
buffer.put(content);
25-
26-
if (padding > 0) buffer.put(new byte[padding]);
27-
28-
return buffer.array();
29-
}
30-
31-
public static byte[] encodeLength(int length){
32-
if (length < 128) return new byte[]{ (byte) length };
33-
34-
return new byte[]{
35-
(byte) ((length >> 24) | 0x80),
36-
(byte) (length >> 16),
37-
(byte) (length >> 8),
38-
(byte) length
39-
};
40-
}
41-
42-
public static byte[] buildParams(boolean empty, int requestId, Map<String, String> params) throws Exception {
43-
if (empty) return buildRecord(Status.FCGI_PARAMS, requestId, new byte[0]);
44-
45-
ByteArrayOutputStream out = new ByteArrayOutputStream();
46-
47-
for (Map.Entry<String, String> entry : params.entrySet()){
48-
byte[] key = entry.getKey().getBytes(StandardCharsets.UTF_8);
49-
byte[] value = entry.getValue().getBytes(StandardCharsets.UTF_8);
50-
51-
out.write(encodeLength(key.length));
52-
out.write(encodeLength(value.length));
53-
out.write(key);
54-
out.write(value);
55-
}
56-
57-
return buildRecord(Status.FCGI_PARAMS, requestId, out.toByteArray());
58-
}
59-
60-
public static byte[] buildStdin(int requestId, byte[] body){
61-
return buildRecord(Status.FCGI_STDIN, requestId, body);
62-
}
63-
64-
public static byte[] buildEmptyStdin(int requestId){
65-
return buildRecord(Status.FCGI_STDIN, requestId, new byte[0]);
66-
}
67-
68-
public static byte[] buildRequest(int requestId){
69-
byte[] body = new byte[8];
70-
71-
body[0] = 0;
72-
body[1] = (byte) Status.FCGI_RESPONDER.getRequestStatusCode();
73-
body[2] = 0;
74-
75-
return buildRecord(Status.FCGI_BEGIN_REQUEST, requestId, body);
76-
}
77-
78-
public static String parseFastCGIRequest(InputStream in) throws Exception {
79-
String result = null;
80-
81-
while (true){
82-
int version = in.read();
83-
int type = in.read();
84-
int requestIdHigh = in.read();
85-
int requestIdLow = in.read();
86-
int contentLengthHigh = in.read();
87-
int contentLengthLow = in.read();
88-
int padding = in.read();
89-
90-
in.read();
91-
92-
if (version == -1) break;
93-
94-
int contentLength = (contentLengthHigh << 8) | contentLengthLow;
95-
byte[] content = in.readNBytes(contentLength);
96-
97-
if (padding > 0) in.skip(padding);
98-
99-
if (type == Status.FCGI_STDOUT.getRequestStatusCode() && contentLength > 0) result = new String(content, StandardCharsets.UTF_8);
100-
if (type == Status.FCGI_END_REQUEST.getRequestStatusCode()) break;
101-
}
102-
103-
return result;
104-
}
105-
}
1+
package fr.breadeater.javaphp;
2+
3+
import java.io.ByteArrayOutputStream;
4+
import java.io.InputStream;
5+
import java.net.Socket;
6+
import java.nio.ByteBuffer;
7+
import java.nio.charset.StandardCharsets;
8+
import java.util.Map;
9+
10+
class FastCGIUtils {
11+
public static byte[] buildRecord(Status type, int requestId, byte[] content){
12+
int length = content.length;
13+
int padding = (8 - (length % 8)) % 8;
14+
15+
ByteBuffer buffer = ByteBuffer.allocate(8 + length + padding);
16+
17+
buffer.put((byte) Status.FCGI_VERSION.getRequestStatusCode());
18+
buffer.put((byte) type.getRequestStatusCode());
19+
20+
buffer.putShort((short) requestId);
21+
buffer.putShort((short) length);
22+
23+
buffer.put((byte) padding);
24+
buffer.put((byte) 0);
25+
buffer.put(content);
26+
27+
if (padding > 0) buffer.put(new byte[padding]);
28+
29+
return buffer.array();
30+
}
31+
32+
public static byte[] encodeLength(int length){
33+
if (length < 128) return new byte[]{ (byte) length };
34+
35+
return new byte[]{
36+
(byte) ((length >> 24) | 0x80),
37+
(byte) (length >> 16),
38+
(byte) (length >> 8),
39+
(byte) length
40+
};
41+
}
42+
43+
public static byte[] buildParams(boolean empty, int requestId, Map<String, String> params) throws Exception {
44+
if (empty) return buildRecord(Status.FCGI_PARAMS, requestId, new byte[0]);
45+
46+
ByteArrayOutputStream out = new ByteArrayOutputStream();
47+
48+
for (Map.Entry<String, String> entry : params.entrySet()){
49+
byte[] key = entry.getKey().getBytes(StandardCharsets.UTF_8);
50+
byte[] value = entry.getValue().getBytes(StandardCharsets.UTF_8);
51+
52+
out.write(encodeLength(key.length));
53+
out.write(encodeLength(value.length));
54+
out.write(key);
55+
out.write(value);
56+
}
57+
58+
return buildRecord(Status.FCGI_PARAMS, requestId, out.toByteArray());
59+
}
60+
61+
public static byte[] buildStdin(int requestId, byte[] body){
62+
return buildRecord(Status.FCGI_STDIN, requestId, body);
63+
}
64+
65+
public static byte[] buildEmptyStdin(int requestId){
66+
return buildRecord(Status.FCGI_STDIN, requestId, new byte[0]);
67+
}
68+
69+
public static byte[] buildRequest(int requestId){
70+
byte[] body = new byte[8];
71+
72+
body[0] = 0;
73+
body[1] = (byte) Status.FCGI_RESPONDER.getRequestStatusCode();
74+
body[2] = 0;
75+
76+
return buildRecord(Status.FCGI_BEGIN_REQUEST, requestId, body);
77+
}
78+
79+
public static String parseFastCGIRequest(Socket client, InputStream in) throws Exception {
80+
String result = null;
81+
82+
while (!client.isClosed()){
83+
int version = in.read();
84+
int type = in.read();
85+
int requestIdHigh = in.read();
86+
int requestIdLow = in.read();
87+
int contentLengthHigh = in.read();
88+
int contentLengthLow = in.read();
89+
int padding = in.read();
90+
91+
in.read();
92+
93+
if (version == -1) break;
94+
95+
int contentLength = (contentLengthHigh << 8) | contentLengthLow;
96+
byte[] content = in.readNBytes(contentLength);
97+
98+
if (padding > 0) in.skip(padding);
99+
100+
if (type == Status.FCGI_STDOUT.getRequestStatusCode() && contentLength > 0){
101+
result = new String(content, StandardCharsets.UTF_8);
102+
103+
client.close();
104+
break;
105+
}
106+
107+
if (type == Status.FCGI_END_REQUEST.getRequestStatusCode()){
108+
client.close();
109+
break;
110+
}
111+
}
112+
113+
return result;
114+
}
115+
}

0 commit comments

Comments
 (0)