PageSourceSearch

https://cloud.medianeira.pr.gov.br/core/js/shareitemmodel.js?v=333d7a1cf5d658b40f68f1bc8a84dac2

js medianeira.pr.gov.br collected 2026-10-02 18:35:12 UTC 32,115 bytes, 1,138 lines download raw bytes

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	 * @property {OC.Share.Types.ShareAttribute[]} attributes
36	 */
37
38	/**
39	 * @typedef {object} OC.Share.Types.ShareInfo
40	 * @property {number} share_type
41	 * @property {number} permissions
42	 * @property {OC.Share.Types.ShareAttribute[]} attributes
43	 * @property {number} file_source optional
44	 * @property {number} item_source
45	 * @property {string} token
46	 * @property {string} share_with
47	 * @property {string} share_with_displayname
48	 * @property {string} mail_send
49	 * @property {Date} expiration optional?
50	 * @property {number} stime optional?
51	 * @property {string} uid_owner
52	 */
53
54	/**
55	 * @typedef {object} OC.Share.Types.ShareItemInfo
56	 * @property {OC.Share.Types.Reshare} reshare
57	 * @property {OC.Share.Types.ShareInfo[]} shares
58	 * @property {OC.Share.Types.LinkShareInfo|undefined} linkShare
59	 */
60
61	/**
62	 * @typedef {object} OC.Share.Types.ShareAttribute
63	 * @property {string} key
64	 * @property {string} scope
65	 * @property {bool}   enabled
66	 */
67
68	/**
69	 * ShareAttributesApi v1 registered attributes
70	 * @typedef {object} OC.Share.Types.RegisteredShareAttribute
71	 * @property {string} key
72	 * @property {bool}   default
73	 * @property {string} scope
74	 * @property {string} label
75	 * @property {string} description
76	 * @property {number[]} shareType
77	 * @property {number[]} incompatiblePermissions
78	 * @property {number[]} requiredPermissions
79	 * @property {OC.Share.Types.ShareAttribute[]} incompatibleAttributes
80	 * @deprecated shareAttributesApi v2 requires apps to extend ShareItemModel with attributes
81	 */
82
83	/**
84	 * These properties are sometimes returned by the server as strings instead
85	 * of integers, so we need to convert them accordingly...
86	 */
87	var SHARE_RESPONSE_INT_PROPS = [
88		'id', 'file_parent', 'mail_send', 'file_source', 'item_source', 'permissions',
89		'storage', 'share_type', 'parent', 'stime'
90	];
91
92	/**
93	 * Properties which are json and need to be parsed
94	 */
95	var SHARE_RESPONSE_JSON_PROPS = [
96		'attributes'
97	];
98
99	/**
100	 * @class OCA.Share.ShareItemModel
101	 * @classdesc
102	 *
103	 * Represents the GUI of the share dialogue
104	 *
105	 * // FIXME: use OC Share API once #17143 is done
106	 *
107	 * // TODO: this really should be a collection of share item models instead,
108	 * where the link share is one of them
109	 */
110	var ShareItemModel = OC.Backbone.Model.extend({
111		/**
112		 * @type share id of the link share, if applicable
113		 */
114		_linkShareId: null,
115
116		_linkSharesCollection: null,
117
118		/**
119		 * @type {OC.Share.Types.RegisteredShareAttribute[]} registered available share permissions for this file/folder share
120		 * @deprecated shareAttributesApi v2 requires apps to extend ShareItemModel with attributes
121		 */
122		_registeredAttributes: null,
123
124		initialize: function(attributes, options) {
125			if(!_.isUndefined(options.configModel)) {
126				this.configModel = options.configModel;
127			}
128			if(!_.isUndefined(options.fileInfoModel)) {
129				/** @type {OC.Files.FileInfo} **/
130				this.fileInfoModel = options.fileInfoModel;
131			}
132
133			this._linkSharesCollection = new OC.Share.SharesCollection();
134			this._registeredAttributes = [];
135
136			_.bindAll(this, 'addShare');
137			OC.Plugins.attach('OC.Share.ShareItemModel', this);
138		},
139
140		defaults: {
141			permissions: 0,
142			linkShare: {}
143		},
144
145		/**
146		 * Returns the collection of link shares
147		 *
148		 * @return {OC.Share.SharesCollection} shares collection
149		 */
150		getLinkSharesCollection: function() {
151			return this._linkSharesCollection;
152		},
153
154		/**
155		 * Returns the file info for the file/folder on which this share information relate to
156		 *
157		 * @return {OC.Files.FileInfoModel} file info model
158		 */
159		getFileInfo: function() {
160			return this.fileInfoModel;
161		},
162
163		addShare: function(properties, options) {
164			var shareType = properties.shareType;
165			options = options || {};
166			properties = _.extend({}, properties);
167
168			// Set default expiration date
169			if (
170				this.configModel.isDefaultExpireDateUserEnabled() && (
171					shareType === OC.Share.SHARE_TYPE_USER ||
172					shareType === OC.Share.SHARE_TYPE_GUEST)
173				) {
174				properties.expireDate = this.configModel.getDefaultExpireDateUser('YYYY-MM-DD')
175			}
176
177			else if (this.configModel.isDefaultExpireDateGroupEnabled() && shareType === OC.Share.SHARE_TYPE_GROUP) {
178				properties.expireDate = this.configModel.getDefaultExpireDateGroup('YYYY-MM-DD')
179			} else if (this.configModel.isDefaultExpireDateRemoteEnabled() && shareType === OC.Share.SHARE_TYPE_REMOTE) {
180				properties.expireDate = this.configModel.getDefaultExpireDateRemote('YYYY-MM-DD')
181			}
182
183			// Get default permissions
184			var permissions = properties.permissions || OC.PERMISSION_ALL;
185			properties.permissions = permissions & this.getDefaultPermissions();
186
187			// Extend attributes for new share
188			// note: required only for compatibility with attributes v1
189			if (this._registeredAttributes.length) {
190				properties.attributes = this._handleAddShareAttributes(properties, options);
191			}
192
193			if (_.isUndefined(properties.path)) {
194				properties.path = this.fileInfoModel.getFullPath();
195			}
196
197			var self = this;
198			return $.ajax({
199				type: 'POST',
200				url: this._getUrl('shares'),
201				data: JSON.stringify(properties),
202				dataType: 'json',
203				contentType: "application/json"
204			}).done(function() {
205				self.fetch().done(function() {
206					if (_.isFunction(options.success)) {
207						options.success(self);
208					}
209				});
210			}).fail(function(xhr) {
211				var msg = t('core', 'Error');
212				var result = xhr.responseJSON;
213				if (result && result.ocs && result.ocs.meta) {
214					msg = result.ocs.meta.message;
215				}
216
217				if (_.isFunction(options.error)) {
218					options.error(self, msg);
219				} else {
220					OC.dialogs.alert(msg, t('core', 'Error while sharing'));
221				}
222			});
223		},
224
225		updateShare: function(shareId, properties, options) {
226			var self = this;
227
228			// Extend attributes for update share if provided for update.
229			// note: required only for compatibility with attributes v1
230			if (this._registeredAttributes.length) {
231				properties.attributes = this._handleUpdateShareAttributes(shareId, properties, options);
232			}
233
234			return $.ajax({
235				type: 'PUT',
236				url: this._getUrl('shares/' + encodeURIComponent(shareId)),
237				data: JSON.stringify(properties),
238				dataType: 'json',
239				contentType: "application/json"
240			}).done(function() {
241				self.fetch({
242					success: function() {
243						if (_.isFunction(options.success)) {
244							options.success(self);
245						}
246					}
247				});
248			}).fail(function(xhr) {
249				var msg = t('core', 'Error');
250				var result = xhr.responseJSON;
251				if (result.ocs && result.ocs.meta) {
252					msg = result.ocs.meta.message;
253				}
254
255				if (_.isFunction(options.error)) {
256					options.error(self, msg);
257				} else {
258					OC.dialogs.alert(msg, t('core', 'Error while sharing'));
259				}
260			});
261		},
262
263		/**
264		 * Deletes the share with the given id
265		 *
266		 * @param {int} shareId share id
267		 * @return {jQuery}
268		 */
269		removeShare: function(shareId, options) {
270			var self = this;
271			options = options || {};
272			return $.ajax({
273				type: 'DELETE',
274				url: this._getUrl('shares/' + encodeURIComponent(shareId)),
275			}).done(function() {
276				self.fetch({
277					success: function() {
278						if (_.isFunction(options.success)) {
279							options.success(self);
280						}
281					}
282				});
283			}).fail(function(xhr) {
284				var msg = t('core', 'Error');
285				var result = xhr.responseJSON;
286				if (result.ocs && result.ocs.meta) {
287					msg = result.ocs.meta.message;
288				}
289
290				if (_.isFunction(options.error)) {
291					options.error(self, msg);
292				} else {
293					OC.dialogs.alert(msg, t('core', 'Error removing share'));
294				}
295			});
296		},
297
298		/**
299		 * Default permissions are Edit (CRUD) and Share
300		 * Check if these permissions are possible
301		 *
302		 * @returns {number}
303		 */
304		getDefaultPermissions: function() {
305			var defaultPermissions = OC.getCapabilities()['files_sharing']['default_permissions'] || OC.PERMISSION_ALL;
306			var possiblePermissions = OC.PERMISSION_READ;
307			if (this.updatePermissionPossible()) {
308				possiblePermissions = possiblePermissions | OC.PERMISSION_UPDATE;
309			}
310			if (this.createPermissionPossible()) {
311				possiblePermissions = possiblePermissions | OC.PERMISSION_CREATE;
312			}
313			if (this.deletePermissionPossible()) {
314				possiblePermissions = possiblePermissions | OC.PERMISSION_DELET
314E;
315			}
316			if (this.configModel.get('isResharingAllowed') && (this.sharePermissionPossible())) {
317				possiblePermissions = possiblePermissions | OC.PERMISSION_SHARE;
318			}
319
320			return defaultPermissions & possiblePermissions;
321		},
322
323		/**
324		 * @returns {boolean}
325		 */
326		isFolder: function() {
327			return this.get('itemType') === 'folder';
328		},
329
330		/**
331		 * @returns {boolean}
332		 */
333		isFile: function() {
334			return this.get('itemType') === 'file';
335		},
336
337		/**
338		 * whether this item has reshare information
339		 * @returns {boolean}
340		 */
341		hasReshare: function() {
342			var reshare = this.get('reshare');
343			return _.isObject(reshare) && !_.isUndefined(reshare.uid_owner);
344		},
345
346		/**
347		 * whether this item has user share information
348		 * @returns {boolean}
349		 */
350		hasUserShares: function() {
351			return this.getSharesWithCurrentItem().length > 0;
352		},
353
354		/**
355		 * Returns whether this item has a link share
356		 *
357		 * @return {bool} true if a link share exists, false otherwise
358		 */
359		hasLinkShare: function() {
360			return this._linkSharesCollection.length > 0;
361		},
362
363		/**
364		 * @returns {string}
365		 */
366		getReshareOwner: function() {
367			return this.get('reshare').uid_owner;
368		},
369
370		/**
371		 * @returns {string}
372		 */
373		getReshareOwnerDisplayname: function() {
374			return this.get('reshare').displayname_owner;
375		},
376
377		/**
378		 * @returns {string}
379		 */
380		getReshareWith: function() {
381			return this.get('reshare').share_with;
382		},
383
384		/**
385		 * @returns {string}
386		 */
387		getReshareWithDisplayName: function() {
388			var reshare = this.get('reshare');
389			return reshare.share_with_displayname || reshare.share_with;
390		},
391
392		/**
393		 * @returns {number}
394		 */
395		getReshareType: function() {
396			return this.get('reshare').share_type;
397		},
398
399		/**
400		 * @returns {OC.Share.Types.ShareAttribute[]}
401		 */
402		getReshareAttributes: function() {
403			return this.get('reshare').attributes;
404		},
405
406		/**
407		 * Returns all share entries that only apply to the current item
408		 * (file/folder)
409		 *
410		 * @return {Array.<OC.Share.Types.ShareInfo>}
411		 */
412		getSharesWithCurrentItem: function() {
413			var shares = this.get('shares') || [];
414			var fileId = this.fileInfoModel.get('id');
415			return _.filter(shares, function(share) {
416				return share.item_source === fileId;
417			});
418		},
419
420		/**
421		 * Returns share entry by share id. Share will only be returned that only apply to the current item
422		 * (file/folder)
423		 *
424		 * @param shareId
425		 * @return {OC.Share.Types.ShareInfo}
426		 */
427		getShareById: function(shareId) {
428			var shares = this.get('shares') || [];
429			for(var shareIndex = 0; shareIndex < shares.length; shareIndex++) {
430				if (shares[shareIndex].id === shareId) {
431					return shares[shareIndex];
432				}
433			}
434
435			throw t('core', 'Unknown Share');
436		},
437
438		/**
439		 * @param shareIndex
440		 * @returns {string}
441		 */
442		getShareWith: function(shareIndex) {
443			/** @type OC.Share.Types.ShareInfo **/
444			var share = this.get('shares')[shareIndex];
445			if(!_.isObject(share)) {
446				throw "Unknown Share";
447			}
448			return share.share_with;
449		},
450
451		/**
452		 * @param shareIndex
453		 * @returns {string}
454		 */
455		getShareWithDisplayName: function(shareIndex) {
456			/** @type OC.Share.Types.ShareInfo **/
457			var share = this.get('shares')[shareIndex];
458			if(!_.isObject(share)) {
459				throw "Unknown Share";
460			}
461			return share.share_with_displayname;
462		},
463
464		/**
465		 * @param shareIndex
466		 * @returns {string}
467		 */
468		getShareWithAdditionalInfo: function(shareIndex) {
469			/** @type OC.Share.Types.ShareInfo **/
470			var share = this.get('shares')[shareIndex];
471			if(!_.isObject(share)) {
472				throw "Unknown Share";
473			}
474			return share.share_with_additional_info;
475		},
476
477		getShareType: function(shareIndex) {
478			/** @type OC.Share.Types.ShareInfo **/
479			var share = this.get('shares')[shareIndex];
480			if(!_.isObject(share)) {
481				throw "Unknown Share";
482			}
483			return share.share_type;
484		},
485
486		getExpirationDate: function(shareIndex) {
487			/** @type OC.Share.Types.ShareInfo **/
488			var share = this.get('shares')[shareIndex];
489			if(!_.isObject(share)) {
490				throw "Unknown Share";
491			}
492			return (share.expiration !== null) ? moment(share.expiration).format('DD-MM-YYYY') : null;
493		},
494
495		/**
496		 * whether permission is in permission bitmap
497		 *
498		 * @param {number} permissions
499		 * @param {number} permission
500		 * @returns {boolean}
501		 * @private
502		 */
503		_hasPermission: function(permissions, permission) {
504			return (permissions & permission) === permission;
505		},
506
507		/**
508		 * whether a share from shares has the requested permission
509		 *
510		 * @param {number} shareIndex
511		 * @param {number} permission
512		 * @returns {boolean}
513		 * @private
514		 */
515		_shareHasPermission: function(shareIndex, permission) {
516			/** @type OC.Share.Types.ShareInfo **/
517			var share = this.get('shares')[shareIndex];
518			if(!_.isObject(share)) {
519				throw "Unknown Share";
520			}
521			return this._hasPermission(share.permissions, permission);
522		},
523
524		notificationMailWasSent: function(shareIndex) {
525			/** @type OC.Share.Types.ShareInfo **/
526			var share = this.get('shares')[shareIndex];
527			if(!_.isObject(share)) {
528				throw "Unknown Share";
529			}
530			return share.mail_send === 1;
531		},
532
533		/**
534		 * Sends an email notification for the given share
535		 *
536		 * @param {int} shareType share type
537		 * @param {string} shareWith recipient
538		 * @param {bool} state whether to set the notification flag or remove it
539		 */
540		sendNotificationForShare: function(shareType, shareWith, state) {
541			var itemType = this.get('itemType');
542			var itemSource = this.get('itemSource');
543			var baseUrl = OC.linkToOCS('/apps/files_sharing/api/v1/notification/', 2);
544			var action = state ? 'send' : 'marksent';
545
546			return $.post(
547				baseUrl + action,
548				{
549					format: 'json',
550					recipient: shareWith,
551					shareType: shareType,
552					itemSource: itemSource,
553					itemType: itemType
554				}
555			);
556		},
557
558		/**
559		 * @returns {boolean}
560		 */
561		sharePermissionPossible: function() {
562			return (this.get('permissions') & OC.PERMISSION_SHARE) === OC.PERMISSION_SHARE;
563		},
564
565		/**
566		 * @param {number} shareIndex
567		 * @returns {boolean}
568		 */
569		hasSharePermission: function(shareIndex) {
570			return this._shareHasPermission(shareIndex, OC.PERMISSION_SHARE);
571		},
572
573		/**
574		 * @returns {boolean}
575		 */
576		createPermissionPossible: function() {
577			return (this.get('permissions') & OC.PERMISSION_CREATE) === OC.PERMISSION_CREATE;
578		},
579
580		/**
581		 * @param {number} shareIndex
582		 * @returns {boolean}
583		 */
584		hasCreatePermission: function(shareIndex) {
585			return this._shareHasPermission(shareIndex, OC.PERMISSION_CREATE);
586		},
587
588		/**
589		 * @returns {boolean}
590		 */
591		updatePermissionPossible: function() {
592			return (this.get('permissions') & OC.PERMISSION_UPDATE) === OC.PERMISSION_UPDATE;
593		},
594
595		/**
596		 * @param {number} shareIndex
597		 * @returns {boolean}
598		 */
599		hasUpdatePermission: function(shareIndex) {
600			return this._shareHasPermission(shareIndex, OC.PERMISSION_UPDATE);
601		},
602
603		/**
604		 * @returns {boolean}
605		 */
606		deletePermissionPossible: function() {
607			return (this.get('permissions') & OC.PERMISSION_DELETE) === OC.PERMISSION_DELETE;
608		},
609
610		/**
611		 * @param {number} shareIndex
612		 * @returns {boolean}
613		 */
614		hasDeletePermission: function(shareIndex) {
615			return this._shareHasPermission(shareIndex, OC.PERMISSION_DELETE);
616		},
617
618		/**
619		 * @returns {boolean}
620		 */
621		editPermissionPossible: function() {
622			return    this.createPermissionPossible()
623				   || this.updatePermissionPossible()
624				   || this.deletePermissionPossible();
625		},
626
627		/**
628		 * @returns {boolean}
629		 */
630		hasEditPermission: function(shareIndex) {
631			return    this.hasCreatePermission(shareIndex)
632				   || this.hasUpdatePermission(shareIndex)
633				   || this.hasDeletePermission(shareIndex);
634		},
635
636		_getUrl: function(base, params) {
637			params = _.extend({format: 'json'}, params || {});
638			return OC.linkToOCS('apps/files_sharing/api/v1', 2) + base + '?' + OC.buildQueryString(params);
639		},
640
641		_fetchShares: function() {
642			var path = this.fileInfoModel.getFullPath();
643			return $.ajax({
644				type: 'GET',
645				url: this._getUrl('shares', {path: path, reshares: true})
646			});
647		},
648
649		_fetchReshare: function() {
650			// only fetch original share once
651			if (!this._reshareFetched) {
652				var path = this.fileInfoModel.getFullPath();
653				this._reshareFetched = true;
654				return $.ajax({
655					type: 'GET',
656					url: this._getUrl('shares', {path: path, shared_with_me: true})
657				});
658			} else {
659				return $.Deferred().resolve([{
660					ocs: {
661						data: [this.get('reshare')]
662					}
663				}]);
664			}
665		},
666
667		/**
668		 * Group reshares into a single super share element.
669		 * Does this by finding the most precise share and
670		 * combines the permissions to be the most permissive.
671		 *
672		 * @param {Array} reshares
673		 * @return {Object} reshare
674		 */
675		_groupReshares: function(reshares) {
676			if (!reshares || !reshares.length) {
677				return false;
678			}
679
680			var superShare = reshares.shift();
681			var combinedPermissions = superShare.permissions;
682			_.each(reshares, function(reshare) {
683				// use share have higher priority than group share
684				if (reshare.share_type === OC.Share.SHARE_TYPE_USER && superShare.share_type === OC.Share.SHARE_TYPE_GROUP) {
685					superShare = reshare;
686				}
687				combinedPermissions |= reshare.permissions;
688			});
689
690			superShare.permissions = combinedPermissions;
691			return superShare;
692		},
693
694		fetch: function(options) {
695			var model = this;
696
697			this.trigger('request', this);
698
699			var deferred = $.when(
700				this._fetchShares(),
701				this._fetchReshare()
702			);
703
704			deferred.done(function(data1, data2) {
705				model.trigger('sync', 'GET', this);
706				var sharesMap = {};
707				_.each(data1[0].ocs.data, function(shareItem) {
708					sharesMap[shareItem.id] = shareItem;
709				});
710
711				var reshare = false;
712				if (data2[0].ocs.data.length) {
713					reshare = model._groupReshares(data2[0].ocs.data);
714				}
715
716				// update model properties,
717				// this should cause rerendering of the object
718				model.set(model.parse({
719					shares: sharesMap,
720					reshare: reshare
721				}), {
722					// do not allow silent, as apps might rely on reacting to
723					// changes to the model
724					silent: false,
725				});
726			});
727
728			return deferred;
729		},
730
731		/**
732		 * Updates OC.Share.itemShares and OC.Share.statuses.
733		 *
734		 * This is required in case the user navigates away and comes back,
735		 * the share statuses from the old arrays are still used to fill in the icons
736		 * in the file list.
737		 */
738		_legacyFillCurrentShares: function(shares) {
739			var fileId = this.fileInfoModel.get('id');
740			if (!shares || !shares.length) {
741				delete OC.Share.statuses[fileId];
742				OC.Share.currentShares = {};
743				OC.Share.itemShares = [];
744				return;
745			}
746
747			var currentShareStatus = OC.Share.statuses[fileId];
748			if (!currentShareStatus) {
749				currentShareStatus = {link: false};
750				OC.Share.statuses[fileId] = currentShareStatus;
751			}
752			currentShareStatus.link = false;
753
754			OC.Share.currentShares = {};
755			OC.Share.itemShares = [];
756			_.each(shares,
757				/**
758				 * @param {OC.Share.Types.ShareInfo} share
759				 */
760				function(share) {
761					if (share.share_type === OC.Share.SHARE_TYPE_LINK) {
762						OC.Share.itemShares[share.share_type] = true;
763						currentShareStatus.link = true;
764					} else {
765						if (!OC.Share.itemShares[share.share_type]) {
766							OC.Share.itemShares[share.share_type] = [];
767						}
768						OC.Share.itemShares[share.share_type].push(share.share_with);
769					}
770				}
771			);
772		},
773
774		parse: function(data) {
775			if(data === false) {
776				console.warn('no data was returned');
777				this.trigger('fetchError');
778				return {};
779			}
780
781			// check if this file has received shares to current user (direct incoming shared_with_me shares)
782			var permissions = this.get('possiblePermissions');
783			if(!_.isUndefined(data.reshare) && !_.isUndefined(data.reshare.permissions) && data.reshare.uid_owner !== OC.currentUser) {
784				if (this.fileInfoModel.get('mountType') === 'shared' && this.fileInfoModel.isDirectory()) {
785					// if this file is already contained in a share (subfolder of shared folder) combine incoming shares permissions
786					// with parent folder share permissions. This handles a case of resharing a file/folder reshared from same 
787					// share mountpoint multiple times in subfolders
788					permissions = permissions & (this.fileInfoModel.get('sharePermissions') | data.reshare.permissions);
789				} else {
790					permissions = permissions & data.reshare.permissions;
791				}
792			}
793
794			/** @type {OC.Share.Types.ShareInfo[]} **/
795			var shares = _.map(data.shares, this._parseShare);
796
797			/** @type {OC.Share.Types.Reshare} **/
798			var reshare = this._parseShare(data.reshare);
799
800			this._legacyFillCurrentShares(shares);
801
802			var linkShares = [];
803			// filter out the share by link
804			shares = _.reject(shares,
805				/**
806				 * @param {OC.Share.Types.ShareInfo} share
807				 */
808				function(share) {
809					var isShareLink =
810						share.share_type === OC.Share.SHARE_TYPE_LINK
811						&& (   share.file_source === this.get('itemSource')
812						|| share.item_source === this.get('itemSource'));
813
814					if (isShareLink) {
815						linkShares.push(share);
816						return share;
817					}
818				},
819				this
820			);
821
822			// populate link shares collection with found link shares
823			this._linkSharesCollection.set(linkShares, {parse: true});
824
825			// use the old crappy way for other shares for now
826			return {
827				reshare: reshare,
828				shares: shares,
829				permissions: permissions
830			};
831		},
832
833		/**
834		 * Parse fields of the response
835		 *
836		 * @param {OC.Share.Types.ShareInfo} share
837		 * @returns {OC.Share.Types.ShareInfo} share
838		 */
839		_parseShare: function(share) {
840			// properly parse some values because sometimes the server
841			// returns integers as string...
842			var i;
843			for (i = 0; i < SHARE_RESPONSE_INT_PROPS.length; i++) {
844				var propInt = SHARE_RESPONSE_INT_PROPS[i];
845				if (!_.isUndefined(share[propInt])) {
846					share[propInt] = parseInt(share[propInt], 10);
847				}
848			}
849			for (i = 0; i < SHARE_RESPONSE_JSON_PROPS.length; i++) {
850				// Parse JSON if not yet parsed
851				var propJson = SHARE_RESPONSE_JSON_PROPS[i];
852				if (!_.isUndefined(share[propJson]) && !_.isObject(share[propJson])) {
853					share[propJson] = JSON.parse(share[propJson]);
854				}
855			}
856			return share;
857		},
858
859		/**
860		 * Parses a string to an valid integer (unix timestamp)
861		 * @param time
862		 * @returns {*}
863		 * @internal Only used to work around a bug in the backend
864		 */
865		_parseTime: function(time) {
866			if (_.isString(time)) {
867				// skip empty strings and hex values
868				if (time === '' || (time.length > 1 && time[0] === '0' && time[1] === 'x')) {
869					return null;
870				}
871				time = parseInt(time, 10);
872				if(isNaN(time)) {
873					time = null;
874				}
875			}
876			return time;
877		},
878
879		/**
880		 * Returns a list of share types from the existing shares.
881		 *
882		 * @return {Array.<int>} array of share types
883		 */
884		getShareTypes: function() {
885			var result;
886			result = _.pluck(this.getSharesWithCurrentItem(), 'share_type');
887			if (this.hasLinkShare()) {
888				result.push(OC.Share.SHARE_TYPE_LINK);
889			}
890			return _.uniq(result);
891		},
892
893		/**
894		 * Returns share attributes for given share index
895		 *
896		 * @param shareIndex
897		 * @returns OC.Share.Types.ShareAttribute[]
898		 * @deprecated ShareAttributesAPI v1 registration will be deprecated. ShareAttributesAPI v2 requires apps to extend this class
899		 */
900		getShareAttributes: function(shareIndex) {
901			/** @type OC.Share.Types.ShareInfo **/
902			var share = this.get('shares')[shareIndex];
903			if(!_.isObject(share)) {
904				throw "Unknown Share";
905			}
906
907			if (_.isNull(share.attributes) || _.isUndefined(share.attributes)) {
908				return [];
909			}
910			return share.attributes;
911		},
912
913		/**
914		 * @param {array} properties
915		 * @param {array} options
916		 * @returns {OC.Share.Types.ShareAttribute[]}
917		 * @deprecated ShareAttributesAPI v1 will be deprecated. ShareAttributesAPI v2 requires apps to overwrite addShare
918		 * @private
919		 */
920		_handleAddShareAttributes: function(properties, options) {
921			var shareAttributesV1 = [];
922			var filteredRegisteredAttributes = this._filterRegisteredAttributes(properties.permissions);
923			_.map(filteredRegisteredAttributes, function (filteredRegisteredAttribute) {
924				var isCompatible = true;
925				// Check if this attribute can be added due to its incompatible attributes
926				_.map(filteredRegisteredAttribute.incompatibleAttributes, function (incompatibleAttribute) {
927					_.map(filteredRegisteredAttributes, function (checkAttr) {
928						if (incompatibleAttribute.scope === checkAttr.scope &&
929							incompatibleAttribute.key === checkAttr.key &&
930							incompatibleAttribute.enabled === checkAttr.default) {
931							isCompatible = false;
932						}
933					});
934				});
935
936				if (isCompatible) {
937					shareAttributesV1.push({
938						scope: filteredRegisteredAttribute.scope,
939						key: filteredRegisteredAttribute.key,
940						enabled: filteredRegisteredAttribute.default
941					});
942				}
943			});
944			var shareAttributes = shareAttributesV1;
945
946			/**
947			 * ShareAttributesAPI v2
948			 */
949			var shareAttributesV2 = properties.attributes || {};
950			for(var i in shareAttributesV2) {
951				var attr = shareAttributesV2[i];
952				shareAttributes = this._updateShareAttribute(shareAttributes, attr);
953			}
954
955			return shareAttributes;
956		},
957
958		/**
959		 * @param {number} shareId
960		 * @param {array} properties
961		 * @param {array} options
962		 * @returns {OC.Share.Types.ShareAttribute[]}
963		 * @deprecated ShareAttributesAPI v1 will be deprecated. ShareAttributesAPI v2 requires apps to overwrite updateShare
964		 * @private
965		 */
966		_handleUpdateShareAttributes: function(shareId, properties, options) {
967			var shareAttributesV1 = [];
968			var filteredAttributes = [];
969			var filteredRegisteredAttributes = this._filterRegisteredAttributes(properties.permissions);
970			_.map(filteredRegisteredAttributes, function(filteredRegisteredAttribute) {
971				// Check if this allowed registered attribute
972				// is on the list of currently set properties,
973				// and set this attribute
974				var found = false;
975				_.map(properties.attributes, function(currentAttribute) {
976					if (currentAttribute.key === filteredRegisteredAttribute.key
977						&& currentAttribute.scope === filteredRegisteredAttribute.scope) {
978						found = true;
979						filteredAttributes.push({
980							scope : filteredRegisteredAttribute.scope,
981							key: filteredRegisteredAttribute.key,
982							incompatibleAttributes: filteredRegisteredAttribute.incompatibleAttributes,
983							enabled: currentAttribute.enabled
984						});
985					}
986				});
987
988				// Make sure allowed registered attributes which are
989				// not yet set are added. These can become available
990				// e.g. because of share permission/attr change
991				// and need to be initialized with their default value
992				if (!found) {
993					filteredAttributes.push({
994						scope : filteredRegisteredAttribute.scope,
995						key: filteredRegisteredAttribute.key,
996						incompatibleAttributes: filteredRegisteredAttribute.incompatibleAttributes,
997						enabled: filteredRegisteredAttribute.default
998					});
999				}
1000			});
1001
1002			_.map(filteredAttributes, function(filteredAttribute) {
1003				// Filter attributes by their incompatible attributes
1004				var isCompatible = true;
1005				// Check if this attribute can be added due to its incompatible attributes
1006				_.map(filteredAttribute.incompatibleAttributes, function(incompatibleAttribute) {
1007					_.map(filteredAttributes, function(checkAttr) {
1008						if (incompatibleAttribute.scope === checkAttr.scope &&
1009							incompatibleAttribute.key === checkAttr.key &&
1010							incompatibleAttribute.enabled === checkAttr.enabled) {
1011							isCompatible = false;
1012						}
1013					});
1014				});
1015
1016				if (isCompatible) {
1017					shareAttributesV1.push({
1018						scope : filteredAttribute.scope,
1019						key: filteredAttribute.key,
1020						enabled: filteredAttribute.enabled
1021					});
1022				}
1023			});
1024
1025			var shareAttributes = shareAttributesV1;
1026
1027			/**
1028			 * ShareAttributesAPI v2
1029			 */
1030			var shareAttributesV2 = properties.attributes || {};
1031			for(var i in shareAttributesV2) {
1032				var attr = shareAttributesV2[i];
1033				if (!this.getRegisteredShareAttribute(attr.scope , attr.key)) {
1034					// modify only ShareAttributesAPI v2
1035					shareAttributes = this._updateShareAttribute(shareAttributes, attr);
1036				}
1037			}
1038
1039			return shareAttributes;
1040		},
1041
1042		_updateShareAttribute: function(shareAttributes, attr) {
1043			var exists = false;
1044			for(var i in shareAttributes) {
1045				if (shareAttributes[i].scope === attr.scope
1046					&& shareAttributes[i].key === attr.key) {
1047					shareAttributes[i] = attr;
1048					exists = true;
1049				}
1050			}
1051			if (!exists) {
1052				shareAttributes.push(attr);
1053			}
1054
1055			return shareAttributes;
1056		},
1057
1058		/**
1059		 * Filter registered attributes by current share permissions
1060		 *
1061		 * @param {number} permissions
1062		 * @returns {OC.Share.Types.RegisteredShareAttribute[]}
1063		 * @deprecated ShareAttributesAPI v1 registration will be deprecated. ShareAttributesAPI v2 requires apps to extend this class
1064		 * @private
1065		 */
1066		_filterRegisteredAttributes: function(permissions) {
1067			var filteredByPermissions = [];
1068			for(var i in this._registeredAttributes) {
1069				var compatible = true;
1070				var attr = this._registeredAttributes[i];
1071				for(var ii in attr.incompatiblePermissions) {
1072					if (this._hasPermission(permissions, attr.incompatiblePermissions[ii])) {
1073						compatible = false;
1074					}
1075				}
1076				for(var ii in attr.requiredPermissions) {
1077					if (!this._hasPermission(permissions, attr.requiredPermissions[ii])) {
1078						compatible = false;
1079					}
1080				}
1081
1082				if (compatible) {
1083					filteredByPermissions.push(attr);
1084				}
1085			}
1086
1087			return filteredByPermissions;
1088		},
1089
1090		/**
1091		 * Returns share attribute label for given attribute scope and name. If
1092		 * attribute does not exist, null is returned.
1093		 *
1094		 * @param scope
1095		 * @param key
1096		 * @returns {OC.Share.Types.RegisteredShareAttribute}
1097		 * @deprecated ShareAttributesAPI v1 registration will be deprecated. ShareAttributesAPI v2 requires apps to extend this class
1098		 */
1099		getRegisteredShareAttribute: function(scope, key) {
1100			for(var i in this._registeredAttributes) {
1101				if (this._registeredAttributes[i].scope === scope
1102					&& this._registeredAttributes[i].key === key) {
1103					return this._registeredAttributes[i];
1104				}
1105			}
1106			return null;
1107		},
1108
1109		/**
1110		 * Apps can register default share attributes. The applications
1111		 * registering share attributes are required to follow the rules:
1112		 *   attribute enabled -> functionality is added (e.g. can download)
1113		 *   attribute disabled -> functionality is restricted
1114		 *   incompatible attribute -> functionality is ignored
1115		 *
1116		 * @param {OC.Share.Types.RegisteredShareAttribute} $shareAttribute
1117		 * @deprecated ShareAttributesAPI v1 registration will be deprecated. ShareAttributesAPI v2 requires apps to extend this class
1118		 */
1119		registerShareAttribute: function($shareAttribute) {
1120			// Add extra permission or update if already existing
1121			var exists = false;
1122			for(var i in this._registeredAttributes) {
1123				if (this._registeredAttributes[i].scope === $shareAttribute.scope
1124					&& this._registeredAttributes[i].key === $shareAttribute.key) {
1125					this._registeredAttributes[i] = $shareAttribute;
1126					exists = true;
1127				}
1128			}
1129			if (!exists) {
1130				this._registeredAttributes.push($shareAttribute);
1131			}
1132
1133		}
1134
1135	});
1136
1137	OC.Share.ShareItemModel = ShareItemModel;
1138})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.