From afc90604bfad7ab5805873cb5bafc3bbb74c4b01 Mon Sep 17 00:00:00 2001 From: Charlie DeTar Date: Sat, 15 Sep 2012 17:48:04 -0400 Subject: [PATCH 1/3] Add `userColor` query param to set initial color Add a URL parameter which sets the initial color for a user, e.g.: http://example.com/p/mypad?userColor=%2300ff00 Sanitize the given color value to ensure that it's a valid css value (could be any supported CSS color format -- #fff, rgba(), "red", etc). Shortly after rejoining a pad, the server responds with a USER_NEWINFO message which may contain an old color value; however, this message arrives after we have set and sent the new color value to the server. To avoid this race condition, if the query parameter has been set, ignore the color value in a USER_NEWINFO message which matches our user ID. --- src/static/js/collab_client.js | 8 ++++++++ src/static/js/pad.js | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/static/js/collab_client.js b/src/static/js/collab_client.js index d149b256..b3e17c25 100644 --- a/src/static/js/collab_client.js +++ b/src/static/js/collab_client.js @@ -358,6 +358,14 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) { var userInfo = msg.userInfo; var id = userInfo.userId; + + // Avoid a race condition when setting colors. If our color was set by a + // query param, ignore our own "new user" message's color value. + if (id === initialUserInfo.userId && initialUserInfo.globalUserColor) + { + msg.userInfo.colorId = initialUserInfo.globalUserColor; + } + if (userSet[id]) { diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 737f5dc6..8f8e8729 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -114,6 +114,7 @@ function getParams() var showControls = params["showControls"]; var showChat = params["showChat"]; var userName = params["userName"]; + var userColor = params["userColor"]; var showLineNumbers = params["showLineNumbers"]; var useMonospaceFont = params["useMonospaceFont"]; var IsnoColors = params["noColors"]; @@ -162,6 +163,11 @@ function getParams() // If the username is set as a parameter we should set a global value that we can call once we have initiated the pad. settings.globalUserName = decodeURIComponent(userName); } + if(userColor) + // If the userColor is set as a parameter, set a global value to use once we have initiated hte pad. + { + settings.globalUserColor = decodeURIComponent(userColor); + } if(rtl) { if(rtl == "true") @@ -363,6 +369,24 @@ function handshake() pad.myUserInfo.name = settings.globalUserName; $('#myusernameedit').attr({"value":settings.globalUserName}); // Updates the current users UI } + if (settings.globalUserColor !== false) + { + // First, check the color to ensure it's a valid css color value. + var check = $("").css("background-color", "white"); + $("body").append(check); + var white = check.css("background-color"); + check.css("background-color", settings.globalUserColor); + // Ensure that setting the element changed the color. + if (check.css("background-color") === white) { + settings.globalUserColor = "#ff0000"; + } + check.remove(); + + // Add a 'globalUserColor' property to myUserInfo, so collabClient knows we have a query parameter. + pad.myUserInfo.globalUserColor = settings.globalUserColor; + pad.notifyChangeColor(settings.globalUserColor); // Updates pad.myUserInfo.colorId + paduserlist.setMyUserInfo(pad.myUserInfo); + } } //This handles every Message after the clientVars else @@ -1025,6 +1049,7 @@ var settings = { , noColors: false , useMonospaceFontGlobal: false , globalUserName: false +, globalUserColor: false , rtlIsTrue: false }; From bc6e495e8c691a3e3ce047b1dbe8ba600ef49eef Mon Sep 17 00:00:00 2001 From: Charlie DeTar Date: Mon, 17 Sep 2012 00:19:57 -0400 Subject: [PATCH 2/3] Use 'transparent' as reference to validate css Use 'transparent' instead of 'white' as a reference color for validating CSS color values. Presumably, a user setting a userColor wants some color other than 'transparent' if they are setting it (they could always duplicate the background's color if not). --- src/static/js/pad.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 8f8e8729..3e2663c8 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -164,7 +164,7 @@ function getParams() settings.globalUserName = decodeURIComponent(userName); } if(userColor) - // If the userColor is set as a parameter, set a global value to use once we have initiated hte pad. + // If the userColor is set as a parameter, set a global value to use once we have initiated the pad. { settings.globalUserColor = decodeURIComponent(userColor); } @@ -372,12 +372,12 @@ function handshake() if (settings.globalUserColor !== false) { // First, check the color to ensure it's a valid css color value. - var check = $("").css("background-color", "white"); + var check = $("").css("background-color", "transparent"); $("body").append(check); - var white = check.css("background-color"); + var transparent = check.css("background-color"); check.css("background-color", settings.globalUserColor); // Ensure that setting the element changed the color. - if (check.css("background-color") === white) { + if (check.css("background-color") === transparent) { settings.globalUserColor = "#ff0000"; } check.remove(); From 53113644a0464929316be67ea878d47d13714aba Mon Sep 17 00:00:00 2001 From: Charlie DeTar Date: Mon, 17 Sep 2012 10:59:12 -0400 Subject: [PATCH 3/3] Require userColor to be valid css hex The utility functions colorutils.js assume that background colors are in CSS hex format, so require userColor to do the same, rather than allowing inputs like "red" and "rgba(...)", to insure that inversion checks will succeed. --- src/static/js/colorutils.js | 7 +++++++ src/static/js/pad.js | 13 ++----------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/static/js/colorutils.js b/src/static/js/colorutils.js index 5fbefb4d..74a2e463 100644 --- a/src/static/js/colorutils.js +++ b/src/static/js/colorutils.js @@ -24,6 +24,13 @@ var colorutils = {}; +// Check that a given value is a css hex color value, e.g. +// "#ffffff" or "#fff" +colorutils.isCssHex = function(cssColor) +{ + return /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(cssColor); +} + // "#ffffff" or "#fff" or "ffffff" or "fff" to [1.0, 1.0, 1.0] colorutils.css2triple = function(cssColor) { diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 3e2663c8..21dea440 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -43,6 +43,7 @@ var padmodals = require('./pad_modals').padmodals; var padsavedrevs = require('./pad_savedrevs'); var paduserlist = require('./pad_userlist').paduserlist; var padutils = require('./pad_utils').padutils; +var colorutils = require('./colorutils').colorutils; var createCookie = require('./pad_utils').createCookie; var readCookie = require('./pad_utils').readCookie; @@ -369,18 +370,8 @@ function handshake() pad.myUserInfo.name = settings.globalUserName; $('#myusernameedit').attr({"value":settings.globalUserName}); // Updates the current users UI } - if (settings.globalUserColor !== false) + if (settings.globalUserColor !== false && colorutils.isCssHex(settings.globalUserColor)) { - // First, check the color to ensure it's a valid css color value. - var check = $("").css("background-color", "transparent"); - $("body").append(check); - var transparent = check.css("background-color"); - check.css("background-color", settings.globalUserColor); - // Ensure that setting the element changed the color. - if (check.css("background-color") === transparent) { - settings.globalUserColor = "#ff0000"; - } - check.remove(); // Add a 'globalUserColor' property to myUserInfo, so collabClient knows we have a query parameter. pad.myUserInfo.globalUserColor = settings.globalUserColor;