1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543 |
- /**
- * Copyright (c) 2006-2020, JGraph Ltd
- * Copyright (c) 2006-2020, 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') ?
- '2e598409-107f-4b59-89ca-d7723c8e00a4' : '45c10911-200f-4e27-a666-9e9fca147395');
- 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.location.protocol + '//' + window.location.host + '/microsoft';
- OneDriveClient.prototype.pickerRedirectUri = window.location.protocol + '//' + window.location.host + '/onedrive3.html';
- /**
- * This is the default endpoint for personal accounts
- */
- OneDriveClient.prototype.defEndpointHint = 'api.onedrive.com';
- OneDriveClient.prototype.endpointHint = OneDriveClient.prototype.defEndpointHint;
- /**
- * 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';
- /**
- * Empty function used when no callback is needed
- */
- OneDriveClient.prototype.emptyFn = function(){};
- 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
- {
- var data = JSON.parse(req.getText());
- this.setUser(new DrawioUser(data.id, null, data.displayName));
- success();
- }
- }
- }), mxUtils.bind(this, function(err)
- {
- window.clearTimeout(timeoutThread);
-
- if (acceptResponse)
- {
- error(err);
- }
- }));
- };
- 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);
- };
- 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();
- }
- };
- 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.hostname + '&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)
- {
- this.updateAuthInfo(JSON.parse(req.getText()), authInfo.remember, false, success, error);
- }
- else
- {
- this.clearPersistentToken();
- this.setUser(null);
- _token = null;
- if (req.getStatus() == 401 && !failOnAuth) // (Unauthorized) [e.g, invalid refresh token]
- {
- auth();
- }
- else
- {
- error({message: mxResources.get('accessDenied'), retry: auth});
- }
- }
- }), error);
- }
- else
- {
- this.ui.showAuthDialog(this, true, mxUtils.bind(this, function(remember, authSuccess)
- {
- var url = 'https://login.microsoftonline.com/common/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.hostname + '&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});
- }
- };
- 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)
- {
- if (_token == null || this.tokenRefreshThread == null || this.tokenExpiresOn - Date.now() < 60000)
- {
- this.authenticate(fn, this.emptyFn);
- }
- else
- {
- fn();
- }
- };
- OneDriveClient.prototype.getItemRef = function(id)
- {
- var idParts = id.split('/');
-
- if (idParts.length > 1)
- {
- return {driveId: idParts[0], id: idParts[1]};
- }
- else
- {
- return {id: id};
- }
- };
- 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.parseFile(new Blob([data], {type: 'application/octet-stream'}), 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') +
- (this.user != null ? ' (' + this.user.displayName + ')' : '')});
- }
- else
- {
- error(this.parseRequestText(req));
- }
- }
- }), 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.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 uploadPart = mxUtils.bind(this, function(uploadUrl, index, 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 req = new mxXmlRequest(uploadUrl, part, 'PUT');
-
- req.setRequestHeaders = mxUtils.bind(this, function(request, params)
- {
- request.setRequestHeader('Content-Length', part.length);
- request.setRequestHeader('Content-Range', 'bytes ' + index + '-' + (index + part.length - 1) + '/' + data.length);
- });
- 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, retryCount);
- }
- }
- else if (status >= 500 && status <= 599 && retryCount < 2) //Retry on server errors
- {
- retryCount++;
- uploadPart(uploadUrl, index, 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);
- }
- 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);
- });
- };
- OneDriveClient.prototype.createInlinePicker = function(fn, foldersOnly)
- {
- return mxUtils.bind(this, function()
- {
- var odPicker = null;
- var div = document.createElement('div');
- div.style.width = '550px';
- div.style.height = '435px';
- 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]
- });
- return;
- }
- else if (!item.folder)
- {
- fn(OneDriveFile.prototype.getIdOf(item));
- return;
- }
- }
-
- return mxResources.get('invalidSel', null, 'Invalid selection');
- }), null, mxResources.get(foldersOnly? 'save' :'open'), null, null, null, null, true);
-
- this.ui.showDialog(dlg.container, 550, 500, true, true);
-
- odPicker = new mxODPicker(div, null, mxUtils.bind(this, function(url, success, error)
- {
- this.executeRequest(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);
- });
- };
- /**
- * 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: [{id: 'root', name: 'root', parentReference: {driveId: 'me'}}]});
-
- }), 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()
- {
- odSaveDlg(false);
- }), errorFn);
- }
- else
- {
- odSaveDlg(direct);
- }
- };
- /**
- * Checks if the client is authorized and calls the next step.
- */
- OneDriveClient.prototype.pickFile = function(fn)
- {
- 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) :
- 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', //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)
- {
- this.ui.hideDialog();
- 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('https://login.microsoftonline.com/common/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.hostname));
- this.clearPersistentToken();
- this.setUser(null);
- _token = null;
- };
- })();
|