regorxxx / Playlist-Manager-SMP

A playlist manager for foobar2000, using Spider Monkey, to save and load (auto)playlists on demand, synchronizing, ... along many more utilities.
https://regorxxx.github.io/foobar2000-SMP.github.io/scripts/playlist-manager-smp/
GNU Affero General Public License v3.0
56 stars 5 forks source link

[BUG] Folder names with regex characters like `[` cause issues #36

Closed dinfinity closed 1 year ago

dinfinity commented 1 year ago

Describe the bug Folder names aren't escaped before using them in a regular expression in getRelPath() in helpers_xxx_playlists_files.js, leading to obvious issues when folders contain special regex-like characters such as [.

The resulting behavior differs depending on how the folder is parsed in the reg exp. For me, the file paths in the produced playlist M3U files were broken.

Suggested fix Just a quick fix for this:

function getRelPath(itemPath, relPathSplit) {
    let cache = '';
    relPathSplit.forEach((folder) => {
        const folderEscaped = escapeRegExp(folder);
        const level = new RegExp(folderEscaped + '\\\\', 'i');
        cache = itemPath.replace(level, '');
        if (itemPath === cache) {itemPath = '..\\' + cache;}
        else {itemPath = cache;}
    });
    if (!itemPath.startsWith('..\\')) {itemPath = '.\\' + itemPath;}
    return itemPath;
}

function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
regorxxx commented 1 year ago

Although that solution works most times (there are a few use-cases where it would fail), I prefer a lazier, safer and totally future proof version (and since the playlist folder doesn't change between sessions... well, result is cached, has zero performance impact):

const escapeRegExpCache = {};
function escapeRegExp(s) {
    s = toString(s);
    if (s && !escapeRegExpCache.hasOwnProperty(s)) {escapeRegExpCache[s] = s.replace(/([^a-zA-Z0-9])/g, '\\$1');}
    return s ? escapeRegExpCache[s] : s; // Can not be safer than this
}

Can't care about readability of the output, since it's all internally used.

Note the problematic path is the playlist folder path not the tracks path. As it is the only thing used on the regexp. You could bypass any problem if the root has no special chars.

Tested it against a playlist folder named: [testplaylist$.+(abc)] and it works fine now, failing with the old code as you reported. So I consider this fixed.

Thanks for the report, totally missed this when coding it.

dinfinity commented 1 year ago

Thanks for the quick action!