Fix Issue 770: Trouncing the nonce. Restructured how random ids are produced. Updated how new documents are created.

git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1962 eee81c28-f429-11dd-99c0-75d572ba1ddd
master
Jeff Schiller 2011-02-01 07:22:18 +00:00
parent 846ee8eca1
commit 9c8ba2361f
4 changed files with 124 additions and 104 deletions

View File

@ -21,6 +21,9 @@ if (!svgedit.draw) {
var svg_ns = "http://www.w3.org/2000/svg";
var se_ns = "http://svg-edit.googlecode.com";
var xmlns_ns = "http://www.w3.org/2000/xmlns/";
var randomize_ids = false;
/**
* This class encapsulates the concept of a layer in the drawing
@ -41,6 +44,12 @@ svgedit.draw.Layer.prototype.getGroup = function() {
};
// Called to ensure that drawings will or will not have
// randomized ids.
svgedit.draw.randomizeIds = function(enableRandomization) {
randomize_ids = enableRandomization;
};
/**
* This class encapsulates the concept of a SVG-edit drawing
*
@ -99,7 +108,17 @@ svgedit.draw.Drawing = function(svgElem, opt_idPrefix) {
* The nonce to use to uniquely identify elements across drawings.
* @type {!String}
*/
this.nonce_ = this.svgElem_.getAttributeNS(se_ns, 'nonce') || "";
this.nonce_ = "";
var n = this.svgElem_.getAttributeNS(se_ns, 'nonce');
// If already set in the DOM, use the nonce throughout the document
// else, if randomizeIds(true) has been called, create and set the nonce.
if (!!n) {
this.nonce_ = n;
} else if (randomize_ids) {
this.nonce_ = Math.floor(Math.random() * 100001);
this.svgElem_.setAttributeNS(xmlns_ns, 'xmlns:se', se_ns);
this.svgElem_.setAttributeNS(se_ns, 'se:nonce', this.nonce_);
}
};
svgedit.draw.Drawing.prototype.getElem_ = function(id) {

View File

@ -15,8 +15,8 @@ svgEditor.addExtension("Arrows", function(S) {
randomize_ids = S.randomize_ids,
selElems;
svgCanvas.bind('setarrownonce', setArrowNonce);
svgCanvas.bind('unsetsetarrownonce', unsetArrowNonce);
svgCanvas.bind('setnonce', setArrowNonce);
svgCanvas.bind('unsetnonce', unsetArrowNonce);
var lang_list = {
"en":[

View File

@ -151,6 +151,11 @@ container.appendChild(svgroot);
// The actual element that represents the final output SVG element
var svgcontent = svgdoc.createElementNS(svgns, "svg");
// This function resets the svgcontent element while keeping it in the DOM.
var clearSvgContentElement = canvas.clearSvgContentElement = function() {
while (svgcontent.firstChild) { svgcontent.removeChild(svgcontent.firstChild); }
// TODO: Clear out all other attributes first?
$(svgcontent).attr({
id: 'svgcontent',
width: dimensions[0],
@ -163,6 +168,12 @@ $(svgcontent).attr({
"xmlns:xlink": xlinkns
}).appendTo(svgroot);
// TODO: make this string optional and set by the client
var comment = svgdoc.createComment(" Created with SVG-edit - http://svg-edit.googlecode.com/ ");
svgcontent.appendChild(comment);
};
clearSvgContentElement();
// Prefix string for element IDs
var idprefix = "svg_";
@ -175,24 +186,15 @@ canvas.setIdPrefix = function(p) {
idprefix = p;
};
// nonce to uniquify id's
var nonce = Math.floor(Math.random() * 100001);
// Boolean to indicate whether or not IDs given to elements should be random
var randomize_ids = false;
// Set nonce if randomize_ids = true
if (randomize_ids) svgcontent.setAttributeNS(se_ns, 'se:nonce', nonce);
// Current svgedit.draw.Drawing object
// @type {svgedit.draw.Drawing}
var current_drawing = new svgedit.draw.Drawing(svgcontent, idprefix);
canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent, idprefix);
// Function: getCurrentDrawing
// Returns the current Drawing.
// @return {svgedit.draw.Drawing}
var getCurrentDrawing = canvas.getCurrentDrawing = function() {
return current_drawing;
return canvas.current_drawing_;
};
// Float displaying the current zoom level (1 = 100%, .5 = 50%, etc)
@ -524,10 +526,6 @@ var restoreRefElems = function(elem) {
};
(function() {
// TODO: make this string optional and set by the client
var comment = svgdoc.createComment(" Created with SVG-edit - http://svg-edit.googlecode.com/ ");
svgcontent.appendChild(comment);
// TODO For Issue 208: this is a start on a thumbnail
// var svgthumb = svgdoc.createElementNS(svgns, "use");
// svgthumb.setAttribute('width', '100');
@ -624,7 +622,7 @@ this.addExtension = function(name, ext_func) {
var ext = ext_func($.extend(canvas.getPrivateMethods(), {
svgroot: svgroot,
svgcontent: svgcontent,
nonce: nonce,
nonce: getCurrentDrawing().getNonce(),
selectorManager: selectorManager
}));
} else {
@ -6346,9 +6344,9 @@ this.getSvgString = function() {
return this.svgCanvasToString();
};
//function randomizeIds
// This function determines whether to add a nonce to the prefix, when
// generating IDs in SVG-Edit
// Function: randomizeIds
// This function determines whether to use a nonce in the prefix, when
// generating IDs for future documents in SVG-Edit.
//
// Parameters:
// an opional boolean, which, if true, adds a nonce to the prefix. Thus
@ -6359,16 +6357,11 @@ this.getSvgString = function() {
//
this.randomizeIds = function() {
if (arguments.length > 0 && arguments[0] == false) {
randomize_ids = false;
if (extensions["Arrows"]) call("unsetarrownonce") ;
svgedit.draw.randomizeIds(false);
} else {
randomize_ids = true;
if (!svgcontent.getAttributeNS(se_ns, 'nonce')) {
svgcontent.setAttributeNS(se_ns, 'se:nonce', nonce);
if (extensions["Arrows"]) call("setarrownonce", nonce) ;
}
}
svgedit.draw.randomizeIds(true);
}
};
// Function: uniquifyElems
// Ensure each element has a unique ID
@ -6701,19 +6694,15 @@ this.setSvgString = function(xmlString) {
var content = $(svgcontent);
// retrieve or set the nonce
n = svgcontent.getAttributeNS(se_ns, 'nonce');
if (n) {
randomize_ids = true;
nonce = n;
if (extensions["Arrows"]) call("setarrownonce", n) ;
} else if (randomize_ids) {
svgcontent.setAttributeNS(xmlnsns, 'xmlns:se', se_ns);
svgcontent.setAttributeNS(se_ns, 'se:nonce', nonce);
if (extensions["Arrows"]) call("setarrownonce", nonce) ;
}
canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent, idprefix);
current_drawing = new svgedit.draw.Drawing(svgcontent, idprefix);
// retrieve or set the nonce
var nonce = getCurrentDrawing().getNonce();
if (nonce) {
call("setnonce", nonce);
} else {
call("unsetnonce");
}
// change image href vals if possible
content.find('image').each(function() {
@ -7038,10 +7027,10 @@ this.cloneLayer = function(name) {
// Deletes the current layer from the drawing and then clears the selection. This function
// then calls the 'changed' handler. This is an undoable action.
this.deleteCurrentLayer = function() {
var current_layer = current_drawing.getCurrentLayer();
var current_layer = getCurrentDrawing().getCurrentLayer();
var nextSibling = current_layer.nextSibling;
var parent = current_layer.parentNode;
current_layer = current_drawing.deleteCurrentLayer();
current_layer = getCurrentDrawing().deleteCurrentLayer();
if (current_layer) {
var batchCmd = new BatchCommand("Delete Layer");
// store in our Undo History
@ -7082,18 +7071,19 @@ this.setCurrentLayer = function(name) {
// Returns:
// true if the rename succeeded, false otherwise.
this.renameCurrentLayer = function(newname) {
if (current_drawing.current_layer) {
var oldLayer = current_drawing.current_layer;
var drawing = getCurrentDrawing();
if (drawing.current_layer) {
var oldLayer = drawing.current_layer;
// setCurrentLayer will return false if the name doesn't already exist
// this means we are free to rename our oldLayer
if (!canvas.setCurrentLayer(newname)) {
var batchCmd = new BatchCommand("Rename Layer");
// find the index of the layer
for (var i = 0; i < current_drawing.getNumLayers(); ++i) {
if (current_drawing.all_layers[i][1] == oldLayer) break;
for (var i = 0; i < drawing.getNumLayers(); ++i) {
if (drawing.all_layers[i][1] == oldLayer) break;
}
var oldname = current_drawing.getLayerName(i);
current_drawing.all_layers[i][0] = svgedit.utilities.toXml(newname);
var oldname = drawing.getLayerName(i);
drawing.all_layers[i][0] = svgedit.utilities.toXml(newname);
// now change the underlying title element contents
var len = oldLayer.childNodes.length;
@ -7112,7 +7102,7 @@ this.renameCurrentLayer = function(newname) {
}
}
}
current_drawing.current_layer = oldLayer;
drawing.current_layer = oldLayer;
}
return false;
};
@ -7129,31 +7119,32 @@ this.renameCurrentLayer = function(newname) {
// Returns:
// true if the current layer position was changed, false otherwise.
this.setCurrentLayerPosition = function(newpos) {
if (current_drawing.current_layer && newpos >= 0 && newpos < current_drawing.getNumLayers()) {
for (var oldpos = 0; oldpos < current_drawing.getNumLayers(); ++oldpos) {
if (current_drawing.all_layers[oldpos][1] == current_drawing.current_layer) break;
var drawing = getCurrentDrawing();
if (drawing.current_layer && newpos >= 0 && newpos < drawing.getNumLayers()) {
for (var oldpos = 0; oldpos < drawing.getNumLayers(); ++oldpos) {
if (drawing.all_layers[oldpos][1] == drawing.current_layer) break;
}
// some unknown error condition (current_layer not in all_layers)
if (oldpos == current_drawing.getNumLayers()) { return false; }
if (oldpos == drawing.getNumLayers()) { return false; }
if (oldpos != newpos) {
// if our new position is below us, we need to insert before the node after newpos
var refLayer = null;
var oldNextSibling = current_drawing.current_layer.nextSibling;
var oldNextSibling = drawing.current_layer.nextSibling;
if (newpos > oldpos ) {
if (newpos < current_drawing.getNumLayers()-1) {
refLayer = current_drawing.all_layers[newpos+1][1];
if (newpos < drawing.getNumLayers()-1) {
refLayer = drawing.all_layers[newpos+1][1];
}
}
// if our new position is above us, we need to insert before the node at newpos
else {
refLayer = current_drawing.all_layers[newpos][1];
refLayer = drawing.all_layers[newpos][1];
}
svgcontent.insertBefore(current_drawing.current_layer, refLayer);
addCommandToHistory(new MoveElementCommand(current_drawing.current_layer, oldNextSibling, svgcontent));
svgcontent.insertBefore(drawing.current_layer, refLayer);
addCommandToHistory(new MoveElementCommand(drawing.current_layer, oldNextSibling, svgcontent));
identifyLayers();
canvas.setCurrentLayer(current_drawing.getLayerName(newpos));
canvas.setCurrentLayer(drawing.getLayerName(newpos));
return true;
}
@ -7203,9 +7194,10 @@ this.setLayerVisibility = function(layername, bVisible) {
this.moveSelectedToLayer = function(layername) {
// find the layer
var layer = null;
for (var i = 0; i < current_drawing.getNumLayers(); ++i) {
if (current_drawing.getLayerName(i) == layername) {
layer = current_drawing.all_layers[i][1];
var drawing = getCurrentDrawing();
for (var i = 0; i < drawing.getNumLayers(); ++i) {
if (drawing.getLayerName(i) == layername) {
layer = drawing.all_layers[i][1];
break;
}
}
@ -7233,28 +7225,29 @@ this.moveSelectedToLayer = function(layername) {
this.mergeLayer = function(skipHistory) {
var batchCmd = new BatchCommand("Merge Layer");
var prev = $(current_drawing.current_layer).prev()[0];
var drawing = getCurrentDrawing();
var prev = $(drawing.current_layer).prev()[0];
if(!prev) return;
var childs = current_drawing.current_layer.childNodes;
var childs = drawing.current_layer.childNodes;
var len = childs.length;
var layerNextSibling = current_drawing.current_layer.nextSibling;
batchCmd.addSubCommand(new RemoveElementCommand(current_drawing.current_layer, layerNextSibling, svgcontent));
var layerNextSibling = drawing.current_layer.nextSibling;
batchCmd.addSubCommand(new RemoveElementCommand(drawing.current_layer, layerNextSibling, svgcontent));
while(current_drawing.current_layer.firstChild) {
var ch = current_drawing.current_layer.firstChild;
while(drawing.current_layer.firstChild) {
var ch = drawing.current_layer.firstChild;
if(ch.localName == 'title') {
var chNextSibling = ch.nextSibling;
batchCmd.addSubCommand(new RemoveElementCommand(ch, chNextSibling, current_drawing.current_layer));
current_drawing.current_layer.removeChild(ch);
batchCmd.addSubCommand(new RemoveElementCommand(ch, chNextSibling, drawing.current_layer));
drawing.current_layer.removeChild(ch);
continue;
}
var oldNextSibling = ch.nextSibling;
prev.appendChild(ch);
batchCmd.addSubCommand(new MoveElementCommand(ch, oldNextSibling, current_drawing.current_layer));
batchCmd.addSubCommand(new MoveElementCommand(ch, oldNextSibling, drawing.current_layer));
}
// Remove current layer
svgcontent.removeChild(current_drawing.current_layer);
svgcontent.removeChild(drawing.current_layer);
if(!skipHistory) {
clearSelection();
@ -7265,13 +7258,14 @@ this.mergeLayer = function(skipHistory) {
addCommandToHistory(batchCmd);
}
current_drawing.current_layer = prev;
drawing.current_layer = prev;
return batchCmd;
}
this.mergeAllLayers = function() {
var batchCmd = new BatchCommand("Merge all Layers");
current_drawing.current_layer = current_drawing.all_layers[current_drawing.getNumLayers()-1][1];
var drawing = getCurrentDrawing();
drawing.current_layer = drawing.all_layers[drawing.getNumLayers()-1][1];
while($(svgcontent).children('g').length > 1) {
batchCmd.addSubCommand(canvas.mergeLayer(true));
}
@ -7339,28 +7333,23 @@ this.clear = function() {
pathActions.clear();
// clear the svgcontent node
var nodes = svgcontent.childNodes;
var len = svgcontent.childNodes.length;
var i = 0;
clearSelection();
for(var rep = 0; rep < len; rep++){
if (nodes[i].nodeType == 1) { // element node
svgcontent.removeChild(nodes[i]);
} else {
i++;
}
}
// create empty first layer
current_drawing.all_layers = [];
canvas.clearSvgContentElement();
// create new document
canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent);
// create empty first layer
canvas.createLayer("Layer 1");
// clear the undo stack
canvas.undoMgr.resetUndoStack();
// reset the selector manager
selectorManager.initGroup();
// reset the rubber band box
rubberBox = selectorManager.getRubberBandBox();
call("cleared");
};

View File

@ -480,6 +480,18 @@
equals(drawing.getCurrentLayer(), drawing.all_layers[1][1]);
});
test('Test svgedit.draw.randomizeIds()', function() {
expect(2);
svgedit.draw.randomizeIds(true);
var drawing = new svgedit.draw.Drawing(svg.cloneNode(true));
ok(!!drawing.getNonce());
svgedit.draw.randomizeIds(false);
var drawing = new svgedit.draw.Drawing(svg);
ok(!drawing.getNonce());
});
});
</script>
</head>