shareitemmodel.js 20 KB

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