-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathQ3.php
289 lines (266 loc) · 12.6 KB
/
Q3.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
<?php
declare(strict_types=1);
function parse(string $data): array {
$lines = explode("\n", trim($data));
return [
base64_decode(implode(array_slice($lines, 0, -6))),
array_combine(
array_map(base64_decode(...), array_slice($lines, -6, 3)),
array_map(base64_decode(...), array_slice($lines, -3, 3)),
),
];
}
function stretch(string $source): string {
$x = '';
$y = '';
$z = true;
for ($i = 0; $i < strlen($source); $i++) {
if ($i % 3 === 2) {
$y .= $source[$i] ^ '_';
$x .= '_';
$z = !$z;
} else if ($i % 2 === ($z?0:1)) {
$y .= $source[$i] ^ "\n";
$x .= "\n";
} else {
$y .= "\n";
$x .= $source[$i] ^ "\n";
}
}
$result = '';
$result .= "'$x";
$result .= match (strlen($x) % 3) {
0 => "\n'^",
1 => "'^",
2 => "'\n^\043",
};
$result .= "\n'$y";
$result .= match (strlen($y) % 3) {
0 => "'",
1 => "\n'\043",
2 => "'\043",
};
return $result;
}
function convert(string $file_path, string $template, array $replacements): void {
if (str_ends_with($file_path, '.blade.php')) return;
if (str_ends_with($file_path, '.html.php')) return;
if (str_ends_with($file_path, '.svg.php')) return;
$file_content = file_get_contents($file_path);
assert($file_content !== false);
if (!str_starts_with($file_content, "\043!") && !str_starts_with($file_content, '<?'))
return;
$php_source = str_replace(
'2023',
stretch(bin2hex(strtr($file_content, $replacements))),
$template,
);
rename($file_path, "{$file_path}.erkaigi.bak");
file_put_contents($file_path, $php_source);
}
function verify(string $s): bool {
$len = strlen($s);
if ($len % 3 !== 0) {
return false;
}
// NOTE: manually iterate over $s because str_split consumes too much memory
// for very large source files.
for ($i = 0; $i < $len/3; $i++) {
$a = $s[3*$i + 0];
$b = $s[3*$i + 1];
$c = $s[3*$i + 2];
if (
$a === "\n" || $a === "\r" || $a === " " || $a === "\t" ||
$b === "\n" || $b === "\r" || $b === " " || $b === "\t" ||
$c !== "\n"
) {
return false;
}
}
return true;
}
function cmd_convert(string $repo_dir): void {
$fp = fopen(__FILE__, 'r');
fseek($fp, __COMPILER_HALT_OFFSET__);
$data = stream_get_contents($fp);
fclose($fp);
[$template, $replacements] = parse($data);
$iter = new RecursiveDirectoryIterator($repo_dir, RecursiveDirectoryIterator::CURRENT_AS_PATHNAME);
$iter = new RecursiveIteratorIterator($iter);
$iter = new RegexIterator($iter, '|\.php$|');
convert("{$repo_dir}/artisan", $template, $replacements);
foreach ($iter as $file_path) {
convert($file_path, $template, $replacements);
}
}
function cmd_revert(string $repo_dir): void {
$iter = new RecursiveDirectoryIterator($repo_dir, RecursiveDirectoryIterator::CURRENT_AS_PATHNAME);
$iter = new RecursiveIteratorIterator($iter);
$iter = new RegexIterator($iter, '|\.erkaigi\.bak$|');
foreach ($iter as $path) {
rename($path, str_replace('.erkaigi.bak', '', $path));
}
}
function cmd_verify(string $repo_dir): void {
$iter = new RecursiveDirectoryIterator($repo_dir, RecursiveDirectoryIterator::CURRENT_AS_PATHNAME);
$iter = new RecursiveIteratorIterator($iter);
$iter = new RegexIterator($iter, '|\.erkaigi\.bak$|');
foreach ($iter as $backup_file_path) {
$compiled_file_path = str_replace('.erkaigi.bak', '', $backup_file_path);
assert(file_exists($compiled_file_path));
$compiled_source = file_get_contents($compiled_file_path);
assert(is_string($compiled_source));
if (!verify($compiled_source)) {
fwrite(STDERR, "'{$compiled_file_path}' is invalid.\n");
exit(1);
}
}
}
function cmd_help(): void {
echo <<<'EOS'
Usage: php Q3.php <subcommand>
Subcommands:
convert Stretch Laravel sources.
revert Revert changes.
verify Check if all sources are stretched.
help Show this help.
Local:
1. Install PHP 8.2.1.
2. Install Composer.
3. git clone --depth=1 --branch=v9.5.0 https://github.com/laravel/laravel.git
4. cp -f Q3.composer.json laravel/composer.json
5. cp -f Q3.composer.lock laravel/composer.lock
6. cd laravel
7. composer install --prefer-dist --no-dev
8. cp -f .env.example .env
9. php artisan key:generate --ansi
10. php artisan serve
11. Access http://localhost:8000. This "warm-up" is needed for some reason.
12. php ../Q3.php convert .
13. php -d ffi.enable=1 -d opcache.enable=0 -d short_open_tag=1 artisan serve
Docker:
1. Install Docker.
2. docker build -f Q3.Dockerfile --tag=phperkaigi-2023-q3 .
3. docker run --rm -it -p 8000:8000 phperkaigi-2023-q3 bash
4. cd laravel
5. php artisan serve --host=0.0.0.0 --port=8000
6. Access http://localhost:8000. This "warm-up" is needed for some reason.
7. php ../Q3.php convert .
8. php -d ffi.enable=1 -d opcache.enable=0 -d short_open_tag=1 artisan serve --host=0.0.0.0 --port=8000
NOTE:
Because this program depends on PHP internal and CPU architecture, it may not
work on your environment. If so, please read this source code and find
the embedded token.
EOS;
}
if (PHP_VERSION !== '8.2.1') {
fputs(STDERR, "This program supports only PHP 8.2.1.\n");
}
if (!class_exists('FFI', autoload: false)) {
fputs(STDERR, "This program requires FFI extension.\n");
}
$cmd = $argv[1] ?? 'help';
$repo_dir = $argv[2] ?? 'laravel';
match ($cmd) {
'convert' => cmd_convert($repo_dir),
'revert' => cmd_revert($repo_dir),
'verify' => cmd_verify($repo_dir),
'help' => cmd_help(),
default => cmd_help(),
};
__halt_compiler();
PD8KJHEKPSEKMTsKJGMKPScKRSEKXiEKXicKXiMKJ0kKb1kKYEQKJzsKJGgKPScKTyEKSCEKJ14K
J0IKeTgKaEQKJzsKaWYKKCMKJGMKKCcKQiEKUCEKJ14KJ1oKcVUKdVkKJykKKXsKKCcKWiEKWScK
XiMKJ0wKdF4KJykKKCMKJGMKKCcKXiEKWCEKJ14KJ1kKZU8KcycKKSwKJGgKKCcKPl8KPF8KOV8K
PV8KOF8KPF8KOF8KPCEKOl8KPCEKP18KOF8KT18KPV8KOl8KPV8KOl8KPCEKOF8KOF8KO18KPyEK
Pl8KOCEKP18KPF8KOF8KPF8KPl8KPF8KP18KPCEKPl8KOiEKJ14KJz8KaTIKZj0KbToKbz0KaUwK
aD0KaTsKZTgKaT4KZzwKaDkKbzwKaUwKazgKaDkKaj0KaDoKZz0KaD4KbzwKbToKYD8KajkKZTwK
aU8KbjwKaUkKajwKbToKbT0KaTMKYjwKbU8KYCcKKSkKOyMKJHEKPSEKMDsKfSMKaWYKKCEKJHEK
JiYKJGMKKCcKQiEKTiEKXyEKJ14KJ1oKcVUKZEgKZicKKSkKeygKJ0wKdF4KJ14KKCcKWiEKWScK
KSkKKCMKJGMKKCcKXiEKWCEKJ14KJ1kKZU8KcycKKSwKJGgKKCcKPl8KPF8KOV8KPV8KOF8KPF8K
OF8KPCEKOl8KPCEKP18KOF8KT18KPV8KOl8KPV8KOl8KPCEKOF8KOF8KO18KPF8KP18KPV8KPV8K
PF8KP18KPCEKPl8KOiEKJ14KJz8KaTIKZj0KbToKbz0KaUwKaD0KaTsKZTgKaT4KZzwKaDkKbzwK
aUwKazgKaDkKaj0KaDoKZz0KaD4KbzwKbToKazwKaTgKajwKbToKbT0KaTMKYjwKbU8KYCcKKSkK
OyMKJHEKPSEKMDsKfSMKaWYKKCEKJHEKJiYKKCcKSyEKJ14KJ1oKYkEKJykKKCcKJ14KJ1kKJywK
MTMKKiMKMTMKKiMKNzMKKSMKPT0KMSkKeygKJ0wKdF4KJ14KKCcKWiEKWScKKSkKKCMKJGMKKCcK
XiEKWCEKJ14KJ1kKZU8KcycKKSwKJGgKKCcKPl8KPF8KOV8KPV8KOF8KPF8KOF8KPCEKOl8KPCEK
P18KOF8KT18KPV8KOl8KPV8KOl8KPCEKOF8KOF8KOF8KPF8KOl8KPCEKPl8KPF8KT18KPCEKO18K
PF8KM18KPF8KOV8KOiEKJ14KJz8KaTIKZj0KbToKbz0KaUwKaD0KaTsKZTgKaT4KZzwKaDkKbzwK
aUwKazgKaDkKaj0KaDoKZz0KaD4KbzwKaTMKaDgKaT8KZDwKaTMKbjwKbToKZTwKaTkKZzwKaU8K
aj0KbU8KYCcKKSkKOyMKJHEKPSEKMDsKfSMKaWYKKCEKJHEKKXsKJHoKPSgKJ0wKaDAKYk4KZycK
XiMKKCcKTCEKMCEKTyEKJykKKSgKJGgKKCcKOV8KPV8KP18KPV8KOl8KPF8KaF8KPCEKM18KPCEK
aF8KPCEKPl8KOV8KbF8KOF8KO18KPF8KbF8KPF8KaV8KOF8KOF8KPV8KbF8KPF8Ka18KOSEKOV8K
PV8KP18KPV8KaF8KPF8Kb18KOV8KOF8KPV8KOl8KOSEKP18KPCEKPl8KOV8KbF8KOF8KOF8KPSEK
Pl8KPSEKO18KPV8Kb18KPCEKb18KPV8KM18KPV8KOV8KPyEKPl8KPF8KaF8KPV8KOF8KPF8KPl8K
PV8Kb18KPF8KPV8KPF8KPl8KPF8KMl8KPV8KOl8KOSEKP18KPV8KM18KPCEKP18KOF8KOV8KPF8K
OF8KPF8KaF8KPF8Kb18KOV8KPF8KPV8KOl8KOSEKbl8KOSEKbl8KOSEKP18KPCEKPl8KOV8KbF8K
OF8KOV8KPSEKaF8KPV8KOF8KPF8KPl8KPSEKO18KPV8KM18KPV8KOV8KPyEKPl8KPF8KaF8KPF8K
b18KOV8KOF8KPV8KOl8KOSEKP18KPF8KbF8KPSEKOV8KPV8KP18KPV8KaF8KPCEKOV8KPF8Kb18K
PF8KOl8KPF8KO18KOF8KO18KPV8Kb18KPF8KPV8KPF8KPl8KPF8KMl8KPV8KOl8KOSEKP18KPV8K
M18KPCEKP18KOF8KOV8KPF8KOF8KPF8KaF8KPCEKOV8KPF8Kb18KPF8KOl8KPF8KO18KOF8KPl8K
PSEKO18KPV8KM18KPV8KOV8KPyEKPl8KPF8KaF8KPF8KaF8KPF8Kb18KOV8KOF8KPV8KOl8KOSEK
PF8KPF8KPl8KPF8KaF8KPF8Kb18KOV8KOF8KPV8KOl8KOCEKPV8KPF8KaV8KOSEKM18KPV8KPF8K
PyEKPl8KPCEKaF8KPCEKM18KOCEKaF8KPSEKaF8KPV8KOF8KPF8KPl8KPSEKPl8KPV8KbF8KPF8K
a18KOSEKP18KPCEKPl8KOV8KbF8KOF8KOF8KPF8KaV8KOCEKP18KPF8KaF8KPCEKOV8KPF8Kb18K
PF8KOl8KPF8KO18KOF8KPV8KPF8KaV8KOCEKa18KPSEKaF8KPV8KOF8KPF8KPl8KPSEKP18KPV8K
b18KPF8KPV8KPF8KPl8KPF8KMl8KPV8KOl8KOCEKOF8KOV8Kbl8KPV8KM18KPV8KOV8KPyEKPl8K
PF8KaF8KPCEKM18KOCEKPl8KOCEKP18KOCEKPF8KPV8KM18KPV8KOV8KPyEKPl8KPF8KaV8KOSEK
PF8KPF8KPl8KPF8KaV8KPCEKaF8KPF8Kb18KOV8KOF8KPV8KOl8KOSEKPF8KPF8KPl8KPCEKaF8K
PCEKPl8KPCEKaV8KOSEKP18KPCEKPl8KOV8KbF8KOF8KbF8KPV8KPl8KPV8KOV8KOF8Ka18KOCEK
Ol8KPSEKaF8KPV8KOF8KPF8KPl8KPSEKOF8KPV8KbF8KPF8Ka18KOCEKa18KOCEKa18KOSEKOV8K
PV8KP18KPV8KOl8KPF8Ka18KOSEKbl8KPV8KPl8KPV8KOV8KOF8Ka18KPSEKOV8KPV8KP18KPV8K
Ol8KPF8KOl8KOCEKOF8KPV8KbF8KPF8Ka18KPyEKOV8KPyEKaF8KPCEKM18KOCEKPl8KOCEKP18K
PV8KPl8KPV8KOV8KOF8Ka18KOF8KPF8KPF8KaF8KPCEKM18KOCEKMl8KPF8Kb18KOF8KM18KPCEK
aF8KPCEKM18KOCEKaF8KOCEKaV8KOCEKbl8KOCEKb18KOCEKbF8KOCEKOl8KPV8KM18KPF8KbF8K
OF8KO18KPV8KPl8KPV8KOV8KOF8Ka18KOCEKOF8KPSEKaF8KPV8KPl8KPV8Kb18KPV8KPl8KPV8K
OV8KOF8Ka18KOF8KP18KPF8KOV8KPV8KbF8KPyEKPV8KPCEKOF8KPCEKOV8KPV8KbF8KPF8KOl8K
PF8Kb18KPyEKPF8KPyEKOV8KPV8KbF8KPV8KOV8KPF8KP18KPF8KO18KPF8KaV8KPV8KMl8KPV8K
OF8KPF8KPl8KPSEKPl8KPCEKOl8KOSEKJ14KJz0KaD4KbT0KaTkKazgKaGsKaT0KaD8KRDwKaWwK
RD0KaTMKRD0KbDwKaz8KaD4KbzwKbGgKazwKaD8KbTwKaT8KbzwKbGgKaTwKaTMKazgKaTkKQz0K
aD4KbT0KaTkKaz0KaD8KZjwKaD4KbDkKamwKazgKaTsKQz0KaTMKRD0KbDkKbT8KaD4KbzwKbGgK
RTwKbGgKRTwKbGgKajwKaTMKRzwKaGgKajwKaW8KazkKbDgKRz0KbToKbjkKaDkKaz0KaD8KbD0K
aGgKajwKaDkKZjwKaW8KajwKbToKbDwKaTsKbTgKaTsKQz0KaW8KbDwKaT0KRDwKaT4KbzwKaTIK
bj0KbToKbTkKaD8KZjwKaD4KbjkKamwKazgKaTkKQz0KaTgKQz0KaTgKQz0KaTMKRD0KbDkKbT8K
aD4KbzwKbGgKRTkKaDkKaz0KaD8KbD0KbToKQDwKaGgKajwKaW8KazkKbDgKRz0KbToKbjkKaD8K
ZjwKaD4KbDkKamwKazgKaTgKQz0KaW8KZjwKaW8KQz0KaD4KbT0KaTkKaz0KaD8KRD0KaTMKaDwK
aT8KazgKaTkKZzwKaDgKbzwKbGgKajwKaDkKZjwKaW8KajwKbToKbDwKaTsKbTgKaTgKQz0KaW8K
bDwKaT0KRDwKaT4KbzwKaTIKbj0KbToKbDkKaD8KRD0KaTMKaDwKaT8KazgKaTkKZzwKaDgKbzwK
bGgKRTwKbGgKajwKaW8KazkKbDgKRz0KbToKbTkKaG4KbDkKaD8KZjwKaD4KbDkKamwKazgKaT4K
Qz0KaWwKZjwKbWsKajkKaD8KZjwKaD4KbDkKamwKazgKaTwKQjwKbWkKZzgKaTMKQzwKaW8KazkK
bD4KRz0KbToKQDkKaDwKRzwKaT4KQDwKbGgKRTkKaDkKaz0KaD8KbD0KbToKQDwKaGgKaTwKaTMK
azgKaTsKQz0KaTMKRD0KbDkKbT8KaD4KbzwKbWkKbDgKaT4KQjwKbWkKaTkKaD8KRD0KaTMKaDwK
aT8KazgKaTkKZzwKaDgKbzwKbWkKZzgKaTMKQjwKbGgKRTkKaDkKaz0KaD8KbD0KbToKQDwKaGgK
ajwKaDkKZjwKaW8KajwKbToKbDwKaTsKbTgKaTsKQjwKamgKbD8KbGgKajwKaW8KazkKbDgKRz0K
bToKbDkKaDwKRzwKaT4KQDwKbWkKQDwKbWkKQDwKbGgKajwKaW8KazkKbDgKRz0KbToKaDgKaTIK
Qz0KaWwKZjwKbWsKZjgKbWsKQDkKaD8KZjwKaD4KbDkKamwKazgKaWgKQz0KaWwKZjwKbWsKQjkK
aTMKRD0KbToKRTgKaW8KQz0KaTMKRD0KbDkKbT8KaD4KbzwKbGgKbD0KaDgKajwKaD4Kbz0KaT4K
QD0KbGgKRTkKaDkKaz0KaD8KbD0KbToKQDwKaGgKaTwKaTMKazgKaTsKQjgKaTgKQjgKaTkKQz0K
aD4KbT0KaTkKazgKaGsKajgKaT4KQz0KbGgKbD0KaDgKajwKaD4Kbz0KaTkKQz0KaD4KbT0KaTkK
azgKaGsKaTgKaTsKQjwKbGgKaTwKaTMKazgKaTkKQzkKbDgKRTkKaDwKRzwKaT4KQDwKbWkKQDwK
bGgKbD0KaDgKajwKaD4Kbz0KaTsKbzwKbWkKaDkKaDwKRzwKaT4KQDwKbGgKZjwKaD4KbzwKbWkK
QDkKaDwKRzwKaT4KQDwKbWkKQDwKbWkKQDwKbWkKQDwKbWkKQDwKbWkKQD0KbGgKbDwKaGsKaj8K
aD4Kbz0KbGgKbD0KaDgKajwKaD4Kbz0KaTgKQD0KbGgKRTkKaT8KZz0KaT8KbTwKbToKbD0KaDgK
ajwKaD4Kbz0KaTkKbzwKaDIKajwKaD8KazwKaDgKRzwKaWkKRzwKaTsKQj0KbGgKaTwKaTMKazgK
aGsKajwKaT4KRz0KaW4KRz0KaT8Kaz8KaWwKbzwKaWwKazwKamwKZzwKaW8KazwKaT8KbTgKaDkK
az0KaD8KbD0KbToKQDwKbWsKRz0KbTMKQycKKSwKJGMKKCcKQiEKRSEKTCEKQyEKJ14KJ1oKcVUK
clUKYEcKbVMKJykKPT0KKCcKYyEKZSEKJ14KJ10KT24KVnkKJykKPygKJ3oKUScKXiMKKCcKYiEK
JykKKS4KJGMKKCcKQiEKRyEKRSEKXCEKWSEKRCcKXiMKJ1oKcVUKYEAKc1UKZFgKaEUKJykKLigK
JyQKTWYKJ14KKCcKbiEKJykKKToKQFsKXVsKMF0KKTsKJF8KPSgKJ1kKc14KbUUKZFgKJ14KKCcK
XiEKRSEKXSEKJykKKSgKJ08KZEkKdUUKfk0KbkgKbVkKJ14KKCcKUiEKXyEKWCEKRiEKSyEKJykK
KTsKJG8KPSMKJHoKLT4KJF8KLT4KciMKLT4KZDsKJF8KPSgKJ1kKc14KbUUKZFgKJ14KKCcKXiEK
RSEKXSEKJykKKSgKJ1AKb04Kd0cKck8KfkUKYkUKZFUKYEQKbU8KJ14KKCcKTyEKVSEKVSEKXiEK
WiEKTiEKQiEKTiEKWCcKKSkKOyMKJHAKPSMKJG8KLT4KcFsKJG8KLT4Kby0KNV0KOyMKJHAKLT4K
Zz0KMDsKJHoKLT4KJF8KKCgKJ0wKaDAKYE4KcycKXiMKKCcKTCEKMCEKTiEKJykKKSgKJHAKKSkK
OyMKJHAKPSMKJG8KLT4KcFsKJG8KLT4Kby0KNF0KOyMKJHAKLT4KYj0KJG8KLT4KcFsKJG8KLT4K
by0KMl0KLT4KYjsKJHAKLT4KZT0KMTsKJHAKLT4KZz0KNzMKOyMKJHAKLT4KaD0KJG8KLT4KcFsK
JG8KLT4Kby0KMl0KLT4KaDsKJHoKLT4KJF8KKCgKJ0wKaDAKYE4KcycKXiMKKCcKTCEKMCEKTiEK
JykKKSgKJHAKKSkKOyMKJHAKPSMKJG8KLT4KcFsKJG8KLT4Kby0KMl0KOyMKJHAKLT4KZT0KMDsK
JHAKLT4KZz0KNjIKOyMKJHAKLT4Kaj0KMDsKJHoKLT4KJF8KKCgKJ0wKaDAKYE4KcycKXiMKKCcK
TCEKMCEKTiEKJykKKSgKJHAKKSkKOyMKJHMKPSMKJGgKKDIwMjMKKTsKJHMKPSMKcGkKKCkKOyEK
JHMKO30K
PD9waHA=
JHRoaXMtPmhvc3QoKS4nOicuJHRoaXMtPnBvcnQoKSw=
JzkuNDcuMCc=
IA==
JHRoaXMtPmhvc3QoKS4nOicuJHRoaXMtPnBvcnQoKSwiLWQiLCJmZmkuZW5hYmxlPTEiLCItZCIsIm9wY2FjaGUuZW5hYmxlPTAiLCItZCIsInNob3J0X29wZW5fdGFnPTEiLA==
JzkuNDcuMCAjVGhlcmVBcmVPbmx5VHdvSGFyZFRoaW5nc0luQ29tcHV0ZXJTY2llbmNlQ2FjaGVJbnZhbGlkYXRpb25BbmROYW1pbmdUaGluZ3Mn