Skip to content

Commit 6163f4f

Browse files
Yish1Copilot
andauthored
Fix: handle GBK-encoded interface names and descriptions in ports polling (librenms#19528)
* Fix: handle GBK-encoded interface names and descriptions in ports polling When SNMP returns GBK-encoded Chinese interface names (ifName/ifDescr), they fail to decode as UTF-8 and become empty or garbled. This patch adds multi-tier encoding support: 1. StringHelpers::inferEncoding() now prioritizes GB18030/GBK/GB2312 fallbacks before Western encodings (Windows-1252/CP850), preventing mojibake when devices return non-UTF-8 interface descriptions. 2. Port polling/discovery explicitly applies inferEncoding() to ifName and ifDescr fields (consistent with ifAlias handling). Fixes interfaces appearing with empty names like "ifName: -> " when devices use GBK encoding for interface aliases. Co-authored-by: Copilot <copilot@github.com> * Fix: prevent encoding detection conflicts between Western and GB codecs Co-authored-by: Copilot <copilot@github.com> * Fix: Improve prevent encoding detection conflicts between Western and GB codecs Co-authored-by: Copilot <copilot@github.com> --------- Co-authored-by: Copilot <copilot@github.com>
1 parent 6828c5b commit 6163f4f

4 files changed

Lines changed: 21 additions & 0 deletions

File tree

LibreNMS/Util/StringHelpers.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,21 @@ public static function inferEncoding(?string $string): ?string
107107
return (string) $converted;
108108
}
109109

110+
// Detect GB multi-byte pattern: strict GB2312 range (0xA1-0xF7, 0xA1-0xFE)
111+
// or GBK extended range (0x81-0xA0, 0x40-0x7E/0x80-0xFE). Count occurrences to avoid
112+
// false positives from Western encodings like CP850 which may have single high-byte pairs.
113+
$gbPatternCount = preg_match_all('/[\xA1-\xF7][\xA1-\xFE]|[\x81-\xA0][\x40-\x7E\x80-\xFE]/s', $string);
114+
$hasGbPattern = $gbPatternCount >= 2;
115+
116+
if ($hasGbPattern) {
117+
// GB pattern detected, prioritize GB family encodings
118+
foreach (['GB18030', 'GBK', 'GB2312'] as $encoding) {
119+
if (($converted = @iconv($encoding, 'UTF-8', $string)) !== false) {
120+
return (string) $converted;
121+
}
122+
}
123+
}
124+
110125
if ($charset !== 'Windows-1252' && ($converted = @iconv('Windows-1252', 'UTF-8', $string)) !== false) {
111126
return (string) $converted;
112127
}

includes/discovery/ports.inc.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@
126126
foreach ($port_stats as $ifIndex => $snmp_data) {
127127
$snmp_data['ifIndex'] = $ifIndex; // Store ifIndex in port entry
128128
$snmp_data['ifAlias'] = StringHelpers::inferEncoding($snmp_data['ifAlias'] ?? null);
129+
$snmp_data['ifName'] = StringHelpers::inferEncoding($snmp_data['ifName'] ?? null);
130+
$snmp_data['ifDescr'] = StringHelpers::inferEncoding($snmp_data['ifDescr'] ?? null);
129131

130132
// Get port_id according to port_association_mode used for this device
131133
$port_id = get_port_id($ports_mapped, $snmp_data, $port_association_mode);

includes/polling/ports.inc.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,9 @@
587587
$this_port['ifName'] = $matches[1];
588588
}
589589

590+
$this_port['ifName'] = StringHelpers::inferEncoding($this_port['ifName'] ?? null);
591+
$this_port['ifDescr'] = StringHelpers::inferEncoding($this_port['ifDescr'] ?? null);
592+
590593
$polled_period = max($polled - $port['poll_time'], 1);
591594

592595
$port['update'] = [];

tests/Unit/Util/StringHelperTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function testInferEncoding(): void
4545

4646
$this->assertEquals('Øverbyvegen', StringHelpers::inferEncoding(base64_decode('w5h2ZXJieXZlZ2Vu')));
4747
$this->assertEquals('Øverbyvegen', StringHelpers::inferEncoding(base64_decode('2HZlcmJ5dmVnZW4=')));
48+
$this->assertEquals('教科网IPv4', StringHelpers::inferEncoding(base64_decode('vcy/xs34SVB2NA==')));
4849

4950
config(['app.charset' => 'Shift_JIS']);
5051
$this->assertEquals('コンサート', StringHelpers::inferEncoding(base64_decode('g1KDk4NUgVuDZw==')));

0 commit comments

Comments
 (0)