Completed
Push — stable9 ( 485cb1...e094cf )
by Lukas
26:41 queued 26:23
created

core/js/shareitemmodel.js (14 issues)

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
/*
2
 * Copyright (c) 2015
3
 *
4
 * This file is licensed under the Affero General Public License version 3
5
 * or later.
6
 *
7
 * See the COPYING-README file.
8
 *
9
 */
10
11
(function() {
12
	if(!OC.Share) {
13
		OC.Share = {};
14
		OC.Share.Types = {};
15
	}
16
17
	/**
18
	 * @typedef {object} OC.Share.Types.LinkShareInfo
19
	 * @property {bool} isLinkShare
20
	 * @property {string} token
21
	 * @property {string|null} password
22
	 * @property {string} link
23
	 * @property {number} permissions
24
	 * @property {Date} expiration
25
	 * @property {number} stime share time
26
	 */
27
28
	/**
29
	 * @typedef {object} OC.Share.Types.Reshare
30
	 * @property {string} uid_owner
31
	 * @property {number} share_type
32
	 * @property {string} share_with
33
	 * @property {string} displayname_owner
34
	 * @property {number} permissions
35
	 */
36
37
	/**
38
	 * @typedef {object} OC.Share.Types.ShareInfo
39
	 * @property {number} share_type
40
	 * @property {number} permissions
41
	 * @property {number} file_source optional
42
	 * @property {number} item_source
43
	 * @property {string} token
44
	 * @property {string} share_with
45
	 * @property {string} share_with_displayname
46
	 * @property {string} mail_send
47
	 * @property {Date} expiration optional?
48
	 * @property {number} stime optional?
49
	 * @property {string} uid_owner
50
	 */
51
52
	/**
53
	 * @typedef {object} OC.Share.Types.ShareItemInfo
54
	 * @property {OC.Share.Types.Reshare} reshare
55
	 * @property {OC.Share.Types.ShareInfo[]} shares
56
	 * @property {OC.Share.Types.LinkShareInfo|undefined} linkShare
57
	 */
58
59
	/**
60
	 * These properties are sometimes returned by the server as strings instead
61
	 * of integers, so we need to convert them accordingly...
62
	 */
63
	var SHARE_RESPONSE_INT_PROPS = [
64
		'id', 'file_parent', 'mail_send', 'file_source', 'item_source', 'permissions',
65
		'storage', 'share_type', 'parent', 'stime'
66
	];
67
68
	/**
69
	 * @class OCA.Share.ShareItemModel
70
	 * @classdesc
71
	 *
72
	 * Represents the GUI of the share dialogue
73
	 *
74
	 * // FIXME: use OC Share API once #17143 is done
75
	 *
76
	 * // TODO: this really should be a collection of share item models instead,
77
	 * where the link share is one of them
78
	 */
79
	var ShareItemModel = OC.Backbone.Model.extend({
80
		/**
81
		 * @type share id of the link share, if applicable
82
		 */
83
		_linkShareId: null,
84
85
		initialize: function(attributes, options) {
86
			if(!_.isUndefined(options.configModel)) {
87
				this.configModel = options.configModel;
88
			}
89
			if(!_.isUndefined(options.fileInfoModel)) {
90
				/** @type {OC.Files.FileInfo} **/
91
				this.fileInfoModel = options.fileInfoModel;
92
			}
93
94
			_.bindAll(this, 'addShare');
95
		},
96
97
		defaults: {
98
			allowPublicUploadStatus: false,
99
			permissions: 0,
100
			linkShare: {}
101
		},
102
103
		/**
104
		 * Saves the current link share information.
105
		 *
106
		 * This will trigger an ajax call and refetch the model afterwards.
107
		 *
108
		 * TODO: this should be a separate model
109
		 */
110
		saveLinkShare: function(attributes, options) {
111
			options = options || {};
112
			attributes = _.extend({}, attributes);
113
114
			var shareId = null;
115
			var call;
116
117
			// oh yeah...
118
			if (attributes.expiration) {
119
				attributes.expireDate = attributes.expiration;
120
				delete attributes.expiration;
121
			}
122
123
			if (this.get('linkShare') && this.get('linkShare').isLinkShare) {
124
				shareId = this.get('linkShare').id;
125
126
				// note: update can only update a single value at a time
127
				call = this.updateShare(shareId, attributes, options);
128
			} else {
129
				attributes = _.defaults(attributes, {
130
					password: '',
131
					passwordChanged: false,
132
					permissions: OC.PERMISSION_READ,
133
					expireDate: this.configModel.getDefaultExpirationDateString(),
134
					shareType: OC.Share.SHARE_TYPE_LINK
135
				});
136
137
				call = this.addShare(attributes, options);
138
			}
139
140
			return call;
141
		},
142
143
		removeLinkShare: function() {
144
			if (this.get('linkShare')) {
145
				return this.removeShare(this.get('linkShare').id);
146
			}
147
		},
148
149
		addShare: function(attributes, options) {
150
			var shareType = attributes.shareType;
151
			options = options || {};
152
			attributes = _.extend({}, attributes);
153
154
			// Default permissions are Edit (CRUD) and Share
155
			// Check if these permissions are possible
156
			var permissions = OC.PERMISSION_READ;
157
			if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
158
				permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_READ;
159
			} else {
160
				if (this.updatePermissionPossible()) {
161
					permissions = permissions | OC.PERMISSION_UPDATE;
162
				}
163
				if (this.createPermissionPossible()) {
164
					permissions = permissions | OC.PERMISSION_CREATE;
165
				}
166
				if (this.deletePermissionPossible()) {
167
					permissions = permissions | OC.PERMISSION_DELETE;
168
				}
169
				if (this.configModel.get('isResharingAllowed') && (this.sharePermissionPossible())) {
170
					permissions = permissions | OC.PERMISSION_SHARE;
171
				}
172
			}
173
174
			attributes.permissions = permissions;
175
			if (_.isUndefined(attributes.path)) {
176
				attributes.path = this.fileInfoModel.getFullPath();
177
			}
178
179
			var self = this;
180
			return $.ajax({
181
				type: 'POST',
182
				url: this._getUrl('shares'),
183
				data: attributes,
184
				dataType: 'json'
185
			}).done(function() {
186
				self.fetch().done(function() {
187
					if (_.isFunction(options.success)) {
188
						options.success(self);
189
					}
190
				});
191
			}).fail(function(xhr) {
192
				var msg = t('core', 'Error');
193
				var result = xhr.responseJSON;
194
				if (result.ocs && result.ocs.meta) {
195
					msg = result.ocs.meta.message;
196
				}
197
198
				if (_.isFunction(options.error)) {
199
					options.error(self, msg);
200
				} else {
201
					OC.dialogs.alert(msg, t('core', 'Error while sharing'));
202
				}
203
			});
204
		},
205
206
		updateShare: function(shareId, attrs, options) {
207
			var self = this;
208
			options = options || {};
209
			return $.ajax({
210
				type: 'PUT',
211
				url: this._getUrl('shares/' + encodeURIComponent(shareId)),
212
				data: attrs,
213
				dataType: 'json'
214
			}).done(function() {
215
				self.fetch({
216
					success: function() {
217
						if (_.isFunction(options.success)) {
218
							options.success(self);
219
						}
220
					}
221
				});
222
			}).fail(function(xhr) {
223
				var msg = t('core', 'Error');
224
				var result = xhr.responseJSON;
225
				if (result.ocs && result.ocs.meta) {
226
					msg = result.ocs.meta.message;
227
				}
228
229
				if (_.isFunction(options.error)) {
230
					options.error(self, msg);
231
				} else {
232
					OC.dialogs.alert(msg, t('core', 'Error while sharing'));
233
				}
234
			});
235
		},
236
237
		/**
238
		 * Deletes the share with the given id
239
		 *
240
		 * @param {int} shareId share id
241
		 * @return {jQuery}
242
		 */
243
		removeShare: function(shareId, options) {
244
			var self = this;
245
			options = options || {};
246
			return $.ajax({
247
				type: 'DELETE',
248
				url: this._getUrl('shares/' + encodeURIComponent(shareId)),
249
			}).done(function() {
250
				self.fetch({
251
					success: function() {
252
						if (_.isFunction(options.success)) {
253
							options.success(self);
254
						}
255
					}
256
				});
257
			}).fail(function(xhr) {
258
				var msg = t('core', 'Error');
259
				var result = xhr.responseJSON;
260
				if (result.ocs && result.ocs.meta) {
261
					msg = result.ocs.meta.message;
262
				}
263
264
				if (_.isFunction(options.error)) {
265
					options.error(self, msg);
266
				} else {
267
					OC.dialogs.alert(msg, t('core', 'Error removing share'));
268
				}
269
			});
270
		},
271
272
		/**
273
		 * @returns {boolean}
274
		 */
275
		isPublicUploadAllowed: function() {
276
			return this.get('allowPublicUploadStatus');
277
		},
278
279
		/**
280
		 * @returns {boolean}
281
		 */
282
		isHideFileListSet: function() {
283
			return this.get('hideFileListStatus');
284
		},
285
286
		/**
287
		 * @returns {boolean}
288
		 */
289
		isFolder: function() {
290
			return this.get('itemType') === 'folder';
291
		},
292
293
		/**
294
		 * @returns {boolean}
295
		 */
296
		isFile: function() {
297
			return this.get('itemType') === 'file';
298
		},
299
300
		/**
301
		 * whether this item has reshare information
302
		 * @returns {boolean}
303
		 */
304
		hasReshare: function() {
305
			var reshare = this.get('reshare');
306
			return _.isObject(reshare) && !_.isUndefined(reshare.uid_owner);
307
		},
308
309
		/**
310
		 * whether this item has user share information
311
		 * @returns {boolean}
312
		 */
313
		hasUserShares: function() {
314
			return this.getSharesWithCurrentItem().length > 0;
315
		},
316
317
		/**
318
		 * Returns whether this item has a link share
319
		 *
320
		 * @return {bool} true if a link share exists, false otherwise
321
		 */
322
		hasLinkShare: function() {
323
			var linkShare = this.get('linkShare');
324
			if (linkShare && linkShare.isLinkShare) {
325
				return true;
326
			}
327
			return false;
328
		},
329
330
		/**
331
		 * @returns {string}
332
		 */
333
		getReshareOwner: function() {
334
			return this.get('reshare').uid_owner;
335
		},
336
337
		/**
338
		 * @returns {string}
339
		 */
340
		getReshareOwnerDisplayname: function() {
341
			return this.get('reshare').displayname_owner;
342
		},
343
344
		/**
345
		 * @returns {string}
346
		 */
347
		getReshareWith: function() {
348
			return this.get('reshare').share_with;
0 ignored issues
show
Identifier 'share_with' is not in camel case.
Loading history...
349
		},
350
351
		/**
352
		 * @returns {number}
353
		 */
354
		getReshareType: function() {
355
			return this.get('reshare').share_type;
0 ignored issues
show
Identifier 'share_type' is not in camel case.
Loading history...
356
		},
357
358
		/**
359
		 * Returns all share entries that only apply to the current item
360
		 * (file/folder)
361
		 *
362
		 * @return {Array.<OC.Share.Types.ShareInfo>}
363
		 */
364
		getSharesWithCurrentItem: function() {
365
			var shares = this.get('shares') || [];
366
			var fileId = this.fileInfoModel.get('id');
367
			return _.filter(shares, function(share) {
368
				return share.item_source === fileId;
369
			});
370
		},
371
372
		/**
373
		 * @param shareIndex
374
		 * @returns {string}
375
		 */
376
		getShareWith: function(shareIndex) {
377
			/** @type OC.Share.Types.ShareInfo **/
378
			var share = this.get('shares')[shareIndex];
379
			if(!_.isObject(share)) {
380
				throw "Unknown Share";
381
			}
382
			return share.share_with;
383
		},
384
385
		/**
386
		 * @param shareIndex
387
		 * @returns {string}
388
		 */
389
		getShareWithDisplayName: function(shareIndex) {
390
			/** @type OC.Share.Types.ShareInfo **/
391
			var share = this.get('shares')[shareIndex];
392
			if(!_.isObject(share)) {
393
				throw "Unknown Share";
394
			}
395
			return share.share_with_displayname;
0 ignored issues
show
Identifier 'share_with_displayname' is not in camel case.
Loading history...
396
		},
397
398
		getShareType: function(shareIndex) {
399
			/** @type OC.Share.Types.ShareInfo **/
400
			var share = this.get('shares')[shareIndex];
401
			if(!_.isObject(share)) {
402
				throw "Unknown Share";
403
			}
404
			return share.share_type;
405
		},
406
407
		/**
408
		 * whether a share from shares has the requested permission
409
		 *
410
		 * @param {number} shareIndex
411
		 * @param {number} permission
412
		 * @returns {boolean}
413
		 * @private
414
		 */
415
		_shareHasPermission: function(shareIndex, permission) {
416
			/** @type OC.Share.Types.ShareInfo **/
417
			var share = this.get('shares')[shareIndex];
418
			if(!_.isObject(share)) {
419
				throw "Unknown Share";
420
			}
421
			if(   share.share_type === OC.Share.SHARE_TYPE_REMOTE
422
			   && (   permission === OC.PERMISSION_SHARE
423
				   || permission === OC.PERMISSION_DELETE))
424
			{
425
				return false;
426
			}
427
			return (share.permissions & permission) === permission;
428
		},
429
430
		notificationMailWasSent: function(shareIndex) {
431
			/** @type OC.Share.Types.ShareInfo **/
432
			var share = this.get('shares')[shareIndex];
433
			if(!_.isObject(share)) {
434
				throw "Unknown Share";
435
			}
436
			return share.mail_send === 1;
437
		},
438
439
		/**
440
		 * Sends an email notification for the given share
441
		 *
442
		 * @param {int} shareType share type
443
		 * @param {string} shareWith recipient
444
		 * @param {bool} state whether to set the notification flag or remove it
445
		 */
446
		sendNotificationForShare: function(shareType, shareWith, state) {
447
			var itemType = this.get('itemType');
448
			var itemSource = this.get('itemSource');
449
450
			return $.post(
451
				OC.generateUrl('core/ajax/share.php'),
452
				{
453
					action: state ? 'informRecipients' : 'informRecipientsDisabled',
454
					recipient: shareWith,
455
					shareType: shareType,
456
					itemSource: itemSource,
457
					itemType: itemType
458
				},
459
				function(result) {
460
					if (result.status !== 'success') {
461
						// FIXME: a model should not show dialogs
462
						OC.dialogs.alert(t('core', result.data.message), t('core', 'Warning'));
463
					}
464
				}
465
			);
466
		},
467
468
		/**
469
		 * Send the link share information by email
470
		 *
471
		 * @param {string} recipientEmail recipient email address
472
		 */
473
		sendEmailPrivateLink: function(recipientEmail) {
474
			var deferred = $.Deferred();
475
			var itemType = this.get('itemType');
476
			var itemSource = this.get('itemSource');
477
			var linkShare = this.get('linkShare');
478
479
			$.post(
480
				OC.generateUrl('core/ajax/share.php'), {
481
					action: 'email',
482
					toaddress: recipientEmail,
483
					link: linkShare.link,
484
					itemType: itemType,
485
					itemSource: itemSource,
486
					file: this.fileInfoModel.get('name'),
487
					expiration: linkShare.expiration || ''
488
				},
489
				function(result) {
490
					if (!result || result.status !== 'success') {
491
						// FIXME: a model should not show dialogs
492
						OC.dialogs.alert(result.data.message, t('core', 'Error while sending notification'));
493
						deferred.reject();
494
					} else {
495
						deferred.resolve();
496
					}
497
				});
498
499
			return deferred.promise();
500
		},
501
502
		/**
503
		 * @returns {boolean}
504
		 */
505
		sharePermissionPossible: function() {
506
			return (this.get('permissions') & OC.PERMISSION_SHARE) === OC.PERMISSION_SHARE;
507
		},
508
509
		/**
510
		 * @param {number} shareIndex
511
		 * @returns {boolean}
512
		 */
513
		hasSharePermission: function(shareIndex) {
514
			return this._shareHasPermission(shareIndex, OC.PERMISSION_SHARE);
515
		},
516
517
		/**
518
		 * @returns {boolean}
519
		 */
520
		createPermissionPossible: function() {
521
			return (this.get('permissions') & OC.PERMISSION_CREATE) === OC.PERMISSION_CREATE;
522
		},
523
524
		/**
525
		 * @param {number} shareIndex
526
		 * @returns {boolean}
527
		 */
528
		hasCreatePermission: function(shareIndex) {
529
			return this._shareHasPermission(shareIndex, OC.PERMISSION_CREATE);
530
		},
531
532
		/**
533
		 * @returns {boolean}
534
		 */
535
		updatePermissionPossible: function() {
536
			return (this.get('permissions') & OC.PERMISSION_UPDATE) === OC.PERMISSION_UPDATE;
537
		},
538
539
		/**
540
		 * @param {number} shareIndex
541
		 * @returns {boolean}
542
		 */
543
		hasUpdatePermission: function(shareIndex) {
544
			return this._shareHasPermission(shareIndex, OC.PERMISSION_UPDATE);
545
		},
546
547
		/**
548
		 * @returns {boolean}
549
		 */
550
		deletePermissionPossible: function() {
551
			return (this.get('permissions') & OC.PERMISSION_DELETE) === OC.PERMISSION_DELETE;
552
		},
553
554
		/**
555
		 * @param {number} shareIndex
556
		 * @returns {boolean}
557
		 */
558
		hasDeletePermission: function(shareIndex) {
559
			return this._shareHasPermission(shareIndex, OC.PERMISSION_DELETE);
560
		},
561
562
		/**
563
		 * @returns {boolean}
564
		 */
565
		editPermissionPossible: function() {
566
			return    this.createPermissionPossible()
567
				|| this.updatePermissionPossible()
568
				|| this.deletePermissionPossible();
569
		},
570
571
		/**
572
		 * @returns {boolean}
573
		 */
574
		hasEditPermission: function(shareIndex) {
575
			return    this.hasCreatePermission(shareIndex)
576
				|| this.hasUpdatePermission(shareIndex)
577
				|| this.hasDeletePermission(shareIndex);
578
		},
579
580
		_getUrl: function(base, params) {
581
			params = _.extend({format: 'json'}, params || {});
582
			return OC.linkToOCS('apps/files_sharing/api/v1', 2) + base + '?' + OC.buildQueryString(params);
583
		},
584
585
		_fetchShares: function() {
586
			var path = this.fileInfoModel.getFullPath();
587
			return $.ajax({
588
				type: 'GET',
589
				url: this._getUrl('shares', {path: path, reshares: true})
590
			});
591
		},
592
593
		_fetchReshare: function() {
594
			// only fetch original share once
595
			if (!this._reshareFetched) {
596
				var path = this.fileInfoModel.getFullPath();
597
				this._reshareFetched = true;
598
				return $.ajax({
599
					type: 'GET',
600
					url: this._getUrl('shares', {path: path, shared_with_me: true})
601
				});
602
			} else {
603
				return $.Deferred().resolve([{
604
					ocs: {
605
						data: [this.get('reshare')]
606
					}
607
				}]);
608
			}
609
		},
610
611
		fetch: function() {
612
			var model = this;
613
			this.trigger('request', this);
614
615
			var deferred = $.when(
616
				this._fetchShares(),
617
				this._fetchReshare()
618
			);
619
			deferred.done(function(data1, data2) {
620
				model.trigger('sync', 'GET', this);
621
				var sharesMap = {};
622
				_.each(data1[0].ocs.data, function(shareItem) {
623
					sharesMap[shareItem.id] = shareItem;
624
				});
625
626
				var reshare = false;
627
				if (data2[0].ocs.data.length) {
628
					reshare = data2[0].ocs.data[0];
629
				}
630
631
				model.set(model.parse({
632
					shares: sharesMap,
633
					reshare: reshare
634
				}));
635
			});
636
637
			return deferred;
638
		},
639
640
		/**
641
		 * Updates OC.Share.itemShares and OC.Share.statuses.
642
		 *
643
		 * This is required in case the user navigates away and comes back,
644
		 * the share statuses from the old arrays are still used to fill in the icons
645
		 * in the file list.
646
		 */
647
		_legacyFillCurrentShares: function(shares) {
648
			var fileId = this.fileInfoModel.get('id');
649
			if (!shares || !shares.length) {
650
				delete OC.Share.statuses[fileId];
651
				OC.Share.currentShares = {};
652
				OC.Share.itemShares = [];
653
				return;
654
			}
655
656
			var currentShareStatus = OC.Share.statuses[fileId];
657
			if (!currentShareStatus) {
658
				currentShareStatus = {link: false};
659
				OC.Share.statuses[fileId] = currentShareStatus;
660
			}
661
			currentShareStatus.link = false;
662
663
			OC.Share.currentShares = {};
664
			OC.Share.itemShares = [];
665
			_.each(shares,
666
				/**
667
				 * @param {OC.Share.Types.ShareInfo} share
668
				 */
669
				function(share) {
670
					if (share.share_type === OC.Share.SHARE_TYPE_LINK) {
671
						OC.Share.itemShares[share.share_type] = true;
672
						currentShareStatus.link = true;
673
					} else {
674
						if (!OC.Share.itemShares[share.share_type]) {
0 ignored issues
show
Identifier 'share_type' is not in camel case.
Loading history...
675
							OC.Share.itemShares[share.share_type] = [];
0 ignored issues
show
Identifier 'share_type' is not in camel case.
Loading history...
676
						}
677
						OC.Share.itemShares[share.share_type].push(share.share_with);
0 ignored issues
show
Identifier 'share_type' is not in camel case.
Loading history...
Identifier 'share_with' is not in camel case.
Loading history...
678
					}
679
				}
680
			);
681
		},
682
683
		parse: function(data) {
684
			if(data === false) {
685
				console.warn('no data was returned');
686
				this.trigger('fetchError');
687
				return {};
688
			}
689
690
			var permissions = this.get('possiblePermissions');
691
			if(!_.isUndefined(data.reshare) && !_.isUndefined(data.reshare.permissions) && data.reshare.uid_owner !== OC.currentUser) {
0 ignored issues
show
Line is too long.
Loading history...
Identifier 'uid_owner' is not in camel case.
Loading history...
692
				permissions = permissions & data.reshare.permissions;
693
			}
694
695
			var allowPublicUploadStatus = false;
696
			if(!_.isUndefined(data.shares)) {
697
				$.each(data.shares, function (key, value) {
698
					if (value.share_type === OC.Share.SHARE_TYPE_LINK) {
0 ignored issues
show
Identifier 'share_type' is not in camel case.
Loading history...
699
						allowPublicUploadStatus = (value.permissions & OC.PERMISSION_CREATE) ? true : false;
700
						return true;
701
					}
702
				});
703
			}
704
705
			var hideFileListStatus = false;
706
			if(!_.isUndefined(data.shares)) {
707
				$.each(data.shares, function (key, value) {
708
					if (value.share_type === OC.Share.SHARE_TYPE_LINK) {
0 ignored issues
show
Identifier 'share_type' is not in camel case.
Loading history...
709
						hideFileListStatus = (value.permissions & OC.PERMISSION_READ) ? false : true;
710
						return true;
711
					}
712
				});
713
			}
714
715
			/** @type {OC.Share.Types.ShareInfo[]} **/
716
			var shares = _.map(data.shares, function(share) {
717
				// properly parse some values because sometimes the server
718
				// returns integers as string...
719
				var i;
720
				for (i = 0; i < SHARE_RESPONSE_INT_PROPS.length; i++) {
721
					var prop = SHARE_RESPONSE_INT_PROPS[i];
722
					if (!_.isUndefined(share[prop])) {
723
						share[prop] = parseInt(share[prop], 10);
724
					}
725
				}
726
				return share;
727
			});
728
729
			this._legacyFillCurrentShares(shares);
730
731
			var linkShare = { isLinkShare: false };
732
			// filter out the share by link
733
			shares = _.reject(shares,
734
				/**
735
				 * @param {OC.Share.Types.ShareInfo} share
736
				 */
737
				function(share) {
738
					var isShareLink =
739
						share.share_type === OC.Share.SHARE_TYPE_LINK
0 ignored issues
show
Identifier 'share_type' is not in camel case.
Loading history...
740
						&& (   share.file_source === this.get('itemSource')
0 ignored issues
show
Identifier 'file_source' is not in camel case.
Loading history...
741
						|| share.item_source === this.get('itemSource'));
0 ignored issues
show
Identifier 'item_source' is not in camel case.
Loading history...
742
743
					if (isShareLink) {
744
						/*
745
						 * Ignore reshared link shares for now
746
						 * FIXME: Find a way to display properly
747
						 */
748
						if (share.uid_owner !== OC.currentUser) {
749
							return share;
750
						}
751
752
						var link = window.location.protocol + '//' + window.location.host;
753
						if (!share.token) {
754
							// pre-token link
755
							var fullPath = this.fileInfoModel.get('path') + '/' +
756
								this.fileInfoModel.get('name');
757
							var location = '/' + OC.currentUser + '/files' + fullPath;
758
							var type = this.fileInfoModel.isDirectory() ? 'folder' : 'file';
759
							link += OC.linkTo('', 'public.php') + '?service=files&' +
760
								type + '=' + encodeURIComponent(location);
761
						} else {
762
							link += OC.generateUrl('/s/') + share.token;
763
						}
764
						linkShare = {
765
							isLinkShare: true,
766
							id: share.id,
767
							token: share.token,
768
							password: share.share_with,
769
							link: link,
770
							permissions: share.permissions,
771
							// currently expiration is only effective for link shares.
772
							expiration: share.expiration,
773
							stime: share.stime
774
						};
775
776
						return share;
777
					}
778
				},
779
				this
780
			);
781
782
			return {
783
				reshare: data.reshare,
784
				shares: shares,
785
				linkShare: linkShare,
786
				permissions: permissions,
787
				allowPublicUploadStatus: allowPublicUploadStatus,
788
				hideFileListStatus: hideFileListStatus
789
			};
790
		},
791
792
		/**
793
		 * Parses a string to an valid integer (unix timestamp)
794
		 * @param time
795
		 * @returns {*}
796
		 * @internal Only used to work around a bug in the backend
797
		 */
798
		_parseTime: function(time) {
799
			if (_.isString(time)) {
800
				// skip empty strings and hex values
801
				if (time === '' || (time.length > 1 && time[0] === '0' && time[1] === 'x')) {
802
					return null;
803
				}
804
				time = parseInt(time, 10);
805
				if(isNaN(time)) {
806
					time = null;
807
				}
808
			}
809
			return time;
810
		}
811
	});
812
813
	OC.Share.ShareItemModel = ShareItemModel;
814
})();
815