diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php
index 1f92e1fb..cdb88804 100644
--- a/data/web/inc/prerequisites.inc.php
+++ b/data/web/inc/prerequisites.inc.php
@@ -63,6 +63,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.en.php';
include $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.'.$_SESSION['mailcow_locale'].'.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailbox.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.customize.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.domain_admin.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.policy.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.dkim.inc.php';
diff --git a/data/web/inc/sessions.inc.php b/data/web/inc/sessions.inc.php
index 2dbc8fff..abbef40f 100644
--- a/data/web/inc/sessions.inc.php
+++ b/data/web/inc/sessions.inc.php
@@ -53,6 +53,7 @@ if (isset($_SESSION['mailcow_cc_role']) && session_check() === false) {
'msg' => 'Form token invalid or timed out'
);
$_POST = array();
+ $_FILES = array();
}
// Handle logouts
diff --git a/data/web/inc/triggers.inc.php b/data/web/inc/triggers.inc.php
index b91acd93..10fbe4cc 100644
--- a/data/web/inc/triggers.inc.php
+++ b/data/web/inc/triggers.inc.php
@@ -63,4 +63,14 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
unset_tfa_key($_POST);
}
}
+if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") {
+ if (isset($_POST["submit_main_logo"])) {
+ if ($_FILES['main_logo']['error'] == 0) {
+ customize('add', 'main_logo', $_FILES);
+ }
+ }
+ if (isset($_POST["reset_main_logo"])) {
+ customize('delete', 'main_logo');
+ }
+}
?>
diff --git a/data/web/index.php b/data/web/index.php
index 3202fb5b..6c5ba3c7 100644
--- a/data/web/index.php
+++ b/data/web/index.php
@@ -23,7 +23,7 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
= $lang['login']['login']; ?>
diff --git a/data/web/js/admin.js b/data/web/js/admin.js
index c6b3b22c..83829ab7 100644
--- a/data/web/js/admin.js
+++ b/data/web/js/admin.js
@@ -90,7 +90,7 @@ var Base64 = {
return t
}
}
-
+
jQuery(function($){
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
var entityMap = {
@@ -730,6 +730,24 @@ jQuery(function($){
}
});
})
+
+ function add_table_row(table_id) {
+ var row = $('
|
');
+ cols = '
| ';
+ cols += '
| ';
+ cols += '
Remove row | ';
+ row.append(cols);
+ table_id.append(row);
+ }
+
+ $('#app_link_table').on('click', 'tr a', function (e) {
+ e.preventDefault();
+ $(this).parents('tr').remove();
+ });
+
+ $('#add_app_link_row').click(function() {
+ add_table_row($('#app_link_table'));
+ });
});
$(window).load(function(){
diff --git a/data/web/js/api.js b/data/web/js/api.js
index a64ce04f..8935f856 100644
--- a/data/web/js/api.js
+++ b/data/web/js/api.js
@@ -14,7 +14,7 @@ $(document).ready(function() {
});
return o;
};
- // Collect values of input fields with name "multi_select" an same data-id to js array multi_data[data-id]
+ // Collect values of input fields with name "multi_select" and same data-id to js array multi_data[data-id]
var multi_data = [];
$(document).on('change', 'input[name=multi_select]:checkbox', function() {
if ($(this).is(':checked') && $(this).data('id')) {
@@ -105,7 +105,8 @@ $(document).ready(function() {
url: '/api/v1/' + api_url,
jsonp: false,
complete: function(data) {
- // var reponse = (JSON.parse(data.responseText));
+ var response = (data.responseText);
+ // alert(response);
// console.log(reponse.type);
// console.log(reponse.msg);
window.location = window.location.href.split("#")[0];
diff --git a/data/web/js/bootstrap-filestyle.min.js b/data/web/js/bootstrap-filestyle.min.js
new file mode 100644
index 00000000..9aa702c6
--- /dev/null
+++ b/data/web/js/bootstrap-filestyle.min.js
@@ -0,0 +1,10 @@
+/*
+ * bootstrap-filestyle
+ * doc: http://markusslima.github.io/bootstrap-filestyle/
+ * github: https://github.com/markusslima/bootstrap-filestyle
+ *
+ * Copyright (c) 2017 Markus Vinicius da Silva Lima
+ * Version 1.2.3
+ * Licensed under the MIT license.
+ */
+!function(t){"use strict";var e=0,i=function(e,i){this.options=i,this.$elementFilestyle=[],this.$element=t(e)};i.prototype={clear:function(){this.$element.val(""),this.$elementFilestyle.find(":text").val(""),this.$elementFilestyle.find(".badge").remove()},destroy:function(){this.$element.removeAttr("style").removeData("filestyle"),this.$elementFilestyle.remove()},disabled:function(t){if(!0===t)this.options.disabled||(this.$element.attr("disabled","true"),this.$elementFilestyle.find("label").attr("disabled","true"),this.options.disabled=!0);else{if(!1!==t)return this.options.disabled;this.options.disabled&&(this.$element.removeAttr("disabled"),this.$elementFilestyle.find("label").removeAttr("disabled"),this.options.disabled=!1)}},buttonBefore:function(t){if(!0===t)this.options.buttonBefore||(this.options.buttonBefore=!0,this.options.input&&(this.$elementFilestyle.remove(),this.constructor(),this.pushNameFiles()));else{if(!1!==t)return this.options.buttonBefore;this.options.buttonBefore&&(this.options.buttonBefore=!1,this.options.input&&(this.$elementFilestyle.remove(),this.constructor(),this.pushNameFiles()))}},icon:function(t){if(!0===t)this.options.icon||(this.options.icon=!0,this.$elementFilestyle.find("label").prepend(this.htmlIcon()));else{if(!1!==t)return this.options.icon;this.options.icon&&(this.options.icon=!1,this.$elementFilestyle.find(".icon-span-filestyle").remove())}},input:function(t){if(!0===t)this.options.input||(this.options.input=!0,this.options.buttonBefore?this.$elementFilestyle.append(this.htmlInput()):this.$elementFilestyle.prepend(this.htmlInput()),this.$elementFilestyle.find(".badge").remove(),this.pushNameFiles(),this.$elementFilestyle.find(".group-span-filestyle").addClass("input-group-btn"));else{if(!1!==t)return this.options.input;if(this.options.input){this.options.input=!1,this.$elementFilestyle.find(":text").remove();var e=this.pushNameFiles();e.length>0&&this.options.badge&&this.$elementFilestyle.find("label").append('
'+e.length+""),this.$elementFilestyle.find(".group-span-filestyle").removeClass("input-group-btn")}}},size:function(t){if(void 0===t)return this.options.size;var e=this.$elementFilestyle.find("label"),i=this.$elementFilestyle.find("input");e.removeClass("btn-lg btn-sm"),i.removeClass("input-lg input-sm"),"nr"!=t&&(e.addClass("btn-"+t),i.addClass("input-"+t))},placeholder:function(t){if(void 0===t)return this.options.placeholder;this.options.placeholder=t,this.$elementFilestyle.find("input").attr("placeholder",t)},buttonText:function(t){if(void 0===t)return this.options.buttonText;this.options.buttonText=t,this.$elementFilestyle.find("label .buttonText").html(this.options.buttonText)},buttonName:function(t){if(void 0===t)return this.options.buttonName;this.options.buttonName=t,this.$elementFilestyle.find("label").attr({class:"btn "+this.options.buttonName})},iconName:function(t){if(void 0===t)return this.options.iconName;this.$elementFilestyle.find(".icon-span-filestyle").attr({class:"icon-span-filestyle "+this.options.iconName})},htmlIcon:function(){return this.options.icon?'
':""},htmlInput:function(){return this.options.input?'
':""},pushNameFiles:function(){var t="",e=[];void 0===this.$element[0].files?e[0]={name:this.$element[0]&&this.$element[0].value}:e=this.$element[0].files;for(var i=0;i
",n=i.options.buttonBefore?l+i.htmlInput():i.htmlInput()+l,i.$elementFilestyle=t(''+n+"
"),i.$elementFilestyle.find(".group-span-filestyle").attr("tabindex","0").keypress(function(t){if(13===t.keyCode||32===t.charCode)return i.$elementFilestyle.find("label").click(),!1}),i.$element.css({position:"absolute",clip:"rect(0px 0px 0px 0px)"}).attr("tabindex","-1").after(i.$elementFilestyle),(i.options.disabled||i.$element.attr("disabled"))&&i.$element.attr("disabled","true"),i.$element.change(function(){var t=i.pushNameFiles();0==i.options.input&&i.options.badge?0==i.$elementFilestyle.find(".badge").length?i.$elementFilestyle.find("label").append(' '+t.length+""):0==t.length?i.$elementFilestyle.find(".badge").remove():i.$elementFilestyle.find(".badge").html(t.length):i.$elementFilestyle.find(".badge").remove()}),window.navigator.userAgent.search(/firefox/i)>-1&&i.$elementFilestyle.find("label").click(function(){return i.$element.click(),!1})}};var n=t.fn.filestyle;t.fn.filestyle=function(e,n){var s="",l=this.each(function(){if("file"===t(this).attr("type")){var l=t(this),o=l.data("filestyle"),a=t.extend({},t.fn.filestyle.defaults,e,"object"==typeof e&&e);o||(l.data("filestyle",o=new i(this,a)),o.constructor()),"string"==typeof e&&(s=o[e](n))}});return void 0!==typeof s?s:l},t.fn.filestyle.defaults={buttonText:"Choose file",iconName:"glyphicon glyphicon-folder-open",buttonName:"btn-default",size:"nr",input:!0,badge:!0,icon:!0,buttonBefore:!1,disabled:!1,placeholder:""},t.fn.filestyle.noConflict=function(){return t.fn.filestyle=n,this},t(function(){t(".filestyle").each(function(){var e=t(this),i={input:"false"!==e.attr("data-input"),icon:"false"!==e.attr("data-icon"),buttonBefore:"true"===e.attr("data-buttonBefore"),disabled:"true"===e.attr("data-disabled"),size:e.attr("data-size"),buttonText:e.attr("data-buttonText"),buttonName:e.attr("data-buttonName"),iconName:e.attr("data-iconName"),badge:"false"!==e.attr("data-badge"),placeholder:e.attr("data-placeholder")};e.filestyle(i)})})}(window.jQuery);
\ No newline at end of file
diff --git a/data/web/json_api.php b/data/web/json_api.php
index 7673f294..0e4f9e87 100644
--- a/data/web/json_api.php
+++ b/data/web/json_api.php
@@ -1795,6 +1795,48 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
));
}
break;
+ case "app_links":
+ if (isset($_POST['attr'])) {
+ $attr = (array)json_decode($_POST['attr'], true);
+ if (is_array($attr)) {
+ if (customize('edit', 'app_links', $attr) === false) {
+ if (isset($_SESSION['return'])) {
+ echo json_encode($_SESSION['return']);
+ }
+ else {
+ echo json_encode(array(
+ 'type' => 'error',
+ 'msg' => 'Edit failed'
+ ));
+ }
+ exit();
+ }
+ else {
+ if (isset($_SESSION['return'])) {
+ echo json_encode($_SESSION['return']);
+ }
+ else {
+ echo json_encode(array(
+ 'type' => 'success',
+ 'msg' => 'Task completed'
+ ));
+ }
+ }
+ }
+ else {
+ echo json_encode(array(
+ 'type' => 'error',
+ 'msg' => 'Incomplete post data'
+ ));
+ }
+ }
+ else {
+ echo json_encode(array(
+ 'type' => 'error',
+ 'msg' => 'Incomplete post data'
+ ));
+ }
+ break;
case "relayhost":
if (isset($_POST['items']) && isset($_POST['attr'])) {
$items = (array)json_decode($_POST['items'], true);
diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php
index 733d3782..681dca4e 100644
--- a/data/web/lang/lang.de.php
+++ b/data/web/lang/lang.de.php
@@ -512,3 +512,14 @@ $lang['success']['relayhost_removed'] = "Relayhost %s wurde entfernt";
$lang['success']['relayhost_added'] = "Relayhost %s wurde hinzugefügt";
$lang['admin']['relay_from'] = "Absenderadresse";
$lang['admin']['relay_run'] = "Test durchführen";
+$lang['admin']['customize'] = "Anpassung";
+$lang['admin']['change_logo'] = "Logo ändern";
+$lang['admin']['logo_info'] = "Die hochgeladene Grafik wird für die Navigationsleiste auf eine Höhe von 40px skaliert. Für die Startseite ist eine Skalierung auf eine maximale Breite von 250px programmiert. Eine frei skalierbare Grafik (etwa SVG) wird empfohlen.";
+$lang['admin']['upload'] = "Hochladen";
+$lang['admin']['app_links'] = "App Links";
+$lang['admin']['app_name'] = "App Name";
+$lang['admin']['link'] = "Link";
+$lang['admin']['remove_row'] = "Zeile entfernen";
+$lang['admin']['add_row'] = "Zeile hinzufügen";
+$lang['admin']['reset_default'] = "Auf Standard zurücksetzen";
+$lang['admin']['merged_vars_hint'] = 'Ausgegraute Zeilen wurden aus der Datei vars.inc.(local.)php
gelesen und können nicht mittels UI verändert werden.';
diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php
index aa41d1b0..527ded11 100644
--- a/data/web/lang/lang.en.php
+++ b/data/web/lang/lang.en.php
@@ -525,3 +525,15 @@ $lang['success']['relayhost_removed'] = "Relayhost %s has been removed";
$lang['success']['relayhost_added'] = "Relayhost %s has been added";
$lang['admin']['relay_from'] = '"From:" address';
$lang['admin']['relay_run'] = "Run test";
+
+$lang['admin']['customize'] = "Customize";
+$lang['admin']['change_logo'] = "Change logo";
+$lang['admin']['logo_info'] = "Your image will be scaled to a height of 40px for the top navigation bar and a max. width of 250px for the start page. A scalable graphic is highly recommended.";
+$lang['admin']['upload'] = "Upload";
+$lang['admin']['app_links'] = "App links";
+$lang['admin']['app_name'] = "App name";
+$lang['admin']['link'] = "Link";
+$lang['admin']['remove_row'] = "Remove row";
+$lang['admin']['add_row'] = "Add row";
+$lang['admin']['reset_default'] = "Reset to default";
+$lang['admin']['merged_vars_hint'] = 'Greyed out rows were merged from vars.inc.(local.)php
and cannot be modified.';