From 060f2f719bc59e40fcbbd3a0db86930b75a5b500 Mon Sep 17 00:00:00 2001 From: nielsengelen Date: Tue, 20 Oct 2020 21:17:58 +0200 Subject: [PATCH] v4.2 update v4.2 update --- download.php | 15 +- exchange.php | 947 ++++++++++++++++++++++---------- index.php | 356 ++++++++++-- microsoft.php | 104 ++++ onedrive.php | 881 +++++++++++++++++++++--------- readme.md | 4 +- sharepoint.php | 1188 ++++++++++++++++++++++++++++------------ veeam.class.php | 1375 +++++++++++++++++++++++------------------------ veeam.php | 126 +++-- 9 files changed, 3333 insertions(+), 1663 deletions(-) create mode 100644 microsoft.php diff --git a/download.php b/download.php index 644d733..0fcaf91 100644 --- a/download.php +++ b/download.php @@ -72,15 +72,15 @@ function get_mime_type($filename) { if (isset($_POST['ext'])) { $ext = $_POST['ext']; } if (isset($_POST['name'])) { $name = $_POST['name']; } - if (isset($_POST['file'])) { - $file = str_replace('..', '', isset($_POST['file'])?$_POST['file']:''); - $filename = basename($name); + if (isset($_POST['file'])) { + $file = sys_get_temp_dir() . '/' . basename($_POST['file']); + $filename = htmlspecialchars(basename($name)); if ($ext != 'plain') $filename .= '.' . $ext; if(!is_file($file)) - exit(); + exit('File not found'); header('Pragma: public'); header('Expires: 0'); @@ -96,12 +96,15 @@ function get_mime_type($filename) { } else { header('Last-Modified: ' . gmdate ('D, d M Y H:i:s', filemtime ($file)).' GMT'); header('Cache-Control: private', false); - if ($ext == "plain") { + + if ($ext == 'plain') { $mime = get_mime_type($filename); + header('Content-Type: ' . $mime); } else { header('Content-Type: application/zip'); } + header('Content-Transfer-Encoding: binary'); header('Content-Length: ' . filesize($file)); header('Content-Disposition: attachment; filename=" ' . $filename . '"'); @@ -110,8 +113,6 @@ function get_mime_type($filename) { readfile($file); unlink($file); - - } else { header('Location: index.php'); } diff --git a/exchange.php b/exchange.php index 6661fce..a2a1916 100644 --- a/exchange.php +++ b/exchange.php @@ -10,8 +10,8 @@ exit('Please modify the configuration file first and configure the Veeam Backup for Microsoft Office 365 host, port and RESTful API version settings.'); } -if (!preg_match('/v[3-4]/', $version)) { - exit('Invalid API version found. Please modify the configuration file and configure the Veeam Backup for Microsoft Office 365 RESTful API version setting. Only version 3 and 4 are supported.'); +if (!preg_match('/v[3-5]/', $version)) { + exit('Invalid API version found. Please modify the configuration file and configure the Veeam Backup for Microsoft Office 365 RESTful API version setting. Only version 3, 4 and 5 are supported.'); } ?> @@ -21,7 +21,7 @@ <?php echo $title; ?> - + @@ -30,6 +30,7 @@ + @@ -43,11 +44,23 @@ $veeam = new VBO($host, $port, $version); $veeam->setToken($_SESSION['token']); - $user = $_SESSION['user']; + if (isset($_SESSION['user'])) { + $user = $_SESSION['user']; + } else { + empty($user); + } + + if (isset($_SESSION['authtype'])) { + $authtype = $_SESSION['authtype']; + } + + if (isset($_SESSION['applicationid'])) { + $applicationid = $_SESSION['applicationid']; + } ?>
- +
-
+
@@ -422,12 +449,12 @@
@@ -474,6 +501,11 @@
= 50) { + echo '
'; + echo 'Load more mailboxes'; + echo '
'; + } } } ?> @@ -486,30 +518,29 @@ e.preventDefault(); const swalWithBootstrapButtons = Swal.mixin({ - confirmButtonClass: 'btn btn-success btn-margin', - cancelButtonClass: 'btn btn-danger', + customClass: { + confirmButton: 'btn btn-success btn-margin', + cancelButton: 'btn btn-danger' + }, buttonsStyling: false, - }) + }); swalWithBootstrapButtons.fire({ - type: 'question', + icon: 'question', title: 'Logout', text: 'You are about to logout. Are you sure you want to continue?', showCancelButton: true, - confirmButtonText: 'Yes', - cancelButtonText: 'No', - }).then((result) => { - if (result.value) { - $.post('index.php', {'logout' : true}, function(data) { - window.location.replace('index.php'); - }); + confirmButtonText: 'Logout', + cancelButtonText: 'Cancel', + }).then(function(result) { + if (result.isConfirmed) { + $.redirect('index.php', {'logout' : true}, 'POST'); } else { return; } }) }); -/* Exchange Restore Buttons */ $('.btn-start-restore').click(function(e) { if (typeof $(this).data('jid') !== 'undefined') { var jid = $(this).data('jid'); @@ -528,7 +559,7 @@ $('#pit-date').addClass('errorClass'); Swal.fire({ - type: 'info', + icon: 'info', title: 'No date selected', text: 'Please select a date first before starting the restore or use the \"explore last backup\" button.' }) @@ -548,15 +579,15 @@ $.post('veeam.php', {'action' : 'startrestore', 'json' : json, 'id' : oid}).done(function(data) { if (data.match(/([a-zA-Z0-9]{8})-([a-zA-Z0-9]{4})-([a-zA-Z0-9]{4})-([a-zA-Z0-9]{4})-([a-zA-Z0-9]{12})/g)) { Swal.fire({ - type: 'success', + icon: 'success', title: 'Session started', - text: 'Restore session has been started and you can now perform restores.' + text: 'Restore session has been started and you can now perform restores' }).then(function(e) { window.location.href = 'exchange'; }); } else { Swal.fire({ - type: 'error', + icon: 'error', title: 'Error starting restore session', text: '' + data }) @@ -565,32 +596,50 @@ } }); }); + $('.btn-stop-restore').click(function(e) { var rid = ''; const swalWithBootstrapButtons = Swal.mixin({ - confirmButtonClass: 'btn btn-success btn-margin', - cancelButtonClass: 'btn btn-danger', + customClass: { + confirmButton: 'btn btn-success btn-margin', + cancelButton: 'btn btn-danger' + }, buttonsStyling: false, - }) + focusConfirm: false, + }); swalWithBootstrapButtons.fire({ - type: 'question', + icon: 'question', title: 'Stop the restore session?', - text: 'This will terminate any restore options for the specific point in time.', + text: 'This will terminate any restore options for the specific point in time', showCancelButton: true, confirmButtonText: 'Stop', cancelButtonText: 'Cancel', - }).then((result) => { - if (result.value) { - $.post('veeam.php', {'action' : 'stoprestore', 'id' : rid}).done(function(data) { - swalWithBootstrapButtons.fire({ - type: 'success', - title: 'Restore session was stopped', - text: 'The restore session was stopped successfully.', - }).then(function(e) { - window.location.href = 'exchange'; - }); + }).then(function(result) { + if (result.isConfirmed) { + $.post('veeam.php', {'action' : 'stoprestore', 'rid' : rid}).done(function(data) { + if (data === 'success') { + swalWithBootstrapButtons.fire({ + icon: 'success', + title: 'Restore session was stopped', + text: 'The restore session was stopped successfully', + }).then(function(e) { + window.location.href = 'exchange'; + }); + } else { + var response = JSON.parse(data); + + swalWithBootstrapButtons.fire({ + icon: 'error', + title: 'Failed to stop restore session', + text: '' + response.slice(0, -1), + }).then(function(e) { + window.location.href = 'exchange'; + }); + } }); } else { return; @@ -598,10 +647,6 @@ }) }); - -/* Dropdown settings for restore buttons */ $('hide.bs.dropdown').dropdown(function(e) { $(e.target).find('>.dropdown-menu:first').slideUp(); }); @@ -609,13 +654,11 @@ $(e.target).find('>.dropdown-menu:first').slideDown(); }); -/* Select all checkbox */ $('#chk-all').click(function(e) { var table = $(e.target).closest('table'); $('tr:visible :checkbox', table).prop('checked', this.checked); }); -/* Item search */ $('#search-mailbox').keyup(function(e) { var searchText = $(this).val().toLowerCase(); @@ -633,24 +676,36 @@ $(this).addClass('active'); }); -/* Load more link for e-mail content */ -$('.load-more-link').click(function(e) { +$('.load-more-folders').click(function(e) { + var mailboxid = $(this).data('mailboxid'); + var offset = $(this).data('offset'); + + loadMailboxFolders(mailboxid, offset); +}); +$('.load-more-items').click(function(e) { var folderid = $(this).data('folderid'); var mailboxid = $(this).data('mailboxid'); var offset = $(this).data('offset'); + var type = $(this).data('type'); - loadMessages(mailboxid, folderid, offset); + loadMessages(mailboxid, folderid, offset); +}); +$('.load-more-mailboxes').click(function(e) { + var offset = $(this).data('offset'); + var org = $(this).data('org'); + + loadMailboxes(org, offset); }); -/* Export to MSG file */ function downloadMsg(itemid, mailboxid, mailsubject) { var rid = ''; var json = '{ "savetoMsg": null }'; Swal.fire({ - type: 'info', + icon: 'info', title: 'Download is starting', - text: 'Download will start soon.' + text: 'Download will start soon', + allowOutsideClick: false, }) $.post('veeam.php', {'action': 'exportmailitem', 'itemid' : itemid, 'mailboxid' : mailboxid, 'rid' : rid, 'json' : json}).done(function(data) { @@ -658,7 +713,7 @@ function downloadMsg(itemid, mailboxid, mailsubject) { $.redirect('download.php', {ext : 'msg', file : data, name : mailsubject}, 'POST'); } else { Swal.fire({ - type: 'error', + icon: 'error', title: 'Export failed', text: 'Export failed.' }) @@ -667,27 +722,27 @@ function downloadMsg(itemid, mailboxid, mailsubject) { }); } -/* Export to PST file */ function downloadPST(itemid, mailboxid, mailsubject, type) { var rid = ''; Swal.fire({ - type: 'info', + icon: 'info', title: 'Download is starting', - text: 'Export in progress and your download will start soon.' + text: 'Export in progress and your download will start soon', + allowOutsideClick: false, }) - if (type == 'multiple') { /* Multiple items export */ + if (type == 'multiple') { var act = 'exportmultiplemailitems'; var ids = ''; var mailsubject = 'exported-mailitems-' + mailsubject; - if ($("input[name='checkbox-mail']:checked").length === 0) { /* Error handling for multiple export button */ + if ($("input[name='checkbox-mail']:checked").length === 0) { Swal.close(); Swal.fire({ - type: 'error', - title: 'Restore failed', + icon: 'info', + title: 'Unable to restore', text: 'No items have been selected.' }) @@ -707,11 +762,11 @@ function downloadPST(itemid, mailboxid, mailsubject, type) { } \ }'; } else { - if (type == 'single') { /* Single item export */ + if (type == 'single') { var act = 'exportmailitem'; - } else { /* Full mailbox export */ + } else { var act = 'exportmailbox'; - var mailsubject = 'mailbox-' + mailsubject; /* mailbox-username */ + var mailsubject = 'mailbox-' + mailsubject; } var json = '{ \ @@ -721,14 +776,14 @@ function downloadPST(itemid, mailboxid, mailsubject, type) { }'; } - $.post('veeam.php', {'action' : act, 'itemid' : itemid, 'mailboxid' : mailboxid, 'rid' : rid, 'json' : json}).done(function(data) { - if (data && data != '500') { - $.redirect('download.php', {ext : 'pst', file : data, name : mailsubject}, 'POST'); - + $.post('veeam.php', {'action' : act, 'itemid' : itemid, 'mailboxid' : mailboxid, 'rid' : rid, 'json' : json}).done(function(data) { + if (data && data != 500) { + $.redirect('download.php', {'ext' : 'pst', 'file' : data, 'name' : mailsubject}, 'POST'); + Swal.close(); } else { Swal.fire({ - type: 'error', + icon: 'error', title: 'Export failed', text: '' + data }) @@ -738,71 +793,71 @@ function downloadPST(itemid, mailboxid, mailsubject, type) { }); } -/* Restore to a different location */ function restoreToDifferent(itemid, mailboxid, type) { var rid = ''; - if (type == 'multiple' && $("input[name='checkbox-mail']:checked").length == 0) { /* Error handling for multiple restore button */ + if (type == 'multiple' && $("input[name='checkbox-mail']:checked").length == 0) { Swal.fire({ - type: 'error', - title: 'Restore failed', + icon: 'info', + title: 'Unable to restore', text: 'No items have been selected.' }) return; } const swalWithBootstrapButtons = Swal.mixin({ - confirmButtonClass: 'btn btn-success', - cancelButtonClass: 'btn btn-danger btn-margin', + customClass: { + confirmButton: 'btn btn-success btn-margin-restore', + cancelButton: 'btn btn-danger' + }, buttonsStyling: false, - input: 'text' - }) + input: 'text', + }); swalWithBootstrapButtons.fire({ - title: 'Restore to a different location', + title: 'Restore to different location', html: '
' + '
' + - '' + - '
' + + '' + + '
' + '
' + '
' + - '' + - '
' + + '' + + '
' + '
' + '
' + - '' + - '
' + + '' + + '
' + '
' + '
' + - '' + - '
' + + '' + + '
' + '
' + '
' + - '' + - '
' + - '
By default items will be restored in a folder named Restored-via-web-client.
' + + '' + + '
' + + '
By default items will be restored in a folder named Restored-via-web-client.
' + + '
' + '
' + '
', - focusConfirm: false, - showCancelButton: true, confirmButtonText: 'Restore', cancelButtonText: 'Cancel', + allowOutsideClick: false, + focusConfirm: false, reverseButtons: true, + showCancelButton: true, inputValidator: () => { - var elem = document.getElementById('swal2-validation-message'); - elem.style.setProperty('margin', '10px 0px', ''); - var restoredata = Object.values(document.getElementsByClassName('restoredata')); - var errors = [ 'No target mailbox defined.', 'No target mailbox server defined.', 'No username defined.', 'No password defined.' ]; + var errors = [ 'No target mailbox defined', 'No target mailbox server defined', 'No username defined', 'No password defined' ]; for (var i = 0; i < restoredata.length; i++) { if (!restoredata[i].value) return errors[i]; } }, - onBeforeOpen: function (dom) { - swal.getInput().style.display = 'none'; + willOpen: function (dom) { + swalWithBootstrapButtons.getInput().style.display = 'none'; }, preConfirm: function() { return new Promise(function(resolve) { @@ -815,7 +870,7 @@ function restoreToDifferent(itemid, mailboxid, type) { }); }, }).then(function(result) { - if (result.value) { + if (result.isConfirmed) { var user = $('#restore-different-user').val(); var pass = $('#restore-different-pass').val(); var server = $('#restore-different-server').val(); @@ -823,16 +878,17 @@ function restoreToDifferent(itemid, mailboxid, type) { var mailbox = $('#restore-different-mailbox').val(); Swal.fire({ - type: 'info', - title: 'Item restore in progress', - text: 'Restore in progress...' + icon: 'info', + title: 'Item restore', + text: 'Restore in progress...', + allowOutsideClick: false, }) if (typeof folder === undefined || !folder) { folder = 'Restored-via-web-client'; } - if (type == 'multiple') { /* Multiple items restore */ + if (type == 'multiple') { var act = 'restoremultiplemailitems'; var ids = ''; @@ -859,9 +915,9 @@ function restoreToDifferent(itemid, mailboxid, type) { } \ }'; } else { - if (type == 'single') { /* Single item restore */ + if (type == 'single') { var act = 'restoremailitem'; - } else { /* Full mailbox restore */ + } else { var act = 'restoremailbox'; } @@ -884,11 +940,41 @@ function restoreToDifferent(itemid, mailboxid, type) { } $.post('veeam.php', {'action' : act, 'itemid' : itemid, 'mailboxid' : mailboxid, 'rid' : rid, 'json' : json}).done(function(data) { - Swal.fire({ - type: 'info', - title: 'Item restore', - text: '' + data - }) + var response = JSON.parse(data); + + if (response['restoreFailed'] === undefined) { + var result = ''; + + if (response['createdItemsCount'] >= '1') { + result += response['createdItemsCount'] + ' item(s) successfully created
'; + } + + if (response['mergedItemsCount'] >= '1') { + result += response['mergedItemsCount'] + ' item(s) merged
'; + } + + if (response['failedItemsCount'] >= '1') { + result += response['failedItemsCount'] + ' item(s) failed
'; + } + + if (response['skippedItemsCount'] >= '1') { + result += response['skippedItemsCount'] + ' item(s) skipped'; + } + + Swal.fire({ + icon: 'info', + title: 'Item restore', + html: '' + result, + allowOutsideClick: false, + }) + } else { + Swal.fire({ + icon: 'info', + title: 'Item restore', + html: 'Restore failed: ' + response['restoreFailed'], + allowOutsideClick: false, + }) + } }); } else { return; @@ -896,121 +982,352 @@ function restoreToDifferent(itemid, mailboxid, type) { }); } -/* Restore to original location */ function restoreToOriginal(itemid, mailboxid, type) { var rid = ''; -console.log(type); - if (type == 'multiple' && $("input[name='checkbox-mail']:checked").length == 0) { /* Error handling for multiple restore button */ + + if (type == 'multiple' && $("input[name='checkbox-mail']:checked").length == 0) { Swal.fire({ - type: 'error', - title: 'Restore failed', + icon: 'info', + title: 'Unable to restore', text: 'No items have been selected.' }) return; } const swalWithBootstrapButtons = Swal.mixin({ - confirmButtonClass: 'btn btn-success', - cancelButtonClass: 'btn btn-danger btn-margin', + title: 'Restore to original location', + allowOutsideClick: false, buttonsStyling: false, - input: 'text' - }) + focusConfirm: false, + input: 'text', + reverseButtons: true, + showCancelButton: true, + cancelButtonText: 'Cancel', + confirmButtonText: 'Next', + customClass: { + confirmButton: 'btn btn-success btn-margin-restore', + cancelButton: 'btn btn-danger', + } + }); swalWithBootstrapButtons.fire({ - title: 'Restore to the original location', - html: - '
' + - '
' + - '' + - '
' + - '
' + - '
' + - '' + - '
' + - '
' + - '
', - focusConfirm: false, - showCancelButton: true, - confirmButtonText: 'Restore', - cancelButtonText: 'Cancel', - reverseButtons: true, - inputValidator: () => { - var elem = document.getElementById('swal2-validation-message'); - elem.style.setProperty('margin', '10px 0px', ''); - - var restoredata = Object.values(document.getElementsByClassName("restoredata")); - var errors = [ 'No username defined.', 'No password defined.' ]; - - for (var i = 0; i < restoredata.length; i++) { - if (!restoredata[i].value) - return errors[i]; - } - }, - onBeforeOpen: function (dom) { - swal.getInput().style.display = 'none'; - }, - preConfirm: function() { - return new Promise(function(resolve) { - resolve([ - $('#restore-original-user').val(), - $('#restore-original-pass').val(), - ]); - }); + text: 'Select authentication method', + input: 'select', + inputOptions: { + + 'basic' : 'Basic Authentication', + 'mfa' : 'Modern Authentication', + + 'mfa' : 'Modern Authentication', + 'basic' : 'Basic Authentication', + }, - }).then(function(result) { - if (result.value) { - var user = $('#restore-original-user').val(); - var pass = $('#restore-original-pass').val(); - - Swal.fire({ - type: 'info', - title: 'Item restore in progress', - text: 'Restore in progress...' - }) + inputValidator: (value) => { + return new Promise((resolve) => { + if (value === 'basic') { + swalWithBootstrapButtons.fire({ + html: + '
' + + '
' + + '' + + '
' + + '' + + '
' + + '
' + + '
' + + '' + + '
' + + '' + + '
' + + '
' + + '
', + confirmButtonText: 'Restore', + cancelButtonText: 'Cancel', + inputValidator: () => { + var restoredata = Object.values(document.getElementsByClassName('restoredata')); + var errors = [ 'No username defined', 'No password defined' ]; + + for (var i = 0; i < restoredata.length; i++) { + if (!restoredata[i].value) + return errors[i]; + } + }, + willOpen: () => { + Swal.getInput().style.display = 'none'; + }, + preConfirm: function() { + return new Promise(function(resolve) { + resolve([ + $('#restore-original-username').val(), + $('#restore-original-password').val(), + ]); + }); + } + }).then(function(result) { + if (result.isConfirmed) { + var user = $('#restore-original-username').val(); + var pass = $('#restore-original-password').val(); + + Swal.fire({ + icon: 'info', + title: 'Item restore', + text: 'Restore in progress...', + allowOutsideClick: false, + }) - if (type == 'multiple') { /* Multiple items restore */ - var act = 'restoremultiplemailitems'; - var ids = ''; - - $("input[name='checkbox-mail']:checked").each(function(e) { - ids = ids + '{ "Id": "' + this.value + '" }, '; - }); - - var json = '{ "restoretoOriginallocation": \ - { "userName": "' + user + '", \ - "userPassword": "' + pass + '", \ - "items": [ \ - ' + ids + ' \ - \ ] \ - } \ - }'; - } else { - if (type == 'single') { /* Single item restore */ - var act = 'restoremailitem'; - } else if (type == 'full') { /* Full mailbox restore */ - var act = 'restoremailbox'; + if (type == 'multiple') { + var act = 'restoremultiplemailitems'; + var ids = ''; + + $("input[name='checkbox-mail']:checked").each(function(e) { + ids = ids + '{ "Id": "' + this.value + '" }, '; + }); + + var json = '{ "restoretoOriginallocation": \ + { "userName": "' + user + '", \ + "userPassword": "' + pass + '", \ + "items": [ \ + ' + ids + ' \ + \ ] \ + } \ + }'; + } else { + if (type == 'single') { + var act = 'restoremailitem'; + } else if (type == 'full') { + var act = 'restoremailbox'; + } + + var json = '{ "restoretoOriginallocation": \ + { "userName": "' + user + '", \ + "userPassword": "' + pass + '", \ + } \ + }'; + } + + $.post('veeam.php', {'action' : act, 'itemid' : itemid, 'mailboxid' : mailboxid, 'rid' : rid, 'json' : json}).done(function(data) { + var response = JSON.parse(data); + + if (response['restoreFailed'] === undefined) { + var result = ''; + + if (response['createdItemsCount'] >= '1') { + result += response['createdItemsCount'] + ' item(s) successfully created
'; + } + + if (response['mergedItemsCount'] >= '1') { + result += response['mergedItemsCount'] + ' item(s) merged
'; + } + + if (response['failedItemsCount'] >= '1') { + result += response['failedItemsCount'] + ' item(s) failed
'; + } + + if (response['skippedItemsCount'] >= '1') { + result += response['skippedItemsCount'] + ' item(s) skipped'; + } + + Swal.fire({ + icon: 'info', + title: 'Item restore', + html: '' + result, + allowOutsideClick: false, + }) + } else { + Swal.fire({ + icon: 'info', + title: 'Item restore', + html: 'Restore failed: ' + response['restoreFailed'], + allowOutsideClick: false, + }) + } + }); + } + }); + } else { + swalWithBootstrapButtons.fire({ + html: + '
' + + '
' + + '' + + '
' + + + '' + + + '' + + + '
' + + '
' + + '
', + confirmButtonText: 'Next', + cancelButtonText: 'Cancel', + inputValidator: () => { + var restoredata = Object.values(document.getElementsByClassName('restoredata')); + var errors = [ 'No Application ID defined.' ]; + + for (var i = 0; i < restoredata.length; i++) { + if (!restoredata[i].value) + return errors[i]; + } + }, + willOpen: () => { + Swal.getInput().style.display = 'none'; + }, + preConfirm: function() { + return new Promise(function(resolve) { + resolve([ + $('#restore-original-applicationid').val(), + ]); + }); + } + }).then(function(result) { + if (result.isConfirmed) { + var clipboard = new ClipboardJS('#btn-copy'); + var applicationid = $('#restore-original-applicationid').val(); + var json = '{ "targetApplicationId" : "' + applicationid + '", }'; + + clipboard.on('success', function(e) { + setTooltip('Copied!'); + hideTooltip(); + }); + clipboard.on('error', function(e) { + setTooltip('Failed!'); + hideTooltip(); + }); + + Swal.fire({ + title: 'Restore to original location', + text: 'Loading, please wait...', + }); + + $.post('veeam.php', {'action' : 'getrestoredevicecode', 'rid' : rid, 'json' : json}).done(function(data) { + var response = JSON.parse(data); + var usercode = response['userCode']; + + swalWithBootstrapButtons.fire({ + html: + '
' + + '
' + + 'To continue, open https://microsoft.com/devicelogin and enter the below code to authenticate.

' + + '
' + + '
' + + '


' + + '
' + + '
' + + '
', + confirmButtonText: 'Restore', + cancelButtonText: 'Cancel', + willOpen: () => { + Swal.getInput().style.display = 'none'; + }, + }).then(function(result) { + if (result.isConfirmed) { + Swal.fire({ + icon: 'info', + title: 'Item restore', + text: 'Restore in progress...', + allowOutsideClick: false, + }) + + if (type == 'multiple') { + var act = 'restoremultiplemailitems'; + var ids = ''; + + $("input[name='checkbox-mail']:checked").each(function(e) { + ids = ids + '{ "Id": "' + this.value + '" }, '; + }); + + var json = '{ "restoretoOriginallocation": \ + { "userCode": "' + usercode + '", \ + "items": [ \ + ' + ids + ' \ + \ ] \ + } \ + }'; + } else { + if (type == 'single') { + var act = 'restoremailitem'; + } else if (type == 'full') { + var act = 'restoremailbox'; + } + + var json = '{ "restoretoOriginallocation": \ + { "userCode": "' + usercode + '", \ + } \ + }'; + } + + $.post('veeam.php', {'action' : act, 'itemid' : itemid, 'mailboxid' : mailboxid, 'rid' : rid, 'json' : json}).done(function(data) { + var response = JSON.parse(data); + + if (response['restoreFailed'] === undefined) { + var result = ''; + + if (response['createdItemsCount'] >= '1') { + result += response['createdItemsCount'] + ' item(s) successfully created
'; + } + + if (response['mergedItemsCount'] >= '1') { + result += response['mergedItemsCount'] + ' item(s) merged
'; + } + + if (response['failedItemsCount'] >= '1') { + result += response['failedItemsCount'] + ' item(s) failed
'; + } + + if (response['skippedItemsCount'] >= '1') { + result += response['skippedItemsCount'] + ' item(s) skipped'; + } + + Swal.fire({ + icon: 'info', + title: 'Item restore', + html: '' + result, + allowOutsideClick: false, + }) + } else { + Swal.fire({ + icon: 'info', + title: 'Item restore', + html: 'Restore failed: ' + response['restoreFailed'], + allowOutsideClick: false, + }) + } + }); + + } + }); + }); + } + }); } - - var json = '{ "restoretoOriginallocation": \ - { "userName": "' + user + '", \ - "userPassword": "' + pass + '", \ - } \ - }'; - } - - $.post('veeam.php', {'action' : act, 'itemid' : itemid, 'mailboxid' : mailboxid, 'rid' : rid, 'json' : json}).done(function(data) { - Swal.fire({ - type: 'info', - title: 'Item restore', - text: '' + data - }) - }); - } else { - return; + }) } }); } +function hideTooltip() { + setTimeout(function() { + $('#btn-copy').tooltip('hide'); + }, 1000); +} + +function setTooltip(message) { + $('#btn-copy').tooltip('hide').attr('data-original-title', message).tooltip('show'); +} + function disableTree() { $('#jstree li.jstree-node').each(function(e) { $('#jstree').jstree('disable_node', this.id) @@ -1020,6 +1337,7 @@ function disableTree() { return false; }); } + function enableTree() { $('#jstree li.jstree-node').each(function(e) { $('#jstree').jstree('enable_node', this.id) @@ -1028,7 +1346,6 @@ function enableTree() { $('#jstree i.jstree-ocl').off('click.block'); } -/* Exchange functions */ function fillTable(response, mailboxid) { if (response.results.length !== 0) { for (var i = 0; i < response.results.length; i++) { @@ -1084,12 +1401,96 @@ function fillTable(response, mailboxid) { } } -function loadMailbox(folderid, mailboxid, parent) { +function loadMailboxes(org, offset) { + var rid = ''; + + $.post('veeam.php', {'action' : 'getmailboxes', 'offset' : offset, 'rid' : rid}).done(function(data) { + var response = JSON.parse(data); + + if (response.results.length != 0) { + for (var i = 0; i < response.results.length; i++) { + if ($('#table-exchange-mailboxes').length > 0){ + $('#table-exchange-mailboxes tbody').append(' \ + ' + response.results[i].name + ' \ + ' + response.results[i].email + ' \ + \ + \ + \ + '); + } + + $('#ul-exchange-users').append('
  • ' + response.results[i].name + '
  • '); + } + + if (response.results.length >= 50) { + $('a.load-more-mailboxes').data('offset', offset + 50); + } else { + $('a.load-more-mailboxes').addClass('hide'); + } + } + }); +} + +function loadMailboxFolders(mailboxid, offset) { + var rid = ''; + + $.post('veeam.php', {'action' : 'getmailboxfolders', 'mailboxid' : mailboxid, 'offset' : offset, 'rid' : rid}).done(function(data) { + var response = JSON.parse(data); + + if (response.results.length != 0) { + var icon, type; + + for (var i = 0; i < response.results.length; i++) { + type = response.results[i].type; + + switch (type.toLowerCase()) { + case 'appointment': + icon = 'far fa-calendar-check'; + break; + case 'contact': + icon = 'far fa-address-book'; + break; + case 'journal': + icon = 'fa fa-book'; + break; + case 'stickynote': + icon = 'far fa-sticky-note'; + break; + case 'task': + icon = 'fa fa-tasks'; + break; + default: + icon = 'far fa-folder'; + } + + $('#jstree').jstree('create_node', '#', {data: {"folderid" : response.results[i].id, "mailboxid" : mailboxid, "jstree" : {"icon" : icon}}, text: response.results[i].name}); + } + + if (response.results.length >= 50) { + $('a.load-more-folders').data('offset', offset + 50); + } else { + $('a.load-more-folders').addClass('hide'); + } + } + }); +} + +function loadMailboxItems(folderid, mailboxid, parent) { var rid = ''; disableTree(); - $.post('veeam.php', {'action' : 'getmailfolders', 'folderid' : folderid, 'mailboxid' : mailboxid, 'rid' : rid}).done(function(data) { + $.post('veeam.php', {'action' : 'getmailboxfolders', 'folderid' : folderid, 'mailboxid' : mailboxid, 'offset' : 0, 'limit' : 250, 'rid' : rid}).done(function(data) { var responsefolders = JSON.parse(data); if (parent !== null) { @@ -1139,18 +1540,19 @@ function loadMailbox(folderid, mailboxid, parent) { $('#table-exchange-items tbody').empty(); $('#loader').removeClass('hide'); - $('a.load-more-link').addClass('hide'); + $('a.load-more-items').addClass('hide'); $.post('veeam.php', {'action' : 'getmailitems', 'folderid' : folderid, 'mailboxid' : mailboxid, 'rid' : rid}).done(function(data) { var responseitems = JSON.parse(data); - if (responseitems.results.length != 0) { + if (typeof responseitems !== 'undefined' && responseitems.results.length != 0) { fillTable(responseitems, mailboxid); - if (responseitems.results.length == 30) { - $('a.load-more-link').removeClass('hide'); + if (responseitems.results.length >= 50) { + $('a.load-more-items').removeClass('hide'); + $('a.load-more-items').data('folderid', folderid); } else { - $('a.load-more-link').addClass('hide'); + $('a.load-more-items').addClass('hide'); } } else { $('#table-exchange-items tbody').append('No items available in this folder.'); @@ -1170,12 +1572,11 @@ function loadMessages(mailboxid, folderid, offset) { if (response.results.length != 0) { fillTable(response, mailboxid); - if (response.results.length == 30) { - $('a.load-more-link').removeClass('hide'); - $('a.load-more-link').data('offset', offset + 30); - $('a.load-more-link').data('folderid', folderid); + if (response.results.length >= 50) { + $('a.load-more-items').removeClass('hide'); + $('a.load-more-items').data('offset', offset + 50); } else { - $('a.load-more-link').addClass('hide'); + $('a.load-more-items').addClass('hide'); } } else { $('#table-exchange-items tbody').append('No more items available in this folder.'); @@ -1199,7 +1600,7 @@ function loadMessages(mailboxid, folderid, offset) { ?> + + @@ -59,7 +82,7 @@ ?> +
    + + +
    + + + +

    The provided username or password is incorrect.

    '; + if ($login == 0) { + echo '
    The provided credentials are incorrect.'; + } else if ($login == 1) { + echo '
    No credentials are provided.'; } else { - echo $login; + echo '
    ' . $login . ''; } } ?>
    - +
    + + - - - - + + diff --git a/microsoft.php b/microsoft.php new file mode 100644 index 0000000..7b96eca --- /dev/null +++ b/microsoft.php @@ -0,0 +1,104 @@ +request('POST', $url, [ + 'form_params' => [ + 'client_id' => $clientid, + 'scope' => $scope, + ], + 'headers' => [ + 'Accept' => 'application/json', + 'Content-Type' => 'application/x-www-form-urlencoded', + ] + ]); + + + if ($response->getStatusCode() === 200) { + $result = json_decode($response->getBody(), true); + } else { + $result = $response['error']; + } + + return $result; + } catch (RequestException $e) { + if ($e->hasResponse()) { + $exception = (string) $e->getResponse()->getBody(); + $exception = json_decode($exception, true); + + echo 'Error: ' . $exception['error'] . '
    ' . $exception['error_description']; + } else { + echo $e->getMessage(); + } + } +} + +function getToken($clientid, $tenantid, $devicecode) { + try { + $client = new \GuzzleHttp\Client(); + + $url = 'https://login.microsoftonline.com/'.$tenantid.'/oauth2/v2.0/token'; + $response = $client->request('POST', $url, [ + 'form_params' => [ + 'grant_type' => 'urn:ietf:params:oauth:grant-type:device_code', + 'client_id' => $clientid, + 'device_code' => $devicecode, + ], + 'headers' => [ + 'Accept' => 'application/json', + 'Content-Type' => 'application/x-www-form-urlencoded', + ] + ]); + + if ($response->getStatusCode() === 200) { + $result = json_decode($response->getBody(), true); + } else { + $result = $response->getStatusCode(); + } + + return $result; + } catch (RequestException $e) { + if ($e->hasResponse()) { + $exception = (string) $e->getResponse()->getBody(); + $exception = json_decode($exception, true); + + return $exception; + } else { + echo $e->getMessage(); + } + } +} + +if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { + if (isset($_POST['action'])) { $action = $_POST['action']; } + if (isset($_POST['assertion'])) { $assertion = $_POST['assertion']; } + if (isset($_POST['clientid'])) { $clientid = $_POST['clientid']; } + if (isset($_POST['tenantid'])) { $tenantid = $_POST['tenantid']; } + if (isset($_POST['devicecode'])) { $devicecode = $_POST['devicecode']; } + + /* Microsoft Calls */ + if ($action == 'getdevicecode') { + $code = getDeviceCode($clientid, $tenantid, $scope); + + echo json_encode($code); + } + if ($action == 'gettoken') { + $token = getToken($clientid, $tenantid, $devicecode); + + echo json_encode($token); + } +} else { + die(); +} +?> \ No newline at end of file diff --git a/onedrive.php b/onedrive.php index 88bd998..d7272ab 100644 --- a/onedrive.php +++ b/onedrive.php @@ -10,8 +10,8 @@ exit('Please modify the configuration file first and configure the Veeam Backup for Microsoft Office 365 host, port and RESTful API version settings.'); } -if (!preg_match('/v[3-4]/', $version)) { - exit('Invalid API version found. Please modify the configuration file and configure the Veeam Backup for Microsoft Office 365 RESTful API version setting. Only version 3 and 4 are supported.'); +if (!preg_match('/v[3-5]/', $version)) { + exit('Invalid API version found. Please modify the configuration file and configure the Veeam Backup for Microsoft Office 365 RESTful API version setting. Only version 3, 4 and 5 are supported.'); } ?> @@ -21,7 +21,7 @@ <?php echo $title; ?> - + @@ -30,6 +30,7 @@ + @@ -44,11 +45,23 @@ $veeam = new VBO($host, $port, $version); $veeam->setToken($_SESSION['token']); - $user = $_SESSION['user']; + if (isset($_SESSION['user'])) { + $user = $_SESSION['user']; + } else { + empty($user); + } + + if (isset($_SESSION['authtype'])) { + $authtype = $_SESSION['authtype']; + } + + if (isset($_SESSION['applicationid'])) { + $applicationid = $_SESSION['applicationid']; + } ?>
    - +