Skip to content

Commit 7962568

Browse files
authored
Merge pull request #3360 from nextcloud/jtr/chore-drop-fgetcsv
chore: drop deprecated fgetcsv / make ReverseGeoCoderService more robust
2 parents 4c78440 + a5117c3 commit 7962568

File tree

1 file changed

+46
-19
lines changed

1 file changed

+46
-19
lines changed

lib/Service/ReverseGeoCoderService.php

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ private function downloadCities1000(bool $force = false): void {
8080
return;
8181
}
8282

83-
// Download zip file to a tmp file.
8483
$response = $this->clientService->newClient()->get('https://download.nextcloud.com/server/apps/photos/cities1000.zip');
8584
$tmpFile = tmpfile();
8685
$cities1000ZipTmpFileName = stream_get_meta_data($tmpFile)['uri'];
@@ -91,37 +90,64 @@ private function downloadCities1000(bool $force = false): void {
9190
$zip = new \ZipArchive;
9291
$res = $zip->open($cities1000ZipTmpFileName);
9392
if ($res !== true) {
94-
throw new \Exception("Fail to unzip place file: $res", $res);
93+
unlink($cities1000ZipTmpFileName);
94+
throw new \Exception("Failed to unzip place file: $res", $res);
95+
}
96+
97+
$cities1000TxtStream = $zip->getStream('cities1000.txt');
98+
if ($cities1000TxtStream === false) {
99+
$zip->close();
100+
unlink($cities1000ZipTmpFileName);
101+
throw new \Exception("Could not extract 'cities1000.txt' from ZIP archive.");
95102
}
96-
$cities1000TxtSteam = $zip->getStream('cities1000.txt');
97103

98104
// Dump the txt file info into a smaller csv file.
99105
$destinationStream = $this->geoNameFolder()->newFile('cities1000.csv')->write();
106+
if ($destinationStream === false || !is_resource($destinationStream)) {
107+
fclose($cities1000TxtStream);
108+
$zip->close();
109+
unlink($cities1000ZipTmpFileName);
110+
throw new \Exception('Failed to open destination stream for cities1000.csv');
111+
}
100112

101-
while (($fields = fgetcsv($cities1000TxtSteam, 0, ' ')) !== false) {
102-
$result = fputcsv(
103-
$destinationStream,
104-
[
105-
'id' => (int)$fields[0],
106-
'name' => $fields[1],
107-
'latitude' => (float)$fields[4],
108-
'longitude' => (float)$fields[5],
109-
]
110-
);
111-
112-
if ($result === false) {
113-
throw new \Exception('Failed to write csv line to tmp stream');
113+
try {
114+
while (($fields = fgetcsv($cities1000TxtStream, 0, "\t")) !== false) {
115+
if (count($fields) < 6) {
116+
throw new \Exception('Malformed cities1000.txt row: expected at least 6 fields, got ' . count($fields));
117+
}
118+
$result = fputcsv(
119+
$destinationStream,
120+
[
121+
'id' => (int)$fields[0],
122+
'name' => $fields[1],
123+
'latitude' => (float)$fields[4],
124+
'longitude' => (float)$fields[5],
125+
]
126+
);
127+
if ($result === false) {
128+
throw new \Exception('Failed to write csv line to tmp stream');
129+
}
114130
}
131+
} finally {
132+
fclose($cities1000TxtStream);
133+
fclose($destinationStream);
134+
$zip->close();
135+
unlink($cities1000ZipTmpFileName);
115136
}
116-
117-
$zip->close();
118137
}
119138

120139
private function loadCities1000(): array {
121140
$csvStream = $this->geoNameFolder()->getFile('cities1000.csv')->read();
141+
if ($csvStream === false || !is_resource($csvStream)) {
142+
throw new \Exception('Failed to open cities1000.csv for reading.');
143+
}
122144
$cities = [];
123145

124-
while (($fields = fgetcsv($csvStream)) !== false) {
146+
while (($fields = fgetcsv($csvStream, 0, ',', '"', '\\')) !== false) {
147+
if (count($fields) < 4) {
148+
fclose($csvStream);
149+
throw new \Exception('Malformed cities1000.csv row: expected at least 4 fields, got ' . count($fields));
150+
}
125151
$cities[] = [
126152
'id' => (int)$fields[0],
127153
'name' => $fields[1],
@@ -130,6 +156,7 @@ private function loadCities1000(): array {
130156
];
131157
}
132158

159+
fclose($csvStream);
133160
return $cities;
134161
}
135162

0 commit comments

Comments
 (0)