Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ For dev or build tags, use the same logical version string embedded in the tag.

## [Unreleased]

- Reloaded search-request filters now preserve the configured regex case mode
instead of always becoming case-sensitive after an options change.
- The web footer and README now offer direct PayPal and Ko-fi links for
supporting slskdN development.
- GitLab CI configuration now keeps the Arch package-smoke sudoers command as
Expand Down
38 changes: 23 additions & 15 deletions src/slskd/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,17 +186,9 @@ public Application(

Flags = Program.Flags;

var regexOptions = RegexOptions.Compiled;

if (!Flags.CaseSensitiveRegEx)
{
regexOptions |= RegexOptions.IgnoreCase;
}

CompiledSearchRequestFilters = OptionsAtStartup.Filters.Search.Request
.Select(f => new Regex(f, regexOptions, SearchRequestFilterMatchTimeout))
.ToList()
.AsReadOnly();
CompiledSearchRequestFilters = CompileSearchRequestFilters(
OptionsAtStartup.Filters.Search.Request,
Flags.CaseSensitiveRegEx);

State = state;
RegisterChange(State.OnChange(state => State_OnChange(state)));
Expand Down Expand Up @@ -782,6 +774,23 @@ internal static SoulseekClientOptionsPatch CreateStartupSoulseekClientOptionsPat
placeInQueueResolver: placeInQueueResolver);
}

internal static IReadOnlyList<Regex> CompileSearchRequestFilters(
IEnumerable<string> filters,
bool caseSensitive)
{
var regexOptions = RegexOptions.Compiled;

if (!caseSensitive)
{
regexOptions |= RegexOptions.IgnoreCase;
}

return filters
.Select(f => new Regex(f, regexOptions, SearchRequestFilterMatchTimeout))
.ToList()
.AsReadOnly();
}

private static UserEndPointCache CreateUserEndPointCache()
{
var cache = new UserEndPointCache();
Expand Down Expand Up @@ -2242,10 +2251,9 @@ static string FormatOptionLogValue(PropertyInfo? property, object? value)
if (PreviousOptions.Filters.Search.Request.Except(newOptions.Filters.Search.Request).Any()
|| newOptions.Filters.Search.Request.Except(PreviousOptions.Filters.Search.Request).Any())
{
CompiledSearchRequestFilters = newOptions.Filters.Search.Request
.Select(f => new Regex(f, RegexOptions.Compiled, SearchRequestFilterMatchTimeout))
.ToList()
.AsReadOnly();
CompiledSearchRequestFilters = CompileSearchRequestFilters(
newOptions.Filters.Search.Request,
Flags.CaseSensitiveRegEx);

Log.Information("Updated and re-compiled search response filters");
}
Expand Down
12 changes: 12 additions & 0 deletions tests/slskd.Tests.Unit/Core/ApplicationLifecycleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ public void CreateStartupSoulseekClientOptionsPatch_DoesNotReapplyListenerSettin
Assert.Null(patch.ListenPort);
}

[Theory]
[InlineData(false, true)]
[InlineData(true, false)]
public void CompileSearchRequestFilters_PreservesConfiguredCaseMode(
bool caseSensitive,
bool expectedMatch)
{
var filters = Application.CompileSearchRequestFilters(["^secret$"], caseSensitive);

Assert.Equal(expectedMatch, filters[0].IsMatch("SECRET"));
}

[Fact]
public void FormatCompletedTransferProgress_ClampsNegativeAverageSpeed()
{
Expand Down
Loading