|
1 | 1 | <?php |
2 | | -/** |
3 | | - * Pterodactyl - Panel |
4 | | - * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>. |
5 | | - * |
6 | | - * This software is licensed under the terms of the MIT license. |
7 | | - * https://opensource.org/licenses/MIT |
8 | | - */ |
9 | 2 |
|
10 | 3 | namespace Pterodactyl\Services\Eggs; |
11 | 4 |
|
12 | 5 | use Illuminate\Support\Arr; |
13 | 6 | use Illuminate\Support\Str; |
14 | | -use Pterodactyl\Models\Egg; |
15 | 7 | use Pterodactyl\Models\Server; |
16 | 8 | use Pterodactyl\Contracts\Repository\EggRepositoryInterface; |
17 | 9 | use Pterodactyl\Services\Servers\ServerConfigurationStructureService; |
18 | 10 |
|
19 | 11 | class EggConfigurationService |
20 | 12 | { |
| 13 | + private const NOT_MATCHED = '__no_match'; |
| 14 | + |
21 | 15 | /** |
22 | 16 | * @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface |
23 | 17 | */ |
@@ -109,63 +103,8 @@ protected function replacePlaceholders(Server $server, object $configs) |
109 | 103 | // can property map the egg placeholders to values. |
110 | 104 | $structure = $this->configurationStructureService->handle($server, true); |
111 | 105 |
|
112 | | - foreach ($configs as $file => $data) { |
113 | | - foreach ($data->find ?? [] as &$value) { |
114 | | - preg_match('/^{{(?<key>.*)}}$/', $value, $matches); |
115 | | - |
116 | | - if (! $key = $matches['key'] ?? null) { |
117 | | - continue; |
118 | | - } |
119 | | - |
120 | | - // Matched something in {{server.X}} format, now replace that with the actual |
121 | | - // value from the server properties. |
122 | | - // |
123 | | - // The Daemon supports server.X, env.X, and config.X placeholders. |
124 | | - if (! Str::startsWith($key, ['server.', 'env.', 'config.'])) { |
125 | | - continue; |
126 | | - } |
127 | | - |
128 | | - // We don't want to do anything with config keys since the Daemon will need to handle |
129 | | - // that. For example, the Spigot egg uses "config.docker.interface" to identify the Docker |
130 | | - // interface to proxy through, but the Panel would be unaware of that. |
131 | | - if (Str::startsWith($key, 'config.')) { |
132 | | - $value = "{{{$key}}}"; |
133 | | - continue; |
134 | | - } |
135 | | - |
136 | | - // The legacy Daemon would set SERVER_MEMORY, SERVER_IP, and SERVER_PORT with their |
137 | | - // respective values on the Daemon side. Ensure that anything referencing those properly |
138 | | - // replaces them with the matching config value. |
139 | | - switch ($key) { |
140 | | - case 'server.build.env.SERVER_MEMORY': |
141 | | - case 'env.SERVER_MEMORY': |
142 | | - $key = 'server.build.memory'; |
143 | | - break; |
144 | | - case 'server.build.env.SERVER_IP': |
145 | | - case 'env.SERVER_IP': |
146 | | - $key = 'server.build.default.ip'; |
147 | | - break; |
148 | | - case 'server.build.env.SERVER_PORT': |
149 | | - case 'env.SERVER_PORT': |
150 | | - $key = 'server.build.default.port'; |
151 | | - break; |
152 | | - } |
153 | | - |
154 | | - // Replace anything starting with "server." with the value out of the server configuration |
155 | | - // array that used to be created for the old daemon. |
156 | | - if (Str::startsWith($key, 'server.')) { |
157 | | - $value = Arr::get( |
158 | | - $structure, preg_replace('/^server\./', '', $key), '' |
159 | | - ); |
160 | | - continue; |
161 | | - } |
162 | | - |
163 | | - // Finally, replace anything starting with env. with the expected environment |
164 | | - // variable from the server configuration. |
165 | | - $value = Arr::get( |
166 | | - $structure, preg_replace('/^env\./', 'build.env.', $key), '' |
167 | | - ); |
168 | | - } |
| 106 | + foreach ($configs as $file => &$data) { |
| 107 | + $this->iterate($data->find, $structure); |
169 | 108 | } |
170 | 109 |
|
171 | 110 | $response = []; |
@@ -194,4 +133,99 @@ protected function replacePlaceholders(Server $server, object $configs) |
194 | 133 |
|
195 | 134 | return $response; |
196 | 135 | } |
| 136 | + |
| 137 | + /** |
| 138 | + * @param string $value |
| 139 | + * @param array $structure |
| 140 | + * @return string|null |
| 141 | + */ |
| 142 | + protected function matchAndReplaceKeys(string $value, array $structure): ?string |
| 143 | + { |
| 144 | + preg_match('/{{(?<key>.*)}}/', $value, $matches); |
| 145 | + |
| 146 | + if (! $key = $matches['key'] ?? null) { |
| 147 | + return self::NOT_MATCHED; |
| 148 | + } |
| 149 | + |
| 150 | + // Matched something in {{server.X}} format, now replace that with the actual |
| 151 | + // value from the server properties. |
| 152 | + // |
| 153 | + // The Daemon supports server.X, env.X, and config.X placeholders. |
| 154 | + if (! Str::startsWith($key, ['server.', 'env.', 'config.'])) { |
| 155 | + return self::NOT_MATCHED; |
| 156 | + } |
| 157 | + |
| 158 | + // We don't want to do anything with config keys since the Daemon will need to handle |
| 159 | + // that. For example, the Spigot egg uses "config.docker.interface" to identify the Docker |
| 160 | + // interface to proxy through, but the Panel would be unaware of that. |
| 161 | + if (Str::startsWith($key, 'config.')) { |
| 162 | + return "{{{$key}}}"; |
| 163 | + } |
| 164 | + |
| 165 | + // The legacy Daemon would set SERVER_MEMORY, SERVER_IP, and SERVER_PORT with their |
| 166 | + // respective values on the Daemon side. Ensure that anything referencing those properly |
| 167 | + // replaces them with the matching config value. |
| 168 | + switch ($key) { |
| 169 | + case 'server.build.env.SERVER_MEMORY': |
| 170 | + case 'env.SERVER_MEMORY': |
| 171 | + $key = 'server.build.memory'; |
| 172 | + break; |
| 173 | + case 'server.build.env.SERVER_IP': |
| 174 | + case 'env.SERVER_IP': |
| 175 | + $key = 'server.build.default.ip'; |
| 176 | + break; |
| 177 | + case 'server.build.env.SERVER_PORT': |
| 178 | + case 'env.SERVER_PORT': |
| 179 | + $key = 'server.build.default.port'; |
| 180 | + break; |
| 181 | + } |
| 182 | + |
| 183 | + // Replace anything starting with "server." with the value out of the server configuration |
| 184 | + // array that used to be created for the old daemon. |
| 185 | + if (Str::startsWith($key, 'server.')) { |
| 186 | + $plucked = Arr::get( |
| 187 | + $structure, preg_replace('/^server\./', '', $key), '' |
| 188 | + ); |
| 189 | + |
| 190 | + return preg_replace('/{{(.*)}}/', $plucked, $value); |
| 191 | + } |
| 192 | + |
| 193 | + // Finally, replace anything starting with env. with the expected environment |
| 194 | + // variable from the server configuration. |
| 195 | + $plucked = Arr::get( |
| 196 | + $structure, preg_replace('/^env\./', 'build.env.', $key), '' |
| 197 | + ); |
| 198 | + |
| 199 | + return preg_replace('/{{(.*)}}/', $plucked, $value); |
| 200 | + } |
| 201 | + |
| 202 | + /** |
| 203 | + * Iterates over a set of "find" values for a given file in the parser configuration. If |
| 204 | + * the value of the line match is something iterable, continue iterating, otherwise perform |
| 205 | + * a match & replace. |
| 206 | + * |
| 207 | + * @param mixed $data |
| 208 | + * @param array $structure |
| 209 | + */ |
| 210 | + private function iterate(&$data, array $structure) |
| 211 | + { |
| 212 | + if (! is_iterable($data) && ! is_object($data)) { |
| 213 | + return; |
| 214 | + } |
| 215 | + |
| 216 | + foreach ($data as &$value) { |
| 217 | + if (is_iterable($value) || is_object($value)) { |
| 218 | + $this->iterate($value, $structure); |
| 219 | + |
| 220 | + continue; |
| 221 | + } |
| 222 | + |
| 223 | + $response = $this->matchAndReplaceKeys($value, $structure); |
| 224 | + if ($response === self::NOT_MATCHED) { |
| 225 | + continue; |
| 226 | + } |
| 227 | + |
| 228 | + $value = $response; |
| 229 | + } |
| 230 | + } |
197 | 231 | } |
0 commit comments