@@ -16,9 +16,9 @@
17.pragma library
17.pragma library
19−// %1 is the template["card-background"] string
19+// %1 is the template["card-background"]["elements"][0]
20−// %2 is the template["card-background"]["elements"][0]
20+// %2 is the template["card-background"]["elements"][1]
21−// %3 is the template["card-background"]["elements"][1]
21+// %3 is the template["card-background"] string
22var kBackgroundLoaderCode = 'Loader {\n\
22var kBackgroundLoaderCode = 'Loader {\n\
23 id: backgroundLoader; \n\
23 id: backgroundLoader; \n\
24 objectName: "backgroundLoader"; \n\
24 objectName: "backgroundLoader"; \n\
@@ -46,14 +46,14 @@ var kBackgroundLoaderCode = 'Loader {\n\
46 objectName: "backgroundImage"; \n\
46 objectName: "backgroundImage"; \n\
47 source: { \n\
47 source: { \n\
48 if (cardData && typeof cardData["background"] === "string") return cardData["background"]; \n\
48 if (cardData && typeof cardData["background"] === "string") return cardData["background"]; \n\
49− else return "%1"; \n\
49+ else return %3; \n\
52 function getColor(index) { \n\
52 function getColor(index) { \n\
53 if (cardData && typeof cardData["background"] === "object" \n\
53 if (cardData && typeof cardData["background"] === "object" \n\
54 && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) { \n\
54 && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) { \n\
55 return cardData["background"]["elements"][index]; \n\
55 return cardData["background"]["elements"][index]; \n\
56− } else return index === 0 ? %2 : %3; \n\
56+ } else return index === 0 ? %1 : %2; \n\
@@ -71,7 +71,7 @@ var kArtShapeHolderCode = 'Item { \n\
71 Loader { \n\
71 Loader { \n\
72 id: artShapeLoader; \n\
72 id: artShapeLoader; \n\
73 objectName: "artShapeLoader"; \n\
73 objectName: "artShapeLoader"; \n\
74− readonly property string cardArt: cardData && cardData["art"] || "%5"; \n\
74+ readonly property string cardArt: cardData && cardData["art"] || %5; \n\
75 active: cardArt != ""; \n\
75 active: cardArt != ""; \n\
76 asynchronous: root.asynchronous; \n\
76 asynchronous: root.asynchronous; \n\
77 visible: status == Loader.Ready; \n\
77 visible: status == Loader.Ready; \n\
@@ -252,7 +252,7 @@ var kMascotImageCode = 'CroppedImageMinimumSourceSize { \n\
252 id: mascotImage; \n\
252 id: mascotImage; \n\
253 objectName: "mascotImage"; \n\
253 objectName: "mascotImage"; \n\
254 anchors { %1 } \n\
254 anchors { %1 } \n\
255− source: cardData && cardData["mascot"] || "%4"; \n\
255+ source: cardData && cardData["mascot"] || %4; \n\
256 width: units.gu(6); \n\
256 width: units.gu(6); \n\
257 height: units.gu(5.625); \n\
257 height: units.gu(5.625); \n\
258 horizontalAlignment: Image.AlignHCenter; \n\
258 horizontalAlignment: Image.AlignHCenter; \n\
@@ -376,27 +376,21 @@ var kAudioProgressBarCode = 'CardAudioProgress { \n\
376 color: %3; \n\
376 color: %3; \n\
379−function evil_param(object) {
379+function sanitizeColor(colorString) {
380− for (var x in object) {
380+ if (colorString !== undefined) {
381− if (typeof object[x] === "object" && evil_param(object[x]))
381+ if (colorString.match(/^[#a-z0-9]*$/i) === null) {
382− return true;
382+ // This is not the perfect regexp for color
383−
383+ // but what we're trying to do here is just protect
384− if (typeof object[x] === "string" && object[x].match(/"(?:[^"\\]|\\.)*"/) != null)
384+ // against injection so it's ok
385− return true;
385+ return "";
388− return false;
388+ return colorString;
391function cardString(template, components) {
391function cardString(template, components) {
392 var code;
392 var code;
394− if (evil_param(template))
397− if (evil_param(components))
400 var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
394 var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
402 code = 'AbstractButton { \n\
396 code = 'AbstractButton { \n\
@@ -445,18 +439,26 @@ function cardString(template, components) {
447 if (hasBackground) {
441 if (hasBackground) {
442+ var templateCardBackground;
448− var templateCardBackground = (template && typeof template["card-background"] === "string") ? template["card-background"] : "";
443+ if (template && typeof template["card-background"] === "string") {
444+ templateCardBackground = 'decodeURI("' + encodeURI(template["card-background"]) + '")';
446+ templateCardBackground = '""';
449 var backgroundElements0;
449 var backgroundElements0;
450 var backgroundElements1;
450 var backgroundElements1;
451 if (template && typeof template["card-background"] === "object" && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
451 if (template && typeof template["card-background"] === "object" && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
452− if (template["card-background"]["elements"][0] !== undefined) {
452+ var element0 = sanitizeColor(template["card-background"]["elements"][0]);
453+ var element1 = sanitizeColor(template["card-background"]["elements"][1]);
454+ if (element0 !== undefined) {
453− backgroundElements0 = '"%1"'.arg(template["card-background"]["elements"][0]);
455+ backgroundElements0 = '"%1"'.arg(element0);
455− if (template["card-background"]["elements"][1] !== undefined) {
457+ if (element1 !== undefined) {
456− backgroundElements1 = '"%1"'.arg(template["card-background"]["elements"][1]);
458+ backgroundElements1 = '"%1"'.arg(element1);
459− code += kBackgroundLoaderCode.arg(templateCardBackground).arg(backgroundElements0).arg(backgroundElements1);
461+ code += kBackgroundLoaderCode.arg(backgroundElements0).arg(backgroundElements1).arg(templateCardBackground);
462 if (hasArt) {
464 if (hasArt) {
@@ -482,11 +484,16 @@ function cardString(template, components) {
484 var fallback = components["art"] && components["art"]["fallback"] || "";
486 var fallback = components["art"] && components["art"]["fallback"] || "";
485− var fallbackCode = "";
487+ fallback = encodeURI(fallback);
488+ var fallbackStatusCode = "";
489+ var fallbackURICode = '""';
486 if (fallback !== "") {
490 if (fallback !== "") {
491+ // fallbackStatusCode has %5 in it because we want to substitute it for fallbackURICode
492+ // which in kArtShapeHolderCode is %5
487− fallbackCode += 'onStatusChanged: if (status === Image.Error) source = "%1";'.arg(fallback);
493+ fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %5;';
494+ fallbackURICode = 'decodeURI("%1")'.arg(fallback);
489− code += kArtShapeHolderCode.arg(artAnchors).arg(widthCode).arg(heightCode).arg(fallbackCode).arg(fallback);
496+ code += kArtShapeHolderCode.arg(artAnchors).arg(widthCode).arg(heightCode).arg(fallbackStatusCode).arg(fallbackURICode);
491 code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
498 code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
@@ -579,11 +586,16 @@ function cardString(template, components) {
580 var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
587 var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
581 var fallback = components["mascot"] && components["mascot"]["fallback"] || "";
588 var fallback = components["mascot"] && components["mascot"]["fallback"] || "";
582− var fallbackCode = "";
589+ fallback = encodeURI(fallback);
590+ var fallbackStatusCode = "";
591+ var fallbackURICode = '""';
583 if (fallback !== "") {
592 if (fallback !== "") {
593+ // fallbackStatusCode has %4 in it because we want to substitute it for fallbackURICode
594+ // which in kMascotImageCode is %4
584− fallbackCode += 'onStatusChanged: if (status === Image.Error) source = "%1";'.arg(fallback);
595+ fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %4;';
596+ fallbackURICode = 'decodeURI("%1")'.arg(fallback);
586− mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible).arg(fallbackCode).arg(fallback);
598+ mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible).arg(fallbackStatusCode).arg(fallbackURICode);
589 var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white")';
601 var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white")';