TdsValidator.java
/*
* Copyright (C) 2017-2025 Gerd Neugebauer
*
* This file is distributed under the 3-clause BSD license.
* See file LICENSE for details.
*/
package org.ctan.site.services.upload.util;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import lombok.extern.slf4j.Slf4j;
/**
* This class constitutes a validator for TDS archives.
*
* @author <a href="gene@ctan.org">Gerd Neugebauer</a>
*/
@Slf4j
public class TdsValidator {
/**
* The field <code>TDS</code> contains the specification if the TDS tree.
*/
protected static final Pattern TDS =
Pattern.compile(
"^(bibtex/(bib|bsf|csf)/"
+ "|doc/"
+ "|dvips/"
+ "|fonts/(afm|enc|misc|opentype|ovp|sfd|tfm|type1|"
+ "cmap|map|ofm|pk|source|truetype|vf)/"
+ "|makeindex/"
+ "|metafont/"
+ "|metapost/"
+ "|mft/"
+ "|omega/"
+ "|pbibtex/"
+ "|pbibtex/"
+ "|scripts/"
+ "|source/"
+ "|tex/(amstex|csplain|generic|lualatex|mltex|psizzl|"
+ "texsis|xelatex|context|eplain|lambda|luatex|plain|"
+ "ptex|uplatex|xetex|cslatex|fontinst|latex|mex|"
+ "platex|startex|uptex|xmltex)/"
+ "|texdoc/"
+ "|web2c/).*");
/**
* The constant <code>SPECIALS_PATTERN</code> contains the pattern to detect
* special characters.
*/
// Pattern.compile(".*([\\x00- "\"`;?\$|(){}\\x7f-\\xff]).*")
private static final Pattern SPECIALS_PATTERN =
Pattern.compile(".*([^a-zA-Z0-9_.]).*");
/**
* The method <code>check</code> provides means to perform the checks.
*
* @param messages the list of messages
* @param name the name of the file
* @param pkg the package
* @param content the content
*/
public void check(Messages messages, String name, String pkg,
byte[] content) {
// TODO unimplemented
throw new UnsupportedOperationException();
}
/**
* This method inspects the TDS archive and adds messages if something
* unusual is found.
*
* @param messages the messages
* @param archiveName the name of the archive under inspection
* @param pkg the name of the package
* @param zip the content of the TDS archive
*/
public void check(Messages messages, String archiveName, String pkg,
ZipInputStream zip) {
messages.info("TDS archive found", archiveName);
// if (content.length <= 0) {
// messages.error("Empty TDS file", archiveName);
// }
try {
// ZipInputStream zip = new ZipFile(new
// SeekableInMemoryByteChannel(content));
// try (zip) {
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry =
zip.getNextEntry()) {
String name = entry.getName();
if (SPECIALS_PATTERN.matcher(name).matches()) {
messages.error("Name contains special character in TDS",
archiveName,
name);
}
if (!entry.isDirectory() && !find(name)) {
messages.error("Illegal path in TDS", archiveName,
name);
}
// }
}
} catch (Exception e) {
messages.errorOrWarning("Error reading TDS file", archiveName,
"File is too highly compressed or no ZIP archive");
log.error("", e);
}
}
/**
* This method checks if the given path is allowed according to the TDS
* specification.
*
* @param path the path
*
* @return <code>true</code> iff the TDS specification allows the path
*/
private boolean find(String path) {
return TDS.matcher(path).matches();
}
}