diff --git a/apps/files_external/ajax/addRootCertificate.php b/apps/files_external/ajax/addRootCertificate.php deleted file mode 100644 index 38b1860594..0000000000 --- a/apps/files_external/ajax/addRootCertificate.php +++ /dev/null @@ -1,25 +0,0 @@ -getCertificateManager(); - -if (!$certificateManager->addCertificate($data, $filename)) { - OCP\Util::writeLog('files_external', - 'Couldn\'t import SSL root certificate (' . $filename . '), allowed formats: PEM and DER', - OCP\Util::WARN); -} - -header('Location:' . OCP\Util::linkToRoute("settings_personal")); -exit; diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php index 9965303f21..a279163ff7 100755 --- a/apps/files_external/personal.php +++ b/apps/files_external/personal.php @@ -23,12 +23,10 @@ OCP\Util::addScript('files_external', 'settings'); OCP\Util::addStyle('files_external', 'settings'); $backends = OC_Mount_Config::getPersonalBackends(); -$certificateManager = \OC::$server->getCertificateManager(); $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('isAdminPage', false); $tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints()); -$tmpl->assign('certs', $certificateManager->listCertificates()); $tmpl->assign('dependencies', OC_Mount_Config::checkDependencies()); $tmpl->assign('backends', $backends); return $tmpl->fetchPage(); diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index dd283f9ff5..072f856dfb 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -119,30 +119,3 @@

- - -
-

t('SSL root certificates'));?>

