<commit_before>package apoc.log;

import apoc.util.FileUtils;
import org.neo4j.procedure.*;
import org.neo4j.logging.Log;

import java.nio.file.NoSuchFileException;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

/**
 * @author moxious
 * @since 27.02.19
 */
public class Neo4jLogStream {
    @Context
    public Log log;

    public static class FileEntry implements Comparable<FileEntry> {
        public final long lineNo;
        public final String line;
        public final String path;

        public FileEntry(long lineNumber, String data, String path) {
            this.lineNo = lineNumber;
            this.line = data;
            this.path = path;
        }

        public int compareTo(FileEntry o) {
            return Long.compare(this.lineNo,o.lineNo);
        }
    }

    @Admin
    @Procedure(mode=Mode.DBMS)
    @Description( "apoc.log.stream('neo4j.log', { last: n }) - retrieve log file contents, optionally return only the last n lines" )
    public Stream<FileEntry> stream(
            @Name("path") String logName,
            @Name(value = "config",defaultValue = "{}") Map<String, Object> config) {

        File logDir = FileUtils.getLogDirectory();

        if (logDir == null) {
            throw new RuntimeException("Neo4j configured server.directories.logs points to a directory that " +
                    "does not exist or is not readable.  Please ensure this configuration is correct.");
        }

        // Prepend neo4jHome if it's a relative path, and use the user's path otherwise.
        File f = new File(logDir, logName);

        try {
            String canonicalPath = f.getCanonicalPath();
            if (!canonicalPath.startsWith(logDir.getAbsolutePath())) {
                throw new RuntimeException("The path you are trying to access has a canonical path outside of the logs " +<commit_msg>vuln-fix: Partial Path Traversal Vulnerability (#3080) (#3094)<commit_after>package apoc.log;

import apoc.util.FileUtils;
import org.neo4j.procedure.*;
import org.neo4j.logging.Log;

import java.nio.file.NoSuchFileException;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

/**
 * @author moxious
 * @since 27.02.19
 */
public class Neo4jLogStream {
    @Context
    public Log log;

    public static class FileEntry implements Comparable<FileEntry> {
        public final long lineNo;
        public final String line;
        public final String path;

        public FileEntry(long lineNumber, String data, String path) {
            this.lineNo = lineNumber;
            this.line = data;
            this.path = path;
        }

        public int compareTo(FileEntry o) {
            return Long.compare(this.lineNo,o.lineNo);
        }
    }

    @Admin
    @Procedure(mode=Mode.DBMS)
    @Description( "apoc.log.stream('neo4j.log', { last: n }) - retrieve log file contents, optionally return only the last n lines" )
    public Stream<FileEntry> stream(
            @Name("path") String logName,
            @Name(value = "config",defaultValue = "{}") Map<String, Object> config) {

        File logDir = FileUtils.getLogDirectory();

        if (logDir == null) {
            throw new RuntimeException("Neo4j configured server.directories.logs points to a directory that " +
                    "does not exist or is not readable.  Please ensure this configuration is correct.");
        }

        // Prepend neo4jHome if it's a relative path, and use the user's path otherwise.
        File f = new File(logDir, logName);

        try {
            if (!f.getCanonicalFile().toPath().startsWith(logDir.getAbsolutePath())) {
                throw new RuntimeException("The path you are trying to access has a canonical path outside of the logs " +
{'fraction_non_alphanumeric': 0.10048899755501223, 'fraction_numerical': 0.007823960880195598, 'mean_word_length': 2.6756513926325245, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4885468', 'n_tokens_mistral': 1194, 'n_tokens_neox': 1143, 'n_words': 347}