mirror of
https://github.com/loot/loot-condition-interpreter.git
synced 2026-07-27 14:16:09 -07:00
Remove check that paths are inside game path
It didn't work correctly for OpenMW or for additional data paths, fixing it would be significantly more complicated, and it doesn't really add any value.
This commit is contained in:
+8
-103
@@ -1,4 +1,4 @@
|
|||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::PathBuf;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
@@ -12,7 +12,7 @@ use regex::{Regex, RegexBuilder};
|
|||||||
|
|
||||||
use super::{ComparisonOperator, Function};
|
use super::{ComparisonOperator, Function};
|
||||||
use crate::error::ParsingErrorKind;
|
use crate::error::ParsingErrorKind;
|
||||||
use crate::{map_err, whitespace, ParsingError, ParsingResult};
|
use crate::{map_err, whitespace, ParsingResult};
|
||||||
|
|
||||||
impl ComparisonOperator {
|
impl ComparisonOperator {
|
||||||
pub fn parse(input: &str) -> IResult<&str, ComparisonOperator> {
|
pub fn parse(input: &str) -> IResult<&str, ComparisonOperator> {
|
||||||
@@ -32,20 +32,6 @@ const INVALID_PATH_CHARS: &str = "\":*?<>|";
|
|||||||
const INVALID_NON_REGEX_PATH_CHARS: &str = "\":*?<>|\\"; // \ is treated as invalid to distinguish regex strings.
|
const INVALID_NON_REGEX_PATH_CHARS: &str = "\":*?<>|\\"; // \ is treated as invalid to distinguish regex strings.
|
||||||
const INVALID_REGEX_PATH_CHARS: &str = "\"<>";
|
const INVALID_REGEX_PATH_CHARS: &str = "\"<>";
|
||||||
|
|
||||||
fn is_in_game_path(path: &Path) -> bool {
|
|
||||||
let mut previous_component = Component::CurDir;
|
|
||||||
for component in path.components() {
|
|
||||||
match (component, previous_component) {
|
|
||||||
(Component::Prefix(_) | Component::RootDir, _)
|
|
||||||
| (Component::ParentDir, Component::ParentDir) => return false,
|
|
||||||
(Component::CurDir, _) => {}
|
|
||||||
_ => previous_component = component,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_regex(input: &str) -> Result<(&'static str, Regex), regex::Error> {
|
fn build_regex(input: &str) -> Result<(&'static str, Regex), regex::Error> {
|
||||||
RegexBuilder::new(input)
|
RegexBuilder::new(input)
|
||||||
.case_insensitive(true)
|
.case_insensitive(true)
|
||||||
@@ -62,10 +48,6 @@ fn parse_anchored_regex(input: &str) -> ParsingResult<Regex> {
|
|||||||
.map_err(|e| Err::Failure(ParsingErrorKind::from(e).at(input)))
|
.map_err(|e| Err::Failure(ParsingErrorKind::from(e).at(input)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn not_in_game_directory(input: &str, path: PathBuf) -> Err<ParsingError<&str>> {
|
|
||||||
Err::Failure(ParsingErrorKind::PathIsNotInGameDirectory(path).at(input))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_path(input: &str) -> IResult<&str, PathBuf> {
|
fn parse_path(input: &str) -> IResult<&str, PathBuf> {
|
||||||
map(
|
map(
|
||||||
delimited(tag("\""), is_not(INVALID_PATH_CHARS), tag("\"")),
|
delimited(tag("\""), is_not(INVALID_PATH_CHARS), tag("\"")),
|
||||||
@@ -89,11 +71,7 @@ fn parse_file_size_args(input: &str) -> ParsingResult<(PathBuf, u64)> {
|
|||||||
|
|
||||||
let (remaining_input, (path, _, size)) = parser.parse(input)?;
|
let (remaining_input, (path, _, size)) = parser.parse(input)?;
|
||||||
|
|
||||||
if is_in_game_path(&path) {
|
Ok((remaining_input, (path, size)))
|
||||||
Ok((remaining_input, (path, size)))
|
|
||||||
} else {
|
|
||||||
Err(not_in_game_directory(input, path))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_version(input: &str) -> IResult<&str, String> {
|
fn parse_version(input: &str) -> IResult<&str, String> {
|
||||||
@@ -115,11 +93,7 @@ fn parse_version_args(input: &str) -> ParsingResult<(PathBuf, String, Comparison
|
|||||||
|
|
||||||
let (remaining_input, (path, _, version, _, comparator)) = map_err(parser).parse(input)?;
|
let (remaining_input, (path, _, version, _, comparator)) = map_err(parser).parse(input)?;
|
||||||
|
|
||||||
if is_in_game_path(&path) {
|
Ok((remaining_input, (path, version, comparator)))
|
||||||
Ok((remaining_input, (path, version, comparator)))
|
|
||||||
} else {
|
|
||||||
Err(not_in_game_directory(input, path))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_filename_version_args(
|
fn parse_filename_version_args(
|
||||||
@@ -175,11 +149,7 @@ fn parse_checksum_args(input: &str) -> ParsingResult<(PathBuf, u32)> {
|
|||||||
|
|
||||||
let (remaining_input, (path, _, crc)) = parser.parse(input)?;
|
let (remaining_input, (path, _, crc)) = parser.parse(input)?;
|
||||||
|
|
||||||
if is_in_game_path(&path) {
|
Ok((remaining_input, (path, crc)))
|
||||||
Ok((remaining_input, (path, crc)))
|
|
||||||
} else {
|
|
||||||
Err(not_in_game_directory(input, path))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_non_regex_path(input: &str) -> ParsingResult<PathBuf> {
|
fn parse_non_regex_path(input: &str) -> ParsingResult<PathBuf> {
|
||||||
@@ -188,11 +158,7 @@ fn parse_non_regex_path(input: &str) -> ParsingResult<PathBuf> {
|
|||||||
})
|
})
|
||||||
.parse(input)?;
|
.parse(input)?;
|
||||||
|
|
||||||
if is_in_game_path(&path) {
|
Ok((remaining_input, path))
|
||||||
Ok((remaining_input, path))
|
|
||||||
} else {
|
|
||||||
Err(not_in_game_directory(input, path))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a string that is a path where the last component is a regex string
|
/// Parse a string that is a path where the last component is a regex string
|
||||||
@@ -210,10 +176,6 @@ fn parse_regex_path(input: &str) -> ParsingResult<(PathBuf, Regex)> {
|
|||||||
|
|
||||||
let parent_path = PathBuf::from(parent_path_slice);
|
let parent_path = PathBuf::from(parent_path_slice);
|
||||||
|
|
||||||
if !is_in_game_path(&parent_path) {
|
|
||||||
return Err(not_in_game_directory(input, parent_path));
|
|
||||||
}
|
|
||||||
|
|
||||||
let regex = parse_anchored_regex(regex_slice)?.1;
|
let regex = parse_anchored_regex(regex_slice)?.1;
|
||||||
|
|
||||||
Ok((remaining_input, (parent_path, regex)))
|
Ok((remaining_input, (parent_path, regex)))
|
||||||
@@ -356,6 +318,8 @@ impl Function {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -397,11 +361,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_file_path_is_outside_the_game_directory() {
|
|
||||||
assert!(Function::parse("file(\"../../Cargo.toml\")").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_a_file_regex_function_with_no_parent_path() {
|
fn function_parse_should_parse_a_file_regex_function_with_no_parent_path() {
|
||||||
let output = Function::parse("file(\"Cargo.*\")").unwrap();
|
let output = Function::parse("file(\"Cargo.*\")").unwrap();
|
||||||
@@ -435,11 +394,6 @@ mod tests {
|
|||||||
assert!(Function::parse("file(\"sub\\dir/\")").is_err());
|
assert!(Function::parse("file(\"sub\\dir/\")").is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_file_regex_parent_path_is_outside_the_game_directory() {
|
|
||||||
assert!(Function::parse("file(\"../../Cargo.*\")").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_a_file_size_function() {
|
fn function_parse_should_parse_a_file_size_function() {
|
||||||
let output = Function::parse("file_size(\"Cargo.toml\", 1234)").unwrap();
|
let output = Function::parse("file_size(\"Cargo.toml\", 1234)").unwrap();
|
||||||
@@ -454,11 +408,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_file_size_is_outside_the_game_directory() {
|
|
||||||
assert!(Function::parse("file_size(\"../../Cargo.toml\", 1234)").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_a_readable_function() {
|
fn function_parse_should_parse_a_readable_function() {
|
||||||
let output = Function::parse("readable(\"Cargo.toml\")").unwrap();
|
let output = Function::parse("readable(\"Cargo.toml\")").unwrap();
|
||||||
@@ -470,11 +419,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_readable_path_is_outside_the_game_directory() {
|
|
||||||
assert!(Function::parse("readable(\"../../Cargo.toml\")").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_an_is_executable_function() {
|
fn function_parse_should_parse_an_is_executable_function() {
|
||||||
let output = Function::parse("is_executable(\"Cargo.toml\")").unwrap();
|
let output = Function::parse("is_executable(\"Cargo.toml\")").unwrap();
|
||||||
@@ -486,11 +430,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_is_executable_path_is_outside_the_game_directory() {
|
|
||||||
assert!(Function::parse("is_executable(\"../../Cargo.toml\")").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_an_active_path_function() {
|
fn function_parse_should_parse_an_active_path_function() {
|
||||||
let output = Function::parse("active(\"Cargo.toml\")").unwrap();
|
let output = Function::parse("active(\"Cargo.toml\")").unwrap();
|
||||||
@@ -502,13 +441,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_active_path_is_outside_the_game_directory() {
|
|
||||||
// Trying to check if a path that isn't a plugin in the data folder is
|
|
||||||
// active is pointless, but it's not worth having a more specific check.
|
|
||||||
assert!(Function::parse("active(\"../../Cargo.toml\")").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_an_active_regex_function() {
|
fn function_parse_should_parse_an_active_regex_function() {
|
||||||
let output = Function::parse("active(\"Cargo.*\")").unwrap();
|
let output = Function::parse("active(\"Cargo.*\")").unwrap();
|
||||||
@@ -533,13 +465,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_is_master_path_is_outside_the_game_directory() {
|
|
||||||
// Trying to check if a path that isn't a plugin in the data folder is
|
|
||||||
// active is pointless, but it's not worth having a more specific check.
|
|
||||||
assert!(Function::parse("is_master(\"../../Blank.esm\")").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_a_many_function_with_no_parent_path() {
|
fn function_parse_should_parse_a_many_function_with_no_parent_path() {
|
||||||
let output = Function::parse("many(\"Cargo.*\")").unwrap();
|
let output = Function::parse("many(\"Cargo.*\")").unwrap();
|
||||||
@@ -573,11 +498,6 @@ mod tests {
|
|||||||
assert!(Function::parse("many(\"subdir/\")").is_err());
|
assert!(Function::parse("many(\"subdir/\")").is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_many_parent_path_is_outside_the_game_directory() {
|
|
||||||
assert!(Function::parse("file(\"../../Cargo.*\")").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_a_many_active_function() {
|
fn function_parse_should_parse_a_many_active_function() {
|
||||||
let output = Function::parse("many_active(\"Cargo.*\")").unwrap();
|
let output = Function::parse("many_active(\"Cargo.*\")").unwrap();
|
||||||
@@ -605,11 +525,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_checksum_path_is_outside_the_game_directory() {
|
|
||||||
assert!(Function::parse("checksum(\"../../Cargo.toml\", DEADBEEF)").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_a_version_equals_function() {
|
fn function_parse_should_parse_a_version_equals_function() {
|
||||||
let output = Function::parse("version(\"Cargo.toml\", \"1.2\", ==)").unwrap();
|
let output = Function::parse("version(\"Cargo.toml\", \"1.2\", ==)").unwrap();
|
||||||
@@ -715,11 +630,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_version_path_is_outside_the_game_directory() {
|
|
||||||
assert!(Function::parse("version(\"../../Cargo.toml\", \"1.2\", ==)").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_a_product_version_equals_function() {
|
fn function_parse_should_parse_a_product_version_equals_function() {
|
||||||
let output = Function::parse("product_version(\"Cargo.toml\", \"1.2\", ==)").unwrap();
|
let output = Function::parse("product_version(\"Cargo.toml\", \"1.2\", ==)").unwrap();
|
||||||
@@ -735,11 +645,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn function_parse_should_error_if_the_product_version_path_is_outside_the_game_directory() {
|
|
||||||
assert!(Function::parse("product_version(\"../../Cargo.toml\", \"1.2\", ==)").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_parse_should_parse_a_filename_version_equals_function() {
|
fn function_parse_should_parse_a_filename_version_equals_function() {
|
||||||
let output =
|
let output =
|
||||||
|
|||||||
-10
@@ -488,16 +488,6 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn expression_from_str_should_error_with_input_on_path_outside_game_directory() {
|
|
||||||
let error = Expression::from_str("file(\"../../Cargo.toml\")").unwrap_err();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
"An error was encountered while parsing the expression \"../../Cargo.toml\\\")\": \"../../Cargo.toml\" is not in the game directory",
|
|
||||||
error.to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn expression_parse_should_handle_a_single_compound_condition() {
|
fn expression_parse_should_handle_a_single_compound_condition() {
|
||||||
let result = Expression::from_str("file(\"Cargo.toml\")").unwrap();
|
let result = Expression::from_str("file(\"Cargo.toml\")").unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user