- '> - - - - - - - - -
class="remove" - style="visibility:hidden;" - ><?php p($l->t('Delete')); ?>
- - - -
- diff --git a/lib/private/certificatemanager.php b/lib/private/certificatemanager.php index 3a93494578..90a30182c6 100644 --- a/lib/private/certificatemanager.php +++ b/lib/private/certificatemanager.php @@ -29,7 +29,7 @@ class CertificateManager implements ICertificateManager { /** * Returns all certificates trusted by the user * - * @return string[] + * @return \OCP\ICertificate[] */ public function listCertificates() { $path = $this->user->getHome() . '/files_external/uploads/'; @@ -45,7 +45,9 @@ class CertificateManager implements ICertificateManager { return array(); } while (false !== ($file = readdir($handle))) { - if ($file != '.' && $file != '..') $result[] = $file; + if ($file != '.' && $file != '..') { + $result[] = new Certificate(file_get_contents($path . $file), $file); + } } return $result; } @@ -75,7 +77,7 @@ class CertificateManager implements ICertificateManager { /** * @param string $certificate the certificate data * @param string $name the filename for the certificate - * @return bool + * @return bool | \OCP\ICertificate */ public function addCertificate($certificate, $name) { if (!\OC\Files\Filesystem::isValidPath($name)) { @@ -93,7 +95,7 @@ class CertificateManager implements ICertificateManager { $file = $this->user->getHome() . '/files_external/uploads/' . $name; file_put_contents($file, $certificate); $this->createCertificateBundle(); - return true; + return new Certificate($certificate, $name); } else { return false; } diff --git a/lib/private/l10n.php b/lib/private/l10n.php index 28b35e92a2..57886a796c 100644 --- a/lib/private/l10n.php +++ b/lib/private/l10n.php @@ -354,7 +354,7 @@ class OC_L10N implements \OCP\IL10N { case 'datetime': case 'time': if($data instanceof DateTime) { - return $data->format($this->localizations[$type]); + $data = $data->getTimestamp(); } elseif(is_string($data) && !is_numeric($data)) { $data = strtotime($data); } diff --git a/lib/public/icertificatemanager.php b/lib/public/icertificatemanager.php index 9ce7d72117..24b8d12363 100644 --- a/lib/public/icertificatemanager.php +++ b/lib/public/icertificatemanager.php @@ -15,14 +15,14 @@ interface ICertificateManager { /** * Returns all certificates trusted by the user * - * @return string[] + * @return \OCP\ICertificate[] */ public function listCertificates(); /** * @param string $certificate the certificate data * @param string $name the filename for the certificate - * @return bool + * @return bool | \OCP\ICertificate */ public function addCertificate($certificate, $name); diff --git a/settings/ajax/addRootCertificate.php b/settings/ajax/addRootCertificate.php new file mode 100644 index 0000000000..9be8fd0025 --- /dev/null +++ b/settings/ajax/addRootCertificate.php @@ -0,0 +1,34 @@ +getCertificateManager(); + +if ($cert = $certificateManager->addCertificate($data, $filename)) { + OCP\JSON::success(array( + 'name' => $cert->getName(), + 'commonName' => $cert->getCommonName(), + 'organization' => $cert->getOrganization(), + 'validFrom' => $cert->getIssueDate()->getTimestamp(), + 'validTill' => $cert->getExpireDate()->getTimestamp(), + 'validFromString' => $l->l('date', $cert->getIssueDate()), + 'validTillString' => $l->l('date', $cert->getExpireDate()), + 'issuer' => $cert->getIssuerName(), + 'issuerOrganization' => $cert->getIssuerOrganization() + )); +} else { + OCP\JSON::error(array('error' => 'Couldn\'t import SSL root certificate, allowed formats: PEM and DER')); +} diff --git a/apps/files_external/ajax/removeRootCertificate.php b/settings/ajax/removeRootCertificate.php similarity index 100% rename from apps/files_external/ajax/removeRootCertificate.php rename to settings/ajax/removeRootCertificate.php diff --git a/settings/css/settings.css b/settings/css/settings.css index a62a971b83..95fab85df9 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -6,9 +6,11 @@ select#languageinput, select#timezone { width:15em; } input#openid, input#webdav { width:20em; } /* PERSONAL */ -#rootcert_import { - margin: 0 0 10px 0; - display: block; +#sslCertificate tr.expired { + background-color: rgba(255, 0, 0, 0.5); +} +#sslCertificate td { + padding: 5px; } /* Sync clients */ diff --git a/settings/js/personal.js b/settings/js/personal.js index f56dd3425f..d6763cdb29 100644 --- a/settings/js/personal.js +++ b/settings/js/personal.js @@ -13,12 +13,12 @@ * * @param callback */ -jQuery.fn.keyUpDelayedOrEnter = function(callback){ +jQuery.fn.keyUpDelayedOrEnter = function (callback) { var cb = callback; var that = this; this.keyup(_.debounce(function (event) { // enter is already handled in keypress - if(event.keyCode === 13) { + if (event.keyCode === 13) { return; } if (that.val() !== '') { @@ -27,7 +27,7 @@ jQuery.fn.keyUpDelayedOrEnter = function(callback){ }, 1000)); this.keypress(function (event) { - if (event.keyCode === 13 && that.val() !== '' ){ + if (event.keyCode === 13 && that.val() !== '') { event.preventDefault(); cb(); } @@ -38,48 +38,48 @@ jQuery.fn.keyUpDelayedOrEnter = function(callback){ /** * Post the email address change to the server. */ -function changeEmailAddress(){ - var emailInfo = $('#email'); - if (emailInfo.val() === emailInfo.defaultValue){ - return; - } - emailInfo.defaultValue = emailInfo.val(); - OC.msg.startSaving('#lostpassword .msg'); - var post = $( "#lostpassword" ).serialize(); - $.post( 'ajax/lostpassword.php', post, function(data){ - OC.msg.finishedSaving('#lostpassword .msg', data); - }); +function changeEmailAddress () { + var emailInfo = $('#email'); + if (emailInfo.val() === emailInfo.defaultValue) { + return; + } + emailInfo.defaultValue = emailInfo.val(); + OC.msg.startSaving('#lostpassword .msg'); + var post = $("#lostpassword").serialize(); + $.post('ajax/lostpassword.php', post, function (data) { + OC.msg.finishedSaving('#lostpassword .msg', data); + }); } /** * Post the display name change to the server. */ -function changeDisplayName(){ - if ($('#displayName').val() !== '' ) { - OC.msg.startSaving('#displaynameform .msg'); - // Serialize the data - var post = $( "#displaynameform" ).serialize(); - // Ajax foo - $.post( 'ajax/changedisplayname.php', post, function(data){ - if( data.status === "success" ){ - $('#oldDisplayName').val($('#displayName').val()); - // update displayName on the top right expand button - $('#expandDisplayName').text($('#displayName').val()); - updateAvatar(); - } - else{ - $('#newdisplayname').val(data.data.displayName); - } - OC.msg.finishedSaving('#displaynameform .msg', data); - }); - } +function changeDisplayName () { + if ($('#displayName').val() !== '') { + OC.msg.startSaving('#displaynameform .msg'); + // Serialize the data + var post = $("#displaynameform").serialize(); + // Ajax foo + $.post('ajax/changedisplayname.php', post, function (data) { + if (data.status === "success") { + $('#oldDisplayName').val($('#displayName').val()); + // update displayName on the top right expand button + $('#expandDisplayName').text($('#displayName').val()); + updateAvatar(); + } + else { + $('#newdisplayname').val(data.data.displayName); + } + OC.msg.finishedSaving('#displaynameform .msg', data); + }); + } } function updateAvatar (hidedefault) { var $headerdiv = $('#header .avatardiv'); var $displaydiv = $('#displayavatar .avatardiv'); - if(hidedefault) { + if (hidedefault) { $headerdiv.hide(); $('#header .avatardiv').removeClass('avatardiv-shown'); } else { @@ -93,16 +93,16 @@ function updateAvatar (hidedefault) { $('#removeavatar').show(); } -function showAvatarCropper() { +function showAvatarCropper () { var $cropper = $('#cropper'); $cropper.prepend(""); var $cropperImage = $('#cropper img'); $cropperImage.attr('src', - OC.generateUrl('/avatar/tmp')+'?requesttoken='+oc_requesttoken+'#'+Math.floor(Math.random()*1000)); + OC.generateUrl('/avatar/tmp') + '?requesttoken=' + oc_requesttoken + '#' + Math.floor(Math.random() * 1000)); // Looks weird, but on('load', ...) doesn't work in IE8 - $cropperImage.ready(function(){ + $cropperImage.ready(function () { $('#displayavatar').hide(); $cropper.show(); @@ -117,7 +117,7 @@ function showAvatarCropper() { }); } -function sendCropData() { +function sendCropData () { cleanCropper(); var cropperData = $('#cropper').data(); @@ -130,11 +130,11 @@ function sendCropData() { $.post(OC.generateUrl('/avatar/cropped'), {crop: data}, avatarResponseHandler); } -function saveCoords(c) { +function saveCoords (c) { $('#cropper').data(c); } -function cleanCropper() { +function cleanCropper () { var $cropper = $('#cropper'); $('#displayavatar').show(); $cropper.hide(); @@ -143,7 +143,7 @@ function cleanCropper() { $('#cropper img').remove(); } -function avatarResponseHandler(data) { +function avatarResponseHandler (data) { var $warning = $('#avatar .warning'); $warning.hide(); if (data.status === "success") { @@ -156,20 +156,20 @@ function avatarResponseHandler(data) { } } -$(document).ready(function(){ - $("#passwordbutton").click( function(){ +$(document).ready(function () { + $("#passwordbutton").click(function () { if ($('#pass1').val() !== '' && $('#pass2').val() !== '') { // Serialize the data - var post = $( "#passwordform" ).serialize(); + var post = $("#passwordform").serialize(); $('#passwordchanged').hide(); $('#passworderror').hide(); // Ajax foo - $.post(OC.generateUrl('/settings/personal/changepassword'), post, function(data){ - if( data.status === "success" ){ + $.post(OC.generateUrl('/settings/personal/changepassword'), post, function (data) { + if (data.status === "success") { $('#pass1').val(''); $('#pass2').val(''); $('#passwordchanged').show(); - } else{ + } else { if (typeof(data.data) !== "undefined") { $('#passworderror').html(data.data.message); } else { @@ -190,22 +190,22 @@ $(document).ready(function(){ $('#displayName').keyUpDelayedOrEnter(changeDisplayName); $('#email').keyUpDelayedOrEnter(changeEmailAddress); - $("#languageinput").change( function(){ + $("#languageinput").change(function () { // Serialize the data - var post = $( "#languageinput" ).serialize(); + var post = $("#languageinput").serialize(); // Ajax foo - $.post( 'ajax/setlanguage.php', post, function(data){ - if( data.status === "success" ){ + $.post('ajax/setlanguage.php', post, function (data) { + if (data.status === "success") { location.reload(); } - else{ - $('#passworderror').html( data.data.message ); + else { + $('#passworderror').html(data.data.message); } }); return false; }); - $('button:button[name="submitDecryptAll"]').click(function() { + $('button:button[name="submitDecryptAll"]').click(function () { var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val(); $('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true); $('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true); @@ -213,23 +213,23 @@ $(document).ready(function(){ }); - $('button:button[name="submitRestoreKeys"]').click(function() { + $('button:button[name="submitRestoreKeys"]').click(function () { $('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true); $('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true); OC.Encryption.restoreKeys(); }); - $('button:button[name="submitDeleteKeys"]').click(function() { + $('button:button[name="submitDeleteKeys"]').click(function () { $('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true); $('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true); OC.Encryption.deleteKeys(); }); - $('#decryptAll input:password[name="privateKeyPassword"]').keyup(function(event) { + $('#decryptAll input:password[name="privateKeyPassword"]').keyup(function (event) { var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val(); - if (privateKeyPassword !== '' ) { + if (privateKeyPassword !== '') { $('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", false); - if(event.which === 13) { + if (event.which === 13) { $('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true); $('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true); OC.Encryption.decryptAll(privateKeyPassword); @@ -240,21 +240,21 @@ $(document).ready(function(){ }); var uploadparms = { - done: function(e, data) { + done: function (e, data) { avatarResponseHandler(data.result); } }; - $('#uploadavatarbutton').click(function(){ + $('#uploadavatarbutton').click(function () { $('#uploadavatar').click(); }); $('#uploadavatar').fileupload(uploadparms); - $('#selectavatar').click(function(){ + $('#selectavatar').click(function () { OC.dialogs.filepicker( t('settings', "Select a profile picture"), - function(path){ + function (path) { $.post(OC.generateUrl('/avatar/'), {path: path}, avatarResponseHandler); }, false, @@ -262,27 +262,27 @@ $(document).ready(function(){ ); }); - $('#removeavatar').click(function(){ + $('#removeavatar').click(function () { $.ajax({ - type: 'DELETE', - url: OC.generateUrl('/avatar/'), - success: function() { + type: 'DELETE', + url: OC.generateUrl('/avatar/'), + success: function () { updateAvatar(true); $('#removeavatar').hide(); } }); }); - $('#abortcropperbutton').click(function(){ + $('#abortcropperbutton').click(function () { cleanCropper(); }); - $('#sendcropperbutton').click(function(){ + $('#sendcropperbutton').click(function () { sendCropData(); }); $('#pass2').strengthify({ - zxcvbn: OC.linkTo('3rdparty','zxcvbn/js/zxcvbn.js'), + zxcvbn: OC.linkTo('3rdparty', 'zxcvbn/js/zxcvbn.js'), titles: [ t('core', 'Very weak password'), t('core', 'Weak password'), @@ -298,18 +298,59 @@ $(document).ready(function(){ '/avatar/{user}/{size}', {user: OC.currentUser, size: 1} ) + '?requesttoken=' + oc_requesttoken; - $.get(url, function(result) { + $.get(url, function (result) { if (typeof(result) === 'object') { $('#removeavatar').hide(); } }); -} ); + + $('#sslCertificate').on('click', 'td.remove > img', function () { + var row = $(this).parent().parent(); + $.post(OC.filePath('settings', 'ajax', 'removeRootCertificate.php'), { + cert: row.data('name') + }); + row.remove(); + return true; + }); + + $('#sslCertificate tr > td').tipsy({fade: true, gravity: 'n', live: true}); + + $('#rootcert_import').fileupload({ + done: function (e, data) { + console.log(data.result); + var issueDate = new Date(data.result.validFrom * 1000); + var expireDate = new Date(data.result.validTill * 1000); + var now = new Date(); + var isExpired = !(issueDate <= now && now <= expireDate); + + var row = $(''); + row.addClass(isExpired? 'expired': 'valid'); + row.append($('').attr('title', data.result.organization).text(data.result.commonName)); + row.append($('').attr('title', t('core,', 'Valid from {date}', {date: data.result.validFromString})) + .text(data.result.validTillString)); + row.append($('').attr('title', data.result.issuerOrganization).text(data.result.issuer)); + row.append($('').addClass('remove').append( + $('').attr({ + alt: t('core', 'Delete'), + title: t('core', 'Delete'), + src: OC.imagePath('core', 'actions/delete.svg') + }).addClass('action') + )); + + $('#sslCertificate tbody').append(row); + } + }); + + $('#rootcert_import_button').click(function () { + $('#rootcert_import').click(); + }); +}); OC.Encryption = { - decryptAll: function(password) { + decryptAll: function (password) { var message = t('settings', 'Decrypting files... Please wait, this can take some time.'); OC.Encryption.msg.start('#decryptAll .msg', message); - $.post('ajax/decryptall.php', {password:password}, function(data) { + $.post('ajax/decryptall.php', {password: password}, function (data) { if (data.status === "error") { OC.Encryption.msg.finished('#decryptAll .msg', data); $('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", false); @@ -320,10 +361,10 @@ OC.Encryption = { }); }, - deleteKeys: function() { + deleteKeys: function () { var message = t('settings', 'Delete encryption keys permanently.'); OC.Encryption.msg.start('#restoreBackupKeys .msg', message); - $.post('ajax/deletekeys.php', null, function(data) { + $.post('ajax/deletekeys.php', null, function (data) { if (data.status === "error") { OC.Encryption.msg.finished('#restoreBackupKeys .msg', data); $('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false); @@ -334,10 +375,10 @@ OC.Encryption = { }); }, - restoreKeys: function() { + restoreKeys: function () { var message = t('settings', 'Restore encryption keys.'); OC.Encryption.msg.start('#restoreBackupKeys .msg', message); - $.post('ajax/restorekeys.php', {}, function(data) { + $.post('ajax/restorekeys.php', {}, function (data) { if (data.status === "error") { OC.Encryption.msg.finished('#restoreBackupKeys .msg', data); $('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false); @@ -349,24 +390,24 @@ OC.Encryption = { } }; -OC.Encryption.msg={ - start:function(selector, msg){ - var spinner = ''; +OC.Encryption.msg = { + start: function (selector, msg) { + var spinner = ''; $(selector) - .html( msg + ' ' + spinner ) + .html(msg + ' ' + spinner) .removeClass('success') .removeClass('error') .stop(true, true) .show(); }, - finished:function(selector, data){ - if( data.status === "success" ){ - $(selector).html( data.data.message ) + finished: function (selector, data) { + if (data.status === "success") { + $(selector).html(data.data.message) .addClass('success') .stop(true, true) .delay(3000); - }else{ - $(selector).html( data.data.message ).addClass('error'); + } else { + $(selector).html(data.data.message).addClass('error'); } } }; diff --git a/settings/personal.php b/settings/personal.php index a72b293413..d426fd7f35 100644 --- a/settings/personal.php +++ b/settings/personal.php @@ -8,6 +8,7 @@ OC_Util::checkLoggedIn(); $defaults = new OC_Defaults(); // initialize themable default strings and urls +$certificateManager = \OC::$server->getCertificateManager(); // Highlight navigation entry OC_Util::addScript( 'settings', 'personal' ); @@ -98,6 +99,7 @@ $tmpl->assign('backupKeysExists' , $backupKeysExists); $tmpl->assign('filesStillEncrypted' , $filesStillEncrypted); $tmpl->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true)); $tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser())); +$tmpl->assign('certs', $certificateManager->listCertificates()); $forms=OC_App::getForms('personal'); $tmpl->assign('forms', array()); diff --git a/settings/routes.php b/settings/routes.php index 1c8ad1b3fe..c7bab409d4 100644 --- a/settings/routes.php +++ b/settings/routes.php @@ -62,6 +62,10 @@ $this->create('settings_ajax_restorekeys', '/settings/ajax/restorekeys.php') ->actionInclude('settings/ajax/restorekeys.php'); $this->create('settings_ajax_deletekeys', '/settings/ajax/deletekeys.php') ->actionInclude('settings/ajax/deletekeys.php'); +$this->create('core_cert_post', '/settings/ajax/addRootCertificate.php') + ->actionInclude('settings/ajax/addRootCertificate.php'); +$this->create('core_cert_remove', '/settings/ajax/removeRootCertificate.php') + ->actionInclude('settings/ajax/removeRootCertificate.php'); // apps $this->create('settings_ajax_apps_ocs', '/settings/ajax/apps/ocs.php') ->actionInclude('settings/ajax/apps/ocs.php'); diff --git a/settings/templates/personal.php b/settings/templates/personal.php index c1fb20dce0..6d07b89954 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -150,6 +150,44 @@ if($_['passwordChangeSupported']) { print_unescaped($form); };?> +
+

t('SSL root certificates')); ?>

+ + + + + + + + + + + + + + + + +
t('Common Name')); ?>t('Valid until')); ?>t('Issued By')); ?> +
+ getCommonName()) ?> + + l('date', $rootCert->getExpireDate()) ?> + + getIssuerName()) ?> + class="remove" + style="visibility:hidden;" + ><?php p($l->t('Delete')); ?> +
+
+ + +
+
+
@@ -177,11 +215,8 @@ if($_['passwordChangeSupported']) {


- - -
> t( "Your encryption keys are moved to a backup location. If something went wrong you can restore the keys. Only delete them permanently if you are sure that all files are decrypted correctly." )); ?>