agent foundation
This commit is contained in:
@@ -84,6 +84,7 @@ class CsvReaderService
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
// Sample-based detection — reading 5 lines is enough to identify the delimiter without scanning the full file.
|
||||
private function detectDelimiter(string $path): string
|
||||
{
|
||||
$sample = '';
|
||||
@@ -154,6 +155,7 @@ class CsvReaderService
|
||||
}
|
||||
}
|
||||
|
||||
// Case-insensitive duplicate check — "Email" and "email" in the same header row are ambiguous.
|
||||
$normalizedKeys = array_map([$this, 'lower'], $headers);
|
||||
if (count(array_unique($normalizedKeys)) !== count($normalizedKeys)) {
|
||||
return ['ok' => false, 'code' => 'invalid_csv_header'];
|
||||
@@ -177,6 +179,7 @@ class CsvReaderService
|
||||
$normalized[] = $this->cleanCell((string) $cell);
|
||||
}
|
||||
|
||||
// Pad short rows and trim over-long rows so every row has exactly as many cells as headers.
|
||||
$current = count($normalized);
|
||||
if ($current < $size) {
|
||||
$normalized = array_pad($normalized, $size, '');
|
||||
@@ -236,6 +239,7 @@ class CsvReaderService
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Remove null bytes (defense against null byte injection) and UTF-8 BOM from each cell.
|
||||
private function cleanCell(string $value): string
|
||||
{
|
||||
$value = str_replace("\0", '', $value);
|
||||
|
||||
Reference in New Issue
Block a user