22
33import java .io .BufferedReader ;
44import java .io .IOException ;
5+ import java .net .URI ;
6+ import java .net .URISyntaxException ;
57import java .net .URL ;
68import java .nio .charset .Charset ;
79import java .nio .charset .StandardCharsets ;
810import java .nio .file .DirectoryStream ;
911import java .nio .file .Files ;
1012import java .nio .file .Path ;
13+ import java .nio .file .Paths ;
1114import java .util .AbstractMap .SimpleImmutableEntry ;
1215import java .util .ArrayList ;
1316import java .util .HashMap ;
2225import gov .loc .repository .bagit .domain .Manifest ;
2326import gov .loc .repository .bagit .domain .Version ;
2427import gov .loc .repository .bagit .exceptions .InvalidBagMetadataException ;
25- import gov .loc .repository .bagit .exceptions .InvalidFetchFormatException ;
26- import gov .loc .repository .bagit .exceptions .InvalidManifestFormatException ;
28+ import gov .loc .repository .bagit .exceptions .InvalidBagitFileFormatException ;
2729import gov .loc .repository .bagit .exceptions .MaliciousPathException ;
2830import gov .loc .repository .bagit .exceptions .UnparsableVersionException ;
2931import gov .loc .repository .bagit .exceptions .UnsupportedAlgorithmException ;
@@ -61,10 +63,9 @@ public BagReader(final BagitAlgorithmNameToSupportedAlgorithmMapping nameMapping
6163 * @throws MaliciousPathException if there is path that is referenced in the manifest or fetch file that is outside the bag root directory
6264 * @throws InvalidBagMetadataException if the metadata or bagit.txt file does not conform to the bagit spec
6365 * @throws UnsupportedAlgorithmException if the manifest uses a algorithm that isn't supported
64- * @throws InvalidManifestFormatException if the manifest is not formatted properly
65- * @throws InvalidFetchFormatException if the fetch format does not follow the bagit specification
66+ * @throws InvalidBagitFileFormatException if the manifest or fetch file is not formatted properly
6667 */
67- public Bag read (final Path rootDir ) throws IOException , UnparsableVersionException , MaliciousPathException , InvalidBagMetadataException , UnsupportedAlgorithmException , InvalidManifestFormatException , InvalidFetchFormatException {
68+ public Bag read (final Path rootDir ) throws IOException , UnparsableVersionException , MaliciousPathException , InvalidBagMetadataException , UnsupportedAlgorithmException , InvalidBagitFileFormatException {
6869 final Bag bag = new Bag ();
6970
7071 //@Incubating
@@ -139,7 +140,7 @@ Version parseVersion(final String version) throws UnparsableVersionException{
139140 /*
140141 * Finds and reads all manifest files in the rootDir and adds them to the given bag.
141142 */
142- void readAllManifests (final Path rootDir , final Bag bag ) throws IOException , MaliciousPathException , UnsupportedAlgorithmException , InvalidManifestFormatException {
143+ void readAllManifests (final Path rootDir , final Bag bag ) throws IOException , MaliciousPathException , UnsupportedAlgorithmException , InvalidBagitFileFormatException {
143144 logger .info ("Attempting to find and read manifests" );
144145 final DirectoryStream <Path > manifests = getAllManifestFiles (rootDir );
145146
@@ -183,9 +184,9 @@ public boolean accept(final Path file) throws IOException {
183184 * @throws IOException if there is a problem reading a file
184185 * @throws MaliciousPathException if there is path that is referenced in the manifest that is outside the bag root directory
185186 * @throws UnsupportedAlgorithmException if the manifest uses a algorithm that isn't supported
186- * @throws InvalidManifestFormatException if the manifest is not formatted properly
187+ * @throws InvalidBagitFileFormatException if the manifest is not formatted properly
187188 */
188- public Manifest readManifest (final Path manifestFile , final Path bagRootDir , final Charset charset ) throws IOException , MaliciousPathException , UnsupportedAlgorithmException , InvalidManifestFormatException {
189+ public Manifest readManifest (final Path manifestFile , final Path bagRootDir , final Charset charset ) throws IOException , MaliciousPathException , UnsupportedAlgorithmException , InvalidBagitFileFormatException {
189190 logger .debug ("Reading manifest [{}]" , manifestFile );
190191 final String alg = PathUtils .getFilename (manifestFile ).split ("[-\\ .]" )[1 ];
191192 final SupportedAlgorithm algorithm = nameMapping .getSupportedAlgorithm (alg );
@@ -201,7 +202,7 @@ public Manifest readManifest(final Path manifestFile, final Path bagRootDir, fin
201202 /*
202203 * read the manifest file into a map of files and checksums
203204 */
204- Map <Path , String > readChecksumFileMap (final Path manifestFile , final Path bagRootDir , final Charset charset ) throws IOException , MaliciousPathException , InvalidManifestFormatException {
205+ Map <Path , String > readChecksumFileMap (final Path manifestFile , final Path bagRootDir , final Charset charset ) throws IOException , MaliciousPathException , InvalidBagitFileFormatException {
205206 final HashMap <Path , String > map = new HashMap <>();
206207 final BufferedReader br = Files .newBufferedReader (manifestFile , charset );
207208
@@ -222,22 +223,31 @@ Map<Path, String> readChecksumFileMap(final Path manifestFile, final Path bagRoo
222223 /*
223224 * Create the file and check it for various things, like starting with a *
224225 */
225- private Path createFileFromManifest (final Path bagRootDir , final String path ) throws MaliciousPathException , InvalidManifestFormatException {
226+ private Path createFileFromManifest (final Path bagRootDir , final String path ) throws MaliciousPathException , InvalidBagitFileFormatException {
226227 String fixedPath = path ;
227228 if (path .charAt (0 ) == '*' ){
228229 logger .warn ("Encountered path that was created by non-bagit tool. Removing * from path. Please remove all * from manifest files!" );
229230 fixedPath = path .substring (1 ); //remove the * from the path
230231 }
231232
232233 if (path .contains ("\\ " )){
233- throw new InvalidManifestFormatException (ERROR_PREFIX + path + "] is invalid due to the use of the path separactor [\\ ]" );
234+ throw new InvalidBagitFileFormatException (ERROR_PREFIX + path + "] is invalid due to the use of the path separactor [\\ ]" );
234235 }
235236
236237 if (path .contains ("~/" )){
237238 throw new MaliciousPathException (ERROR_PREFIX + path + "] is trying to be malicious and access a file outside the bag" );
238239 }
239240
240- final Path file = bagRootDir .resolve (PathUtils .decodeFilname (fixedPath )).normalize ();
241+ fixedPath = PathUtils .decodeFilname (fixedPath );
242+ Path file = bagRootDir .resolve (fixedPath ).normalize ();
243+ if (fixedPath .startsWith ("file://" )){
244+ try {
245+ file = Paths .get (new URI (fixedPath ));
246+ } catch (URISyntaxException e ) {
247+ // TODO Auto-generated catch block
248+ e .printStackTrace ();
249+ }
250+ }
241251
242252 if (!file .normalize ().startsWith (bagRootDir )){
243253 throw new MaliciousPathException (ERROR_PREFIX + file + "] is outside the bag root directory of " + bagRootDir +
@@ -284,11 +294,11 @@ public List<SimpleImmutableEntry<String, String>> readBagMetadata(final Path roo
284294 * @return a list of items to fetch
285295 *
286296 * @throws IOException if there is a problem reading a file
287- * @throws InvalidFetchFormatException if the fetch format does not follow the bagit specification
288297 * @throws MaliciousPathException if the path was crafted to point outside the bag directory
298+ * @throws InvalidBagitFileFormatException if the fetch format does not follow the bagit specification
289299 */
290300 @ SuppressWarnings ("PMD.AvoidInstantiatingObjectsInLoops" )
291- public List <FetchItem > readFetch (final Path fetchFile , final Charset encoding , final Path bagRootDir ) throws IOException , MaliciousPathException , InvalidFetchFormatException {
301+ public List <FetchItem > readFetch (final Path fetchFile , final Charset encoding , final Path bagRootDir ) throws IOException , MaliciousPathException , InvalidBagitFileFormatException {
292302 logger .info ("Attempting to read [{}]" , fetchFile );
293303 final BufferedReader br = Files .newBufferedReader (fetchFile , encoding );
294304 final List <FetchItem > itemsToFetch = new ArrayList <>();
@@ -299,12 +309,12 @@ public List<FetchItem> readFetch(final Path fetchFile, final Charset encoding, f
299309 URL url = null ;
300310 while (line != null ){
301311 parts = line .split ("\\ s+" , 3 );
302- checkPath ( parts [2 ], bagRootDir );
312+ final Path path = createFileFromManifest ( bagRootDir , parts [2 ]);
303313 length = parts [1 ].equals ("-" ) ? -1 : Long .decode (parts [1 ]);
304314 url = new URL (parts [0 ]);
305315
306316 logger .debug ("Read URL [{}] length [{}] path [{}] from fetch file [{}]" , url , length , parts [2 ], fetchFile );
307- final FetchItem itemToFetch = new FetchItem (url , length , parts [ 2 ] );
317+ final FetchItem itemToFetch = new FetchItem (url , length , path );
308318 itemsToFetch .add (itemToFetch );
309319
310320 line = br .readLine ();
@@ -313,26 +323,6 @@ public List<FetchItem> readFetch(final Path fetchFile, final Charset encoding, f
313323 return itemsToFetch ;
314324 }
315325
316- /*
317- * Check for malicious paths as well as invalid format
318- */
319- private void checkPath (final String path , final Path bagRoot ) throws MaliciousPathException , InvalidFetchFormatException {
320- if (path .contains ("\\ " )){
321- logger .warn ("Path [{}] contains [\\ ] which is not allowed by the bagit specification. Use [/] instead." , path );
322- throw new InvalidFetchFormatException (ERROR_PREFIX + path + "] uses invalid path separator [\\ ]. Use [/] instead." );
323- }
324-
325- if (path .contains ("~/" )){
326- throw new MaliciousPathException (ERROR_PREFIX + path + "] is trying to be malicious by accessing a file outside the bag" );
327- }
328-
329- final Path finalPath = bagRoot .resolve (path ).normalize ();
330- if (!finalPath .startsWith (bagRoot )){
331- throw new MaliciousPathException (ERROR_PREFIX + path + "] is outside the bag root directory of " + bagRoot +
332- "! This is not allowed according to the bagit specification!" );
333- }
334- }
335-
336326 /*
337327 * Generic method to read key value pairs from the bagit files, like bagit.txt or bag-info.txt
338328 */
0 commit comments