| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622 |
- /**
- * Copyright (c) 2006-2024, JGraph Ltd
- * Copyright (c) 2006-2024, draw.io AG
- */
- //Add a closure to hide the class private variables without changing the code a lot
- (function ()
- {
- var _token = null;
- window.OneDriveClient = function(editorUi, isExtAuth, inlinePicker, noLogout)
- {
- if (isExtAuth == null && window.urlParams != null && window.urlParams['extAuth'] == '1')
- {
- isExtAuth = true;
- }
-
- if (inlinePicker == null) //Use inline picker as default
- {
- inlinePicker = window.Editor != null? Editor.oneDriveInlinePicker : true;
- }
-
- if (noLogout == null && window.urlParams != null && window.urlParams['noLogoutOD'] == '1')
- {
- noLogout = true;
- }
-
- DrawioClient.call(this, editorUi, isExtAuth? 'oneDriveExtAuthInfo' : 'oneDriveAuthInfo');
-
- this.isExtAuth = isExtAuth;
- this.inlinePicker = inlinePicker;
- this.noLogout = noLogout;
- var authInfo = JSON.parse(this.token);
-
- if (authInfo != null)
- {
- this.endpointHint = authInfo.endpointHint != null ? authInfo.endpointHint.replace('/Documents', '/_layouts/15/onedrive.aspx') : authInfo.endpointHint;
- }
- };
- // Extends DrawioClient
- mxUtils.extend(OneDriveClient, DrawioClient);
- /**
- * Specifies if thumbnails should be enabled. Default is true.
- * LATER: If thumbnails are disabled, make sure to replace the
- * existing thumbnail with the placeholder only once.
- */
- OneDriveClient.prototype.clientId = window.DRAWIO_MSGRAPH_CLIENT_ID || ((window.location.hostname == 'test.draw.io') ?
- '95e4b4ed-ed5c-4a05-935b-b411b4562ef2' : '24b129a6-117b-4394-bdc8-3b9955e5cdef');
- OneDriveClient.prototype.clientId = window.location.hostname == 'app.diagrams.net' ?
- 'b5ff67d6-3155-4fca-965a-59a3655c4476' : OneDriveClient.prototype.clientId;
- OneDriveClient.prototype.clientId = window.location.hostname == 'viewer.diagrams.net' ?
- '417a451a-a343-4788-b6c1-901e63182565' : OneDriveClient.prototype.clientId;
- /**
- * OAuth 2.0 scopes for installing Drive Apps.
- */
- OneDriveClient.prototype.scopes = 'user.read files.readwrite.all sites.read.all';
- /**
- * OAuth 2.0 scopes for installing Drive Apps.
- */
- OneDriveClient.prototype.redirectUri = window.DRAWIO_SERVER_URL + 'microsoft';
- OneDriveClient.prototype.pickerRedirectUri = window.DRAWIO_SERVER_URL + 'onedrive3.html';
- /**
- * This is the default endpoint for personal accounts
- */
- OneDriveClient.prototype.defEndpointHint = 'api.onedrive.com';
- OneDriveClient.prototype.endpointHint = OneDriveClient.prototype.defEndpointHint;
- /**
- * Value for the root folder.
- */
- OneDriveClient.prototype.rootId = {id: 'root', name: 'root', parentReference: {driveId: 'me'}};
- /**
- * Executes the first step for connecting to Google Drive.
- */
- OneDriveClient.prototype.extension = '.drawio';
- /**
- * Executes the first step for connecting to Google Drive.
- */
- OneDriveClient.prototype.baseUrl = 'https://graph.microsoft.com/v1.0';
- OneDriveClient.prototype.authUrl = 'https://login.microsoftonline.com/' + (window.DRAWIO_MSGRAPH_TENANT_ID || 'common');
- /**
- * Empty function used when no callback is needed
- */
- OneDriveClient.prototype.emptyFn = function(){};
- /**
- * Authorizes the client, gets the userId and calls <open>.
- */
- OneDriveClient.prototype.invalidFilenameRegExs = [
- /[~"#%\*:<>\?\/\\{\|}]/,
- /^\.lock$/i,
- /^CON$/i,
- /^PRN$/i,
- /^AUX$/i,
- /^NUL$/i,
- /^COM\d$/i,
- /^LPT\d$/i,
- /^desktop\.ini$/i,
- /_vti_/i
- ];
- /**
- * Check if the file/folder name is valid
- */
- OneDriveClient.prototype.isValidFilename = function(filename)
- {
- if (filename == null || filename === '') return false;
-
- for (var i = 0; i < this.invalidFilenameRegExs.length; i++)
- {
- if (this.invalidFilenameRegExs[i].test(filename)) return false;
- }
-
- return true;
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.get = function(url, onload, onerror)
- {
- var req = new mxXmlRequest(url, null, 'GET');
-
- req.setRequestHeaders = mxUtils.bind(this, function(request, params)
- {
- request.setRequestHeader('Authorization', 'Bearer ' + _token);
- });
-
- req.send(onload, onerror);
-
- return req;
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.updateUser = function(success, error, failOnAuth)
- {
- var acceptResponse = true;
-
- var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
- {
- acceptResponse = false;
- error({code: App.ERROR_TIMEOUT});
- }), this.ui.timeout);
-
- this.get(this.baseUrl + '/me', mxUtils.bind(this, function(req)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- if (req.getStatus() < 200 || req.getStatus() >= 300)
- {
- if (!failOnAuth)
- {
- this.logout();
-
- this.authenticate(mxUtils.bind(this, function()
- {
- this.updateUser(success, error, true);
- }), error);
- }
- else
- {
- error({message: mxResources.get('accessDenied')});
- }
- }
- else
- {
- try
- {
- var data = JSON.parse(req.getText());
- this.setUser(new DrawioUser(data.id, data.mail, data.displayName));
- success();
- }
- catch (e)
- {
- error(e);
- }
- }
- }
- }), mxUtils.bind(this, function(err)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- error(err);
- }
- }));
- };
- /**
- * Authorizes the client, gets the userId and calls <open>.
- */
- OneDriveClient.prototype.resetTokenRefresh = function(expires_in)
- {
- if (this.tokenRefreshThread != null)
- {
- window.clearTimeout(this.tokenRefreshThread);
- this.tokenRefreshThread = null;
- }
- // Starts timer to refresh token before it expires
- if (expires_in > 0)
- {
- this.tokenRefreshInterval = expires_in * 1000;
-
- this.tokenRefreshThread = window.setTimeout(mxUtils.bind(this, function()
- {
- //Get a new fresh accessToken
- this.authenticate(this.emptyFn, this.emptyFn, true);
- }), expires_in * 900);
- }
- };
- /**
- * Authorizes the client, gets the userId and calls <open>.
- */
- OneDriveClient.prototype.authenticate = function(success, error, failOnAuth)
- {
- if (this.isExtAuth)
- {
- window.parent.oneDriveAuth(mxUtils.bind(this, function(newAuthInfo)
- {
- this.updateAuthInfo(newAuthInfo, true, this.endpointHint == null, success, error);
- }), error, window.urlParams != null && urlParams['odAuthCancellable'] == '1');
- return;
- }
-
- var req = new mxXmlRequest(this.redirectUri + '?getState=1', null, 'GET');
-
- req.send(mxUtils.bind(this, function(req)
- {
- if (req.getStatus() >= 200 && req.getStatus() <= 299)
- {
- this.authenticateStep2(req.getText(), success, error, failOnAuth);
- }
- else if (error != null)
- {
- error(req);
- }
- }), error);
- };
- /**
- * Authorizes the client, gets the userId and calls <open>.
- */
- OneDriveClient.prototype.updateAuthInfo = function(newAuthInfo, remember, forceUserUpdate, success, error)
- {
- if (forceUserUpdate)
- {
- this.setUser(null);
- }
-
- _token = newAuthInfo.access_token;
- delete newAuthInfo.access_token; //Don't store access token
- newAuthInfo.expiresOn = Date.now() + newAuthInfo.expires_in * 1000;
- this.tokenExpiresOn = newAuthInfo.expiresOn;
- newAuthInfo.remember = remember;
- this.setPersistentToken(JSON.stringify(newAuthInfo), !remember);
- this.resetTokenRefresh(newAuthInfo.expires_in);
- if (forceUserUpdate)
- {
- //Find out the type of the account + endpoint
- this.getAccountTypeAndEndpoint(mxUtils.bind(this, function()
- {
- success();
- }), error);
- }
- else
- {
- success();
- }
- };
- /**
- * Authorizes the client, gets the userId and calls <open>.
- */
- OneDriveClient.prototype.authenticateStep2 = function(state, success, error, failOnAuth)
- {
- if (window.onOneDriveCallback == null)
- {
- var auth = mxUtils.bind(this, function()
- {
- var acceptAuthResponse = true;
-
- //Retry request with refreshed token
- var authInfo = JSON.parse(this.getPersistentToken(true));
-
- if (authInfo != null)
- {
- var req = new mxXmlRequest(this.redirectUri + '?state=' + encodeURIComponent('cId=' + this.clientId +
- '&domain=' + window.location.host + '&token=' + state), null, 'GET'); // To identify which app/domain is used
-
- req.send(mxUtils.bind(this, function(req)
- {
- if (req.getStatus() >= 200 && req.getStatus() <= 299)
- {
- try
- {
- this.updateAuthInfo(JSON.parse(req.getText()), authInfo.remember, false, success, error);
- }
- catch (e)
- {
- error({message: mxResources.get('authFailed'), retry: auth});
- }
- }
- else
- {
- this.clearPersistentToken();
- this.setUser(null);
- _token = null;
- // (Unauthorized) [e.g, invalid refresh token] or bad request
- if ((req.getStatus() == 401 || req.getStatus() == 400) && !failOnAuth)
- {
- auth();
- }
- else
- {
- error({message: mxResources.get('accessDenied'), retry: auth});
- }
- }
- }), error);
- }
- else
- {
- this.ui.showAuthDialog(this, true, mxUtils.bind(this, function(remember, authSuccess)
- {
- var url = this.authUrl + '/oauth2/v2.0/authorize' +
- '?client_id=' + this.clientId + '&response_type=code' +
- '&redirect_uri=' + encodeURIComponent(this.redirectUri) +
- '&scope=' + encodeURIComponent(this.scopes + (remember? ' offline_access' : '')) +
- '&state=' + encodeURIComponent('cId=' + this.clientId + '&domain=' + window.location.host + '&token=' + state); //To identify which app/domain is used
-
- var width = 525,
- height = 525,
- screenX = window.screenX,
- screenY = window.screenY,
- outerWidth = window.outerWidth,
- outerHeight = window.outerHeight;
-
- var left = screenX + Math.max(outerWidth - width, 0) / 2;
- var top = screenY + Math.max(outerHeight - height, 0) / 2;
-
- var features = ['width=' + width, 'height=' + height,
- 'top=' + top, 'left=' + left,
- 'status=no', 'resizable=yes',
- 'toolbar=no', 'menubar=no',
- 'scrollbars=yes'];
- var popup = window.open(url, 'odauth', features.join(','));
-
- if (popup != null)
- {
- window.onOneDriveCallback = mxUtils.bind(this, function(authInfo, authWindow)
- {
- if (acceptAuthResponse)
- {
- window.onOneDriveCallback = null;
- acceptAuthResponse = false;
-
- try
- {
- if (authInfo == null)
- {
- error({message: mxResources.get('accessDenied'), retry: auth});
- }
- else
- {
- if (authSuccess != null)
- {
- authSuccess();
- }
-
- this.updateAuthInfo(authInfo, remember, true, success, error);
- }
- }
- catch (e)
- {
- error(e);
- }
- finally
- {
- if (authWindow != null)
- {
- authWindow.close();
- }
- }
- }
- else if (authWindow != null)
- {
- authWindow.close();
- }
- });
-
- popup.focus();
- }
- }), mxUtils.bind(this, function()
- {
- if (acceptAuthResponse)
- {
- window.onOneDriveCallback = null;
- acceptAuthResponse = false;
- error({message: mxResources.get('accessDenied'), retry: auth});
- }
- }));
- }
- });
-
- auth();
- }
- else
- {
- error({code: App.ERROR_BUSY});
- }
- };
- /**
- * Authorizes the client, gets the userId and calls <open>.
- */
- OneDriveClient.prototype.getAccountTypeAndEndpoint = function(success, error)
- {
- this.get(this.baseUrl + '/me/drive/root', mxUtils.bind(this, function(req)
- {
- try
- {
- if (req.getStatus() >= 200 && req.getStatus() <= 299)
- {
- var resp = JSON.parse(req.getText());
-
- if (resp.webUrl.indexOf('.sharepoint.com') > 0)
- {
- //TODO Confirm this works with all sharepoint sites
- this.endpointHint = resp.webUrl.replace('/Documents', '/_layouts/15/onedrive.aspx');
- }
- else
- {
- this.endpointHint = this.defEndpointHint;
- }
-
- //Update authInfo with endpointHint
- var authInfo = JSON.parse(this.getPersistentToken(true));
-
- if (authInfo != null)
- {
- authInfo.endpointHint = this.endpointHint;
- this.setPersistentToken(JSON.stringify(authInfo), !authInfo.remember);
- }
-
- success();
- return;
- }
- }
- catch(e) {}
- //It is expected to work as this call immediately follows getting a fresh access token
- error({message: mxResources.get('unknownError') + ' (Code: ' + req.getStatus() + ')'});
-
- }), error);
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.executeRequest = function(url, success, error)
- {
- var doExecute = mxUtils.bind(this, function(failOnAuth)
- {
- var acceptResponse = true;
-
- var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
- {
- acceptResponse = false;
- error({code: App.ERROR_TIMEOUT, retry: doExecute});
- }), this.ui.timeout);
- this.get(url, mxUtils.bind(this, function(req)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- // 404 (file not found) is a valid response for checkExists
- if ((req.getStatus() >= 200 && req.getStatus() <= 299) || req.getStatus() == 404)
- {
- if (this.user == null)
- {
- this.updateUser(this.emptyFn, this.emptyFn, true);
- }
-
- success(req);
- }
- // 400 is returns if wrong user for this file
- else if (!failOnAuth && (req.getStatus() === 401 || req.getStatus() === 400))
- {
- //Authorize again using the refresh token
- this.authenticate(function()
- {
- doExecute(true);
- }, error, failOnAuth);
- }
- else
- {
- error(this.parseRequestText(req));
- }
- }
- }), mxUtils.bind(this, function(err)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- error(err);
- }
- }));
- });
-
- if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
- {
- this.authenticate(function()
- {
- doExecute(true);
- }, error);
- }
- else
- {
- doExecute(false);
- }
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.checkToken = function(fn, error)
- {
- if (_token == null || this.tokenRefreshThread == null || this.tokenExpiresOn - Date.now() < 60000)
- {
- this.authenticate(fn, (error != null) ? error : this.emptyFn);
- }
- else
- {
- fn();
- }
- };
- /**
- * Authorizes the client, gets the userId and calls <open>.
- */
- OneDriveClient.prototype.getItemRef = function(id)
- {
- var idParts = id.split('/');
-
- if (idParts.length > 1)
- {
- return {driveId: idParts[0], id: idParts[1]};
- }
- else
- {
- return {id: id};
- }
- };
- /**
- * Authorizes the client, gets the userId and calls <open>.
- */
- OneDriveClient.prototype.getItemURL = function(id, relative)
- {
- var idParts = id.split('/');
-
- if (idParts.length > 1)
- {
- var driveId = idParts[0];
- var itemId = idParts[1];
- return (relative? '' : this.baseUrl) + '/drives/' + driveId + (itemId == 'root' ? '/root' : '/items/' + itemId);
- }
- else
- {
- return (relative? '' : this.baseUrl) + '/me/drive/items/' + id;
- }
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.getLibrary = function(id, success, error)
- {
- this.getFile(id, success, error, false, true);
- };
- /**
- * Workaround for added content to HTML files in Sharepoint.
- */
- OneDriveClient.prototype.removeExtraHtmlContent = function(data)
- {
- var idx = data.lastIndexOf('<html><head><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8"><meta name="Robots" ');
- if (idx > 0)
- {
- data = data.substring(0, idx);
- }
-
- return data;
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.getFile = function(id, success, error, denyConvert, asLibrary)
- {
- asLibrary = (asLibrary != null) ? asLibrary : false;
- this.executeRequest(this.getItemURL(id), mxUtils.bind(this, function(req)
- {
- if (req.getStatus() >= 200 && req.getStatus() <= 299)
- {
- var meta = JSON.parse(req.getText());
- var binary = /\.png$/i.test(meta.name);
-
- // Handles .vsdx, Gliffy and PNG+XML files by creating a temporary file
- if (/\.v(dx|sdx?)$/i.test(meta.name) || /\.gliffy$/i.test(meta.name) ||
- /\.pdf$/i.test(meta.name) || (!this.ui.useCanvasForExport && binary))
- {
- var mimeType = (meta.file != null) ? meta.file.mimeType : null;
- this.ui.convertFile(meta['@microsoft.graph.downloadUrl'], meta.name, mimeType,
- this.extension, success, error);
- }
- else
- {
- var acceptResponse = true;
-
- var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
- {
- acceptResponse = false;
- error({code: App.ERROR_TIMEOUT})
- }), this.ui.timeout);
-
- this.ui.editor.loadUrl(meta['@microsoft.graph.downloadUrl'], mxUtils.bind(this, function(data)
- {
- try
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- if (/\.html$/i.test(meta.name))
- {
- data = this.removeExtraHtmlContent(data);
- }
-
- var index = (binary) ? data.lastIndexOf(',') : -1;
- var file = null;
-
- if (index > 0)
- {
- var xml = this.ui.extractGraphModelFromPng(data);
-
- if (xml != null && xml.length > 0)
- {
- data = xml;
- }
- else
- {
- // Imports as PNG image
- file = new LocalFile(this.ui, data, meta.name, true);
- }
- }
- // Checks for base64 encoded mxfile
- else if (data.substring(0, 32) == 'data:image/png;base64,PG14ZmlsZS')
- {
- var temp = data.substring(22);
- data = (window.atob && !mxClient.IS_SF) ? atob(temp) : Base64.decode(temp);
- }
-
- if (Graph.fileSupport && new XMLHttpRequest().upload && this.ui.isRemoteFileFormat(data, meta['@microsoft.graph.downloadUrl']))
- {
- this.ui.parseFileData(data, mxUtils.bind(this, function(xhr)
- {
- try
- {
- if (xhr.readyState == 4)
- {
- if (xhr.status >= 200 && xhr.status <= 299)
- {
- success(new LocalFile(this.ui, xhr.responseText, meta.name + this.extension, true));
- }
- else if (error != null)
- {
- error({message: mxResources.get('errorLoadingFile')});
- }
- }
- }
- catch (e)
- {
- if (error != null)
- {
- error(e);
- }
- else
- {
- throw e;
- }
- }
- }), meta.name);
- }
- else
- {
- if (file != null)
- {
- success(file);
- }
- else if (asLibrary)
- {
- success(new OneDriveLibrary(this.ui, data, meta));
- }
- else
- {
- success(new OneDriveFile(this.ui, data, meta));
- }
- }
- }
- }
- catch (e)
- {
- if (error != null)
- {
- error(e);
- }
- else
- {
- throw e;
- }
- }
- }), mxUtils.bind(this, function(req)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- error(this.parseRequestText(req));
- }
- }), binary || (meta.file != null && meta.file.mimeType != null &&
- ((meta.file.mimeType.substring(0, 6) == 'image/' &&
- meta.file.mimeType.substring(0, 9) != 'image/svg') ||
- meta.file.mimeType == 'application/pdf')));
- }
- }
- else
- {
- if (this.isExtAuth)
- {
- error({message: mxResources.get('fileNotFoundOrDenied'),
- ownerEmail: window.urlParams != null? urlParams['ownerEml'] : null});
- }
- else
- {
- error(this.parseRequestText(req));
- }
- }
- }), function(err)
- {
- if (error != null)
- {
- // Replaces ObjectHandle is Invalid error message
- if (err != null && err.error != null &&
- err.error.message === 'ObjectHandle is Invalid')
- {
- err.error.message = mxResources.get('fileNotFoundOrDenied');
- }
-
- error(err);
- }
- });
- };
- /**
- * Translates this point by the given vector.
- *
- * @param {number} dx X-coordinate of the translation.
- * @param {number} dy Y-coordinate of the translation.
- */
- OneDriveClient.prototype.renameFile = function(file, filename, success, error)
- {
- if (file != null && filename != null)
- {
- if (!this.isValidFilename(filename))
- {
- error({message: this.invalidFilenameRegExs[0].test(filename) ?
- mxResources.get('oneDriveCharsNotAllowed') : mxResources.get('oneDriveInvalidDeviceName')});
- return;
- }
-
- // TODO: How to force overwrite file with same name?
- this.checkExists(file.getParentId(), filename, false, mxUtils.bind(this, function(checked)
- {
- if (checked)
- {
- this.writeFile(this.getItemURL(file.getId()), JSON.stringify({name: filename}), 'PATCH', 'application/json', success, error);
- }
- else
- {
- error();
- }
- }));
- }
- };
- /**
- * Translates this point by the given vector.
- *
- * @param {number} dx X-coordinate of the translation.
- * @param {number} dy Y-coordinate of the translation.
- */
- OneDriveClient.prototype.moveFile = function(id, folderId, success, error)
- {
- //check that the source and destination are on the same drive
- var folderInfo = this.getItemRef(folderId);
- var fileInfo = this.getItemRef(id);
-
- if (folderInfo.driveId != fileInfo.driveId)
- {
- error({message: mxResources.get('cannotMoveOneDrive', null, 'Moving a file between accounts is not supported yet.')});
- }
- else
- {
- this.writeFile(this.getItemURL(id), JSON.stringify({parentReference: folderInfo}), 'PATCH', 'application/json', success, error);
- }
- };
- /**
- * Translates this point by the given vector.
- *
- * @param {number} dx X-coordinate of the translation.
- * @param {number} dy Y-coordinate of the translation.
- */
- OneDriveClient.prototype.insertLibrary = function(filename, data, success, error, folderId)
- {
- this.insertFile(filename, data, success, error, true, folderId);
- };
- /**
- * Translates this point by the given vector.
- *
- * @param {number} dx X-coordinate of the translation.
- * @param {number} dy Y-coordinate of the translation.
- */
- OneDriveClient.prototype.insertFile = function(filename, data, success, error, asLibrary, folderId)
- {
- if (!this.isValidFilename(filename))
- {
- error({message: this.invalidFilenameRegExs[0].test(filename) ?
- mxResources.get('oneDriveCharsNotAllowed') : mxResources.get('oneDriveInvalidDeviceName')});
- return;
- }
- asLibrary = (asLibrary != null) ? asLibrary : false;
-
- this.checkExists(folderId, filename, true, mxUtils.bind(this, function(checked)
- {
- if (checked)
- {
- var folder = '/me/drive/root';
-
- if (folderId != null)
- {
- folder = this.getItemURL(folderId, true);
- }
-
- var insertSuccess = mxUtils.bind(this, function(meta)
- {
- if (asLibrary)
- {
- success(new OneDriveLibrary(this.ui, data, meta));
- }
- else
- {
- success(new OneDriveFile(this.ui, data, meta));
- }
- });
- var url = this.baseUrl + folder + '/children/' + encodeURIComponent(filename) + '/content';
-
- //OneDrive has a limit on PUT API of 4MB, larger files needs to use the upload session method
- if (data.length >= 4000000 /*4MB*/)
- {
- //Create empty file first then upload. TODO Can we get an upload session for non-existing files?
- this.writeFile(url, '', 'PUT', null, mxUtils.bind(this, function(meta)
- {
- this.writeLargeFile(this.getItemURL(meta.id), data, insertSuccess, error);
- }), error);
- }
- else
- {
- this.writeFile(url, data, 'PUT', null, insertSuccess, error);
- }
- }
- else
- {
- error();
- }
- }))
- };
- /**
- * Translates this point by the given vector.
- *
- * @param {number} dx X-coordinate of the translation.
- * @param {number} dy Y-coordinate of the translation.
- */
- OneDriveClient.prototype.checkExists = function(parentId, filename, askReplace, fn)
- {
- var folder = '/me/drive/root';
-
- if (parentId != null)
- {
- folder = this.getItemURL(parentId, true);
- }
-
- this.executeRequest(this.baseUrl + folder + '/children/' + encodeURIComponent(filename), mxUtils.bind(this, function(req)
- {
- if (req.getStatus() == 404)
- {
- fn(true);
- }
- else
- {
- if (askReplace)
- {
- this.ui.spinner.stop();
-
- this.ui.confirm(mxResources.get('replaceIt', [filename]), function()
- {
- fn(true);
- }, function()
- {
- fn(false);
- });
- }
- else
- {
- this.ui.spinner.stop();
-
- this.ui.showError(mxResources.get('error'), mxResources.get('fileExists'), mxResources.get('ok'), function()
- {
- fn(false);
- });
- }
- }
- }), function(req)
- {
- fn(false);
- }, true);
- };
- /**
- * Translates this point by the given vector.
- *
- * @param {number} dx X-coordinate of the translation.
- * @param {number} dy Y-coordinate of the translation.
- */
- OneDriveClient.prototype.saveFile = function(file, success, error, etag)
- {
- try
- {
- var savedData = file.getData();
-
- var fn = mxUtils.bind(this, function(data)
- {
- var saveSuccess = mxUtils.bind(this, function(resp)
- {
- success(resp, savedData);
- });
- var url = this.getItemURL(file.getId());
-
- //OneDrive has a limit on PUT API of 4MB, larger files needs to use the upload session method
- if (data.length >= 4000000 /*4MB*/)
- {
- this.writeLargeFile(url, data, saveSuccess, error, etag);
- }
- else
- {
- this.writeFile(url + '/content/', data, 'PUT', null, saveSuccess, error, etag);
- }
- });
-
- if (this.ui.useCanvasForExport && /(\.png)$/i.test(file.meta.name))
- {
- var p = this.ui.getPngFileProperties(this.ui.fileNode);
-
- this.ui.getEmbeddedPng(mxUtils.bind(this, function(data)
- {
- fn(this.ui.base64ToBlob(data, 'image/png'));
- }), error, (this.ui.getCurrentFile() != file) ?
- savedData : null, p.scale, p.border);
- }
- else
- {
- fn(savedData);
- }
- }
- catch (e)
- {
- error(e);
- }
- };
- OneDriveClient.prototype.writeLargeFile = function(url, data, success, error, etag)
- {
- try
- {
- var chunkSize = 4 * 1024 * 1024; //4MB chunk;
-
- if (data != null)
- {
- var dataByteLength = (new TextEncoder().encode(data)).length;
- var uploadPart = mxUtils.bind(this, function(uploadUrl, index, byteIndex, retryCount)
- {
- try
- {
- retryCount = retryCount || 0;
- var acceptResponse = true;
- var timeoutThread = null;
-
- timeoutThread = window.setTimeout(mxUtils.bind(this, function()
- {
- acceptResponse = false;
- error({code: App.ERROR_TIMEOUT});
- }), this.ui.timeout);
-
- var part = data.substr(index, chunkSize);
- var partByteLength = (new TextEncoder().encode(part)).length;
- var req = new mxXmlRequest(uploadUrl, part, 'PUT');
- req.setRequestHeaders = mxUtils.bind(this, function(request, params)
- {
- request.setRequestHeader('Content-Range', 'bytes ' + byteIndex + '-' +
- (byteIndex + partByteLength - 1) + '/' + dataByteLength);
- });
- req.send(mxUtils.bind(this, function(req)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- var status = req.getStatus();
- if (status >= 200 && status <= 299)
- {
- var nextByte = index + part.length;
-
- if (nextByte == data.length)
- {
- success(JSON.parse(req.getText()));
- }
- else
- {
- uploadPart(uploadUrl, nextByte, byteIndex + partByteLength, retryCount);
- }
- }
- else if (status >= 500 && status <= 599 && retryCount < 2) //Retry on server errors
- {
- retryCount++;
- uploadPart(uploadUrl, index, byteIndex, retryCount);
- }
- else
- {
- error(this.parseRequestText(req), req);
- }
- }
- }), mxUtils.bind(this, function(req)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- error(this.parseRequestText(req));
- }
- }));
- }
- catch (e)
- {
- error(e);
- }
- });
-
- var doExecute = mxUtils.bind(this, function(failOnAuth)
- {
- try
- {
- var acceptResponse = true;
- var timeoutThread = null;
-
- try
- {
- timeoutThread = window.setTimeout(mxUtils.bind(this, function()
- {
- acceptResponse = false;
- error({code: App.ERROR_TIMEOUT});
- }), this.ui.timeout);
- }
- catch (e)
- {
- // Ignore window closed
- }
-
- var req = new mxXmlRequest(url + '/createUploadSession', '{}', 'POST');
-
- req.setRequestHeaders = mxUtils.bind(this, function(request, params)
- {
- request.setRequestHeader('Content-Type', 'application/json');
- request.setRequestHeader('Authorization', 'Bearer ' + _token);
-
- if (etag != null)
- {
- request.setRequestHeader('If-Match', etag);
- }
- });
-
- req.send(mxUtils.bind(this, function(req)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- if (req.getStatus() >= 200 && req.getStatus() <= 299)
- {
- var resp = JSON.parse(req.getText());
- uploadPart(resp.uploadUrl, 0, 0);
- }
- else if (!failOnAuth && req.getStatus() === 401)
- {
- this.authenticate(function()
- {
- doExecute(true);
- }, error, failOnAuth);
- }
- else
- {
- error(this.parseRequestText(req), req);
- }
- }
- }), mxUtils.bind(this, function(req)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- error(this.parseRequestText(req));
- }
- }));
- }
- catch (e)
- {
- error(e);
- }
- });
-
- if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
- {
- this.authenticate(function()
- {
- doExecute(true);
- }, error);
- }
- else
- {
- doExecute(false);
- }
- }
- else
- {
- error({message: mxResources.get('unknownError')});
- }
- }
- catch (e)
- {
- error(e);
- }
- };
- /**
- * Translates this point by the given vector.
- *
- * @param {number} dx X-coordinate of the translation.
- * @param {number} dy Y-coordinate of the translation.
- */
- OneDriveClient.prototype.writeFile = function(url, data, method, contentType, success, error, etag)
- {
- try
- {
- if (url != null && data != null)
- {
- var doExecute = mxUtils.bind(this, function(failOnAuth)
- {
- try
- {
- var acceptResponse = true;
- var timeoutThread = null;
-
- try
- {
- timeoutThread = window.setTimeout(mxUtils.bind(this, function()
- {
- acceptResponse = false;
- error({code: App.ERROR_TIMEOUT});
- }), this.ui.timeout);
- }
- catch (e)
- {
- // Ignore window closed
- }
-
- var req = new mxXmlRequest(url, data, method);
-
- req.setRequestHeaders = mxUtils.bind(this, function(request, params)
- {
- // Space deletes content type header. Specification says "text/plain"
- // should work but returns an 415 Unsupported Media Type error
- request.setRequestHeader('Content-Type', contentType || ' ');
- //TODO This header is needed for moving a file between two different drives.
- // 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)
- //request.setRequestHeader('Prefer', 'respond-async');
- request.setRequestHeader('Authorization', 'Bearer ' + _token);
-
- if (etag != null)
- {
- request.setRequestHeader('If-Match', etag);
- }
- });
-
- req.send(mxUtils.bind(this, function(req)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- if (req.getStatus() >= 200 && req.getStatus() <= 299)
- {
- if (this.user == null)
- {
- this.updateUser(this.emptyFn, this.emptyFn, true);
- }
-
- success(JSON.parse(req.getText()));
- }
- else if (!failOnAuth && req.getStatus() === 401)
- {
- this.authenticate(function()
- {
- doExecute(true);
- }, error, failOnAuth);
- }
- else
- {
- error(this.parseRequestText(req), req);
- }
- }
- }), mxUtils.bind(this, function(req)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- error(this.parseRequestText(req));
- }
- }));
- }
- catch (e)
- {
- error(e);
- }
- });
-
- if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
- {
- this.authenticate(function()
- {
- doExecute(true);
- }, error);
- }
- else
- {
- doExecute(false);
- }
- }
- else
- {
- error({message: mxResources.get('unknownError')});
- }
- }
- catch (e)
- {
- error(e);
- }
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.parseRequestText = function(req)
- {
- var result = {message: mxResources.get('unknownError')};
-
- try
- {
- result = JSON.parse(req.getText());
- result.status = req.getStatus();
-
- if (result.error)
- {
- result.error.status = result.status;
- result.error.code = result.status;
- }
- }
- catch (e)
- {
- // ignore
- }
-
- return result;
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.pickLibrary = function(fn)
- {
- this.pickFile(function(id)
- {
- // Ignores second argument
- fn(id);
- });
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.createInlinePicker = function(fn, foldersOnly, acceptAllFiles)
- {
- return mxUtils.bind(this, function()
- {
- var odPicker = null;
- var div = document.createElement('div');
- div.style.position = 'relative';
-
- var dlg = new CustomDialog(this.ui, div, mxUtils.bind(this, function()
- {
- var item = odPicker.getSelectedItem();
-
- if (item != null)
- {
- if (foldersOnly && typeof item.folder == 'object')
- {
- fn({value: [item]});
- }
- else if (!item.folder && this.ui.spinner.spin(document.body, mxResources.get('loading')))
- {
- var id = OneDriveFile.prototype.getIdOf(item);
- this.executeRequest(this.getItemURL(id), mxUtils.bind(this, function(req)
- {
- this.ui.spinner.stop();
- if (req.getStatus() >= 200 && req.getStatus() <= 299)
- {
- var meta = JSON.parse(req.getText());
- fn(id, {value: [meta]});
- }
- else
- {
- this.ui.handleError({code: req.getStatus()});
- }
- }), mxUtils.bind(this, function(req)
- {
- this.ui.spinner.stop();
- this.ui.handleError(req);
- }));
- }
- return;
- }
-
- return mxResources.get('invalidSel', null, 'Invalid selection');
- }), null, mxResources.get(foldersOnly? 'select' :'open'), null, null, null, null, true);
-
- this.ui.showDialog(dlg.container, 550, 500, true, true);
- //Set width/height of the picker container
- div.style.width = dlg.container.parentNode.style.width;
- div.style.height = (parseInt(dlg.container.parentNode.style.height) - 60) + 'px';
-
- odPicker = new mxODPicker(div, null, mxUtils.bind(this, function(url, success, error, isAbsUrl)
- {
- this.executeRequest(isAbsUrl? url : this.baseUrl + url, function(req)
- {
- success(JSON.parse(req.getText()));
- }, error);
- }), mxUtils.bind(this, function(id, driveId, success, error)
- {
- this.executeRequest(this.baseUrl + '/drives/' + driveId + '/items/' + id, function(req)
- {
- success(JSON.parse(req.getText()));
- }, error);
- }), null, null, function(item)
- {
- if (foldersOnly) //Currently this is not called when in foldersOnly mode
- {
- fn({
- value: [item]
- });
- }
- else
- {
- fn(OneDriveFile.prototype.getIdOf(item));
- }
- },
- mxUtils.bind(this, function(err)
- {
- this.ui.showError(mxResources.get('error'), err);
- }), foldersOnly, null, null, null, null, acceptAllFiles);
- });
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.pickFolder = function(fn, direct)
- {
- var errorFn = mxUtils.bind(this, function(e)
- {
- this.ui.showError(mxResources.get('error'), e && e.message? e.message : e);
- });
-
- var odSaveDlg = mxUtils.bind(this, function(direct)
- {
- var openSaveDlg = this.inlinePicker ?
- this.createInlinePicker(fn, true) :
- mxUtils.bind(this, function()
- {
- OneDrive.save(
- {
- clientId: this.clientId,
- action: 'query',
- openInNewWindow: true,
- advanced:
- {
- '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!
- 'redirectUri': this.pickerRedirectUri,
- 'queryParameters': 'select=id,name,parentReference',
- 'accessToken': _token,
- isConsumerAccount: false
- },
- success: mxUtils.bind(this, function(files)
- {
- fn(files);
-
- //Update the token in case a login with a different user
- if (mxClient.IS_IE11)
- {
- _token = files.accessToken;
- }
- }),
- cancel: mxUtils.bind(this, function()
- {
- // do nothing
- }),
- error: errorFn
- });
- });
-
- if (direct)
- {
- openSaveDlg();
- }
- else
- {
- this.ui.confirm(mxResources.get('useRootFolder'), mxUtils.bind(this, function()
- {
- fn({value: [this.rootId]});
-
- }), openSaveDlg, mxResources.get('yes'), mxResources.get('noPickFolder') + '...', true);
- }
-
- if (this.user == null)
- {
- this.updateUser(this.emptyFn, this.emptyFn, true);
- }
- });
-
- if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
- {
- this.authenticate(mxUtils.bind(this, function()
- {
- // Direct only possible within user event
- odSaveDlg(this.inlinePicker && direct);
- }), errorFn);
- }
- else
- {
- odSaveDlg(direct);
- }
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.pickFile = function(fn, acceptAllFiles)
- {
- fn = (fn != null) ? fn : mxUtils.bind(this, function(id)
- {
- this.ui.loadFile('W' + encodeURIComponent(id));
- });
-
- var errorFn = mxUtils.bind(this, function(e)
- {
- this.ui.showError(mxResources.get('error'), e && e.message? e.message : e);
- });
-
- var odOpenDlg = this.inlinePicker? this.createInlinePicker(fn, null, acceptAllFiles) :
- mxUtils.bind(this, function()
- {
- OneDrive.open(
- {
- clientId: this.clientId,
- action: 'query',
- multiSelect: false,
- advanced:
- {
- '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!
- 'redirectUri': this.pickerRedirectUri,
- 'queryParameters': 'select=id,name,parentReference,webUrl', //We can also get @microsoft.graph.downloadUrl within this request but it will break the normal process
- 'accessToken': _token,
- isConsumerAccount: false
- },
- success: mxUtils.bind(this, function(files)
- {
- if (files != null && files.value != null && files.value.length > 0)
- {
- //Update the token in case a login with a different user
- if (mxClient.IS_IE11)
- {
- _token = files.accessToken;
- }
-
- fn(OneDriveFile.prototype.getIdOf(files.value[0]), files);
- }
- }),
- cancel: mxUtils.bind(this, function()
- {
- // do nothing
- }),
- error: errorFn
- });
-
- if (this.user == null)
- {
- this.updateUser(this.emptyFn, this.emptyFn, true);
- }
- });
-
- if (_token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
- {
- this.authenticate(mxUtils.bind(this, function()
- {
- if (this.inlinePicker)
- {
- odOpenDlg();
- }
- else
- {
- this.ui.showDialog(new BtnDialog(this.ui, this, mxResources.get('open'), mxUtils.bind(this, function()
- {
- this.ui.hideDialog();
- odOpenDlg();
- })).container, 300, 140, true, true);
- }
- }), errorFn);
- }
- else
- {
- odOpenDlg();
- }
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.logout = function()
- {
- if (isLocalStorage)
- {
- var check = localStorage.getItem('odpickerv7cache');
-
- if (check != null && check.substring(0, 19) == '{"odsdkLoginHint":{')
- {
- localStorage.removeItem('odpickerv7cache');
- }
- }
- window.open(this.authUrl + '/oauth2/v2.0/logout', 'logout', 'width=525,height=525,status=no,resizable=yes,toolbar=no,menubar=no,scrollbars=yes');
- //Send to server to clear refresh token cookie
- this.ui.editor.loadUrl(this.redirectUri + '?doLogout=1&state=' + encodeURIComponent('cId=' + this.clientId + '&domain=' + window.location.host));
- this.clearPersistentToken();
- this.setUser(null);
- _token = null;
- };
- })();
|