<exclude>src/test/resources/test-repo/**</exclude>
<exclude>src/test/resources/releases-test-repo-one/**</exclude>
<exclude>nbactions.xml</exclude>
+ <exclude>src/test/resources/checksum/**</exclude>
</excludes>
</configuration>
</plugin>
--- /dev/null
+package org.apache.archiva.checksum;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Exception thrown by the ChecksumValidator
+ *
+ * Has an error type for different validation errors.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class ChecksumValidationException extends Exception
+{
+
+ public enum ValidationError {
+ INVALID_FORMAT, DIGEST_ERROR, READ_ERROR, FILE_NOT_FOUND
+ };
+
+ final private ValidationError errorType;
+
+ public ChecksumValidationException( ValidationError errorType )
+ {
+ super( );
+ this.errorType = errorType;
+ }
+
+ public ChecksumValidationException( ValidationError errorType, String message )
+ {
+ super( message );
+ this.errorType = errorType;
+ }
+
+ public ChecksumValidationException( ValidationError errorType, String message, Throwable cause )
+ {
+ super( message, cause );
+ this.errorType = errorType;
+ }
+
+ public ChecksumValidationException( ValidationError errorType, Throwable cause )
+ {
+ super( cause );
+ this.errorType = errorType;
+ }
+
+ public ValidationError getErrorType() {
+ return errorType;
+ }
+}
--- /dev/null
+package org.apache.archiva.checksum;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import javax.xml.bind.DatatypeConverter;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.apache.archiva.checksum.ChecksumValidationException.ValidationError.*;
+
+/**
+ * Class for validating checksums.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class ChecksumValidator
+{
+ private final int NOT_INITALIZED = 0;
+ private final int INITIALIZING = 1;
+ private final int INITIALIZED = 2;
+ private AtomicInteger status = new AtomicInteger( NOT_INITALIZED );
+ private static final Map<String, String> supportedTypes = new HashMap<>( );
+
+ public ChecksumValidator() {
+ init();
+ }
+
+ private void init() {
+ int val;
+ if (status.compareAndSet( NOT_INITALIZED, INITIALIZING ))
+ {
+ try
+ {
+ supportedTypes.put( "md5", "MD5" );
+ supportedTypes.put( "sha1", "SHA-1" );
+ supportedTypes.put( "sha-1", "SHA-1" );
+ supportedTypes.put( "sha2", "SHA-256" );
+ supportedTypes.put( "sha256", "SHA-256" );
+ supportedTypes.put( "sha-256", "SHA-256" );
+ supportedTypes.put( "sha3", "SHA-384" );
+ supportedTypes.put( "sha384", "SHA-384" );
+ supportedTypes.put( "sha-384", "SHA-384" );
+ supportedTypes.put( "sha5", "SHA-512" );
+ supportedTypes.put( "sha512", "SHA-512" );
+ supportedTypes.put( "sha-512", "SHA-512" );
+ } finally
+ {
+ status.set(INITIALIZED);
+ }
+ } else if ((val = status.intValue())!=INITIALIZED) {
+ do
+ {
+ try
+ {
+ Thread.currentThread().sleep(100);
+ val = status.intValue();
+ }
+ catch ( InterruptedException e )
+ {
+ // Ignore
+ }
+ } while(val!=INITIALIZED);
+ }
+ }
+
+ public boolean isValidChecksum(Path checksumFile) throws ChecksumValidationException
+ {
+ String fileName = checksumFile.getFileName().toString();
+ if (!Files.exists( checksumFile )) {
+ throw new ChecksumValidationException( FILE_NOT_FOUND, "Checksum file does not exist: "+checksumFile );
+ }
+ String extension = fileName.substring( fileName.lastIndexOf( '.' )+1).toLowerCase();
+ String digestType = this.supportedTypes.get(extension);
+ if (digestType==null) {
+ throw new ChecksumValidationException( INVALID_FORMAT, "The extension '"+extension+"' ist not known." );
+ }
+ Path checkFile = null;
+ try
+ {
+ MessageDigest md = MessageDigest.getInstance( digestType );
+ checkFile = getCheckFile( checksumFile );
+ byte[] computedChecksum = computeHash( checkFile, md );
+ byte[] readChecksum = readHashFile( checksumFile );
+ return md.isEqual( computedChecksum, readChecksum );
+ }
+ catch ( NoSuchAlgorithmException e )
+ {
+ throw new ChecksumValidationException( DIGEST_ERROR, "The digest is not supported "+digestType );
+ }
+ catch ( IOException e )
+ {
+ throw new ChecksumValidationException( READ_ERROR, "Error while computing the checksum of "+checkFile+": "+e.getMessage(), e);
+ }
+ }
+
+ private Path getCheckFile(Path checksumFile) {
+ String fileName = checksumFile.getFileName().toString();
+ String newName = fileName.substring(0, fileName.lastIndexOf('.'));
+ return checksumFile.getParent().resolve(newName);
+ }
+
+ public Set<String> getSupportedExtensions() {
+ return supportedTypes.keySet();
+ }
+
+ public byte[] computeHash(Path file, MessageDigest digest) throws IOException
+ {
+ byte[] result;
+ try(FileChannel inChannel = FileChannel.open( file, StandardOpenOption.READ ))
+ {
+ MappedByteBuffer buffer = inChannel.map( FileChannel.MapMode.READ_ONLY, 0, inChannel.size( ) );
+ digest.update( buffer );
+ result = digest.digest( );
+ }
+ return result;
+ }
+
+ public byte[] computeHash(Path file, String type) throws ChecksumValidationException, NoSuchAlgorithmException, IOException
+ {
+ if (!supportedTypes.containsKey( type )) {
+ throw new ChecksumValidationException( INVALID_FORMAT );
+ }
+ return computeHash( file, MessageDigest.getInstance( supportedTypes.get(type) ) );
+ }
+
+ public byte[] readHashFile(Path file) throws IOException
+ {
+ StringBuilder sb = new StringBuilder( );
+ try(BufferedReader reader = Files.newBufferedReader( file, StandardCharsets.US_ASCII )){
+ int ci;
+ while((ci = reader.read()) != -1) {
+ char c = (char)ci;
+ if (Character.isWhitespace( c )) {
+ break;
+ } else {
+ sb.append(c);
+ }
+ }
+ return convertFromHex( sb.toString() );
+ }
+ }
+
+ protected String convertToHex(byte[] array) {
+ return DatatypeConverter.printHexBinary( array ).trim().toLowerCase();
+ }
+
+ protected byte[] convertFromHex(String checksum) {
+ return DatatypeConverter.parseHexBinary( checksum.trim().toLowerCase() );
+ }
+
+
+}
* under the License.
*/
-import org.apache.archiva.common.plexusbridge.DigesterUtils;
-import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
-import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
+import org.apache.archiva.checksum.ChecksumValidationException;
+import org.apache.archiva.checksum.ChecksumValidator;
import org.apache.archiva.consumers.AbstractMonitoredConsumer;
import org.apache.archiva.consumers.ConsumerException;
import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
import org.apache.archiva.repository.ManagedRepository;
-import org.codehaus.plexus.digest.ChecksumFile;
-import org.codehaus.plexus.digest.Digester;
-import org.codehaus.plexus.digest.DigesterException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-import java.io.FileNotFoundException;
-import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.Set;
+
+import static org.apache.archiva.checksum.ChecksumValidationException.ValidationError.*;
/**
* ValidateChecksumConsumer - validate the provided checksum against the file it represents.
private String description = "Validate checksums against file.";
- private ChecksumFile checksum;
-
- private List<Digester> allDigesters;
-
- @Inject
- private PlexusSisuBridge plexusSisuBridge;
-
- @Inject
- private DigesterUtils digesterUtils;
+ ThreadLocal<ChecksumValidator> validatorThreadLocal = new ThreadLocal<>();
private Path repositoryDir;
public void processFile( String path )
throws ConsumerException
{
+ ChecksumValidator validator;
+ if ((validator=validatorThreadLocal.get())==null) {
+ validator = new ChecksumValidator();
+ validatorThreadLocal.set(validator);
+ }
Path checksumFile = this.repositoryDir.resolve( path );
try
{
- if ( !checksum.isValidChecksum( checksumFile.toFile() ) )
+
+ if ( !validator.isValidChecksum( checksumFile ) )
{
log.warn( "The checksum for {} is invalid.", checksumFile );
triggerConsumerWarning( NOT_VALID_CHECKSUM, "The checksum for " + checksumFile + " is invalid." );
}
}
- catch ( FileNotFoundException e )
+ catch ( ChecksumValidationException e )
{
- log.error( "File not found during checksum validation: ", e );
- triggerConsumerError( CHECKSUM_NOT_FOUND, "File not found during checksum validation: " + e.getMessage( ) );
- }
- catch ( DigesterException e )
- {
- log.error( "Digester failure during checksum validation on {}", checksumFile );
- triggerConsumerError( CHECKSUM_DIGESTER_FAILURE,
- "Digester failure during checksum validation on " + checksumFile );
- }
- catch ( IOException e )
- {
- log.error( "Checksum I/O error during validation on {}", checksumFile );
- triggerConsumerError( CHECKSUM_IO_ERROR, "Checksum I/O error during validation on " + checksumFile );
+ if (e.getErrorType()==READ_ERROR) {
+ log.error( "Checksum read error during validation on {}", checksumFile );
+ triggerConsumerError( CHECKSUM_IO_ERROR, "Checksum I/O error during validation on " + checksumFile );
+ } else if (e.getErrorType()==INVALID_FORMAT || e.getErrorType()==DIGEST_ERROR) {
+ log.error( "Digester failure during checksum validation on {}", checksumFile );
+ triggerConsumerError( CHECKSUM_DIGESTER_FAILURE,
+ "Digester failure during checksum validation on " + checksumFile );
+ } else if (e.getErrorType()==FILE_NOT_FOUND) {
+ log.error( "File not found during checksum validation: ", e );
+ triggerConsumerError( CHECKSUM_NOT_FOUND, "File not found during checksum validation: " + e.getMessage( ) );
+ }
}
}
@PostConstruct
public void initialize( )
- throws PlexusSisuBridgeException
{
- checksum = plexusSisuBridge.lookup( ChecksumFile.class );
- List<Digester> allDigesters = new ArrayList<>( digesterUtils.getAllDigesters( ) );
- includes = new ArrayList<>( allDigesters.size( ) );
- for ( Digester digester : allDigesters )
+ ChecksumValidator validator;
+ if ((validator=validatorThreadLocal.get())==null) {
+ validator = new ChecksumValidator();
+ validatorThreadLocal.set(validator);
+ }
+ Set<String> extensions = validator.getSupportedExtensions();
+ includes = new ArrayList<>( extensions.size() );
+ for ( String ext : extensions )
{
- includes.add( "**/*" + digester.getFilenameExtension( ) );
+ includes.add( "**/*." + ext );
}
}
}
--- /dev/null
+package org.apache.archiva.checksum;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+
+public class ChecksumValidatorTest
+{
+
+ @Test
+ public void isValidChecksum( ) throws URISyntaxException, ChecksumValidationException
+ {
+ ChecksumValidator validator = new ChecksumValidator();
+ String fileName = "checksum/checksumTest1.txt";
+ List<String> exts = Arrays.asList( "md5", "sha1", "sha2", "sha3", "sha5" );
+ for(String ext : exts)
+ {
+ Path hashFile = Paths.get( Thread.currentThread( ).getContextClassLoader( ).getResource( fileName + "."+ext ).toURI( ) );
+ assertTrue( validator.isValidChecksum( hashFile ) );
+ }
+ fileName = "checksum/checksumTest2.txt";
+ for(String ext : exts)
+ {
+ Path hashFile = Paths.get( Thread.currentThread( ).getContextClassLoader( ).getResource( fileName + "."+ext ).toURI( ) );
+ assertTrue( validator.isValidChecksum( hashFile ) );
+ }
+ }
+
+ @Test
+ public void isInValidChecksum( ) throws URISyntaxException, ChecksumValidationException
+ {
+ ChecksumValidator validator = new ChecksumValidator();
+ String fileName = "checksum/checksumTest3.txt";
+ List<String> exts = Arrays.asList( "md5", "sha1", "sha2", "sha3", "sha5" );
+ for(String ext : exts)
+ {
+ Path hashFile = Paths.get( Thread.currentThread( ).getContextClassLoader( ).getResource( fileName + "."+ext ).toURI( ) );
+ assertFalse( validator.isValidChecksum( hashFile ) );
+ }
+ }
+
+ @Test
+ public void isInvalidExtension( ) throws URISyntaxException, ChecksumValidationException
+ {
+ ChecksumValidator validator = new ChecksumValidator();
+ String fileName = "checksum/checksumTest1.txt";
+ String ext = "md8";
+ try
+ {
+ Path hashFile = Paths.get( Thread.currentThread( ).getContextClassLoader( ).getResource( fileName + "." + ext ).toURI( ) );
+ validator.isValidChecksum( hashFile );
+ } catch (ChecksumValidationException e) {
+ assertEquals(ChecksumValidationException.ValidationError.INVALID_FORMAT, e.getErrorType());
+ }
+ }
+
+ @Test
+ public void computeFileDoesNotExist( ) throws URISyntaxException, ChecksumValidationException
+ {
+ ChecksumValidator validator = new ChecksumValidator();
+ String fileName = "checksum/checksumTest4.txt";
+ String ext = "md5";
+ try
+ {
+ Path hashFile = Paths.get( Thread.currentThread( ).getContextClassLoader( ).getResource( fileName + "." + ext ).toURI( ) );
+ validator.isValidChecksum( hashFile );
+ } catch (ChecksumValidationException e) {
+ assertEquals(ChecksumValidationException.ValidationError.READ_ERROR, e.getErrorType());
+ }
+ }
+
+ @Test
+ public void checksumFileDoesNotExist( ) throws URISyntaxException, ChecksumValidationException
+ {
+ ChecksumValidator validator = new ChecksumValidator();
+ String fileName = "checksumTest5.txt";
+ String ext = "md5";
+ try
+ {
+ Path sibling = Paths.get( Thread.currentThread( ).getContextClassLoader( ).getResource( "checksum/checksumTest1.txt." + ext ).toURI( ) );
+ Path hashFile = sibling.getParent().resolve(fileName);
+ validator.isValidChecksum( hashFile );
+ } catch (ChecksumValidationException e) {
+ assertEquals(ChecksumValidationException.ValidationError.FILE_NOT_FOUND, e.getErrorType());
+ }
+ }
+
+ @Test
+ public void computeHash( ) throws URISyntaxException, NoSuchAlgorithmException, IOException, ChecksumValidationException
+ {
+ ChecksumValidator validator = new ChecksumValidator();
+ Map<String, String> hashes = new HashMap<>( );
+ hashes.put("md5","079fe13e970ae7311172df6657f36892");
+ hashes.put("sha1", "01e14abba5401e1a63be468f9c3b723167f27dc8");
+ hashes.put("sha2", "ae7278e7bdfd8d7c06f9b1932ddccdddb0061a58a893aec3f00932e53ef9c794");
+ hashes.put("sha3", "a52efc629f256cd2b390f080ab7e23fc706ab9e2c8948cea2bd8504a70894f69f44f48e83c889edc82b40b673b575bad");
+ hashes.put("sha5", "b2340bbf150403725fdf6a6f340a8a33bb9526bad7e0220f1dfea67d5a06217bc1d5c3a773b083ed8c9f5352c94ecc6da2a6d8a33ad0347566f0acc55e042fde");
+ Path hashFile = Paths.get( Thread.currentThread( ).getContextClassLoader( ).getResource( "checksum/checksumTest1.txt").toURI( ) );
+
+ for (String key : hashes.keySet()) {
+ byte[] expectedSum = validator.convertFromHex( hashes.get(key) );
+ byte[] computedSum = validator.computeHash( hashFile, key );
+ assertArrayEquals( expectedSum, computedSum );
+ }
+ }
+
+ @Test
+ public void readHashFile( )
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
+sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum
+dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
+sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
+At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero
+eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel
+eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto
+odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet,
+consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis
+nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
+
+At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
+At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
+consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et
+gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
--- /dev/null
+079fe13e970ae7311172df6657f36892 checksumTest1.txt
--- /dev/null
+079fe13e970ae7311172df6657f36892 checksumTest1.txt
--- /dev/null
+01e14abba5401e1a63be468f9c3b723167f27dc8 checksumTest1.txt
--- /dev/null
+ae7278e7bdfd8d7c06f9b1932ddccdddb0061a58a893aec3f00932e53ef9c794 checksumTest1.txt
--- /dev/null
+a52efc629f256cd2b390f080ab7e23fc706ab9e2c8948cea2bd8504a70894f69f44f48e83c889edc82b40b673b575bad checksumTest1.txt
--- /dev/null
+b2340bbf150403725fdf6a6f340a8a33bb9526bad7e0220f1dfea67d5a06217bc1d5c3a773b083ed8c9f5352c94ecc6da2a6d8a33ad0347566f0acc55e042fde checksumTest1.txt
--- /dev/null
+Check 2
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
+sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum
+dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
+sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
+At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero
+eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel
+eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto
+odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet,
+consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis
+nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
+
+At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
+At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
+consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et
+gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
--- /dev/null
+f3b8a0ebd9ce6dd66c2830c46eeb62dc
--- /dev/null
+b293f144df87783d66020a0f73654be459673054
--- /dev/null
+0DD0E1EFBF8F699A0EF286A271D8210CE2E80702AD5528F36592C89985D6B151
--- /dev/null
+5a5d1b11fdc498da5a592205714117656f40fea644adab07f110e1d512c79c6ded126972c1693483f21b592dd2030878
--- /dev/null
+a379ef07490328fb934fcadfa1b7794e532782c2097d3aa82e41ff9bd86527830f711a0c456af65a14a511bad73ddc08a30593d74ec6d42bcc9ee0747acfdf91
--- /dev/null
+Check 3
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
+sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum
+dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
+sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
+At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero
+eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel
+eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto
+odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet,
+consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis
+nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
+At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
+consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et
+gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
--- /dev/null
+f3b8a0ebd9ce6dd66c2830c46eeb62dc
--- /dev/null
+b293f144df87783d66020a0f73654be459673054
--- /dev/null
+0dd0e1efbf8f699a0ef286a271d8210ce2e80702ad5528f36592c89985d6b151
--- /dev/null
+5a5d1b11fdc498da5a592205714117656f40fea644adab07f110e1d512c79c6ded126972c1693483f21b592dd2030878
--- /dev/null
+a379ef07490328fb934fcadfa1b7794e532782c2097d3aa82e41ff9bd86527830f711a0c456af65a14a511bad73ddc08a30593d74ec6d42bcc9ee0747acfdf91
--- /dev/null
+f3b8a0ebd9ce6dd66c2830c46eeb62dc