Equals signs also need to be escaped when parsing #SONGSELECT parameters.

This commit is contained in:
Michael Votaw
2024-02-23 20:53:29 -06:00
committed by teejusb
parent bf5404a71a
commit dcb1a2e3db
3 changed files with 37 additions and 12 deletions
+9 -3
View File
@@ -111,15 +111,18 @@ Complete Course Template
-- - Unlike the #SONG tag, this will not take into account group names.
-- If you want to specify a specific song from a specific group, use
-- this along with the GROUP parameter.
-- - This does not support names that have commmas.
-- - Commas, and other control characters (`#`,`;`, `=`, and `:`) can be used,
-- but they must be escaped (like `\#`, `\,`, etc).
-- Example:
#SONGSELECT:TITLE=Goin' Under,Springtime;
#SONGSELECT:TITLE=thank u\, next;
-- GROUP= A list of one or more song groups, separated by commas.
-- Notes:
-- - The "group" refers to the directory name of the song group.
-- - This does not support folders that have commas in their name.
-- - Group names must be an *exact match*.
-- - Commas, and other control characters (`#`,`;`, `=`, and `:`) can be used,
-- but they must be escaped (like `\#`, `\,`, etc).
-- Example:
#SONGSELECT:GROUP=Stepmania 5,In The Groove;
@@ -127,13 +130,16 @@ Complete Course Template
-- Notes:
-- - The "artist" refers to either the #ARTIST or #ARTISTTRANSLIT value
-- of the simfile.
-- - This does not support artist names that contain commas.
-- - Commas, and other control characters (`#`,`;`, `=`, and `:`) can be used,
-- but they must be escaped (like `\#`, `\,`, etc).
-- Example:
#SONGSELECT:ARTIST=Kommisar,NegaRen;
-- GENRE= A list of one or more song genres, separated by commas.
-- Notes:
-- - The "genre" refers to the #GENRE tag of a song.
-- - Commas, and other control characters (`#`,`;`, `=`, and `:`) can be used,
-- but they must be escaped (like `\#`, `\,`, etc).
-- - Most songs don't actually have a #GENRE defined, which unfortunately
-- makes this parameter not terribly useful at this time.
-- Example:
+24 -5
View File
@@ -32,6 +32,25 @@ const char *g_CRSDifficultyNames[] =
"Edit",
};
// This is a convenience function to handle splitting a string that potentially has
// escaped delimitor characters.
// We need to split the string while still maintaining those escaped characters.
// So first, replace escaped characters with "||escaped-delim||"
// Then, replace any remaining delimitor characters with "||regular-delim||"
// Then, put the escaped characters back, by replacing "||escaped-delim||" with "\\" + sDelimitor
// And finally, split the string by instances of "||regular-delim||"
// So for instance, "Thing 1, Thing\,2" becomes "Thing 1||regular-delim||Thing \, 2"
void split_minding_escaped_delims(const RString &sSource, const RString &sDelimitor, std::vector<RString>& asAddit)
{
RString sourceCopy = sSource;
RString escaped_delim = "||escaped-delim||";
RString regular_delim = "||regular-delim||";
sourceCopy.Replace("\\" + sDelimitor, escaped_delim);
sourceCopy.Replace(sDelimitor, regular_delim);
sourceCopy.Replace(escaped_delim, "\\" + sDelimitor);
split(sourceCopy, regular_delim, asAddit);
}
/**
* @brief Retrieve the course difficulty based on the string name.
* @param s the name of the difficulty.
@@ -531,7 +550,8 @@ bool CourseLoaderCRS::ParseCourseSongSelect(const MsdFile::value_t &sParams, Cou
for( unsigned i = 1; i < sParams.params.size(); ++i )
{
std::vector<RString> sParamParts;
split(sParams[i], "=", sParamParts);
split_minding_escaped_delims(sParams[i], "=", sParamParts);
if( sParamParts.size() != 2 )
{
LOG->UserLog( "Course file", sPath, "has an invalid SONGSELECT sub-parameter, \"%s\"", sParams[i].c_str());
@@ -688,9 +708,8 @@ bool CourseLoaderCRS::ParseCommaSeparatedList(const RString &sParamValue, std::v
// Because we're dealing with a comma-separated list, we have to handle any escaped commas
// as a special case. Hopefully nobody writes a song called "||escaped-comma||"
RString unescapedParamValue = sParamValue;
unescapedParamValue.Replace("\\,", "||escaped-comma||");
unescapedParamValue = SmUnescape(unescapedParamValue);
split(unescapedParamValue, ",", items);
split_minding_escaped_delims(sParamValue, ",", items);
if(items.size() == 0)
{
LOG->UserLog( "Course file", sPath, "has an invalid %s parameter, expected at least one sub-parameter, but found none.", sParamName.c_str() );
@@ -698,7 +717,7 @@ bool CourseLoaderCRS::ParseCommaSeparatedList(const RString &sParamValue, std::v
}
for (unsigned long i = 0; i < items.size(); i++)
{
items[i].Replace("||escaped-comma||", ",");
items[i] = SmUnescape(items[i]);
Trim(items[i]);
}
dest.insert(dest.end(), items.begin(), items.end());
+4 -4
View File
@@ -229,23 +229,23 @@ bool CourseWriterCRS::WriteSongSelectCourseEntry( const CourseEntry &entry, Rage
//TODO: Re-escape everything
if( entry.songCriteria.m_vsSongNames.size() > 0 )
{
RString songNames = join(",", SmEscape( entry.songCriteria.m_vsSongNames, {'\\', ':', ';', '#', ','} ));
RString songNames = join(",", SmEscape( entry.songCriteria.m_vsSongNames, {'\\', ':', ';', '#', ',', '='} ));
songSelectParams.push_back(ssprintf("TITLE=%s", songNames.c_str()));
}
if( entry.songCriteria.m_vsGroupNames.size() > 0)
{
RString groupNames = join(",", SmEscape( entry.songCriteria.m_vsGroupNames, {'\\', ':', ';', '#', ','} ));
RString groupNames = join(",", SmEscape( entry.songCriteria.m_vsGroupNames, {'\\', ':', ';', '#', ',', '='} ));
songSelectParams.push_back(ssprintf("GROUP=%s", groupNames.c_str()));
}
if( entry.songCriteria.m_vsArtistNames.size() > 0)
{
RString artistNames = join(",", SmEscape( entry.songCriteria.m_vsArtistNames, {'\\', ':', ';', '#', ','} ));
RString artistNames = join(",", SmEscape( entry.songCriteria.m_vsArtistNames, {'\\', ':', ';', '#', ',', '='} ));
songSelectParams.push_back(ssprintf("ARTIST=%s", artistNames.c_str()));
}
if( entry.songCriteria.m_bUseSongAllowedList &&
entry.songCriteria.m_vsSongGenreAllowedList.size() > 0)
{
RString genreNames = join(",", SmEscape( entry.songCriteria.m_vsSongGenreAllowedList, {'\\', ':', ';', '#', ','} ));
RString genreNames = join(",", SmEscape( entry.songCriteria.m_vsSongGenreAllowedList, {'\\', ':', ';', '#', ',', '='} ));
songSelectParams.push_back(ssprintf("GENRE=%s", genreNames.c_str()));
}
if( entry.stepsCriteria.m_vDifficulties.size() > 0 )