Completed
Pull Request — master (#315)
by
unknown
02:46
created

Utility.sortBy   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
/**
2
 * Nextcloud - Gallery
3
 *
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Olivier Paroz <[email protected]>
9
 *
10
 * @copyright Olivier Paroz 2017
11
 */
12
/* global DOMPurify, oc_requesttoken, Gallery */
13
14
// The Utility class can also be loaded by the Files app
15
window.Gallery = window.Gallery || {};
16
17
(function ($, OC, t, oc_requesttoken, Gallery) {
0 ignored issues
show
Coding Style introduced by
Identifier 'oc_requesttoken' is not in camel case.
Loading history...
18
	"use strict";
19
	/**
20
	 * Contains utility methods
21
	 *
22
	 * @fixme OC.generateUrl, OC.buildQueryString, OC.Notification are private APIs
23
	 *
24
	 * @constructor
25
	 */
26
	var Utility = function () {
27
	};
28
29
	Utility.prototype = {
30
		/**
31
		 * Detects if the browser is a recent or an old version of Internet Explorer
32
		 *
33
		 * @returns {string|boolean}
34
		 */
35
		getIeVersion: function () {
36
			// Blocking IE8
37
			if ($('html').is('.ie8')) {
38
				return 'unsupportedIe';
39
			} else if (navigator.userAgent.indexOf("MSIE") > 0) {
0 ignored issues
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
40
				return 'unsupportedIe';
41
			} else if (!!navigator.userAgent.match(/Trident.*rv[ :]*11\./)) {
42
				return 'modernIe';
43
			} else if (navigator.userAgent.indexOf("Edge/") > 0) {
44
				return 'edge';
45
			}
46
47
			return false;
48
		},
49
50
		/**
51
		 * Shows a notification to IE users, letting them know that they should use another browser
52
		 * in order to get the best experience
53
		 *
54
		 * @param {string} version
55
		 */
56
		showIeWarning: function (version) {
57
			var line1 = t('gallery', 'This application may not work properly on your browser.');
58
			var line2 = t('gallery',
59
				'For an improved experience, please install one of the following alternatives');
60
			var timeout = 15;
61
			if (version === 'unsupportedIe') {
62
				line1 = t('gallery', 'Your browser is not supported!');
63
				line2 = t('gallery', 'please install one of the following alternatives');
64
				timeout = 60;
65
			}
66
67
			var recommendedBrowsers = '</br>' +
68
				'<a href="http://www.getfirefox.com"><strong>Mozilla Firefox</strong></a> or ' +
69
				'<a href="https://www.google.com/chrome/"><strong>Google Chrome</strong></a>' +
70
				'</br>';
71
72
			var text = '<strong>' + line1 + '</strong></br>' + line2 + recommendedBrowsers;
73
			this.showHtmlNotification(text, timeout);
74
		},
75
76
		/**
77
		 * Shows a notification at the top of the screen
78
		 *
79
		 * @param {string} text
80
		 * @param {int} timeout
81
		 */
82
		showHtmlNotification: function (text, timeout) {
83
			var options = {
84
				timeout: timeout,
85
				isHTML: true
86
			};
87
			OC.Notification.showTemporary(text, options);
88
		},
89
90
		/**
91
		 * Returns the token allowing access to files shared via link
92
		 *
93
		 * @returns {string}
94
		 */
95
		getPublicToken: function () {
96
			var element = $('#gallery');
97
			var token;
98
99
			if (element.data('token')) {
100
				token = element.data('token');
101
			}
102
103
			if (element.data('requesttoken')) {
104
				/* jshint camelcase: false */
105
				oc_requesttoken = element.data('requesttoken');
106
			}
107
108
			return token;
0 ignored issues
show
Bug introduced by
The variable token does not seem to be initialized in case element.data("token") on line 99 is false. Are you sure this can never be the case?
Loading history...
109
		},
110
111
		/**
112
		 * Returns the host we can use for WebDAV
113
		 * 
114
		 * On public galleries, we need to provide the token as authorization
115
		 *
116
		 * @returns {string}
117
		 */
118
		getWebdavHost: function () {
119
			var host = OC.getHost();
120
			if (Gallery.token) {
121
				host = Gallery.token + '@' + host;
122
			}
123
124
			return host;
125
		},
126
127
		/**
128
		 * Returns the WebDAV endpoint we can use for files operations
129
		 *
130
		 * @returns {string}
131
		 */
132
		getWebdavRoot: function () {
133
			var root = OC.linkToRemoteBase('webdav');
134
			if (Gallery.token) {
135
				root = root.replace('remote.php', 'public.php');
136
			}
137
138
			return root;
139
		},
140
141
		/**
142
		 * Builds the URL which will retrieve a large preview of the file
143
		 *
144
		 * @fixme we cannot get rid of oc_requesttoken parameter as it's missing from the headers
145
		 *
146
		 * @param {number} fileId
147
		 * @param {number} etag
148
		 *
149
		 * @return {string}
150
		 */
151
		getPreviewUrl: function (fileId, etag) {
152
			var width = Math.ceil(screen.width * window.devicePixelRatio);
0 ignored issues
show
Bug introduced by
The variable screen seems to be never declared. If this is a global, consider adding a /** global: screen */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
153
			var height = Math.ceil(screen.height * window.devicePixelRatio);
154
155
			/* Find value of longest edge. */
156
			var longEdge = Math.max(width, height);
157
158
			/* Find the next larger image size. */
159
			if (longEdge % 100 !== 0) {
160
				longEdge = ( longEdge + 100 ) - ( longEdge % 100 );
161
			}
162
163
			/* jshint camelcase: false */
164
			var params = {
165
				c: etag,
166
				width: longEdge,
167
				height: longEdge,
168
				requesttoken: oc_requesttoken
169
			};
170
			return this.buildGalleryUrl('preview', '/' + fileId, params);
171
		},
172
173
		/**
174
		 * Builds a URL pointing to one of the app's controllers
175
		 *
176
		 * @param {string} endPoint
177
		 * @param {undefined|string} path
178
		 * @param params
179
		 *
180
		 * @returns {string}
181
		 */
182
		buildGalleryUrl: function (endPoint, path, params) {
183
			if (path === undefined) {
184
				path = '';
185
			}
186
			var extension = '';
187
			if (Gallery.token) {
188
				params.token = Gallery.token;
189
				extension = '.public';
190
			}
191
			var query = OC.buildQueryString(params);
192
			return OC.generateUrl('apps/' + Gallery.appName + '/' + endPoint + extension + path,
193
					null) +
194
				'?' +
195
				query;
196
		},
197
198
		/**
199
		 * Builds a URL pointing to one of the files' controllers
200
		 *
201
		 * @param {string} path
202
		 * @param {string} files
203
		 *
204
		 * @returns {string}
205
		 */
206
		buildFilesUrl: function (path, files) {
207
			var subUrl = '';
208
			var params = {
209
				path: path,
210
				files: files
211
			};
212
213
			if (Gallery.token) {
214
				params.token = Gallery.token;
215
				subUrl = 's/{token}/download?dir={path}&files={files}';
216
			} else {
217
				subUrl = 'apps/files/ajax/download.php?dir={path}&files={files}';
218
			}
219
220
			return OC.generateUrl(subUrl, params);
221
		},
222
223
		/**
224
		 * Sorts arrays based on name or date
225
		 *
226
		 * @param {string} sortType
227
		 * @param {string} sortOrder
228
		 *
229
		 * @returns {Function}
230
		 */
231
		sortBy: function (sortType, sortOrder) {
232
			switch (sortType) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
233
				case 'name':
234
		//if (sortType === 'name') {
235
				if (sortOrder === 'asc') {
236
					//sortByNameAsc
237
					return function (a, b) {
238
						return OC.Util.naturalSortCompare(a.path, b.path);
239
					};
240
				}
241
				//sortByNameDes
242
				return function (a, b) {
243
					return -OC.Util.naturalSortCompare(a.path, b.path);
244
				};
245
		//}
246
				case 'date':
247
		//if (sortType === 'date') {
248
				if (sortOrder === 'asc') {
249
					//sortByDateAsc
250
					return function (a, b) {
251
						return b.mTime - a.mTime;
252
					};
253
				}
254
				//sortByDateDes
255
				return function (a, b) {
256
					return a.mTime - b.mTime;
257
				};
258
		//}
259
				case 'date-taken':     // EXIF 'DateTimeOriginal' field
260
					return sortOrder === 'asc' ?
261
						function (a, b) {
262
							return b.exif.taken_date - a.exif.taken_date;
0 ignored issues
show
Coding Style introduced by
Identifier 'taken_date' is not in camel case.
Loading history...
263
						} :
264
						function (a, b) {
265
							return a.exif.taken_date - b.exif.taken_date;
0 ignored issues
show
Coding Style introduced by
Identifier 'taken_date' is not in camel case.
Loading history...
266
						};
267
			}
0 ignored issues
show
Comprehensibility introduced by
There is no default case in this switch, so nothing gets returned when all cases fail. You might want to consider adding a default or return undefined explicitly.
Loading history...
268
		},
269
270
		/**
271
		 * Adds hooks to DOMPurify
272
		 */
273
		addDomPurifyHooks: function () {
274
			// allowed URI schemes
275
			var whitelist = ['http', 'https'];
276
277
			// build fitting regex
278
			var regex = new RegExp('^(' + whitelist.join('|') + '):', 'gim');
279
280
			DOMPurify.addHook('afterSanitizeAttributes', function (node) {
281
				// This hook enforces URI scheme whitelist
282
				// @link
283
				// https://github.com/cure53/DOMPurify/blob/master/demos/hooks-scheme-whitelist.html
284
285
				// build an anchor to map URLs to
286
				var anchor = document.createElement('a');
287
288
				// check all href attributes for validity
289
				if (node.hasAttribute('href')) {
290
					anchor.href = node.getAttribute('href');
291
					if (anchor.protocol && !anchor.protocol.match(regex)) {
292
						node.removeAttribute('href');
293
					}
294
				}
295
				// check all action attributes for validity
296
				if (node.hasAttribute('action')) {
297
					anchor.href = node.getAttribute('action');
298
					if (anchor.protocol && !anchor.protocol.match(regex)) {
299
						node.removeAttribute('action');
300
					}
301
				}
302
				// check all xlink:href attributes for validity
303
				if (node.hasAttribute('xlink:href')) {
304
					anchor.href = node.getAttribute('xlink:href');
305
					if (anchor.protocol && !anchor.protocol.match(regex)) {
306
						node.removeAttribute('xlink:href');
307
					}
308
				}
309
310
				// This hook restores the proper, standard namespace in SVG files
311
				var encodedXmlns, decodedXmlns;
312
313
				// Restores namespaces which were put in the DOCTYPE by Illustrator
314
				if (node.hasAttribute('xmlns') && node.getAttribute('xmlns') === '&ns_svg;') {
315
					encodedXmlns = node.getAttribute('xmlns');
316
					decodedXmlns = encodedXmlns.replace('&ns_svg;', 'http://www.w3.org/2000/svg');
317
					node.setAttribute('xmlns', decodedXmlns);
318
				}
319
				if (node.hasAttribute('xmlns:xlink') &&
320
					node.getAttribute('xmlns:xlink') === '&ns_xlink;') {
321
					encodedXmlns = node.getAttribute('xmlns:xlink');
322
					decodedXmlns =
323
						encodedXmlns.replace('&ns_xlink;', 'http://www.w3.org/1999/xlink');
324
					node.setAttribute('xmlns:xlink', decodedXmlns);
325
				}
326
			});
327
		}
328
	};
329
330
	Gallery.Utility = Utility;
331
})(jQuery, OC, t, oc_requesttoken, Gallery);
0 ignored issues
show
Coding Style introduced by
Identifier 'oc_requesttoken' is not in camel case.
Loading history...
332