diff --git a/src/main/java/org/metricshub/winrm/WmiHelper.java b/src/main/java/org/metricshub/winrm/WmiHelper.java index 054e036..03f4899 100644 --- a/src/main/java/org/metricshub/winrm/WmiHelper.java +++ b/src/main/java/org/metricshub/winrm/WmiHelper.java @@ -43,7 +43,7 @@ private WmiHelper() {} */ private static final Pattern WQL_SIMPLE_SELECT_PATTERN = Pattern.compile( "^\\s*SELECT\\s+(\\*|(?!SELECT|FROM|WHERE)[a-z0-9._]+|((?!SELECT|FROM|WHERE)[a-z0-9._]+\\s*,\\s*)+((?!SELECT|FROM|WHERE)[a-z0-9._]+))\\s+FROM\\s+((?!WHERE|FROM)\\w+)\\s*(WHERE\\s+.*)?$", - Pattern.CASE_INSENSITIVE + Pattern.CASE_INSENSITIVE | Pattern.DOTALL ); /** diff --git a/src/site/markdown/wql.md b/src/site/markdown/wql.md index 7aa531c..562b1e8 100644 --- a/src/site/markdown/wql.md +++ b/src/site/markdown/wql.md @@ -140,7 +140,8 @@ SELECT Name FROM Win32_Process WHERE Name = 'explorer.exe' ``` The grammar is a single `SELECT` of either `*` or a comma-separated property list, a `FROM` clause -naming one class, and an optional `WHERE` clause. Anything else, such as `ASSOCIATORS OF`, +naming one class, and an optional `WHERE` clause. Line breaks are accepted wherever whitespace is, +so queries written as Java text blocks work as is. Anything else, such as `ASSOCIATORS OF`, `REFERENCES OF` or event queries (`WITHIN`), is rejected: an invalid query raises a [`WqlSyntaxException`](apidocs/org/metricshub/winrm/exceptions/WqlSyntaxException.html) before anything is sent to the host. diff --git a/src/test/java/org/metricshub/winrm/WmiHelperTest.java b/src/test/java/org/metricshub/winrm/WmiHelperTest.java new file mode 100644 index 0000000..1c7091f --- /dev/null +++ b/src/test/java/org/metricshub/winrm/WmiHelperTest.java @@ -0,0 +1,63 @@ +package org.metricshub.winrm; + +/*- + * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ + * WinRM Java Client + * ჻჻჻჻჻჻ + * Copyright 2023 - 2026 MetricsHub + * ჻჻჻჻჻჻ + * Licensed 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 static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class WmiHelperTest { + + @Test + void isValidWqlAcceptsSingleLineQueries() { + assertTrue(WmiHelper.isValidWql("SELECT * FROM Win32_Service")); + assertTrue(WmiHelper.isValidWql("SELECT Name FROM Win32_Service WHERE State = 'Running' AND StartMode = 'Auto'")); + } + + @Test + void isValidWqlAcceptsLineBreaksBeforeWhere() { + assertTrue(WmiHelper.isValidWql("SELECT Name FROM Win32_Service\nWHERE State = 'Running'")); + } + + @Test + void isValidWqlAcceptsMultiLineWhereClause() { + assertTrue( + WmiHelper.isValidWql("SELECT Name FROM Win32_Service\nWHERE State = 'Running'\n AND StartMode = 'Auto'\n") + ); + assertTrue( + WmiHelper.isValidWql( + "SELECT Name, ProcessId\r\nFROM Win32_Service\r\nWHERE State = 'Running'\r\n AND StartMode = 'Auto'" + ) + ); + } + + @Test + void isValidWqlRejectsNonSelectQueries() { + assertFalse(WmiHelper.isValidWql("ASSOCIATORS OF {Win32_Service.Name='W32Time'}")); + assertFalse(WmiHelper.isValidWql("REFERENCES OF {Win32_Service.Name='W32Time'}")); + assertFalse( + WmiHelper + .isValidWql("SELECT * FROM __InstanceModificationEvent WITHIN 1\nWHERE TargetInstance ISA 'Win32_Service'") + ); + assertFalse(WmiHelper.isValidWql("SELECT Name FROM Win32_Service\nSELECT Name FROM Win32_Process")); + assertFalse(WmiHelper.isValidWql("SELECT Name FROM Win32_Service WHERE")); + } +}