OneDriveClient.js 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543
  1. /**
  2. * Copyright (c) 2006-2020, JGraph Ltd
  3. * Copyright (c) 2006-2020, draw.io AG
  4. */
  5. //Add a closure to hide the class private variables without changing the code a lot
  6. (function ()
  7. {
  8. var _token = null;
  9. window.OneDriveClient = function(editorUi, isExtAuth, inlinePicker, noLogout)
  10. {
  11. if (isExtAuth == null && window.urlParams != null && window.urlParams['extAuth'] == '1')
  12. {
  13. isExtAuth = true;
  14. }
  15. if (inlinePicker == null) //Use inline picker as default
  16. {
  17. inlinePicker = window.Editor != null? Editor.oneDriveInlinePicker : true;
  18. }
  19. if (noLogout == null && window.urlParams != null && window.urlParams['noLogoutOD'] == '1')
  20. {
  21. noLogout = true;
  22. }
  23. DrawioClient.call(this, editorUi, isExtAuth? 'oneDriveExtAuthInfo' : 'oneDriveAuthInfo');
  24. this.isExtAuth = isExtAuth;
  25. this.inlinePicker = inlinePicker;
  26. this.noLogout = noLogout;
  27. var authInfo = JSON.parse(this.token);
  28. if (authInfo != null)
  29. {
  30. this.endpointHint = authInfo.endpointHint != null ? authInfo.endpointHint.replace('/Documents', '/_layouts/15/onedrive.aspx') : authInfo.endpointHint;
  31. }
  32. };
  33. // Extends DrawioClient
  34. mxUtils.extend(OneDriveClient, DrawioClient);
  35. /**
  36. * Specifies if thumbnails should be enabled. Default is true.
  37. * LATER: If thumbnails are disabled, make sure to replace the
  38. * existing thumbnail with the placeholder only once.
  39. */
  40. OneDriveClient.prototype.clientId = window.DRAWIO_MSGRAPH_CLIENT_ID || ((window.location.hostname == 'test.draw.io') ?
  41. '2e598409-107f-4b59-89ca-d7723c8e00a4' : '45c10911-200f-4e27-a666-9e9fca147395');
  42. OneDriveClient.prototype.clientId = window.location.hostname == 'app.diagrams.net' ?
  43. 'b5ff67d6-3155-4fca-965a-59a3655c4476' : OneDriveClient.prototype.clientId;
  44. OneDriveClient.prototype.clientId = window.location.hostname == 'viewer.diagrams.net' ?
  45. '417a451a-a343-4788-b6c1-901e63182565' : OneDriveClient.prototype.clientId;
  46. /**
  47. * OAuth 2.0 scopes for installing Drive Apps.
  48. */
  49. OneDriveClient.prototype.scopes = 'user.read files.readwrite.all sites.read.all';
  50. /**
  51. * OAuth 2.0 scopes for installing Drive Apps.
  52. */
  53. OneDriveClient.prototype.redirectUri = window.location.protocol + '//' + window.location.host + '/microsoft';
  54. OneDriveClient.prototype.pickerRedirectUri = window.location.protocol + '//' + window.location.host + '/onedrive3.html';
  55. /**
  56. * This is the default endpoint for personal accounts
  57. */
  58. OneDriveClient.prototype.defEndpointHint = 'api.onedrive.com';
  59. OneDriveClient.prototype.endpointHint = OneDriveClient.prototype.defEndpointHint;
  60. /**
  61. * Executes the first step for connecting to Google Drive.
  62. */
  63. OneDriveClient.prototype.extension = '.drawio';
  64. /**
  65. * Executes the first step for connecting to Google Drive.
  66. */
  67. OneDriveClient.prototype.baseUrl = 'https://graph.microsoft.com/v1.0';
  68. /**
  69. * Empty function used when no callback is needed
  70. */
  71. OneDriveClient.prototype.emptyFn = function(){};
  72. OneDriveClient.prototype.invalidFilenameRegExs = [
  73. /[~"#%\*:<>\?\/\\{\|}]/,
  74. /^\.lock$/i,
  75. /^CON$/i,
  76. /^PRN$/i,
  77. /^AUX$/i,
  78. /^NUL$/i,
  79. /^COM\d$/i,
  80. /^LPT\d$/i,
  81. /^desktop\.ini$/i,
  82. /_vti_/i
  83. ];
  84. /**
  85. * Check if the file/folder name is valid
  86. */
  87. OneDriveClient.prototype.isValidFilename = function(filename)
  88. {
  89. if (filename == null || filename === '') return false;
  90. for (var i = 0; i < this.invalidFilenameRegExs.length; i++)
  91. {
  92. if (this.invalidFilenameRegExs[i].test(filename)) return false;
  93. }
  94. return true;
  95. };
  96. /**
  97. * Checks if the client is authorized and calls the next step.
  98. */
  99. OneDriveClient.prototype.get = function(url, onload, onerror)
  100. {
  101. var req = new mxXmlRequest(url, null, 'GET');
  102. req.setRequestHeaders = mxUtils.bind(this, function(request, params)
  103. {
  104. request.setRequestHeader('Authorization', 'Bearer ' + _token);
  105. });
  106. req.send(onload, onerror);
  107. return req;
  108. };
  109. /**
  110. * Checks if the client is authorized and calls the next step.
  111. */
  112. OneDriveClient.prototype.updateUser = function(success, error, failOnAuth)
  113. {
  114. var acceptResponse = true;
  115. var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
  116. {
  117. acceptResponse = false;
  118. error({code: App.ERROR_TIMEOUT});
  119. }), this.ui.timeout);
  120. this.get(this.baseUrl + '/me', mxUtils.bind(this, function(req)
  121. {
  122. window.clearTimeout(timeoutThread);
  123. if (acceptResponse)
  124. {
  125. if (req.getStatus() < 200 || req.getStatus() >= 300)
  126. {
  127. if (!failOnAuth)
  128. {
  129. this.logout();
  130. this.authenticate(mxUtils.bind(this, function()
  131. {
  132. this.updateUser(success, error, true);
  133. }), error);
  134. }
  135. else
  136. {
  137. error({message: mxResources.get('accessDenied')});
  138. }
  139. }
  140. else
  141. {
  142. var data = JSON.parse(req.getText());
  143. this.setUser(new DrawioUser(data.id, null, data.displayName));
  144. success();
  145. }
  146. }
  147. }), mxUtils.bind(this, function(err)
  148. {
  149. window.clearTimeout(timeoutThread);
  150. if (acceptResponse)
  151. {
  152. error(err);
  153. }
  154. }));
  155. };
  156. OneDriveClient.prototype.resetTokenRefresh = function(expires_in)
  157. {
  158. if (this.tokenRefreshThread != null)
  159. {
  160. window.clearTimeout(this.tokenRefreshThread);
  161. this.tokenRefreshThread = null;
  162. }
  163. // Starts timer to refresh token before it expires
  164. if (expires_in > 0)
  165. {
  166. this.tokenRefreshInterval = expires_in * 1000;
  167. this.tokenRefreshThread = window.setTimeout(mxUtils.bind(this, function()
  168. {
  169. //Get a new fresh accessToken
  170. this.authenticate(this.emptyFn, this.emptyFn, true);
  171. }), expires_in * 900);
  172. }
  173. };
  174. /**
  175. * Authorizes the client, gets the userId and calls <open>.
  176. */
  177. OneDriveClient.prototype.authenticate = function(success, error, failOnAuth)
  178. {
  179. if (this.isExtAuth)
  180. {
  181. window.parent.oneDriveAuth(mxUtils.bind(this, function(newAuthInfo)
  182. {
  183. this.updateAuthInfo(newAuthInfo, true, this.endpointHint == null, success, error);
  184. }), error, window.urlParams != null && urlParams['odAuthCancellable'] == '1');
  185. return;
  186. }
  187. var req = new mxXmlRequest(this.redirectUri + '?getState=1', null, 'GET');
  188. req.send(mxUtils.bind(this, function(req)
  189. {
  190. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  191. {
  192. this.authenticateStep2(req.getText(), success, error, failOnAuth);
  193. }
  194. else if (error != null)
  195. {
  196. error(req);
  197. }
  198. }), error);
  199. };
  200. OneDriveClient.prototype.updateAuthInfo = function(newAuthInfo, remember, forceUserUpdate, success, error)
  201. {
  202. if (forceUserUpdate)
  203. {
  204. this.setUser(null);
  205. }
  206. _token = newAuthInfo.access_token;
  207. delete newAuthInfo.access_token; //Don't store access token
  208. newAuthInfo.expiresOn = Date.now() + newAuthInfo.expires_in * 1000;
  209. this.tokenExpiresOn = newAuthInfo.expiresOn;
  210. newAuthInfo.remember = remember;
  211. this.setPersistentToken(JSON.stringify(newAuthInfo), !remember);
  212. this.resetTokenRefresh(newAuthInfo.expires_in);
  213. if (forceUserUpdate)
  214. {
  215. //Find out the type of the account + endpoint
  216. this.getAccountTypeAndEndpoint(mxUtils.bind(this, function()
  217. {
  218. success();
  219. }), error);
  220. }
  221. else
  222. {
  223. success();
  224. }
  225. };
  226. OneDriveClient.prototype.authenticateStep2 = function(state, success, error, failOnAuth)
  227. {
  228. if (window.onOneDriveCallback == null)
  229. {
  230. var auth = mxUtils.bind(this, function()
  231. {
  232. var acceptAuthResponse = true;
  233. //Retry request with refreshed token
  234. var authInfo = JSON.parse(this.getPersistentToken(true));
  235. if (authInfo != null)
  236. {
  237. var req = new mxXmlRequest(this.redirectUri + '?state=' + encodeURIComponent('cId=' + this.clientId + '&domain=' + window.location.hostname + '&token=' + state), null, 'GET'); //To identify which app/domain is used
  238. req.send(mxUtils.bind(this, function(req)
  239. {
  240. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  241. {
  242. this.updateAuthInfo(JSON.parse(req.getText()), authInfo.remember, false, success, error);
  243. }
  244. else
  245. {
  246. this.clearPersistentToken();
  247. this.setUser(null);
  248. _token = null;
  249. if (req.getStatus() == 401 && !failOnAuth) // (Unauthorized) [e.g, invalid refresh token]
  250. {
  251. auth();
  252. }
  253. else
  254. {
  255. error({message: mxResources.get('accessDenied'), retry: auth});
  256. }
  257. }
  258. }), error);
  259. }
  260. else
  261. {
  262. this.ui.showAuthDialog(this, true, mxUtils.bind(this, function(remember, authSuccess)
  263. {
  264. var url = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize' +
  265. '?client_id=' + this.clientId + '&response_type=code' +
  266. '&redirect_uri=' + encodeURIComponent(this.redirectUri) +
  267. '&scope=' + encodeURIComponent(this.scopes + (remember? ' offline_access' : '')) +
  268. '&state=' + encodeURIComponent('cId=' + this.clientId + '&domain=' + window.location.hostname + '&token=' + state); //To identify which app/domain is used
  269. var width = 525,
  270. height = 525,
  271. screenX = window.screenX,
  272. screenY = window.screenY,
  273. outerWidth = window.outerWidth,
  274. outerHeight = window.outerHeight;
  275. var left = screenX + Math.max(outerWidth - width, 0) / 2;
  276. var top = screenY + Math.max(outerHeight - height, 0) / 2;
  277. var features = ['width=' + width, 'height=' + height,
  278. 'top=' + top, 'left=' + left,
  279. 'status=no', 'resizable=yes',
  280. 'toolbar=no', 'menubar=no',
  281. 'scrollbars=yes'];
  282. var popup = window.open(url, 'odauth', features.join(','));
  283. if (popup != null)
  284. {
  285. window.onOneDriveCallback = mxUtils.bind(this, function(authInfo, authWindow)
  286. {
  287. if (acceptAuthResponse)
  288. {
  289. window.onOneDriveCallback = null;
  290. acceptAuthResponse = false;
  291. try
  292. {
  293. if (authInfo == null)
  294. {
  295. error({message: mxResources.get('accessDenied'), retry: auth});
  296. }
  297. else
  298. {
  299. if (authSuccess != null)
  300. {
  301. authSuccess();
  302. }
  303. this.updateAuthInfo(authInfo, remember, true, success, error);
  304. }
  305. }
  306. catch (e)
  307. {
  308. error(e);
  309. }
  310. finally
  311. {
  312. if (authWindow != null)
  313. {
  314. authWindow.close();
  315. }
  316. }
  317. }
  318. else if (authWindow != null)
  319. {
  320. authWindow.close();
  321. }
  322. });
  323. popup.focus();
  324. }
  325. }), mxUtils.bind(this, function()
  326. {
  327. if (acceptAuthResponse)
  328. {
  329. window.onOneDriveCallback = null;
  330. acceptAuthResponse = false;
  331. error({message: mxResources.get('accessDenied'), retry: auth});
  332. }
  333. }));
  334. }
  335. });
  336. auth();
  337. }
  338. else
  339. {
  340. error({code: App.ERROR_BUSY});
  341. }
  342. };
  343. OneDriveClient.prototype.getAccountTypeAndEndpoint = function(success, error)
  344. {
  345. this.get(this.baseUrl + '/me/drive/root', mxUtils.bind(this, function(req)
  346. {
  347. try
  348. {
  349. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  350. {
  351. var resp = JSON.parse(req.getText());
  352. if (resp.webUrl.indexOf('.sharepoint.com') > 0)
  353. {
  354. //TODO Confirm this works with all sharepoint sites
  355. this.endpointHint = resp.webUrl.replace('/Documents', '/_layouts/15/onedrive.aspx');
  356. }
  357. else
  358. {
  359. this.endpointHint = this.defEndpointHint;
  360. }
  361. //Update authInfo with endpointHint
  362. var authInfo = JSON.parse(this.getPersistentToken(true));
  363. if (authInfo != null)
  364. {
  365. authInfo.endpointHint = this.endpointHint;
  366. this.setPersistentToken(JSON.stringify(authInfo), !authInfo.remember);
  367. }
  368. success();
  369. return;
  370. }
  371. }
  372. catch(e) {}
  373. //It is expected to work as this call immediately follows getting a fresh access token
  374. error({message: mxResources.get('unknownError') + ' (Code: ' + req.getStatus() + ')'});
  375. }), error);
  376. };
  377. /**
  378. * Checks if the client is authorized and calls the next step.
  379. */
  380. OneDriveClient.prototype.executeRequest = function(url, success, error)
  381. {
  382. var doExecute = mxUtils.bind(this, function(failOnAuth)
  383. {
  384. var acceptResponse = true;
  385. var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
  386. {
  387. acceptResponse = false;
  388. error({code: App.ERROR_TIMEOUT, retry: doExecute});
  389. }), this.ui.timeout);
  390. this.get(url, mxUtils.bind(this, function(req)
  391. {
  392. window.clearTimeout(timeoutThread);
  393. if (acceptResponse)
  394. {
  395. // 404 (file not found) is a valid response for checkExists
  396. if ((req.getStatus() >= 200 && req.getStatus() <= 299) || req.getStatus() == 404)
  397. {
  398. if (this.user == null)
  399. {
  400. this.updateUser(this.emptyFn, this.emptyFn, true);
  401. }
  402. success(req);
  403. }
  404. // 400 is returns if wrong user for this file
  405. else if (!failOnAuth && (req.getStatus() === 401 || req.getStatus() === 400))
  406. {
  407. //Authorize again using the refresh token
  408. this.authenticate(function()
  409. {
  410. doExecute(true);
  411. }, error, failOnAuth);
  412. }
  413. else
  414. {
  415. error(this.parseRequestText(req));
  416. }
  417. }
  418. }), mxUtils.bind(this, function(err)
  419. {
  420. window.clearTimeout(timeoutThread);
  421. if (acceptResponse)
  422. {
  423. error(err);
  424. }
  425. }));
  426. });
  427. if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
  428. {
  429. this.authenticate(function()
  430. {
  431. doExecute(true);
  432. }, error);
  433. }
  434. else
  435. {
  436. doExecute(false);
  437. }
  438. };
  439. /**
  440. * Checks if the client is authorized and calls the next step.
  441. */
  442. OneDriveClient.prototype.checkToken = function(fn)
  443. {
  444. if (_token == null || this.tokenRefreshThread == null || this.tokenExpiresOn - Date.now() < 60000)
  445. {
  446. this.authenticate(fn, this.emptyFn);
  447. }
  448. else
  449. {
  450. fn();
  451. }
  452. };
  453. OneDriveClient.prototype.getItemRef = function(id)
  454. {
  455. var idParts = id.split('/');
  456. if (idParts.length > 1)
  457. {
  458. return {driveId: idParts[0], id: idParts[1]};
  459. }
  460. else
  461. {
  462. return {id: id};
  463. }
  464. };
  465. OneDriveClient.prototype.getItemURL = function(id, relative)
  466. {
  467. var idParts = id.split('/');
  468. if (idParts.length > 1)
  469. {
  470. var driveId = idParts[0];
  471. var itemId = idParts[1];
  472. return (relative? '' : this.baseUrl) + '/drives/' + driveId + (itemId == 'root' ? '/root' : '/items/' + itemId);
  473. }
  474. else
  475. {
  476. return (relative? '' : this.baseUrl) + '/me/drive/items/' + id;
  477. }
  478. };
  479. /**
  480. * Checks if the client is authorized and calls the next step.
  481. */
  482. OneDriveClient.prototype.getLibrary = function(id, success, error)
  483. {
  484. this.getFile(id, success, error, false, true);
  485. };
  486. /**
  487. * Workaround for added content to HTML files in Sharepoint.
  488. */
  489. OneDriveClient.prototype.removeExtraHtmlContent = function(data)
  490. {
  491. var idx = data.lastIndexOf('<html><head><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8"><meta name="Robots" ');
  492. if (idx > 0)
  493. {
  494. data = data.substring(0, idx);
  495. }
  496. return data;
  497. };
  498. /**
  499. * Checks if the client is authorized and calls the next step.
  500. */
  501. OneDriveClient.prototype.getFile = function(id, success, error, denyConvert, asLibrary)
  502. {
  503. asLibrary = (asLibrary != null) ? asLibrary : false;
  504. this.executeRequest(this.getItemURL(id), mxUtils.bind(this, function(req)
  505. {
  506. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  507. {
  508. var meta = JSON.parse(req.getText());
  509. var binary = /\.png$/i.test(meta.name);
  510. // Handles .vsdx, Gliffy and PNG+XML files by creating a temporary file
  511. if (/\.v(dx|sdx?)$/i.test(meta.name) || /\.gliffy$/i.test(meta.name) ||
  512. /\.pdf$/i.test(meta.name) || (!this.ui.useCanvasForExport && binary))
  513. {
  514. var mimeType = (meta.file != null) ? meta.file.mimeType : null;
  515. this.ui.convertFile(meta['@microsoft.graph.downloadUrl'], meta.name, mimeType,
  516. this.extension, success, error);
  517. }
  518. else
  519. {
  520. var acceptResponse = true;
  521. var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
  522. {
  523. acceptResponse = false;
  524. error({code: App.ERROR_TIMEOUT})
  525. }), this.ui.timeout);
  526. this.ui.editor.loadUrl(meta['@microsoft.graph.downloadUrl'], mxUtils.bind(this, function(data)
  527. {
  528. try
  529. {
  530. window.clearTimeout(timeoutThread);
  531. if (acceptResponse)
  532. {
  533. if (/\.html$/i.test(meta.name))
  534. {
  535. data = this.removeExtraHtmlContent(data);
  536. }
  537. var index = (binary) ? data.lastIndexOf(',') : -1;
  538. var file = null;
  539. if (index > 0)
  540. {
  541. var xml = this.ui.extractGraphModelFromPng(data);
  542. if (xml != null && xml.length > 0)
  543. {
  544. data = xml;
  545. }
  546. else
  547. {
  548. // Imports as PNG image
  549. file = new LocalFile(this.ui, data, meta.name, true);
  550. }
  551. }
  552. // Checks for base64 encoded mxfile
  553. else if (data.substring(0, 32) == 'data:image/png;base64,PG14ZmlsZS')
  554. {
  555. var temp = data.substring(22);
  556. data = (window.atob && !mxClient.IS_SF) ? atob(temp) : Base64.decode(temp);
  557. }
  558. if (Graph.fileSupport && new XMLHttpRequest().upload && this.ui.isRemoteFileFormat(data, meta['@microsoft.graph.downloadUrl']))
  559. {
  560. this.ui.parseFile(new Blob([data], {type: 'application/octet-stream'}), mxUtils.bind(this, function(xhr)
  561. {
  562. try
  563. {
  564. if (xhr.readyState == 4)
  565. {
  566. if (xhr.status >= 200 && xhr.status <= 299)
  567. {
  568. success(new LocalFile(this.ui, xhr.responseText, meta.name + this.extension, true));
  569. }
  570. else if (error != null)
  571. {
  572. error({message: mxResources.get('errorLoadingFile')});
  573. }
  574. }
  575. }
  576. catch (e)
  577. {
  578. if (error != null)
  579. {
  580. error(e);
  581. }
  582. else
  583. {
  584. throw e;
  585. }
  586. }
  587. }), meta.name);
  588. }
  589. else
  590. {
  591. if (file != null)
  592. {
  593. success(file);
  594. }
  595. else if (asLibrary)
  596. {
  597. success(new OneDriveLibrary(this.ui, data, meta));
  598. }
  599. else
  600. {
  601. success(new OneDriveFile(this.ui, data, meta));
  602. }
  603. }
  604. }
  605. }
  606. catch (e)
  607. {
  608. if (error != null)
  609. {
  610. error(e);
  611. }
  612. else
  613. {
  614. throw e;
  615. }
  616. }
  617. }), mxUtils.bind(this, function(req)
  618. {
  619. window.clearTimeout(timeoutThread);
  620. if (acceptResponse)
  621. {
  622. error(this.parseRequestText(req));
  623. }
  624. }), binary || (meta.file != null && meta.file.mimeType != null &&
  625. ((meta.file.mimeType.substring(0, 6) == 'image/' &&
  626. meta.file.mimeType.substring(0, 9) != 'image/svg') ||
  627. meta.file.mimeType == 'application/pdf')));
  628. }
  629. }
  630. else
  631. {
  632. if (this.isExtAuth)
  633. {
  634. error({message: mxResources.get('fileNotFoundOrDenied') +
  635. (this.user != null ? ' (' + this.user.displayName + ')' : '')});
  636. }
  637. else
  638. {
  639. error(this.parseRequestText(req));
  640. }
  641. }
  642. }), error);
  643. };
  644. /**
  645. * Translates this point by the given vector.
  646. *
  647. * @param {number} dx X-coordinate of the translation.
  648. * @param {number} dy Y-coordinate of the translation.
  649. */
  650. OneDriveClient.prototype.renameFile = function(file, filename, success, error)
  651. {
  652. if (file != null && filename != null)
  653. {
  654. if (!this.isValidFilename(filename))
  655. {
  656. error({message: this.invalidFilenameRegExs[0].test(filename) ?
  657. mxResources.get('oneDriveCharsNotAllowed') : mxResources.get('oneDriveInvalidDeviceName')});
  658. return;
  659. }
  660. // TODO: How to force overwrite file with same name?
  661. this.checkExists(file.getParentId(), filename, false, mxUtils.bind(this, function(checked)
  662. {
  663. if (checked)
  664. {
  665. this.writeFile(this.getItemURL(file.getId()), JSON.stringify({name: filename}), 'PATCH', 'application/json', success, error);
  666. }
  667. else
  668. {
  669. error();
  670. }
  671. }));
  672. }
  673. };
  674. /**
  675. * Translates this point by the given vector.
  676. *
  677. * @param {number} dx X-coordinate of the translation.
  678. * @param {number} dy Y-coordinate of the translation.
  679. */
  680. OneDriveClient.prototype.moveFile = function(id, folderId, success, error)
  681. {
  682. //check that the source and destination are on the same drive
  683. var folderInfo = this.getItemRef(folderId);
  684. var fileInfo = this.getItemRef(id);
  685. if (folderInfo.driveId != fileInfo.driveId)
  686. {
  687. error({message: mxResources.get('cannotMoveOneDrive', null, 'Moving a file between accounts is not supported yet.')});
  688. }
  689. else
  690. {
  691. this.writeFile(this.getItemURL(id), JSON.stringify({parentReference: folderInfo}), 'PATCH', 'application/json', success, error);
  692. }
  693. };
  694. /**
  695. * Translates this point by the given vector.
  696. *
  697. * @param {number} dx X-coordinate of the translation.
  698. * @param {number} dy Y-coordinate of the translation.
  699. */
  700. OneDriveClient.prototype.insertLibrary = function(filename, data, success, error, folderId)
  701. {
  702. this.insertFile(filename, data, success, error, true, folderId);
  703. };
  704. /**
  705. * Translates this point by the given vector.
  706. *
  707. * @param {number} dx X-coordinate of the translation.
  708. * @param {number} dy Y-coordinate of the translation.
  709. */
  710. OneDriveClient.prototype.insertFile = function(filename, data, success, error, asLibrary, folderId)
  711. {
  712. if (!this.isValidFilename(filename))
  713. {
  714. error({message: this.invalidFilenameRegExs[0].test(filename) ?
  715. mxResources.get('oneDriveCharsNotAllowed') : mxResources.get('oneDriveInvalidDeviceName')});
  716. return;
  717. }
  718. asLibrary = (asLibrary != null) ? asLibrary : false;
  719. this.checkExists(folderId, filename, true, mxUtils.bind(this, function(checked)
  720. {
  721. if (checked)
  722. {
  723. var folder = '/me/drive/root';
  724. if (folderId != null)
  725. {
  726. folder = this.getItemURL(folderId, true);
  727. }
  728. var insertSuccess = mxUtils.bind(this, function(meta)
  729. {
  730. if (asLibrary)
  731. {
  732. success(new OneDriveLibrary(this.ui, data, meta));
  733. }
  734. else
  735. {
  736. success(new OneDriveFile(this.ui, data, meta));
  737. }
  738. });
  739. var url = this.baseUrl + folder + '/children/' + encodeURIComponent(filename) + '/content';
  740. //OneDrive has a limit on PUT API of 4MB, larger files needs to use the upload session method
  741. if (data.length >= 4000000 /*4MB*/)
  742. {
  743. //Create empty file first then upload. TODO Can we get an upload session for non-existing files?
  744. this.writeFile(url, '', 'PUT', null, mxUtils.bind(this, function(meta)
  745. {
  746. this.writeLargeFile(this.getItemURL(meta.id), data, insertSuccess, error);
  747. }), error);
  748. }
  749. else
  750. {
  751. this.writeFile(url, data, 'PUT', null, insertSuccess, error);
  752. }
  753. }
  754. else
  755. {
  756. error();
  757. }
  758. }))
  759. };
  760. /**
  761. * Translates this point by the given vector.
  762. *
  763. * @param {number} dx X-coordinate of the translation.
  764. * @param {number} dy Y-coordinate of the translation.
  765. */
  766. OneDriveClient.prototype.checkExists = function(parentId, filename, askReplace, fn)
  767. {
  768. var folder = '/me/drive/root';
  769. if (parentId != null)
  770. {
  771. folder = this.getItemURL(parentId, true);
  772. }
  773. this.executeRequest(this.baseUrl + folder + '/children/' + encodeURIComponent(filename), mxUtils.bind(this, function(req)
  774. {
  775. if (req.getStatus() == 404)
  776. {
  777. fn(true);
  778. }
  779. else
  780. {
  781. if (askReplace)
  782. {
  783. this.ui.spinner.stop();
  784. this.ui.confirm(mxResources.get('replaceIt', [filename]), function()
  785. {
  786. fn(true);
  787. }, function()
  788. {
  789. fn(false);
  790. });
  791. }
  792. else
  793. {
  794. this.ui.spinner.stop();
  795. this.ui.showError(mxResources.get('error'), mxResources.get('fileExists'), mxResources.get('ok'), function()
  796. {
  797. fn(false);
  798. });
  799. }
  800. }
  801. }), function(req)
  802. {
  803. fn(false);
  804. }, true);
  805. };
  806. /**
  807. * Translates this point by the given vector.
  808. *
  809. * @param {number} dx X-coordinate of the translation.
  810. * @param {number} dy Y-coordinate of the translation.
  811. */
  812. OneDriveClient.prototype.saveFile = function(file, success, error, etag)
  813. {
  814. try
  815. {
  816. var savedData = file.getData();
  817. var fn = mxUtils.bind(this, function(data)
  818. {
  819. var saveSuccess = mxUtils.bind(this, function(resp)
  820. {
  821. success(resp, savedData);
  822. });
  823. var url = this.getItemURL(file.getId());
  824. //OneDrive has a limit on PUT API of 4MB, larger files needs to use the upload session method
  825. if (data.length >= 4000000 /*4MB*/)
  826. {
  827. this.writeLargeFile(url, data, saveSuccess, error, etag);
  828. }
  829. else
  830. {
  831. this.writeFile(url + '/content/', data, 'PUT', null, saveSuccess, error, etag);
  832. }
  833. });
  834. if (this.ui.useCanvasForExport && /(\.png)$/i.test(file.meta.name))
  835. {
  836. var p = this.ui.getPngFileProperties(this.ui.fileNode);
  837. this.ui.getEmbeddedPng(mxUtils.bind(this, function(data)
  838. {
  839. fn(this.ui.base64ToBlob(data, 'image/png'));
  840. }), error, (this.ui.getCurrentFile() != file) ?
  841. savedData : null, p.scale, p.border);
  842. }
  843. else
  844. {
  845. fn(savedData);
  846. }
  847. }
  848. catch (e)
  849. {
  850. error(e);
  851. }
  852. };
  853. OneDriveClient.prototype.writeLargeFile = function(url, data, success, error, etag)
  854. {
  855. try
  856. {
  857. var chunkSize = 4 * 1024 * 1024; //4MB chunk;
  858. if (data != null)
  859. {
  860. var uploadPart = mxUtils.bind(this, function(uploadUrl, index, retryCount)
  861. {
  862. try
  863. {
  864. retryCount = retryCount || 0;
  865. var acceptResponse = true;
  866. var timeoutThread = null;
  867. timeoutThread = window.setTimeout(mxUtils.bind(this, function()
  868. {
  869. acceptResponse = false;
  870. error({code: App.ERROR_TIMEOUT});
  871. }), this.ui.timeout);
  872. var part = data.substr(index, chunkSize);
  873. var req = new mxXmlRequest(uploadUrl, part, 'PUT');
  874. req.setRequestHeaders = mxUtils.bind(this, function(request, params)
  875. {
  876. request.setRequestHeader('Content-Length', part.length);
  877. request.setRequestHeader('Content-Range', 'bytes ' + index + '-' + (index + part.length - 1) + '/' + data.length);
  878. });
  879. req.send(mxUtils.bind(this, function(req)
  880. {
  881. window.clearTimeout(timeoutThread);
  882. if (acceptResponse)
  883. {
  884. var status = req.getStatus();
  885. if (status >= 200 && status <= 299)
  886. {
  887. var nextByte = index + part.length;
  888. if (nextByte == data.length)
  889. {
  890. success(JSON.parse(req.getText()));
  891. }
  892. else
  893. {
  894. uploadPart(uploadUrl, nextByte, retryCount);
  895. }
  896. }
  897. else if (status >= 500 && status <= 599 && retryCount < 2) //Retry on server errors
  898. {
  899. retryCount++;
  900. uploadPart(uploadUrl, index, retryCount);
  901. }
  902. else
  903. {
  904. error(this.parseRequestText(req), req);
  905. }
  906. }
  907. }), mxUtils.bind(this, function(req)
  908. {
  909. window.clearTimeout(timeoutThread);
  910. if (acceptResponse)
  911. {
  912. error(this.parseRequestText(req));
  913. }
  914. }));
  915. }
  916. catch (e)
  917. {
  918. error(e);
  919. }
  920. });
  921. var doExecute = mxUtils.bind(this, function(failOnAuth)
  922. {
  923. try
  924. {
  925. var acceptResponse = true;
  926. var timeoutThread = null;
  927. try
  928. {
  929. timeoutThread = window.setTimeout(mxUtils.bind(this, function()
  930. {
  931. acceptResponse = false;
  932. error({code: App.ERROR_TIMEOUT});
  933. }), this.ui.timeout);
  934. }
  935. catch (e)
  936. {
  937. // Ignore window closed
  938. }
  939. var req = new mxXmlRequest(url + '/createUploadSession', '{}', 'POST');
  940. req.setRequestHeaders = mxUtils.bind(this, function(request, params)
  941. {
  942. request.setRequestHeader('Content-Type', 'application/json');
  943. request.setRequestHeader('Authorization', 'Bearer ' + _token);
  944. if (etag != null)
  945. {
  946. request.setRequestHeader('If-Match', etag);
  947. }
  948. });
  949. req.send(mxUtils.bind(this, function(req)
  950. {
  951. window.clearTimeout(timeoutThread);
  952. if (acceptResponse)
  953. {
  954. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  955. {
  956. var resp = JSON.parse(req.getText());
  957. uploadPart(resp.uploadUrl, 0);
  958. }
  959. else if (!failOnAuth && req.getStatus() === 401)
  960. {
  961. this.authenticate(function()
  962. {
  963. doExecute(true);
  964. }, error, failOnAuth);
  965. }
  966. else
  967. {
  968. error(this.parseRequestText(req), req);
  969. }
  970. }
  971. }), mxUtils.bind(this, function(req)
  972. {
  973. window.clearTimeout(timeoutThread);
  974. if (acceptResponse)
  975. {
  976. error(this.parseRequestText(req));
  977. }
  978. }));
  979. }
  980. catch (e)
  981. {
  982. error(e);
  983. }
  984. });
  985. if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
  986. {
  987. this.authenticate(function()
  988. {
  989. doExecute(true);
  990. }, error);
  991. }
  992. else
  993. {
  994. doExecute(false);
  995. }
  996. }
  997. else
  998. {
  999. error({message: mxResources.get('unknownError')});
  1000. }
  1001. }
  1002. catch (e)
  1003. {
  1004. error(e);
  1005. }
  1006. };
  1007. /**
  1008. * Translates this point by the given vector.
  1009. *
  1010. * @param {number} dx X-coordinate of the translation.
  1011. * @param {number} dy Y-coordinate of the translation.
  1012. */
  1013. OneDriveClient.prototype.writeFile = function(url, data, method, contentType, success, error, etag)
  1014. {
  1015. try
  1016. {
  1017. if (url != null && data != null)
  1018. {
  1019. var doExecute = mxUtils.bind(this, function(failOnAuth)
  1020. {
  1021. try
  1022. {
  1023. var acceptResponse = true;
  1024. var timeoutThread = null;
  1025. try
  1026. {
  1027. timeoutThread = window.setTimeout(mxUtils.bind(this, function()
  1028. {
  1029. acceptResponse = false;
  1030. error({code: App.ERROR_TIMEOUT});
  1031. }), this.ui.timeout);
  1032. }
  1033. catch (e)
  1034. {
  1035. // Ignore window closed
  1036. }
  1037. var req = new mxXmlRequest(url, data, method);
  1038. req.setRequestHeaders = mxUtils.bind(this, function(request, params)
  1039. {
  1040. // Space deletes content type header. Specification says "text/plain"
  1041. // should work but returns an 415 Unsupported Media Type error
  1042. request.setRequestHeader('Content-Type', contentType || ' ');
  1043. //TODO This header is needed for moving a file between two different drives.
  1044. // Note: the response is empty when this header is used, also the server may take some time to really execute the request (i.e. async)
  1045. //request.setRequestHeader('Prefer', 'respond-async');
  1046. request.setRequestHeader('Authorization', 'Bearer ' + _token);
  1047. if (etag != null)
  1048. {
  1049. request.setRequestHeader('If-Match', etag);
  1050. }
  1051. });
  1052. req.send(mxUtils.bind(this, function(req)
  1053. {
  1054. window.clearTimeout(timeoutThread);
  1055. if (acceptResponse)
  1056. {
  1057. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  1058. {
  1059. if (this.user == null)
  1060. {
  1061. this.updateUser(this.emptyFn, this.emptyFn, true);
  1062. }
  1063. success(JSON.parse(req.getText()));
  1064. }
  1065. else if (!failOnAuth && req.getStatus() === 401)
  1066. {
  1067. this.authenticate(function()
  1068. {
  1069. doExecute(true);
  1070. }, error, failOnAuth);
  1071. }
  1072. else
  1073. {
  1074. error(this.parseRequestText(req), req);
  1075. }
  1076. }
  1077. }), mxUtils.bind(this, function(req)
  1078. {
  1079. window.clearTimeout(timeoutThread);
  1080. if (acceptResponse)
  1081. {
  1082. error(this.parseRequestText(req));
  1083. }
  1084. }));
  1085. }
  1086. catch (e)
  1087. {
  1088. error(e);
  1089. }
  1090. });
  1091. if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
  1092. {
  1093. this.authenticate(function()
  1094. {
  1095. doExecute(true);
  1096. }, error);
  1097. }
  1098. else
  1099. {
  1100. doExecute(false);
  1101. }
  1102. }
  1103. else
  1104. {
  1105. error({message: mxResources.get('unknownError')});
  1106. }
  1107. }
  1108. catch (e)
  1109. {
  1110. error(e);
  1111. }
  1112. };
  1113. /**
  1114. * Checks if the client is authorized and calls the next step.
  1115. */
  1116. OneDriveClient.prototype.parseRequestText = function(req)
  1117. {
  1118. var result = {message: mxResources.get('unknownError')};
  1119. try
  1120. {
  1121. result = JSON.parse(req.getText());
  1122. result.status = req.getStatus();
  1123. if (result.error)
  1124. {
  1125. result.error.status = result.status;
  1126. result.error.code = result.status;
  1127. }
  1128. }
  1129. catch (e)
  1130. {
  1131. // ignore
  1132. }
  1133. return result;
  1134. };
  1135. /**
  1136. * Checks if the client is authorized and calls the next step.
  1137. */
  1138. OneDriveClient.prototype.pickLibrary = function(fn)
  1139. {
  1140. this.pickFile(function(id)
  1141. {
  1142. // Ignores second argument
  1143. fn(id);
  1144. });
  1145. };
  1146. OneDriveClient.prototype.createInlinePicker = function(fn, foldersOnly)
  1147. {
  1148. return mxUtils.bind(this, function()
  1149. {
  1150. var odPicker = null;
  1151. var div = document.createElement('div');
  1152. div.style.width = '550px';
  1153. div.style.height = '435px';
  1154. div.style.position = 'relative';
  1155. var dlg = new CustomDialog(this.ui, div, mxUtils.bind(this, function()
  1156. {
  1157. var item = odPicker.getSelectedItem();
  1158. if (item != null)
  1159. {
  1160. if (foldersOnly && typeof item.folder == 'object')
  1161. {
  1162. fn({
  1163. value: [item]
  1164. });
  1165. return;
  1166. }
  1167. else if (!item.folder)
  1168. {
  1169. fn(OneDriveFile.prototype.getIdOf(item));
  1170. return;
  1171. }
  1172. }
  1173. return mxResources.get('invalidSel', null, 'Invalid selection');
  1174. }), null, mxResources.get(foldersOnly? 'save' :'open'), null, null, null, null, true);
  1175. this.ui.showDialog(dlg.container, 550, 500, true, true);
  1176. odPicker = new mxODPicker(div, null, mxUtils.bind(this, function(url, success, error)
  1177. {
  1178. this.executeRequest(this.baseUrl + url, function(req)
  1179. {
  1180. success(JSON.parse(req.getText()));
  1181. }, error);
  1182. }), mxUtils.bind(this, function(id, driveId, success, error)
  1183. {
  1184. this.executeRequest(this.baseUrl + '/drives/' + driveId + '/items/' + id, function(req)
  1185. {
  1186. success(JSON.parse(req.getText()));
  1187. }, error);
  1188. }), null, null, function(item)
  1189. {
  1190. if (foldersOnly) //Currently this is not called when in foldersOnly mode
  1191. {
  1192. fn({
  1193. value: [item]
  1194. });
  1195. }
  1196. else
  1197. {
  1198. fn(OneDriveFile.prototype.getIdOf(item));
  1199. }
  1200. },
  1201. mxUtils.bind(this, function(err)
  1202. {
  1203. this.ui.showError(mxResources.get('error'), err);
  1204. }), foldersOnly);
  1205. });
  1206. };
  1207. /**
  1208. * Checks if the client is authorized and calls the next step.
  1209. */
  1210. OneDriveClient.prototype.pickFolder = function(fn, direct)
  1211. {
  1212. var errorFn = mxUtils.bind(this, function(e)
  1213. {
  1214. this.ui.showError(mxResources.get('error'), e && e.message? e.message : e);
  1215. });
  1216. var odSaveDlg = mxUtils.bind(this, function(direct)
  1217. {
  1218. var openSaveDlg = this.inlinePicker? this.createInlinePicker(fn, true) :
  1219. mxUtils.bind(this, function()
  1220. {
  1221. OneDrive.save(
  1222. {
  1223. clientId: this.clientId,
  1224. action: 'query',
  1225. openInNewWindow: true,
  1226. advanced:
  1227. {
  1228. 'endpointHint': mxClient.IS_IE11? null : this.endpointHint, //IE11 doen't work with our modified version, so, setting endpointHint disable using our token BUT will force relogin!
  1229. 'redirectUri': this.pickerRedirectUri,
  1230. 'queryParameters': 'select=id,name,parentReference',
  1231. 'accessToken': _token,
  1232. isConsumerAccount: false
  1233. },
  1234. success: mxUtils.bind(this, function(files)
  1235. {
  1236. fn(files);
  1237. //Update the token in case a login with a different user
  1238. if (mxClient.IS_IE11)
  1239. {
  1240. _token = files.accessToken;
  1241. }
  1242. }),
  1243. cancel: mxUtils.bind(this, function()
  1244. {
  1245. // do nothing
  1246. }),
  1247. error: errorFn
  1248. });
  1249. });
  1250. if (direct)
  1251. {
  1252. openSaveDlg();
  1253. }
  1254. else
  1255. {
  1256. this.ui.confirm(mxResources.get('useRootFolder'), mxUtils.bind(this, function()
  1257. {
  1258. fn({value: [{id: 'root', name: 'root', parentReference: {driveId: 'me'}}]});
  1259. }), openSaveDlg, mxResources.get('yes'), mxResources.get('noPickFolder') + '...', true);
  1260. }
  1261. if (this.user == null)
  1262. {
  1263. this.updateUser(this.emptyFn, this.emptyFn, true);
  1264. }
  1265. });
  1266. if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
  1267. {
  1268. this.authenticate(mxUtils.bind(this, function()
  1269. {
  1270. odSaveDlg(false);
  1271. }), errorFn);
  1272. }
  1273. else
  1274. {
  1275. odSaveDlg(direct);
  1276. }
  1277. };
  1278. /**
  1279. * Checks if the client is authorized and calls the next step.
  1280. */
  1281. OneDriveClient.prototype.pickFile = function(fn)
  1282. {
  1283. fn = (fn != null) ? fn : mxUtils.bind(this, function(id)
  1284. {
  1285. this.ui.loadFile('W' + encodeURIComponent(id));
  1286. });
  1287. var errorFn = mxUtils.bind(this, function(e)
  1288. {
  1289. this.ui.showError(mxResources.get('error'), e && e.message? e.message : e);
  1290. });
  1291. var odOpenDlg = this.inlinePicker? this.createInlinePicker(fn) :
  1292. mxUtils.bind(this, function()
  1293. {
  1294. OneDrive.open(
  1295. {
  1296. clientId: this.clientId,
  1297. action: 'query',
  1298. multiSelect: false,
  1299. advanced:
  1300. {
  1301. 'endpointHint': mxClient.IS_IE11? null : this.endpointHint, //IE11 doen't work with our modified version, so, setting endpointHint disable using our token BUT will force relogin!
  1302. 'redirectUri': this.pickerRedirectUri,
  1303. 'queryParameters': 'select=id,name,parentReference', //We can also get @microsoft.graph.downloadUrl within this request but it will break the normal process
  1304. 'accessToken': _token,
  1305. isConsumerAccount: false
  1306. },
  1307. success: mxUtils.bind(this, function(files)
  1308. {
  1309. if (files != null && files.value != null && files.value.length > 0)
  1310. {
  1311. //Update the token in case a login with a different user
  1312. if (mxClient.IS_IE11)
  1313. {
  1314. _token = files.accessToken;
  1315. }
  1316. fn(OneDriveFile.prototype.getIdOf(files.value[0]), files);
  1317. }
  1318. }),
  1319. cancel: mxUtils.bind(this, function()
  1320. {
  1321. // do nothing
  1322. }),
  1323. error: errorFn
  1324. });
  1325. if (this.user == null)
  1326. {
  1327. this.updateUser(this.emptyFn, this.emptyFn, true);
  1328. }
  1329. });
  1330. if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
  1331. {
  1332. this.authenticate(mxUtils.bind(this, function()
  1333. {
  1334. if (this.inlinePicker)
  1335. {
  1336. this.ui.hideDialog();
  1337. odOpenDlg();
  1338. }
  1339. else
  1340. {
  1341. this.ui.showDialog(new BtnDialog(this.ui, this, mxResources.get('open'), mxUtils.bind(this, function()
  1342. {
  1343. this.ui.hideDialog();
  1344. odOpenDlg();
  1345. })).container, 300, 140, true, true);
  1346. }
  1347. }), errorFn);
  1348. }
  1349. else
  1350. {
  1351. odOpenDlg();
  1352. }
  1353. };
  1354. /**
  1355. * Checks if the client is authorized and calls the next step.
  1356. */
  1357. OneDriveClient.prototype.logout = function()
  1358. {
  1359. if (isLocalStorage)
  1360. {
  1361. var check = localStorage.getItem('odpickerv7cache');
  1362. if (check != null && check.substring(0, 19) == '{"odsdkLoginHint":{')
  1363. {
  1364. localStorage.removeItem('odpickerv7cache');
  1365. }
  1366. }
  1367. window.open('https://login.microsoftonline.com/common/oauth2/v2.0/logout', 'logout', 'width=525,height=525,status=no,resizable=yes,toolbar=no,menubar=no,scrollbars=yes');
  1368. //Send to server to clear refresh token cookie
  1369. this.ui.editor.loadUrl(this.redirectUri + '?doLogout=1&state=' + encodeURIComponent('cId=' + this.clientId + '&domain=' + window.location.hostname));
  1370. this.clearPersistentToken();
  1371. this.setUser(null);
  1372. _token = null;
  1373. };
  1374. })();