Do not close zip input stream

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2018-12-08 03:47:43 +01:00
parent bb43804d58
commit 5aa8191cd3
2 changed files with 54 additions and 42 deletions

View File

@ -43,8 +43,10 @@ import com.wireguard.android.widget.fab.FloatingActionsMenuRecyclerViewScrollLis
import com.wireguard.config.Config; import com.wireguard.config.Config;
import com.wireguard.config.ParseException; import com.wireguard.config.ParseException;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -122,7 +124,8 @@ public class TunnelListFragment extends BaseFragment {
throw new IllegalArgumentException("File must be .conf or .zip"); throw new IllegalArgumentException("File must be .conf or .zip");
if (isZip) { if (isZip) {
try (ZipInputStream zip = new ZipInputStream(contentResolver.openInputStream(uri))) { try (ZipInputStream zip = new ZipInputStream(contentResolver.openInputStream(uri));
BufferedReader reader = new BufferedReader(new InputStreamReader(zip))) {
ZipEntry entry; ZipEntry entry;
while ((entry = zip.getNextEntry()) != null) { while ((entry = zip.getNextEntry()) != null) {
if (entry.isDirectory()) if (entry.isDirectory())
@ -140,7 +143,7 @@ public class TunnelListFragment extends BaseFragment {
continue; continue;
Config config = null; Config config = null;
try { try {
config = Config.parse(zip); config = Config.parse(reader);
} catch (Exception e) { } catch (Exception e) {
throwables.add(e); throwables.add(e);
} }

View File

@ -43,50 +43,59 @@ public final class Config {
* @return a {@code Config} instance representing the supplied configuration * @return a {@code Config} instance representing the supplied configuration
*/ */
public static Config parse(final InputStream stream) throws IOException, ParseException { public static Config parse(final InputStream stream) throws IOException, ParseException {
return parse(new BufferedReader(new InputStreamReader(stream)));
}
/**
* Parses an series of "Interface" and "Peer" sections into a {@code Config}. Throws
* {@link ParseException} if the input is not well-formed or contains unparseable sections.
*
* @param reader a BufferedReader of UTF-8 text that is interpreted as a WireGuard configuration file
* @return a {@code Config} instance representing the supplied configuration
*/
public static Config parse(final BufferedReader reader) throws IOException, ParseException {
final Builder builder = new Builder(); final Builder builder = new Builder();
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { final Collection<String> interfaceLines = new ArrayList<>();
final Collection<String> interfaceLines = new ArrayList<>(); final Collection<String> peerLines = new ArrayList<>();
final Collection<String> peerLines = new ArrayList<>(); boolean inInterfaceSection = false;
boolean inInterfaceSection = false; boolean inPeerSection = false;
boolean inPeerSection = false; @Nullable String line;
@Nullable String line; while ((line = reader.readLine()) != null) {
while ((line = reader.readLine()) != null) { final int commentIndex = line.indexOf('#');
final int commentIndex = line.indexOf('#'); if (commentIndex != -1)
if (commentIndex != -1) line = line.substring(0, commentIndex);
line = line.substring(0, commentIndex); line = line.trim();
line = line.trim(); if (line.isEmpty())
if (line.isEmpty()) continue;
continue; if (line.startsWith("[")) {
if (line.startsWith("[")) { // Consume all [Peer] lines read so far.
// Consume all [Peer] lines read so far. if (inPeerSection) {
if (inPeerSection) { builder.parsePeer(peerLines);
builder.parsePeer(peerLines); peerLines.clear();
peerLines.clear();
}
if ("[Interface]".equalsIgnoreCase(line)) {
inInterfaceSection = true;
inPeerSection = false;
} else if ("[Peer]".equalsIgnoreCase(line)) {
inInterfaceSection = false;
inPeerSection = true;
} else {
throw new ParseException("top level", line, "Unknown section name");
}
} else if (inInterfaceSection) {
interfaceLines.add(line);
} else if (inPeerSection) {
peerLines.add(line);
} else {
throw new ParseException("top level", line, "Expected [Interface] or [Peer]");
} }
if ("[Interface]".equalsIgnoreCase(line)) {
inInterfaceSection = true;
inPeerSection = false;
} else if ("[Peer]".equalsIgnoreCase(line)) {
inInterfaceSection = false;
inPeerSection = true;
} else {
throw new ParseException("top level", line, "Unknown section name");
}
} else if (inInterfaceSection) {
interfaceLines.add(line);
} else if (inPeerSection) {
peerLines.add(line);
} else {
throw new ParseException("top level", line, "Expected [Interface] or [Peer]");
} }
if (inPeerSection)
builder.parsePeer(peerLines);
else if (!inInterfaceSection)
throw new ParseException("top level", "", "Empty configuration");
// Combine all [Interface] sections in the file.
builder.parseInterface(interfaceLines);
} }
if (inPeerSection)
builder.parsePeer(peerLines);
else if (!inInterfaceSection)
throw new ParseException("top level", "", "Empty configuration");
// Combine all [Interface] sections in the file.
builder.parseInterface(interfaceLines);
return builder.build(); return builder.build();
} }