Equals signs also need to be escaped when parsing #SONGSELECT parameters.
This commit is contained in:
@@ -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
@@ -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());
|
||||
|
||||
@@ -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 )
|
||||
|
||||
Reference in New Issue
Block a user