Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sanitize zoom sequence value #837

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/js/timeline/Timeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,9 @@ class Timeline {
// Set TimeNav Height
this.options.timenav_height = this._calculateTimeNavHeight(this.options.timenav_height);

// Sanitize zoom sequence
this.options.zoom_sequence = this._sanitizeZoomSequence(this.options.zoom_sequence);

// Create TimeNav
this._timenav = new TimeNav(this._el.timenav, this.config, this.options, this.language);
this._timenav.on('loaded', this._onTimeNavLoaded, this);
Expand Down Expand Up @@ -724,6 +727,51 @@ class Timeline {
return height;
}

/**
* Sanitize value of zoom sequence.
* Should be an array with numeric values or respective string or
* undefined if not set by author
* @param {number[]|string} [zoomSequence] - Values intended as possible zoom levels
* @returns {number[]} Sanitized array of possible zoom levels.
*/
_sanitizeZoomSequence(zoomSequence) {
// Ensure string contains proper number array representation
if (typeof zoomSequence === 'string') {
// Forgive spaces in URL fragment
zoomSequence = decodeURI(zoomSequence).replace(/\s/g, '');

const validRegExp = /^\[([0-9]*[.])?[0-9]+(,([0-9]*[.])?[0-9]+)*\]$/;
if (!validRegExp.test(zoomSequence)) {
return Timeline.DEFAULT_ZOOM_SEQUENCE; // Not valid string representation of array with numbers
}

zoomSequence = zoomSequence
.substring(1, zoomSequence.length - 1)
.split(',');
}

if (!Array.isArray(zoomSequence)) {
return Timeline.DEFAULT_ZOOM_SEQUENCE; // Nothing that we can work with
}

// Remove invalid values and sort in ascending order
zoomSequence = zoomSequence.reduce((valid, value) => {
const numberValue = Number.parseFloat(value);
if (
Number.isNaN(numberValue) ||
numberValue < 0 || // Zoom factor must be greater than zero
valid.includes(numberValue) // Duplicate
) {
return valid;
}

return [...valid, numberValue];
}, []);
zoomSequence.sort((a, b) => a - b);

return zoomSequence;
}

_validateOptions() {
// assumes that this.options and this.config have been set.
var INTEGER_PROPERTIES = ['timenav_height', 'timenav_height_min', 'marker_height_min', 'marker_width_min', 'marker_padding', 'start_at_slide', 'slide_padding_lr'];
Expand Down Expand Up @@ -1023,6 +1071,9 @@ class Timeline {

}

/** @const {number[]} DEFAULT_ZOOM_SEQUENCE Array of Fibonacci numbers for TimeNav zoom levels */
Timeline.DEFAULT_ZOOM_SEQUENCE = [0.5, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89];

classMixin(Timeline, I18NMixins, Events)

export { Timeline }