Skip to content

Commit 30413a7

Browse files
committed
ClientIp + SystemInfo
1 parent 5362bdf commit 30413a7

File tree

3 files changed

+119
-1
lines changed

3 files changed

+119
-1
lines changed

config/services/services.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,15 @@ services:
3131
autoconfigure: true
3232
public: true
3333

34-
PhpList\Core\Domain\Messaging\Service\CampaignProcessor:
34+
PhpList\Core\Domain\Messaging\Service\Processor\CampaignProcessor:
3535
autowire: true
3636
autoconfigure: true
3737
public: true
38+
39+
PhpList\Core\Domain\Common\ClientIpResolver:
40+
autowire: true
41+
autoconfigure: true
42+
43+
PhpList\Core\Domain\Common\SystemInfoCollector:
44+
autowire: true
45+
autoconfigure: true
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Domain\Common;
6+
7+
use Symfony\Component\HttpFoundation\RequestStack;
8+
9+
class ClientIpResolver
10+
{
11+
public function __construct(private readonly RequestStack $requestStack) {}
12+
13+
public function resolve(): string
14+
{
15+
$request = $this->requestStack->getCurrentRequest();
16+
17+
if ($request !== null) {
18+
return $request->getClientIp() ?? '';
19+
}
20+
21+
return (gethostname() ?: 'localhost') . ':' . getmypid();
22+
}
23+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Domain\Common;
6+
7+
use Symfony\Component\HttpFoundation\RequestStack;
8+
9+
class SystemInfoCollector
10+
{
11+
private RequestStack $requestStack;
12+
private array $configuredKeys;
13+
private array $defaultKeys = ['HTTP_USER_AGENT','HTTP_REFERER','REMOTE_ADDR','REQUEST_URI','HTTP_X_FORWARDED_FOR'];
14+
15+
/**
16+
* @param string[] $configuredKeys keys to include (empty => use defaults)
17+
*/
18+
public function __construct(
19+
RequestStack $requestStack,
20+
array $configuredKeys = []
21+
) {
22+
$this->requestStack = $requestStack;
23+
$this->configuredKeys = $configuredKeys;
24+
}
25+
26+
/**
27+
* Return key=>value pairs (already sanitized for safe logging/HTML display).
28+
*
29+
* @return array<string,string>
30+
*/
31+
public function collect(): array
32+
{
33+
$request = $this->requestStack->getCurrentRequest();
34+
35+
$data = [];
36+
37+
if ($request) {
38+
$headers = $request->headers;
39+
40+
$data['HTTP_USER_AGENT'] = (string) $headers->get('User-Agent', '');
41+
$data['HTTP_REFERER'] = (string) $headers->get('Referer', '');
42+
$data['HTTP_X_FORWARDED_FOR'] = (string) $headers->get('X-Forwarded-For', '');
43+
$data['REQUEST_URI'] = $request->getRequestUri();
44+
$data['REMOTE_ADDR'] = $request->getClientIp() ?? '';
45+
} else {
46+
$server = $_SERVER;
47+
$data['HTTP_USER_AGENT'] = (string) ($server['HTTP_USER_AGENT'] ?? '');
48+
$data['HTTP_REFERER'] = (string) ($server['HTTP_REFERER'] ?? '');
49+
$data['HTTP_X_FORWARDED_FOR'] = (string) ($server['HTTP_X_FORWARDED_FOR'] ?? '');
50+
$data['REQUEST_URI'] = (string) ($server['REQUEST_URI'] ?? '');
51+
$data['REMOTE_ADDR'] = (string) ($server['REMOTE_ADDR'] ?? '');
52+
}
53+
54+
$keys = $this->configuredKeys ?: $this->defaultKeys;
55+
56+
$out = [];
57+
foreach ($keys as $key) {
58+
if (!array_key_exists($key, $data)) {
59+
continue;
60+
}
61+
$val = $data[$key];
62+
63+
$safeKey = strip_tags($key);
64+
$safeVal = htmlspecialchars((string) $val, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
65+
66+
$out[$safeKey] = $safeVal;
67+
}
68+
69+
return $out;
70+
}
71+
72+
/**
73+
* Convenience to match the legacy multi-line string format.
74+
*/
75+
public function collectAsString(): string
76+
{
77+
$pairs = $this->collect();
78+
if (!$pairs) {
79+
return '';
80+
}
81+
$lines = [];
82+
foreach ($pairs as $k => $v) {
83+
$lines[] = sprintf("%s = %s", $k, $v);
84+
}
85+
return "\n" . implode("\n", $lines);
86+
}
87+
}

0 commit comments

Comments
 (0)