mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Alternate Json string protection
.. when embedding json in xml element attributes the string decoding mangles results. this is because of the way \ and " are handled at each pass, causing combinations to be lost early when decoding. This is largely a non-issue, except the user chart config is stored in perspectives.xml and worse, when embedded on an overview is encoded as .gcchart (xml) before being encoded in the perspective.xml. To avoid this issue, specifically with user charts and to leave all other json string encoding and decoding unaffected (e.g. ridefile.json) a new protect/unprotect method has been introduced. Utils::jsonprotect2() and Utils::jsonunprotect2() will still decode older style encoding for backwards compatibility, but now will translate \ and " in the encoded string with :sl: and :qu: This means that, for example, the following substitutions will be made: newline (\n) -> :sl:n cr (\r) -> :sl:r \ -> :sl: " -> :qu: If users add text with these characters (e.g. :sl:) then it will be decoded to a slash, but it is highly unlikely they will do this, and if they do, it should be harmless as these text strings aren't part of the the datafilter syntax. Fixes #3996
This commit is contained in:
@@ -324,8 +324,8 @@ UserChart::settings() const
|
||||
out << "{ ";
|
||||
|
||||
// chartinfo
|
||||
out << "\"title\": \"" << Utils::jsonprotect(chartinfo.title) << "\",\n";
|
||||
out << "\"description\": \"" << Utils::jsonprotect(chartinfo.description) << "\",\n";
|
||||
out << "\"title\": \"" << Utils::jsonprotect2(chartinfo.title) << "\",\n";
|
||||
out << "\"description\": \"" << Utils::jsonprotect2(chartinfo.description) << "\",\n";
|
||||
out << "\"type\": " << chartinfo.type << ",\n";
|
||||
out << "\"animate\": " << (chartinfo.animate ? "true" : "false") << ",\n";
|
||||
out << "\"legendpos\": " << chartinfo.legendpos << ",\n";
|
||||
@@ -346,11 +346,11 @@ UserChart::settings() const
|
||||
|
||||
// out as a json object in the "SERIES" array
|
||||
out << "{ ";
|
||||
out << "\"name\": \"" << Utils::jsonprotect(series.name) << "\", ";
|
||||
out << "\"group\": \"" << Utils::jsonprotect(series.group) << "\", ";
|
||||
out << "\"xname\": \"" << Utils::jsonprotect(series.xname) << "\", ";
|
||||
out << "\"yname\": \"" << Utils::jsonprotect(series.yname) << "\", ";
|
||||
out << "\"program\": \"" << Utils::jsonprotect(series.string1) << "\", ";
|
||||
out << "\"name\": \"" << Utils::jsonprotect2(series.name) << "\", ";
|
||||
out << "\"group\": \"" << Utils::jsonprotect2(series.group) << "\", ";
|
||||
out << "\"xname\": \"" << Utils::jsonprotect2(series.xname) << "\", ";
|
||||
out << "\"yname\": \"" << Utils::jsonprotect2(series.yname) << "\", ";
|
||||
out << "\"program\": \"" << Utils::jsonprotect2(series.string1) << "\", ";
|
||||
out << "\"line\": " << series.line << ", ";
|
||||
out << "\"symbol\": " << series.symbol << ", ";
|
||||
out << "\"size\": " << series.size << ", ";
|
||||
@@ -377,7 +377,7 @@ UserChart::settings() const
|
||||
// out as a json object in the AXES array
|
||||
out << "{ ";
|
||||
|
||||
out << "\"name\": \"" << Utils::jsonprotect(axis.name) << "\", ";
|
||||
out << "\"name\": \"" << Utils::jsonprotect2(axis.name) << "\", ";
|
||||
out << "\"type\": " << axis.type << ", ";
|
||||
out << "\"orientation\": " << axis.orientation << ", ";
|
||||
out << "\"align\": " << axis.align << ", ";
|
||||
@@ -411,8 +411,8 @@ UserChart::applySettings(QString x)
|
||||
QJsonObject obj = doc.object();
|
||||
|
||||
// chartinfo
|
||||
chartinfo.title = Utils::jsonunprotect(obj["title"].toString());
|
||||
chartinfo.description = Utils::jsonunprotect(obj["description"].toString());
|
||||
chartinfo.title = Utils::jsonunprotect2(obj["title"].toString());
|
||||
chartinfo.description = Utils::jsonunprotect2(obj["description"].toString());
|
||||
chartinfo.type = obj["type"].toInt();
|
||||
chartinfo.animate = obj["animate"].toBool();
|
||||
chartinfo.legendpos = obj["legendpos"].toInt();
|
||||
@@ -433,11 +433,11 @@ UserChart::applySettings(QString x)
|
||||
QJsonObject series=it.toObject();
|
||||
|
||||
GenericSeriesInfo add;
|
||||
add.name = Utils::jsonunprotect(series["name"].toString());
|
||||
add.group = Utils::jsonunprotect(series["group"].toString());
|
||||
add.xname = Utils::jsonunprotect(series["xname"].toString());
|
||||
add.yname = Utils::jsonunprotect(series["yname"].toString());
|
||||
add.string1 = Utils::jsonunprotect(series["program"].toString());
|
||||
add.name = Utils::jsonunprotect2(series["name"].toString());
|
||||
add.group = Utils::jsonunprotect2(series["group"].toString());
|
||||
add.xname = Utils::jsonunprotect2(series["xname"].toString());
|
||||
add.yname = Utils::jsonunprotect2(series["yname"].toString());
|
||||
add.string1 = Utils::jsonunprotect2(series["program"].toString());
|
||||
add.line = series["line"].toInt();
|
||||
add.symbol = series["symbol"].toInt();
|
||||
add.size = series["size"].toDouble();
|
||||
@@ -463,7 +463,7 @@ UserChart::applySettings(QString x)
|
||||
QJsonObject axis=it.toObject();
|
||||
|
||||
GenericAxisInfo add;
|
||||
add.name = Utils::jsonunprotect(axis["name"].toString());
|
||||
add.name = Utils::jsonunprotect2(axis["name"].toString());
|
||||
add.type = static_cast<GenericAxisInfo::AxisInfoType>(axis["type"].toInt());
|
||||
add.orientation = static_cast<Qt::Orientation>(axis["orientation"].toInt());
|
||||
add.align = static_cast<Qt::AlignmentFlag>(axis["align"].toInt());
|
||||
|
||||
@@ -236,6 +236,47 @@ QString jsonunprotect(const QString &string)
|
||||
return s;
|
||||
}
|
||||
|
||||
// json protection with special handling for " and \
|
||||
// used when embedding in xml
|
||||
QString jsonprotect2(const QString &string)
|
||||
{
|
||||
QString s = string;
|
||||
s.replace("\t", "\\t"); // tab
|
||||
s.replace("\n", "\\n"); // newline
|
||||
s.replace("\r", "\\r"); // carriage-return
|
||||
s.replace("\b", "\\b"); // backspace
|
||||
s.replace("\f", "\\f"); // formfeed
|
||||
s.replace("/", "\\/"); // solidus
|
||||
s.replace("\\", ":sl:"); // backslash
|
||||
s.replace("\"", ":qu:"); // quote
|
||||
|
||||
// add a trailing space to avoid conflicting with GC special tokens
|
||||
s += " ";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
QString jsonunprotect2(const QString &string)
|
||||
{
|
||||
QString s = string;
|
||||
// legacy- these should never be present
|
||||
// but included to read older files
|
||||
s.replace("\\\"", "\""); // quote
|
||||
s.replace("\\\\", "\\"); // backslash
|
||||
|
||||
s.replace(":qu:", "\""); // quote
|
||||
s.replace(":sl:", "\\"); // backslash
|
||||
s.replace("\\t", "\t"); // tab
|
||||
s.replace("\\n", "\n"); // newline
|
||||
s.replace("\\r", "\r"); // carriage-return
|
||||
s.replace("\\b", "\b"); // backspace
|
||||
s.replace("\\f", "\f"); // formfeed
|
||||
s.replace("\\/", "/"); // solidus
|
||||
|
||||
// those trailing spaces.
|
||||
while (s.endsWith(" ")) s = s.mid(0,s.length()-1);
|
||||
return s;
|
||||
}
|
||||
QStringList
|
||||
searchPath(QString path, QString binary, bool isexec)
|
||||
{
|
||||
@@ -540,4 +581,3 @@ double myisinf(double x) { return isinf(x); } // math.h
|
||||
double myisnan(double x) { return isnan(x); } // math.h
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Utils
|
||||
QString unescape(const QString &string); // simple string unescaping, used in datafilters
|
||||
QString jsonprotect(const QString &buffer);
|
||||
QString jsonunprotect(const QString &buffer);
|
||||
QString jsonprotect2(const QString &buffer); // internal use- encodes / and " as :sl: :qu:
|
||||
QString jsonunprotect2(const QString &buffer); // internal use- encodes / and " as :sl: :qu:
|
||||
QStringList searchPath(QString path, QString binary, bool isexec=true);
|
||||
QString removeDP(QString);
|
||||
double number(QString);
|
||||
|
||||
Reference in New Issue
Block a user