Issues (61)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

js/slideshowcontrols.js (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
/* global OC, SlideShow */
2
(function ($, SlideShow) {
3
	"use strict";
4
	/**
5
	 * Button and key controls for the slideshow
6
	 *
7
	 * @param {Object} slideshow
8
	 * @param {*} container
9
	 * @param {Object} zoomablePreview
10
	 * @param {number} interval
11
	 * @param {Array} features
12
	 * @constructor
13
	 */
14
	var Controls = function (slideshow, container, zoomablePreview, interval, features) {
15
		this.slideshow = slideshow;
16
		this.container = container;
17
		this.zoomablePreview = zoomablePreview;
18
		this.progressBar = container.find('.progress');
19
		this.interval = interval || 5000;
20
		if (features.indexOf('background_colour_toggle') > -1) {
21
			this.backgroundToggle = true;
22
		}
23
	};
24
25
	Controls.prototype = {
26
		current: 0,
27
		errorLoadingImage: false,
28
		playTimeout: 0,
29
		playing: false,
30
		active: false,
31
		backgroundToggle: false,
32
33
		/**
34
		 * Initialises the controls
35
		 */
36
		init: function () {
37
			var makeCallBack = function (handler) {
38
				return function (evt) {
39
					if (!this.active) {
40
						return;
41
					}
42
					evt.stopPropagation();
43
					evt.preventDefault();
44
					handler.call(this);
45
				}.bind(this);
46
			}.bind(this);
47
48
			this._buttonSetup(makeCallBack);
49
			this._specialButtonSetup(makeCallBack);
50
			this._keyCodeSetup(makeCallBack);
51
		},
52
53
		/**
54
		 * Updates the controls
55
		 *
56
		 * @param {{name:string, url: string, path: string, fallBack: string}[]} images
57
		 * @param {boolean} autoPlay
58
		 */
59
		update: function (images, autoPlay) {
60
			this.images = images;
61
			this.active = true;
62
			this.showButton('.play');
63
			this.hideButton('.pause, .progress');
64
			this.playing = false;
65
66
			// Hide prev/next and play buttons when we only have one pic
67
			this.container.find('.next, .previous, .play').toggle(this.images.length > 1);
68
69
			// Hide the action buttons until we have something to show
70
			this.hideActionButtons();
71
72
			if (autoPlay) {
73
				this._playPauseToggle();
74
			}
75
		},
76
77
		/**
78
		 * Initialises local variables when the show starts
79
		 *
80
		 * @param {number} currentImageId
81
		 */
82
		show: function (currentImageId) {
83
			var currentImage = this.images[currentImageId];
84
			this.current = currentImageId;
85
			this.errorLoadingImage = false;
86
			if (this.playing) {
87
				this._setTimeout();
88
			}
89
			this._setName(currentImage.name);
90
		},
91
92
		/**
93
		 * Stops and hides the slideshow
94
		 */
95
		stop: function () {
96
			this._setName('');
97
			this.playing = false;
98
			this.slideshow.stop();
99
			this.zoomablePreview.stop();
100
101
			this._clearTimeout();
102
			this.container.hide();
103
			this.active = false;
104
		},
105
106
		/**
107
		 * Updates the private variables in case of problems loading an image
108
		 *
109
		 * @param {Array} images
110
		 * @param {boolean} errorLoadingImage
111
		 */
112
		updateControls: function (images, errorLoadingImage) {
113
			this.images = images;
114
			this.errorLoadingImage = errorLoadingImage;
115
		},
116
117
		/**
118
		 * Shows the action buttons
119
		 *
120
		 * @param {boolean} transparent
121
		 * @param {boolean} isPublic
122
		 * @param {number} permissions
123
		 */
124
		showActionButtons: function (transparent, isPublic, permissions) {
125
			if (transparent) {
126
				this._showBackgroundToggle();
127
			}
128
			this.showButton('.downloadImage');
129
			var canDelete = ((permissions & OC.PERMISSION_DELETE) !== 0);
130
			if (!isPublic && canDelete) {
131
				this.showButton('.deleteImage');
132
			}
133
		},
134
135
		/**
136
		 * Hides the action buttons
137
		 */
138
		hideActionButtons: function () {
139
			this.hideButton('.changeBackground');
140
			this.hideButton('.downloadImage');
141
			this.hideButton('.deleteImage');
142
		},
143
144
		/**
145
		 * Shows a button which has been hidden
146
		 */
147
		showButton: function (button) {
148
			this.container.find(button).removeClass('hidden');
149
		},
150
151
		/**
152
		 * Hides a button
153
		 *
154
		 * @param button
155
		 */
156
		hideButton: function (button) {
157
			this.container.find(button).addClass('hidden');
158
		},
159
160
		/**
161
		 * Removes a button
162
		 *
163
		 * @param button
164
		 */
165
		removeButton: function (button) {
166
			this.container.find(button).remove();
167
		},
168
169
		/**
170
		 * Sets up the button based navigation
171
		 *
172
		 * @param {Function} makeCallBack
173
		 * @private
174
		 */
175
		_buttonSetup: function (makeCallBack) {
176
			this.container.children('.next').click(makeCallBack(this._next));
177
			this.container.children('.previous').click(makeCallBack(this._previous));
178
			this.container.children('.exit').click(makeCallBack(this._exit));
179
			this.container.children('.pause, .play').click(makeCallBack(this._playPauseToggle));
180
			this.progressBar.click(makeCallBack(this._playPauseToggle));
181
			this.container.children('.previous, .next, .menu, .name').on(
182
				'mousewheel DOMMouseScroll mousemove', function (evn) {
183
					this.container.children('.bigshotContainer')[0].dispatchEvent(
184
						new WheelEvent(evn.originalEvent.type, evn.originalEvent));
185
				}.bind(this));
186
		},
187
188
		/**
189
		 * Sets up additional buttons
190
		 *
191
		 * @param {Function} makeCallBack
192
		 * @private
193
		 */
194
		_specialButtonSetup: function (makeCallBack) {
195
			this.container.find('.downloadImage').click(makeCallBack(this._getImageDownload));
196
			this.container.find('.deleteImage').click(makeCallBack(this._deleteImage));
197
			this.container.find('.menu').width = 52;
198
			if (this.backgroundToggle) {
199
				this.container.find('.changeBackground').click(
200
					makeCallBack(this._toggleBackground));
201
				this.container.find('.menu').width += 52;
202
			} else {
203
				this.hideButton('.changeBackground');
204
			}
205
206
207
		},
208
209
		/**
210
		 * Shows the background colour switcher, if activated in the configuration
211
		 */
212
		_showBackgroundToggle: function () {
213
			if (this.backgroundToggle) {
214
				this.showButton('.changeBackground');
215
			}
216
		},
217
218
		/**
219
		 * Sets up the key based controls
220
		 *
221
		 * @param {Function} makeCallBack
222
		 * @private
223
		 */
224
		_keyCodeSetup: function (makeCallBack) {
225
			$(document).keyup(function (evt) {
226
				var escKey = 27;
227
				var leftKey = 37;
228
				var rightKey = 39;
229
				var spaceKey = 32;
230
				var fKey = 70;
231
				var zoomOutKeys = [48, 96, 79, 40]; // zero, o or down key
232
				var zoomInKeys = [57, 105, 73, 38]; // 9, i or up key
233
				if (evt.keyCode === escKey) {
234
					makeCallBack(this._exit)(evt);
235
				} else if (evt.keyCode === leftKey) {
236
					makeCallBack(this._previous)(evt);
237
				} else if (evt.keyCode === rightKey) {
238
					makeCallBack(this._next)(evt);
239
				} else if (evt.keyCode === spaceKey) {
240
					makeCallBack(this._playPauseToggle)(evt);
241
				} else if (evt.keyCode === fKey) {
242
					makeCallBack(this._fullScreenToggle)(evt);
243
				} else if (this._hasKeyBeenPressed(evt, zoomOutKeys)) {
244
					makeCallBack(this._zoomToOriginal)(evt);
245
				} else if (this._hasKeyBeenPressed(evt, zoomInKeys)) {
246
					makeCallBack(this._zoomToFit)(evt);
247
				}
248
			}.bind(this));
249
		},
250
251
		/**
252
		 * Determines if a key has been pressed by comparing the event and the key
253
		 *
254
		 * @param evt
255
		 * @param {Array} keys
256
		 *
257
		 * @returns {boolean}
258
		 * @private
259
		 */
260
		_hasKeyBeenPressed: function (evt, keys) {
261
			var i, keysLength = keys.length;
262
			for (i = 0; i < keysLength; i++) {
263
				if (evt.keyCode === keys[i]) {
264
					return true;
265
				}
266
			}
267
			return false;
268
		},
269
270
		/**
271
		 * Starts the slideshow timer
272
		 *
273
		 * @private
274
		 */
275
		_setTimeout: function () {
276
			this._clearTimeout();
277
			this.playTimeout = setTimeout(this._next.bind(this), this.interval);
278
			this.progressBar.stop();
279
			this.progressBar.css('height', '6px');
280
			this.progressBar.animate({'height': '26px'}, this.interval, 'linear');
281
		},
282
283
		/**
284
		 * Stops the slideshow timer
285
		 *
286
		 * @private
287
		 */
288
		_clearTimeout: function () {
289
			if (this.playTimeout) {
290
				clearTimeout(this.playTimeout);
291
			}
292
			this.progressBar.stop();
293
			this.progressBar.css('height', '6px');
294
			this.playTimeout = 0;
295
		},
296
297
		/**
298
		 * Starts/stops autoplay and shows/hides the play/pause buttons
299
		 *
300
		 * @private
301
		 */
302
		_playPauseToggle: function () {
303
			if (this.playing === true) {
304
				this.playing = false;
305
				this._clearTimeout();
306
			} else {
307
				this.playing = true;
308
				this._setTimeout();
309
			}
310
311
			this.container.find('.play, .pause, .progress').toggleClass('hidden');
312
		},
313
314
		/**
315
		 * Shows the next slide
316
		 *
317
		 * @private
318
		 */
319
		_next: function () {
320
			this._setName('');
321
			this.slideshow.hideErrorNotification();
322
			this.zoomablePreview.reset();
323
324
			if (this.errorLoadingImage) {
325
				this.current -= 1;
326
			}
327
			this.current = (this.current + 1) % this.images.length;
328
			var next = (this.current + 1) % this.images.length;
329
			this._updateSlideshow(next);
330
		},
331
332
		/**
333
		 * Shows the previous slide
334
		 *
335
		 * @private
336
		 */
337
		_previous: function () {
338
			this._setName('');
339
			this.slideshow.hideErrorNotification();
340
			this.zoomablePreview.reset();
341
342
			this.current = (this.current - 1 + this.images.length) % this.images.length;
343
			var previous = (this.current - 1 + this.images.length) % this.images.length;
344
			this._updateSlideshow(previous);
345
		},
346
347
		/**
348
		 * Asks the slideshow for the next image
349
		 *
350
		 * @param {number} imageId
351
		 * @private
352
		 */
353
		_updateSlideshow: function (imageId) {
354
			this.slideshow.next(this.current, this.images[imageId]);
355
		},
356
357
		/**
358
		 * Exits the slideshow by going back in history
359
		 *
360
		 * @private
361
		 */
362
		_exit: function () {
363
364
			// Only modern browsers can manipulate history
365
			if (history && history.replaceState) {
0 ignored issues
show
If you intend to check if the variable history is declared in the current environment, consider using typeof history === "undefined" instead. This is safe if the variable is not actually declared.
Loading history...
366
				// We simulate a click on the back button in order to be consistent
367
				window.history.back();
368
			} else {
369
				// For ancient browsers supported in core
370
				this.stop();
371
			}
372
		},
373
374
		/**
375
		 * Launches fullscreen mode if the browser supports it
376
		 *
377
		 * @private
378
		 */
379
		_fullScreenToggle: function () {
380
			this.zoomablePreview.fullScreenToggle();
381
		},
382
383
		/**
384
		 * Resizes the image to its original size
385
		 *
386
		 * @private
387
		 */
388
		_zoomToOriginal: function () {
389
			this.zoomablePreview.zoomToOriginal();
390
		},
391
392
		/**
393
		 * Fits the image in the browser window
394
		 *
395
		 * @private
396
		 */
397
		_zoomToFit: function () {
398
			this.zoomablePreview.zoomToFit();
399
		},
400
401
		/**
402
		 * Sends the current image as a download
403
		 *
404
		 * @returns {boolean}
405
		 * @private
406
		 */
407
		_getImageDownload: function () {
408
			var downloadUrl = this.images[this.current].downloadUrl;
409
410
			return this.slideshow.getImageDownload(downloadUrl);
411
		},
412
413
		/**
414
		 * Changes the colour of the background of the image
415
		 *
416
		 * @private
417
		 */
418
		_toggleBackground: function () {
419
			this.slideshow.toggleBackground();
420
		},
421
422
		/**
423
		 * Shows the filename of the current image
424
		 * @param {string} imageName
425
		 * @private
426
		 */
427
		_setName: function (imageName) {
428
			var nameElement = this.container.find('.title');
429
			nameElement.text(imageName);
430
		},
431
432
		/**
433
		 * Delete the image from the slideshow
434
		 * @private
435
		 */
436
		_deleteImage: function () {
437
			var image = this.images[this.current];
438
			var self = this;
439
			$.ajax({
440
				type: 'DELETE',
441
				url: OC.getRootPath() + '/remote.php/webdav/' + image.path,
442
				success: function () {
443
					self.slideshow.deleteImage(image, self.current);
444
					self.images.splice(self.current, 1);
445
					if (self.images.length === 0) {
446
						self._exit();
447
					}
448
					else {
449
						self.current = self.current % self.images.length;
450
						self._updateSlideshow(self.current);
451
					}
452
				}
453
			});
454
		}
455
	};
456
457
	SlideShow.Controls = Controls;
458
})(jQuery, SlideShow);
459