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.
|
-- - 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
|
-- If you want to specify a specific song from a specific group, use
|
||||||
-- this along with the GROUP parameter.
|
-- 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:
|
-- Example:
|
||||||
#SONGSELECT:TITLE=Goin' Under,Springtime;
|
#SONGSELECT:TITLE=Goin' Under,Springtime;
|
||||||
|
#SONGSELECT:TITLE=thank u\, next;
|
||||||
|
|
||||||
-- GROUP= A list of one or more song groups, separated by commas.
|
-- GROUP= A list of one or more song groups, separated by commas.
|
||||||
-- Notes:
|
-- Notes:
|
||||||
-- - The "group" refers to the directory name of the song group.
|
-- - 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*.
|
-- - Group names must be an *exact match*.
|
||||||
|
-- - Commas, and other control characters (`#`,`;`, `=`, and `:`) can be used,
|
||||||
|
-- but they must be escaped (like `\#`, `\,`, etc).
|
||||||
-- Example:
|
-- Example:
|
||||||
#SONGSELECT:GROUP=Stepmania 5,In The Groove;
|
#SONGSELECT:GROUP=Stepmania 5,In The Groove;
|
||||||
|
|
||||||
@@ -127,13 +130,16 @@ Complete Course Template
|
|||||||
-- Notes:
|
-- Notes:
|
||||||
-- - The "artist" refers to either the #ARTIST or #ARTISTTRANSLIT value
|
-- - The "artist" refers to either the #ARTIST or #ARTISTTRANSLIT value
|
||||||
-- of the simfile.
|
-- 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:
|
-- Example:
|
||||||
#SONGSELECT:ARTIST=Kommisar,NegaRen;
|
#SONGSELECT:ARTIST=Kommisar,NegaRen;
|
||||||
|
|
||||||
-- GENRE= A list of one or more song genres, separated by commas.
|
-- GENRE= A list of one or more song genres, separated by commas.
|
||||||
-- Notes:
|
-- Notes:
|
||||||
-- - The "genre" refers to the #GENRE tag of a song.
|
-- - 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
|
-- - Most songs don't actually have a #GENRE defined, which unfortunately
|
||||||
-- makes this parameter not terribly useful at this time.
|
-- makes this parameter not terribly useful at this time.
|
||||||
-- Example:
|
-- Example:
|
||||||
|
|||||||
+24
-5
@@ -32,6 +32,25 @@ const char *g_CRSDifficultyNames[] =
|
|||||||
"Edit",
|
"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.
|
* @brief Retrieve the course difficulty based on the string name.
|
||||||
* @param s the name of the difficulty.
|
* @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 )
|
for( unsigned i = 1; i < sParams.params.size(); ++i )
|
||||||
{
|
{
|
||||||
std::vector<RString> sParamParts;
|
std::vector<RString> sParamParts;
|
||||||
split(sParams[i], "=", sParamParts);
|
split_minding_escaped_delims(sParams[i], "=", sParamParts);
|
||||||
|
|
||||||
if( sParamParts.size() != 2 )
|
if( sParamParts.size() != 2 )
|
||||||
{
|
{
|
||||||
LOG->UserLog( "Course file", sPath, "has an invalid SONGSELECT sub-parameter, \"%s\"", sParams[i].c_str());
|
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
|
// 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||"
|
// as a special case. Hopefully nobody writes a song called "||escaped-comma||"
|
||||||
RString unescapedParamValue = sParamValue;
|
RString unescapedParamValue = sParamValue;
|
||||||
unescapedParamValue.Replace("\\,", "||escaped-comma||");
|
|
||||||
unescapedParamValue = SmUnescape(unescapedParamValue);
|
split_minding_escaped_delims(sParamValue, ",", items);
|
||||||
split(unescapedParamValue, ",", items);
|
|
||||||
if(items.size() == 0)
|
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() );
|
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++)
|
for (unsigned long i = 0; i < items.size(); i++)
|
||||||
{
|
{
|
||||||
items[i].Replace("||escaped-comma||", ",");
|
items[i] = SmUnescape(items[i]);
|
||||||
Trim(items[i]);
|
Trim(items[i]);
|
||||||
}
|
}
|
||||||
dest.insert(dest.end(), items.begin(), items.end());
|
dest.insert(dest.end(), items.begin(), items.end());
|
||||||
|
|||||||
@@ -229,23 +229,23 @@ bool CourseWriterCRS::WriteSongSelectCourseEntry( const CourseEntry &entry, Rage
|
|||||||
//TODO: Re-escape everything
|
//TODO: Re-escape everything
|
||||||
if( entry.songCriteria.m_vsSongNames.size() > 0 )
|
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()));
|
songSelectParams.push_back(ssprintf("TITLE=%s", songNames.c_str()));
|
||||||
}
|
}
|
||||||
if( entry.songCriteria.m_vsGroupNames.size() > 0)
|
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()));
|
songSelectParams.push_back(ssprintf("GROUP=%s", groupNames.c_str()));
|
||||||
}
|
}
|
||||||
if( entry.songCriteria.m_vsArtistNames.size() > 0)
|
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()));
|
songSelectParams.push_back(ssprintf("ARTIST=%s", artistNames.c_str()));
|
||||||
}
|
}
|
||||||
if( entry.songCriteria.m_bUseSongAllowedList &&
|
if( entry.songCriteria.m_bUseSongAllowedList &&
|
||||||
entry.songCriteria.m_vsSongGenreAllowedList.size() > 0)
|
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()));
|
songSelectParams.push_back(ssprintf("GENRE=%s", genreNames.c_str()));
|
||||||
}
|
}
|
||||||
if( entry.stepsCriteria.m_vDifficulties.size() > 0 )
|
if( entry.stepsCriteria.m_vDifficulties.size() > 0 )
|
||||||
|
|||||||
Reference in New Issue
Block a user