(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else {
		var a = factory();
		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
	}
})(typeof self !== 'undefined' ? self : this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 786);
/******/ })
/************************************************************************/
/******/ ({

/***/ 0:
/***/ (function(module, exports) {

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
// css base code, injected by the css-loader
module.exports = function(useSourceMap) {
	var list = [];

	// return the list of modules as css string
	list.toString = function toString() {
		return this.map(function (item) {
			var content = cssWithMappingToString(item, useSourceMap);
			if(item[2]) {
				return "@media " + item[2] + "{" + content + "}";
			} else {
				return content;
			}
		}).join("");
	};

	// import a list of modules into the list
	list.i = function(modules, mediaQuery) {
		if(typeof modules === "string")
			modules = [[null, modules, ""]];
		var alreadyImportedModules = {};
		for(var i = 0; i < this.length; i++) {
			var id = this[i][0];
			if(typeof id === "number")
				alreadyImportedModules[id] = true;
		}
		for(i = 0; i < modules.length; i++) {
			var item = modules[i];
			// skip already imported module
			// this implementation is not 100% perfect for weird media query combinations
			//  when a module is imported multiple times with different media queries.
			//  I hope this will never occur (Hey this way we have smaller bundles)
			if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
				if(mediaQuery && !item[2]) {
					item[2] = mediaQuery;
				} else if(mediaQuery) {
					item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
				}
				list.push(item);
			}
		}
	};
	return list;
};

function cssWithMappingToString(item, useSourceMap) {
	var content = item[1] || '';
	var cssMapping = item[3];
	if (!cssMapping) {
		return content;
	}

	if (useSourceMap && typeof btoa === 'function') {
		var sourceMapping = toComment(cssMapping);
		var sourceURLs = cssMapping.sources.map(function (source) {
			return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
		});

		return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
	}

	return [content].join('\n');
}

// Adapted from convert-source-map (MIT)
function toComment(sourceMap) {
	// eslint-disable-next-line no-undef
	var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
	var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;

	return '/*# ' + data + ' */';
}


/***/ }),

/***/ 1:
/***/ (function(module, exports, __webpack_require__) {

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

var stylesInDom = {};

var	memoize = function (fn) {
	var memo;

	return function () {
		if (typeof memo === "undefined") memo = fn.apply(this, arguments);
		return memo;
	};
};

var isOldIE = memoize(function () {
	// Test for IE <= 9 as proposed by Browserhacks
	// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
	// Tests for existence of standard globals is to allow style-loader
	// to operate correctly into non-standard environments
	// @see https://github.com/webpack-contrib/style-loader/issues/177
	return window && document && document.all && !window.atob;
});

var getElement = (function (fn) {
	var memo = {};

	return function(selector) {
		if (typeof memo[selector] === "undefined") {
			var styleTarget = fn.call(this, selector);
			// Special case to return head of iframe instead of iframe itself
			if (styleTarget instanceof window.HTMLIFrameElement) {
				try {
					// This will throw an exception if access to iframe is blocked
					// due to cross-origin restrictions
					styleTarget = styleTarget.contentDocument.head;
				} catch(e) {
					styleTarget = null;
				}
			}
			memo[selector] = styleTarget;
		}
		return memo[selector]
	};
})(function (target) {
	return document.querySelector(target)
});

var singleton = null;
var	singletonCounter = 0;
var	stylesInsertedAtTop = [];

var	fixUrls = __webpack_require__(2);

module.exports = function(list, options) {
	if (typeof DEBUG !== "undefined" && DEBUG) {
		if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
	}

	options = options || {};

	options.attrs = typeof options.attrs === "object" ? options.attrs : {};

	// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
	// tags it will allow on a page
	if (!options.singleton) options.singleton = isOldIE();

	// By default, add <style> tags to the <head> element
	if (!options.insertInto) options.insertInto = "head";

	// By default, add <style> tags to the bottom of the target
	if (!options.insertAt) options.insertAt = "bottom";

	var styles = listToStyles(list, options);

	addStylesToDom(styles, options);

	return function update (newList) {
		var mayRemove = [];

		for (var i = 0; i < styles.length; i++) {
			var item = styles[i];
			var domStyle = stylesInDom[item.id];

			domStyle.refs--;
			mayRemove.push(domStyle);
		}

		if(newList) {
			var newStyles = listToStyles(newList, options);
			addStylesToDom(newStyles, options);
		}

		for (var i = 0; i < mayRemove.length; i++) {
			var domStyle = mayRemove[i];

			if(domStyle.refs === 0) {
				for (var j = 0; j < domStyle.parts.length; j++) domStyle.parts[j]();

				delete stylesInDom[domStyle.id];
			}
		}
	};
};

function addStylesToDom (styles, options) {
	for (var i = 0; i < styles.length; i++) {
		var item = styles[i];
		var domStyle = stylesInDom[item.id];

		if(domStyle) {
			domStyle.refs++;

			for(var j = 0; j < domStyle.parts.length; j++) {
				domStyle.parts[j](item.parts[j]);
			}

			for(; j < item.parts.length; j++) {
				domStyle.parts.push(addStyle(item.parts[j], options));
			}
		} else {
			var parts = [];

			for(var j = 0; j < item.parts.length; j++) {
				parts.push(addStyle(item.parts[j], options));
			}

			stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
		}
	}
}

function listToStyles (list, options) {
	var styles = [];
	var newStyles = {};

	for (var i = 0; i < list.length; i++) {
		var item = list[i];
		var id = options.base ? item[0] + options.base : item[0];
		var css = item[1];
		var media = item[2];
		var sourceMap = item[3];
		var part = {css: css, media: media, sourceMap: sourceMap};

		if(!newStyles[id]) styles.push(newStyles[id] = {id: id, parts: [part]});
		else newStyles[id].parts.push(part);
	}

	return styles;
}

function insertStyleElement (options, style) {
	var target = getElement(options.insertInto)

	if (!target) {
		throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");
	}

	var lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];

	if (options.insertAt === "top") {
		if (!lastStyleElementInsertedAtTop) {
			target.insertBefore(style, target.firstChild);
		} else if (lastStyleElementInsertedAtTop.nextSibling) {
			target.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling);
		} else {
			target.appendChild(style);
		}
		stylesInsertedAtTop.push(style);
	} else if (options.insertAt === "bottom") {
		target.appendChild(style);
	} else if (typeof options.insertAt === "object" && options.insertAt.before) {
		var nextSibling = getElement(options.insertInto + " " + options.insertAt.before);
		target.insertBefore(style, nextSibling);
	} else {
		throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top', 'bottom', or Object.\n (https://github.com/webpack-contrib/style-loader#insertat)\n");
	}
}

function removeStyleElement (style) {
	if (style.parentNode === null) return false;
	style.parentNode.removeChild(style);

	var idx = stylesInsertedAtTop.indexOf(style);
	if(idx >= 0) {
		stylesInsertedAtTop.splice(idx, 1);
	}
}

function createStyleElement (options) {
	var style = document.createElement("style");

	options.attrs.type = "text/css";

	addAttrs(style, options.attrs);
	insertStyleElement(options, style);

	return style;
}

function createLinkElement (options) {
	var link = document.createElement("link");

	options.attrs.type = "text/css";
	options.attrs.rel = "stylesheet";

	addAttrs(link, options.attrs);
	insertStyleElement(options, link);

	return link;
}

function addAttrs (el, attrs) {
	Object.keys(attrs).forEach(function (key) {
		el.setAttribute(key, attrs[key]);
	});
}

function addStyle (obj, options) {
	var style, update, remove, result;

	// If a transform function was defined, run it on the css
	if (options.transform && obj.css) {
	    result = options.transform(obj.css);

	    if (result) {
	    	// If transform returns a value, use that instead of the original css.
	    	// This allows running runtime transformations on the css.
	    	obj.css = result;
	    } else {
	    	// If the transform function returns a falsy value, don't add this css.
	    	// This allows conditional loading of css
	    	return function() {
	    		// noop
	    	};
	    }
	}

	if (options.singleton) {
		var styleIndex = singletonCounter++;

		style = singleton || (singleton = createStyleElement(options));

		update = applyToSingletonTag.bind(null, style, styleIndex, false);
		remove = applyToSingletonTag.bind(null, style, styleIndex, true);

	} else if (
		obj.sourceMap &&
		typeof URL === "function" &&
		typeof URL.createObjectURL === "function" &&
		typeof URL.revokeObjectURL === "function" &&
		typeof Blob === "function" &&
		typeof btoa === "function"
	) {
		style = createLinkElement(options);
		update = updateLink.bind(null, style, options);
		remove = function () {
			removeStyleElement(style);

			if(style.href) URL.revokeObjectURL(style.href);
		};
	} else {
		style = createStyleElement(options);
		update = applyToTag.bind(null, style);
		remove = function () {
			removeStyleElement(style);
		};
	}

	update(obj);

	return function updateStyle (newObj) {
		if (newObj) {
			if (
				newObj.css === obj.css &&
				newObj.media === obj.media &&
				newObj.sourceMap === obj.sourceMap
			) {
				return;
			}

			update(obj = newObj);
		} else {
			remove();
		}
	};
}

var replaceText = (function () {
	var textStore = [];

	return function (index, replacement) {
		textStore[index] = replacement;

		return textStore.filter(Boolean).join('\n');
	};
})();

function applyToSingletonTag (style, index, remove, obj) {
	var css = remove ? "" : obj.css;

	if (style.styleSheet) {
		style.styleSheet.cssText = replaceText(index, css);
	} else {
		var cssNode = document.createTextNode(css);
		var childNodes = style.childNodes;

		if (childNodes[index]) style.removeChild(childNodes[index]);

		if (childNodes.length) {
			style.insertBefore(cssNode, childNodes[index]);
		} else {
			style.appendChild(cssNode);
		}
	}
}

function applyToTag (style, obj) {
	var css = obj.css;
	var media = obj.media;

	if(media) {
		style.setAttribute("media", media)
	}

	if(style.styleSheet) {
		style.styleSheet.cssText = css;
	} else {
		while(style.firstChild) {
			style.removeChild(style.firstChild);
		}

		style.appendChild(document.createTextNode(css));
	}
}

function updateLink (link, options, obj) {
	var css = obj.css;
	var sourceMap = obj.sourceMap;

	/*
		If convertToAbsoluteUrls isn't defined, but sourcemaps are enabled
		and there is no publicPath defined then lets turn convertToAbsoluteUrls
		on by default.  Otherwise default to the convertToAbsoluteUrls option
		directly
	*/
	var autoFixUrls = options.convertToAbsoluteUrls === undefined && sourceMap;

	if (options.convertToAbsoluteUrls || autoFixUrls) {
		css = fixUrls(css);
	}

	if (sourceMap) {
		// http://stackoverflow.com/a/26603875
		css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
	}

	var blob = new Blob([css], { type: "text/css" });

	var oldSrc = link.href;

	link.href = URL.createObjectURL(blob);

	if(oldSrc) URL.revokeObjectURL(oldSrc);
}


/***/ }),

/***/ 12:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M28.1,21c0-2-0.7-3.7-2.1-5.1s-3.1-2.1-5.1-2.1s-3.7,0.7-5.1,2.1S13.8,19,13.8,21s0.7,3.7,2.1,5.1s3.1,2.1,5.1,2.1 s3.7-0.7,5.1-2.1S28.1,22.9,28.1,21z M37.9,18.5v4.9c0,0.2-0.1,0.3-0.2,0.5c-0.1,0.2-0.3,0.3-0.4,0.3l-4.1,0.6 c-0.3,0.8-0.6,1.5-0.9,2c0.5,0.7,1.3,1.8,2.4,3c0.1,0.2,0.2,0.4,0.2,0.6s-0.1,0.4-0.2,0.5c-0.4,0.5-1.1,1.3-2.2,2.4 c-1.1,1-1.8,1.6-2.1,1.6c-0.2,0-0.4-0.1-0.6-0.2l-3-2.4c-0.6,0.3-1.3,0.6-2,0.8c-0.2,2-0.4,3.4-0.6,4.1c-0.1,0.4-0.4,0.6-0.8,0.6 h-4.9c-0.2,0-0.4-0.1-0.5-0.2c-0.2-0.1-0.2-0.3-0.3-0.5l-0.6-4.1c-0.7-0.2-1.4-0.5-2-0.8L12,34.7c-0.1,0.1-0.3,0.2-0.6,0.2 c-0.2,0-0.4-0.1-0.6-0.2C9,33,7.8,31.8,7.2,31c-0.1-0.1-0.2-0.3-0.2-0.5c0-0.2,0.1-0.3,0.2-0.5c0.2-0.3,0.6-0.8,1.1-1.5 s0.9-1.2,1.2-1.6c-0.4-0.7-0.7-1.5-0.9-2.2l-4-0.6c-0.2,0-0.3-0.1-0.5-0.3C4.1,23.7,4,23.5,4,23.4v-4.9c0-0.2,0.1-0.3,0.2-0.5 s0.3-0.3,0.4-0.3L8.7,17c0.2-0.7,0.5-1.4,0.9-2c-0.6-0.8-1.4-1.9-2.4-3C7.1,11.8,7,11.6,7,11.4c0-0.1,0.1-0.3,0.2-0.5 c0.4-0.5,1.1-1.3,2.2-2.4S11.1,7,11.4,7c0.2,0,0.4,0.1,0.6,0.2l3,2.4c0.6-0.3,1.3-0.6,2-0.8c0.2-2,0.4-3.4,0.6-4.1 C17.8,4.2,18.1,4,18.5,4h4.9c0.2,0,0.4,0.1,0.5,0.2c0.2,0.1,0.2,0.3,0.3,0.5l0.6,4.1c0.7,0.2,1.4,0.5,2,0.8l3.1-2.4 C30.1,7,30.2,7,30.5,7c0.2,0,0.4,0.1,0.6,0.2c1.9,1.8,3.1,3,3.6,3.8c0.1,0.1,0.2,0.3,0.2,0.5c0,0.2-0.1,0.3-0.2,0.5 c-0.2,0.3-0.6,0.8-1.1,1.5c-0.5,0.7-0.9,1.2-1.2,1.6c0.4,0.7,0.7,1.5,0.9,2.2l4,0.6c0.2,0,0.3,0.1,0.5,0.3 C37.8,18.2,37.9,18.4,37.9,18.5z'/%3E %3C/svg%3E\""

/***/ }),

/***/ 2:
/***/ (function(module, exports) {


/**
 * When source maps are enabled, `style-loader` uses a link element with a data-uri to
 * embed the css on the page. This breaks all relative urls because now they are relative to a
 * bundle instead of the current page.
 *
 * One solution is to only use full urls, but that may be impossible.
 *
 * Instead, this function "fixes" the relative urls to be absolute according to the current page location.
 *
 * A rudimentary test suite is located at `test/fixUrls.js` and can be run via the `npm test` command.
 *
 */

module.exports = function (css) {
  // get current location
  var location = typeof window !== "undefined" && window.location;

  if (!location) {
    throw new Error("fixUrls requires window.location");
  }

	// blank or null?
	if (!css || typeof css !== "string") {
	  return css;
  }

  var baseUrl = location.protocol + "//" + location.host;
  var currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");

	// convert each url(...)
	/*
	This regular expression is just a way to recursively match brackets within
	a string.

	 /url\s*\(  = Match on the word "url" with any whitespace after it and then a parens
	   (  = Start a capturing group
	     (?:  = Start a non-capturing group
	         [^)(]  = Match anything that isn't a parentheses
	         |  = OR
	         \(  = Match a start parentheses
	             (?:  = Start another non-capturing groups
	                 [^)(]+  = Match anything that isn't a parentheses
	                 |  = OR
	                 \(  = Match a start parentheses
	                     [^)(]*  = Match anything that isn't a parentheses
	                 \)  = Match a end parentheses
	             )  = End Group
              *\) = Match anything and then a close parens
          )  = Close non-capturing group
          *  = Match anything
       )  = Close capturing group
	 \)  = Match a close parens

	 /gi  = Get all matches, not the first.  Be case insensitive.
	 */
	var fixedCss = css.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(fullMatch, origUrl) {
		// strip quotes (if they exist)
		var unquotedOrigUrl = origUrl
			.trim()
			.replace(/^"(.*)"$/, function(o, $1){ return $1; })
			.replace(/^'(.*)'$/, function(o, $1){ return $1; });

		// already a full url? no change
		if (/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/)/i.test(unquotedOrigUrl)) {
		  return fullMatch;
		}

		// convert the url to a full url
		var newUrl;

		if (unquotedOrigUrl.indexOf("//") === 0) {
		  	//TODO: should we add protocol?
			newUrl = unquotedOrigUrl;
		} else if (unquotedOrigUrl.indexOf("/") === 0) {
			// path should be relative to the base url
			newUrl = baseUrl + unquotedOrigUrl; // already starts with '/'
		} else {
			// path should be relative to current directory
			newUrl = currentDir + unquotedOrigUrl.replace(/^\.\//, ""); // Strip leading './'
		}

		// send back the fixed url(...)
		return "url(" + JSON.stringify(newUrl) + ")";
	});

	// send back the fixed css
	return fixedCss;
};


/***/ }),

/***/ 20:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M28.7,31.9c0-0.3-0.1-0.6-0.3-0.8s-0.5-0.3-0.8-0.3c-0.3,0-0.6,0.1-0.8,0.3s-0.3,0.5-0.3,0.8s0.1,0.6,0.3,0.8 c0.2,0.2,0.5,0.3,0.8,0.3c0.3,0,0.6-0.1,0.8-0.3C28.6,32.5,28.7,32.3,28.7,31.9z M33.2,31.9c0-0.3-0.1-0.6-0.3-0.8s-0.5-0.3-0.8-0.3 s-0.6,0.1-0.8,0.3s-0.3,0.5-0.3,0.8s0.1,0.6,0.3,0.8c0.2,0.2,0.5,0.3,0.8,0.3s0.6-0.1,0.8-0.3C33.1,32.5,33.2,32.3,33.2,31.9z M35.5,28v5.7c0,0.5-0.2,0.9-0.5,1.2s-0.7,0.5-1.2,0.5H7.7c-0.5,0-0.9-0.2-1.2-0.5C6.2,34.5,6,34.1,6,33.6V28c0-0.5,0.2-0.9,0.5-1.2 c0.3-0.3,0.7-0.5,1.2-0.5h7.6c0.2,0.7,0.7,1.2,1.2,1.6c0.6,0.4,1.2,0.6,2,0.6H23c0.7,0,1.4-0.2,2-0.6s1-1,1.2-1.6h7.6 c0.5,0,0.9,0.2,1.2,0.5C35.3,27.1,35.5,27.5,35.5,28z M11.8,16.8c0.2-0.5,0.5-0.7,1-0.7h4.5V8.1c0-0.3,0.1-0.6,0.3-0.8 C17.9,7.1,18.2,7,18.5,7H23c0.3,0,0.6,0.1,0.8,0.3c0.2,0.2,0.3,0.5,0.3,0.8v7.9h4.5c0.5,0,0.8,0.2,1,0.7c0.2,0.5,0.1,0.9-0.2,1.2 l-7.9,7.9c-0.2,0.2-0.5,0.3-0.8,0.3s-0.6-0.1-0.8-0.3L12,18C11.6,17.6,11.6,17.2,11.8,16.8z'/%3E %3C/svg%3E\""

/***/ }),

/***/ 33:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M34.7,30.4c0-0.2-0.1-0.3-0.2-0.5L23.3,18.8c0.4-1,0.7-2.2,0.7-3.3c0-2.3-0.9-4.4-2.5-6c-1.6-1.6-3.7-2.5-6-2.5 c-2.3,0-4.4,0.9-6,2.5c-3.3,3.3-3.3,8.7,0,12c1.6,1.6,3.7,2.5,6,2.5c1.2,0,2.3-0.2,3.3-0.7l3.7,3.7c0.2,0.2,0.4,0.2,0.6,0.2l2-0.1 l-0.1,2c0,0.2,0.1,0.4,0.2,0.6c0.1,0.2,0.4,0.2,0.6,0.2l2-0.1l-0.1,2c0,0.2,0.1,0.4,0.2,0.6c0.2,0.2,0.3,0.2,0.6,0.2l2-0.1l-0.1,2 c0,0.2,0.1,0.4,0.2,0.6c0.1,0.1,0.3,0.2,0.5,0.2c0,0,0.1,0,0.1,0l3.1-0.3c0.4,0,0.7-0.4,0.7-0.8L34.7,30.4z M14.4,14.5 c-0.9,0.9-2.5,0.9-3.4,0c-0.9-0.9-0.9-2.5,0-3.4c0.9-0.9,2.5-0.9,3.4,0C15.4,12,15.4,13.5,14.4,14.5L14.4,14.5z M32,30.7 c-0.1,0.1-0.3,0.2-0.4,0.2c-0.1,0-0.3-0.1-0.4-0.2l-9.5-9.5c0.3-0.3,0.5-0.6,0.7-0.9l9.6,9.6C32.3,30.1,32.3,30.5,32,30.7L32,30.7z M32,30.7'/%3E %3C/svg%3E\""

/***/ }),

/***/ 35:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M35.6,21c0-2.6-0.7-5.1-2-7.3s-3.1-4-5.3-5.3s-4.7-2-7.3-2s-5.1,0.7-7.3,2s-4,3.1-5.3,5.3s-2,4.7-2,7.3s0.7,5.1,2,7.3 s3.1,4,5.3,5.3s4.7,2,7.3,2s5.1-0.7,7.3-2s4-3.1,5.3-5.3S35.6,23.6,35.6,21z M38,21c0,3.1-0.8,5.9-2.3,8.5c-1.5,2.6-3.6,4.7-6.2,6.2 C26.9,37.2,24.1,38,21,38c-3.1,0-5.9-0.8-8.5-2.3c-2.6-1.5-4.7-3.6-6.2-6.2S4,24.1,4,21c0-3.1,0.8-5.9,2.3-8.5s3.6-4.7,6.2-6.2 S17.9,4,21,4c3.1,0,5.9,0.8,8.5,2.3s4.7,3.6,6.2,6.2C37.2,15.1,38,17.9,38,21z M21.7,30.8h-1.4c-0.2,0-0.4-0.1-0.5-0.2 c-0.1-0.1-0.2-0.3-0.2-0.5v-7.7h-7.7c-0.2,0-0.4-0.1-0.5-0.2c-0.1-0.1-0.2-0.3-0.2-0.5v-1.4c0-0.2,0.1-0.4,0.2-0.5 c0.1-0.1,0.3-0.2,0.5-0.2h7.7v-7.7c0-0.2,0.1-0.4,0.2-0.5c0.1-0.1,0.3-0.2,0.5-0.2h1.4c0.2,0,0.4,0.1,0.5,0.2 c0.1,0.1,0.2,0.3,0.2,0.5v7.7h7.7c0.2,0,0.4,0.1,0.5,0.2c0.1,0.1,0.2,0.3,0.2,0.5v1.4c0,0.2-0.1,0.4-0.2,0.5s-0.3,0.2-0.5,0.2h-7.7 v7.7c0,0.2-0.1,0.4-0.2,0.5S21.9,30.8,21.7,30.8z'/%3E %3C/svg%3E\""

/***/ }),

/***/ 47:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M35.6,21c0-2.6-0.7-5.1-2-7.3s-3.1-4-5.3-5.3s-4.7-2-7.3-2s-5.1,0.7-7.3,2s-4,3.1-5.3,5.3s-2,4.7-2,7.3s0.7,5.1,2,7.3 s3.1,4,5.3,5.3s4.7,2,7.3,2s5.1-0.7,7.3-2s4-3.1,5.3-5.3S35.6,23.6,35.6,21z M38,21c0,3.1-0.8,5.9-2.3,8.5c-1.5,2.6-3.6,4.7-6.2,6.2 C26.9,37.2,24.1,38,21,38c-3.1,0-5.9-0.8-8.5-2.3c-2.6-1.5-4.7-3.6-6.2-6.2S4,24.1,4,21c0-3.1,0.8-5.9,2.3-8.5s3.6-4.7,6.2-6.2 S17.9,4,21,4c3.1,0,5.9,0.8,8.5,2.3s4.7,3.6,6.2,6.2C37.2,15.1,38,17.9,38,21z M26.3,27.9v1.8c0,0.2-0.1,0.5-0.2,0.6 c-0.2,0.2-0.4,0.3-0.6,0.3h-8.7c-0.2,0-0.4-0.1-0.6-0.3c-0.2-0.2-0.2-0.4-0.2-0.6v-1.8c0-0.2,0.1-0.5,0.2-0.6 c0.2-0.2,0.4-0.3,0.6-0.3h2.7v-5.5h-2.7c-0.2,0-0.4-0.1-0.6-0.3C16.1,21,16,20.8,16,20.6v-1.8c0-0.2,0.1-0.5,0.2-0.6 c0.2-0.2,0.4-0.3,0.6-0.3h5.8c0.2,0,0.4,0.1,0.6,0.3s0.2,0.4,0.2,0.6V27h2.1c0.2,0,0.4,0.1,0.6,0.3C26.2,27.4,26.3,27.6,26.3,27.9z M23.4,12.3v1.9c0,0.2-0.1,0.5-0.2,0.6c-0.2,0.2-0.4,0.3-0.6,0.3h-2.2c-0.2,0-0.4-0.1-0.6-0.3c-0.2-0.2-0.2-0.4-0.2-0.6v-1.9 c0-0.2,0.1-0.5,0.2-0.6c0.2-0.2,0.4-0.3,0.6-0.3h2.2c0.2,0,0.4,0.1,0.6,0.3C23.3,11.9,23.4,12.1,23.4,12.3z'/%3E %3C/svg%3E\""

/***/ }),

/***/ 48:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='5 5 32.5 32.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='27.5' height='27.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23000000;%7D %3C/style%3E %3Cpath id='hook' class='st0' d='M29.5,17.6L18.6,28.5c-0.2,0.2-0.5,0.3-0.8,0.3c-0.3,0-0.6-0.1-0.8-0.3l-5.4-5.4 c-0.2-0.2-0.3-0.5-0.3-0.8c0-0.3,0.1-0.6,0.3-0.8l0.8-0.8c0.2-0.2,0.5-0.3,0.8-0.3s0.6,0.1,0.8,0.3l3.8,3.8l9.3-9.3 c0.2-0.2,0.5-0.3,0.8-0.3c0.3,0,0.6,0.1,0.8,0.3l0.8,0.8c0.2,0.2,0.3,0.5,0.3,0.8C29.8,17.1,29.7,17.4,29.5,17.6z'/%3E %3C/svg%3E\""

/***/ }),

/***/ 66:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M35.6,21c0-2.6-0.7-5.1-2-7.3s-3.1-4-5.3-5.3s-4.7-2-7.3-2s-5.1,0.7-7.3,2s-4,3.1-5.3,5.3s-2,4.7-2,7.3s0.7,5.1,2,7.3 s3.1,4,5.3,5.3s4.7,2,7.3,2s5.1-0.7,7.3-2s4-3.1,5.3-5.3S35.6,23.6,35.6,21z M38,21c0,3.1-0.8,5.9-2.3,8.5c-1.5,2.6-3.6,4.7-6.2,6.2 C26.9,37.2,24.1,38,21,38c-3.1,0-5.9-0.8-8.5-2.3c-2.6-1.5-4.7-3.6-6.2-6.2S4,24.1,4,21c0-3.1,0.8-5.9,2.3-8.5s3.6-4.7,6.2-6.2 S17.9,4,21,4c3.1,0,5.9,0.8,8.5,2.3s4.7,3.6,6.2,6.2C37.2,15.1,38,17.9,38,21z M19.6,22.4h-7.7c-0.2,0-0.4-0.1-0.5-0.2 c-0.1-0.1-0.2-0.3-0.2-0.5v-1.4c0-0.2,0.1-0.4,0.2-0.5c0.1-0.1,0.3-0.2,0.5-0.2h7.7h10.5c0.2,0,0.4,0.1,0.5,0.2 c0.1,0.1,0.2,0.3,0.2,0.5v1.4c0,0.2-0.1,0.4-0.2,0.5s-0.3,0.2-0.5,0.2H19.6z'/%3E %3C/svg%3E\""

/***/ }),

/***/ 67:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='5 5 32.5 32.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='27.5' height='27.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23000000;%7D %3C/style%3E %3Cpath id='red_x5F_cross_x5F_big_1_' class='st0' d='M28.7,27.5l-1.2,1.2c-0.2,0.2-0.4,0.2-0.6,0.2s-0.4-0.1-0.6-0.2l-5-5l-5,5 c-0.2,0.2-0.4,0.2-0.6,0.2s-0.4-0.1-0.6-0.2l-1.2-1.2c-0.2-0.2-0.2-0.4-0.2-0.6s0.1-0.4,0.2-0.6l5-5l-5-5c-0.2-0.2-0.2-0.4-0.2-0.6 s0.1-0.4,0.2-0.6l1.2-1.2c0.2-0.2,0.4-0.2,0.6-0.2s0.4,0.1,0.6,0.2l5,5l5-5c0.2-0.2,0.4-0.2,0.6-0.2s0.4,0.1,0.6,0.2l1.2,1.2 c0.2,0.2,0.2,0.4,0.2,0.6s-0.1,0.4-0.2,0.6l-5,5l5,5c0.2,0.2,0.2,0.4,0.2,0.6S28.9,27.3,28.7,27.5z'/%3E %3C/svg%3E\""

/***/ }),

/***/ 786:
/***/ (function(module, exports, __webpack_require__) {

__webpack_require__(787);
__webpack_require__(788);
__webpack_require__(789);
__webpack_require__(790);
__webpack_require__(791);
__webpack_require__(792);
__webpack_require__(793);
__webpack_require__(794);
__webpack_require__(795);
__webpack_require__(796);
__webpack_require__(797);
__webpack_require__(798);


/***/ }),

/***/ 787:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 * 
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */

/*global Ext, Tine*/

Ext.ns('Tine', 'Tine.Setup');

/**
 * local storage prefix for Setup
 */
Tine.Tinebase.tineInit.initAjax.lsPrefix = Tine.Tinebase.common.getUrl('path') + 'TineSetup';

/**
 * init ajax
 */
Tine.Tinebase.tineInit.initAjax = Tine.Tinebase.tineInit.initAjax.createInterceptor(function () {
    // setup calls can take quite a while
    Ext.Ajax.timeout = 900000; // 15 mins
    Tine.Tinebase.tineInit.requestUrl = 'setup.php';
    
    return true;
});

/**
 * init registry
 */
Tine.Tinebase.tineInit.initRegistry = Tine.Tinebase.tineInit.initRegistry.createInterceptor(function () {
    Tine.Tinebase.tineInit.clearRegistry();
    Tine.Tinebase.tineInit.getAllRegistryDataMethod = 'Setup.getAllRegistryData';
    Tine.Tinebase.tineInit.jsonKeyCookieId = 'TINE20SETUPJSONKEY';
    Tine.Tinebase.tineInit.stateful = false;
    
    return true;
});

Tine.Tinebase.tineInit.onRegistryLoad = Tine.Tinebase.tineInit.onRegistryLoad.createInterceptor(function () {
    // fake a setup user
    var setupUser = {
        accountId           : 1,
        accountDisplayName  : Tine.Setup.registry.get('currentAccount'),
        accountLastName     : 'Admin',
        accountFirstName    : 'Setup',
        accountFullName     : 'Setup Admin'
    };
    Tine.Tinebase.registry.add('currentAccount', setupUser);

    // enable setup app
    Tine.Tinebase.registry.add('userApplications', [{
        name:   'Setup',
        status: 'enabled'
    }]);
    Tine.Tinebase.MainScreenPanel.prototype.defaultAppName = 'Setup';
    Tine.Tinebase.MainScreenPanel.prototype.hideAppTabs = true;

    return true;
});

/**
 * render window
 */
Tine.Tinebase.tineInit.renderWindow = Tine.Tinebase.tineInit.renderWindow.createInterceptor(function () {
    var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel;
    
    // if a config file exists, the admin needs to login!        
    if (Tine.Setup.registry.get('configExists') && !Tine.Setup.registry.get('currentAccount')) {
        Tine.loginPanel = new Tine.Tinebase.LoginPanel({
            loginMethod: 'Setup.login',
            headsUpText: window.i18n._('Setup'),
            scope: this,
            onLogin: function (response) {
                Tine.Tinebase.tineInit.initRegistry(true, function() {
                    Ext.MessageBox.hide();
                    Tine.Tinebase.tineInit.renderWindow();
                });
            }
        });
        mainCardPanel.layout.container.add(Tine.loginPanel);
        mainCardPanel.layout.setActiveItem(Tine.loginPanel.id);
        Tine.loginPanel.doLayout();
        
        return false;
    }
});



/***/ }),

/***/ 788:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 *
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 - 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */

Ext.ns('Tine', 'Tine.Setup', 'Tine.Setup.Model');

/**
 * @namespace   Tine.Setup.Model
 * @class       Tine.Setup.Model.Application
 * @extends     Tine.Tinebase.data.Record
 *
 * Application Record Definition
 */
Tine.Setup.Model.Application = Tine.Tinebase.data.Record.create([
    { name: 'id'              },
    { name: 'name'            },
    { name: 'status'          },
    { name: 'order'           },
    { name: 'version'         },
    { name: 'current_version' },
    { name: 'install_status'  },
    { name: 'depends'         }
], {
    appName: 'Setup',
    modelName: 'Application',
    idProperty: 'name',
    titleProperty: 'name',
    // ngettext('Application', 'Applications', n); gettext('Application');
    recordName: 'Application',
    recordsName: 'Applications'
});

/**
 * @namespace   Tine.Setup
 * @class       Tine.Setup.ApplicationBackend
 * @extends     Tine.Tinebase.data.RecordProxy
 *
 * default application backend
 */
Tine.Setup.ApplicationBackend = new Tine.Tinebase.data.RecordProxy({
    appName: 'Setup',
    modelName: 'Application',
    recordClass: Tine.Setup.Model.Application
});

/**
 * @namespace   Tine.Setup.Model
 * @class       Tine.Setup.Model.EnvCheck
 * @extends     Ext.data.Record
 *
 * env check Record Definition
 */
Tine.Setup.Model.EnvCheck = Ext.data.Record.create([
    {name: 'key'},
    {name: 'value'},
    {name: 'message'}
]);


/***/ }),

/***/ 789:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 * 
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 - 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
 
Ext.ns('Tine', 'Tine.Setup');

/**
 * @namespace   Tine.Setup
 * @class       Tine.Setup.TreePanel
 * @extends     Ext.tree.TreePanel
 * 
 * <p>Setup TreePanel</p>
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 * 
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Setup.TreePanel
 */
Tine.Setup.TreePanel = Ext.extend(Ext.tree.TreePanel, {
    
    /**
     * tree panel cfg
     * 
     * @private
     */
    border: false,
    rootVisible: false, 
    
    /**
     * @private
     */
    initComponent: function() {
        this.app = Tine.Tinebase.appMgr.get('Setup');
        
        var termsFailed   = !Tine.Setup.registry.get('acceptedTermsVersion') || Tine.Setup.registry.get('acceptedTermsVersion') < Tine.Setup.CurrentTermsVersion;
        var testsFailed   = !Tine.Setup.registry.get('setupChecks').success;
        var configMissing = !Tine.Setup.registry.get('configExists');
        var dbMissing     = !Tine.Setup.registry.get('checkDB');
        var setupRequired = Tine.Setup.registry.get('setupRequired');
        var licenseFailed = !Tine.Setup.registry.get('licenseCheck');

        this.root = {
            id: '/',
            children: [{
                text: this.app.i18n._('Terms and Conditions'),
                iconCls: termsFailed ? 'setup_checks_fail' : 'setup_checks_success',
                id: 'TermsPanel',
                leaf: true
            }, {
                text: this.app.i18n._('Setup Checks'),
                iconCls: testsFailed ? 'setup_checks_fail' : 'setup_checks_success',
                disabled: termsFailed,
                id: 'EnvCheckGridPanel',
                leaf: true
            }, {
                text: this.app.i18n._('Config Manager'),
                iconCls: 'setup_config_manager',
                disabled: termsFailed || testsFailed,
                id: 'ConfigManagerPanel',
                leaf: true
            }, {
                text: this.app.i18n._('Authentication/Accounts'),
                iconCls: 'setup_authentication_manager',
                disabled: termsFailed || testsFailed || configMissing || dbMissing,
                id: 'AuthenticationPanel',
                leaf: true
            }, {
                text: this.app.i18n._('Email'),
                iconCls: 'action_composeEmail',
                disabled: termsFailed || testsFailed || configMissing || dbMissing || setupRequired,
                id: 'EmailPanel',
                leaf: true
            }, {
                text: this.app.i18n._('Application Manager'),
                iconCls: 'setup_application_manager',
                disabled: termsFailed || testsFailed || configMissing || dbMissing || setupRequired,
                id: 'ApplicationGridPanel',
                leaf: true
            }, {
                text: this.app.i18n._('License'),
                iconCls: licenseFailed ? 'setup_checks_fail' : 'setup_checks_success',
                disabled: termsFailed || testsFailed || configMissing || dbMissing || setupRequired,
                id: 'LicensePanel',
                leaf: true
            }]
        };
        
        Tine.Setup.TreePanel.superclass.initComponent.call(this);
        
        this.on('click', this.onNodeClick, this);
    },
    
    /**
     * @private
     */
    onNodeClick: function(node) {
        if (! node.disabled) {
            this.app.getMainScreen().setActiveContentType(node.id);
        } else {
            return false;
        }
        
    },
    
    /**
     * @private
     */
    afterRender: function() {
        Tine.Setup.TreePanel.superclass.afterRender.call(this);

        // select last non disabled entry
        var activeType = '';
        var contentTypes = this.getRootNode().childNodes;
        for (var i=0; i<contentTypes.length; i++) {
            if(! contentTypes[i].disabled) {
                activeType = contentTypes[i];
            }
        }

        // NOTE: do not interfere with standard mainscreen rendering
        (function() {
            activeType.select();
            this.app.getMainScreen().setActiveContentType(activeType.id);

            Tine.Setup.registry.on('replace', this.applyRegistryState, this);
        }).defer(100, this);
    },
    
    /**
     * apply registry state
     */
    applyRegistryState: function() {
        var termsChecks  = Tine.Setup.registry.get('acceptedTermsVersion') >= Tine.Setup.CurrentTermsVersion;
        var setupChecks  = Tine.Setup.registry.get('setupChecks');
        var configExists = Tine.Setup.registry.get('configExists');
        var checkDB      = Tine.Setup.registry.get('checkDB');
        var setupRequired = Tine.Setup.registry.get('setupRequired');
        var licenseCheck = Tine.Setup.registry.get('licenseCheck');
        
        setupChecks = (setupChecks && setupChecks.success) ? setupChecks.success : false;

        this.setNodeIcon('TermsPanel', termsChecks);
        this.setNodeIcon('EnvCheckGridPanel', setupChecks);
        this.setNodeIcon('LicensePanel', licenseCheck);
        
        this.getNodeById('EnvCheckGridPanel')[termsChecks ? 'enable': 'disable']();
        this.getNodeById('LicensePanel')[termsChecks ? 'enable': 'disable']();
        this.getNodeById('ConfigManagerPanel')[termsChecks && setupChecks ? 'enable': 'disable']();
        this.getNodeById('AuthenticationPanel')[termsChecks && setupChecks && configExists && checkDB ? 'enable': 'disable']();
        this.getNodeById('ApplicationGridPanel')[termsChecks && setupChecks && configExists && checkDB && !setupRequired ? 'enable': 'disable']();
        this.getNodeById('EmailPanel')[termsChecks && setupChecks && configExists && checkDB && !setupRequired ? 'enable': 'disable']();
        this.getNodeById('LicensePanel')[termsChecks && setupChecks && configExists && checkDB && !setupRequired ? 'enable': 'disable']();
    },
    
    setNodeIcon: function (nodeId, success) {
        var node = this.getNodeById(nodeId);
        var iconCls = success ? 'setup_checks_success' : 'setup_checks_fail';
        if (node.rendered) {
            var iconEl = Ext.get(node.ui.iconNode);
            iconEl.removeClass('setup_checks_success');
            iconEl.removeClass('setup_checks_fail');
            iconEl.addClass(iconCls);
        } else {
            envNode.iconCls = iconCls;
        }
    }
});


/***/ }),

/***/ 790:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 * 
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
 
Ext.ns('Tine', 'Tine.Setup');

/**
 * @namespace   Tine.Setup
 * @class       Tine.Setup.MainScreen
 * @extends     Tine.widgets.MainScreen
 * 
 * <p>MainScreen Definition</p>
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 * 
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Setup.MainScreen
 */
Tine.Setup.MainScreen = Ext.extend(Tine.widgets.MainScreen, {
    
    /**
     * active panel
     * 
     * @property activeContentType
     * @type String
     */
    activeContentType: 'EnvCheckGridPanel',

    /**
     * get content panel
     *
     * @return {Ext.Panel}
     */
    getCenterPanel: function() {
        if (! this[this.activeContentType]) {
            this[this.activeContentType] = new Tine.Setup[this.activeContentType]({
                app: this.app
            });
        }

        return this[this.activeContentType];
    },

    /**
     * get north panel for given activeContentType
     *
     * @param {String} activeContentType
     * @return {Ext.Panel}
     */
    getNorthPanel: function(activeContentType) {
        var panel = this.activeContentType;

        if (! this[panel + 'ActionToolbar']) {
            this[panel + 'ActionToolbar'] = this[panel].actionToolbar;
        }

        // hide and disable stuff in main menu
        Tine.Tinebase.MainScreen.getMainMenu().action_changePassword.setHidden(true);
        Tine.Tinebase.MainScreen.getMainMenu().action_showPreferencesDialog.setHidden(true);
        Tine.Tinebase.MainScreen.getMainMenu().action_editProfile.setDisabled(true);

        return this[panel + 'ActionToolbar'];
    },

    /**
     * get west panel for given activeContentType
     *
     * template method to be overridden by subclasses to modify default behaviour
     *
     * @return {Ext.Panel}
     */
    getWestPanel: function() {
        if (! this.setupTreePanel) {
            this.setupTreePanel = new Tine.Setup.TreePanel();
        }

        return this.setupTreePanel;
    }
});


/***/ }),

/***/ 791:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 * 
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
 
Ext.ns('Tine', 'Tine.Setup');

Tine.Setup.CurrentTermsVersion = 1;

Tine.Setup.TermsPanel = Ext.extend(Ext.Panel, {
    border: false,
    layout: 'fit',
    version: 1,
    
    /**
     * @property actionToolbar
     * @type Ext.Toolbar
     */
    actionToolbar: null,
    
    getLicensePanel: function() {
        var acceptField = new Ext.form.Checkbox({
            name: 'acceptLicense',
            xtype: 'checkbox',
            boxLabel: this.app.i18n._('I have read the license agreement and accept it')
        });
        this.acceptFields.push(acceptField);
        
        return new Ext.Panel({
            autoScroll: true,
            layout: 'fit',
            title: this.app.i18n._('License Agreement'),
            bwrapCfg: {tag: 'pre'},
            autoLoad: {
                url: 'LICENSE',
                isUpload: true,
                method: 'GET',
                callback: function(el, s, response) {
                    el.update(Ext.util.Format.nl2br(response.responseText));
                }
            },
            bbar: [acceptField]
        });
    },
    
    getPrivacyPanel: function() {
        
        var acceptField = new Ext.form.Checkbox({
            name: 'acceptPrivacy',
            xtype: 'checkbox',
            boxLabel: this.app.i18n._('I have read the privacy agreement and accept it')
        });
        this.acceptFields.push(acceptField);
        
        return new Ext.Panel({
            autoScroll: true,
            layout: 'fit',
            title: this.app.i18n._('Privacy Agreement'),
            bwrapCfg: {tag: 'pre'},
            autoLoad: {
                url: 'PRIVACY',
                isUpload: true,
                method: 'GET',
                callback: function(el, s, response) {
                    el.update(Ext.util.Format.nl2br(response.responseText));
                }
            },
            bbar: [acceptField]
        });
    },
    
    initActions: function() {
        this.actionToolbar = new Ext.Toolbar({
            items: [{
                text: this.app.i18n._('Accept Terms and Conditions'),
                iconCls: 'setup_checks_success',
                handler: this.onAcceptConditions,
                scope: this
            }]
        });
    },
    
    initComponent: function() {
        this.initActions();
        
        this.acceptFields = [];
        this.items = [{
            layout: 'vbox',
            border: false,
            layoutConfig: {
                align:'stretch'
            },
            items: [{
                layout: 'fit',
                border: false,
                flex: 1,
                items: this.getLicensePanel()
            }, {
                layout: 'fit',
                border: false,
                flex: 1,
                items: this.getPrivacyPanel()
            }]
        }];
        
        this.supr().initComponent.call(this);
    },
    
    onAcceptConditions: function() {
        var isValid = true;
        
        Ext.each(this.acceptFields, function(field) {
            if (! field.getValue()) {
                field.wrap.setStyle('border-bottom', '1px solid red');
                isValid = false;
            } else {
                field.wrap.setStyle('border-bottom', 'none');
            }
        }, this);
        
        if (isValid) {
            Tine.Setup.registry.replace('acceptedTermsVersion', Tine.Setup.CurrentTermsVersion);
        } else {
            Tine.log.notice('Terms not accepted.');
        }
    }
});


/***/ }),

/***/ 792:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 *
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Michael Spahn <m.spahn@metaways.de>
 * @copyright   Copyright (c) 2009-2015 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */

Ext.ns('Tine', 'Tine.Setup');

/**
 * Licensecheck Panel
 *
 * @namespace   Tine.Setup
 * @class       Tine.Setup.LicensePanel
 * @extends     Ext.Panel
 *
 * <p>Licensecheck Panel</p>
 * <p><pre>
 * </pre></p>
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Michael Spahn <m.spahn@metaways.de
 * @copyright   Copyright (c) 2014 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Setup.LicensePanel
 */
Tine.Setup.LicensePanel = Ext.extend(Tine.Tinebase.widgets.form.ConfigPanel, {

    /**
     * @property actionToolbar
     * @type Ext.Toolbar
     */
    actionToolbar: null,

    /**
     * @property contextMenu
     * @type Ext.Menu
     */
    contextMenu: null,

    /**
     * @private
     */
    border: false,

    /**
     * license type switch
     *
     * * allowed values: BusinessEdition
     *
     * TODO: read this from config
     *
     * @property licenseType
     * @type String
     */
    licenseType: 'BusinessEdition',

    /**
     * license
     */
    license: null,

    initActions: function() {
        var items = (Tine.Setup.registry.get('version') && Tine.Setup.registry.get('version').buildType === 'DEVELOPMENT') ? [ new Ext.Action({
            text: this.app.i18n._('Delete current license'),
            iconCls: 'setup_action_uninstall',
            scope: this,
            handler: this.onDeleteLicense
        })] : [];

        this.actionToolbar = new Ext.Toolbar({
            items: items
        });
    },

    onDeleteLicense: function() {
        this.loadMask.show();
        Ext.Ajax.request({
            params: {
                method: 'Setup.deleteLicense'
            },
            scope: this,
            success: function (response) {
                this.loadMask.hide();
                this.setLicenseInformation(response);

                // TODO reset upload button (setText/Icon?)
                //this.uploadLicense.setText('');
            }
        });
    },

     /**
     * init component
     */
    initComponent: function () {
        this.initActions();
        Tine.Setup.LicensePanel.superclass.initComponent.call(this);
    },

    /**
     * @private
     */
    onRender: function (ct, position) {
        Tine.Setup.LicensePanel.superclass.onRender.call(this, ct, position);
        this.initLicense();
    },

    /**
     * init store
     * @private
     */
    initLicense: function () {
        this.loadMask.show();
        Ext.Ajax.request({
            params: {
                method: 'Setup.getLicense'
            },
            scope: this,
            success: function (response) {
                this.setLicenseInformation(response);

                this.loadMask.hide();
            }
        });
    },

    /**
     * Sets license data to textfields
     * @param response
     */
    setLicenseInformation: function (response) {
        var data = (response.responseText) ? Ext.util.JSON.decode(response.responseText) : {};

        if (data.status && data.status == 'status_license_invalid') {
            Ext.Msg.alert('Status', this.app.i18n._('Your license is not valid.'));
        }

        if (data.hasOwnProperty('error') && data.error == false || ! data.serialNumber) {
            Tine.Setup.registry.replace('licenseCheck', false);
            Ext.getCmp('serialNumber').reset();
            Ext.getCmp('maxUsers').reset();

            if (this.licenseType === 'BusinessEdition') {
                Ext.getCmp('contractId').reset();
                Ext.getCmp('validFrom').reset();
                Ext.getCmp('validTo').reset();
            }
        } else {
            Ext.getCmp('serialNumber').setValue(data.serialNumber);
            Ext.getCmp('maxUsers').setValue(data.maxUsers);

            if (this.licenseType === 'BusinessEdition') {
                Ext.getCmp('contractId').setValue(data.contractId);
                Ext.getCmp('validFrom').setValue(new Date(Date.parseDate(String(data.validFrom.date).substr(0, 19), Date.patterns.ISO8601Long)));
                Ext.getCmp('validTo').setValue(new Date(Date.parseDate(String(data.validTo.date).substr(0, 19), Date.patterns.ISO8601Long)));
            }

            Tine.Setup.registry.replace('licenseCheck', data.status && data.status == 'status_license_ok');
        }
    },

    /**
     * If license uploaded successfully ..
     */
    onFileReady: function () {
        Ext.Ajax.request({
            params: {
                method: 'Setup.uploadLicense',
                tempFileId: this.uploadLicense.getTempFileId()
            },
            scope: this,
            success: function (response) {
                this.setLicenseInformation(response);
            }
        })
    },

    /**
     * @private
     *
     */
    getFormItems: function () {
        var licenseFields = [],
            licenseConfiguration = this.licenseType === 'BusinessEdition' ? {
                xtype: 'fieldset',
                title: this.app.i18n._('License Configuration'),
                collapsible: false,
                autoHeight: true,
                defaults: {
                    anchor: '-20',
                    width: 200
                },
                items: [{
                    xtype: 'tw.uploadbutton',
                    fieldLabel: this.app.i18n._('Upload from disk'),
                    ref: '../../uploadLicense',
                    text: String.format(this.app.i18n._('Select file containing your license key')),
                    handler: this.onFileReady,
                    allowedTypes: null,
                    uploadTempFileMethod: 'Setup.uploadTempFile',
                    uploadUrl: 'setup.php',
                    scope: this
                }]
            } : {};

        switch (this.licenseType) {
            case 'BusinessEdition':
                licenseFields = [{
                    fieldLabel: this.app.i18n._('Contract ID'),
                    name: 'contractId',
                    id: 'contractId',
                    emptyText: this.app.i18n._('No valid license')
                }, {
                    fieldLabel: this.app.i18n._('Serial Number'),
                    name: 'serialNumber',
                    id: 'serialNumber',
                    emptyText: this.app.i18n._('No valid license')
                }, {
                    fieldLabel: this.app.i18n._('Maximum Users (0=unlimited)'),
                    name: 'maxUsers',
                    id: 'maxUsers',
                    emptyText: this.app.i18n._('No valid license')
                }, {
                    fieldLabel: this.app.i18n._('Valid from'),
                    name: 'validFrom',
                    id: 'validFrom',
                    xtype: 'datetimefield',
                    emptyText: this.app.i18n._('No valid license')
                }, {
                    fieldLabel: this.app.i18n._('Valid to'),
                    name: 'validTo',
                    id: 'validTo',
                    xtype: 'datetimefield',
                    emptyText: this.app.i18n._('No valid license')
                }];
                break;
        }

        return [{
            defaults: {
                tabIndex: this.getTabIndex
            },
            border: false,
            autoScroll: true,
            items: [{
                xtype: 'fieldset',
                title: this.app.i18n._('License Information'),
                collapsible: false,
                autoHeight: true,
                defaults: {
                    width: 200,
                    readOnly: true
                },
                defaultType: 'textfield',
                items: licenseFields
            }, licenseConfiguration
            ]
        }];
    }
});


/***/ }),

/***/ 793:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 * 
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2011 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
 
Ext.ns('Tine', 'Tine.Setup');

/**
 * @namespace   Tine.Setup
 * @class       Tine.Setup.ApplicationGridPanel
 * @extends     Tine.widgets.grid.GridPanel
 * 
 * <p>Application Setup Grid Panel</p>
 * <p></p>
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * 
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Setup.ApplicationGridPanel
 */
Tine.Setup.ApplicationGridPanel = Ext.extend(Tine.widgets.grid.GridPanel, {

    /**
     * @private
     */
    recordClass: Tine.Setup.Model.Application,
    recordProxy: Tine.Setup.ApplicationBackend,
    stateful: false,
    evalGrants: false,
    defaultSortInfo: {field: 'name', dir: 'ASC'},
    gridConfig: {
        autoExpandColumn: 'name'
    },
    
    /**
     * @private
     */
    initComponent: function() {
                
        this.gridConfig.columns = this.getColumns();
        
        Tine.Setup.ApplicationGridPanel.superclass.initComponent.call(this);
        
        // activate local sort
        this.store.remoteSort = false;
        
        // add selection of updateable apps after store load
        this.store.on('load', this.selectApps, this);
    },
    
    /**
     * @private
     */
    getColumns: function() {
        return  [
            {id: 'name',            width: 350, sortable: true, dataIndex: 'name',            header: this.app.i18n._("Name")}, 
            {id: 'status',          width: 70,  sortable: true, dataIndex: 'status',          header: this.app.i18n._("Enabled"),       renderer: this.enabledRenderer}, 
            {id: 'order',           width: 50,  sortable: true, dataIndex: 'order',           header: this.app.i18n._("Order")},
            {id: 'version',         width: 85,  sortable: true, dataIndex: 'version',         header: this.app.i18n._("Installed Version")},
            {id: 'current_version', width: 85,  sortable: true, dataIndex: 'current_version', header: this.app.i18n._("Available Version")},
            {id: 'install_status',  width: 70,  sortable: true, dataIndex: 'install_status',  header: this.app.i18n._("Status"),        renderer: this.upgradeStatusRenderer.createDelegate(this)},
            {id: 'depends',         width: 150, sortable: true, dataIndex: 'depends',         header: this.app.i18n._("Depends on")}
        ];
    },
    
    /**
     * @private
     */
    initActions: function() {
        this.action_installApplications = new Ext.Action({
            text: this.app.i18n._('Install application'),
            handler: this.onAlterApplications,
            actionType: 'install',
            iconCls: 'setup_action_install',
            disabled: true,
            scope: this
        });
        
        this.action_uninstallApplications = new Ext.Action({
            text: this.app.i18n._('Uninstall application'),
            handler: this.onAlterApplications,
            actionType: 'uninstall',
            iconCls: 'setup_action_uninstall',
            disabled: true,
            scope: this
        });
        
        this.action_updateApplications = new Ext.Action({
            text: this.app.i18n._('Update application'),
            handler: this.onAlterApplications,
            actionType: 'update',
            iconCls: 'setup_action_update',
            disabled: true,
            scope: this
        });
        
        this.action_gotoLogin = new Ext.Action({
            text: String.format(this.app.i18n._('Go to {0} login'), Tine.title),
            handler: this.onGotoLogin,
            iconCls: 'action_login',
            scope: this
        });
        
        this.actions = [
            this.action_installApplications,
            this.action_uninstallApplications,
            this.action_updateApplications,
            '-',
            this.action_gotoLogin
        ];
        
        this.actionToolbar = new Ext.Toolbar({
            split: false,
            height: 26,
            items: this.actions
        });
        
        this.contextMenu = new Ext.menu.Menu({
            plugins: [{
                ptype: 'ux.itemregistry',
                key:   'Tinebase-MainContextMenu'
            }],
            items: this.actions
        });
    },
    
    /**
     * overwrite default - we do not have a filterpanel here
     */
    initFilterPanel: function() {},
    
    /**
     * @private
     */
    initGrid: function() {
        Tine.Setup.ApplicationGridPanel.superclass.initGrid.call(this);
        this.selectionModel.purgeListeners();
        
        this.selectionModel.on('selectionchange', this.onSelectionChange, this);
    },

    /**
     * @private
     */
    onSelectionChange: function(sm) {
        var apps = sm.getSelections();
        var disabled = sm.getCount() == 0;
        
        var nIn = disabled, nUp = disabled, nUn = disabled,        
            addressbook, admin, tinebase;
        
        for(var i=0; i<apps.length; i++) {
            var status = apps[i].get('install_status');
            nIn = nIn || status == 'uptodate' || status == 'updateable';
            nUp = nUp || status == 'uptodate' || status == 'uninstalled';
            nUn = nUn || status == 'uninstalled';
            if (apps[i].id == 'Addressbook') addressbook = true;
            else if (apps[i].id == 'Tinebase') tinebase = true;
            else if (apps[i].id == 'Admin') admin = true;
        }
        
        if(this.store.getById('Tinebase').get('install_status') == 'uninstalled') tinebase = false;
        if((addressbook || admin ) && !tinebase) nUn = true;
        
        this.action_installApplications.setDisabled(nIn);
        this.action_uninstallApplications.setDisabled(nUn);
        this.action_updateApplications.setDisabled(nUp);
    },
    
    /**
     * @private
     */
    onAlterApplications: function(btn, e) {

        if (btn.actionType == 'uninstall') {
            // get user confirmation before uninstall
            Ext.Msg.confirm(this.app.i18n._('uninstall'), this.app.i18n._('Do you really want to uninstall the application(s)?'), function(confirmbtn, value) {
                if (confirmbtn == 'yes') {
                    this.alterApps(btn.actionType);
                }
            }, this);
        } else {
            this.alterApps(btn.actionType);
        }
    },
    
    /**
     * goto tine 2.0 login screen
     * 
     * @param {Button} btn
     * @param {Event} e
     */
    onGotoLogin: function(btn, e) {
        window.location = window.location.href.replace(/setup(\.php)*/, '');
    },
    
    /**
     * select all installable or updateable apps
     * @private
     */
    selectApps: function() {
        
        var updateable = [];
        
        this.store.each(function(record) {
            if (record.get('install_status') == 'updateable') {
                updateable.push(record);
            }
        }, this);
        
        this.selectionModel.selectRecords(updateable);
    },
    
    /**
     * alter applications
     * 
     * @param {} type (uninstall/install/update)
     * @private
     */
    alterApps: function(type) {

        var appNames = [];
        var apps = this.selectionModel.getSelections();
        
        for(var i=0; i<apps.length; i++) {
            appNames.push(apps[i].get('name'));
        }

        this.sendAlterApplicationsRequest(type, appNames, null);
    },
    
    /**
     * @private
     */
    sendAlterApplicationsRequest: function(type, appNames, options) {
        var msg = this.app.i18n.n_('Updating Application "{0}".', 'Updating {0} Applications.', appNames.length);
        msg = String.format(msg, appNames.length == 1 ? appNames[0] : appNames.length ) + ' ' + this.app.i18n._('This may take a while');

        var longLoadMask = new Ext.LoadMask(this.grid.getEl(), {
            msg: msg,
            removeMask: true
        });
        longLoadMask.show();
        Ext.Ajax.request({
            scope: this,
            params: {
                method: 'Setup.' + type + 'Applications',
                applicationNames: appNames,
                options: options
            },
            success: function(response) {
                var regData = Ext.util.JSON.decode(response.responseText);
                // replace some registry data
                for (key in regData) {
                    if (key != 'status' && key != 'success') {
                        Tine.Setup.registry.replace(key, regData[key]);
                    }
                }
                this.store.load();
                longLoadMask.hide();
            },
            failure: function(exception) {
                longLoadMask.hide();
                
                var exception = Ext.util.JSON.decode(exception.responseText).data;
                
                switch (exception.code) {
                    //Dependency Exception
                    case 501:
                        Ext.MessageBox.show({
                            title: this.app.i18n._('Dependency Violation'), 
                            msg: exception.message,
                            buttons: Ext.Msg.OK,
                            icon: Ext.MessageBox.WARNING
                        });
                        this.store.load();
                        break;
                    case 901:
                        Ext.MessageBox.show({
                            title: this.app.i18n._('CLI Required'), 
                            msg: this.app.i18n._(exception.message),
                            buttons: Ext.Msg.OK,
                            icon: Ext.MessageBox.ERROR
                        });
                        break;
                    default:
                        Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
                }
            }
        });
    },
    
    /**
     * @private
     */
    enabledRenderer: function(value) {
        return Tine.Tinebase.common.booleanRenderer(value == 'enabled');
    },
    
    /**
     * @private
     */
    upgradeStatusRenderer: function(value) {
        return this.app.i18n._hidden(value);
    }
});


/***/ }),

/***/ 794:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 * 
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Philipp Schüle <p.schuele@metaways.de>
 * @copyright   Copyright (c) 2009-2011 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
 
Ext.ns('Tine', 'Tine.Setup');

/**
 * Environment Check Grid Panel
 * 
 * @namespace   Tine.Setup
 * @class       Tine.Setup.EnvCheckGridPanel
 * @extends     Ext.Panel
 * 
 * <p>Environment Check Grid Panel</p>
 * <p><pre>
 * </pre></p>
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Philipp Schuele <p.schuele@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 * 
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Setup.EnvCheckGridPanel
 */
 Tine.Setup.EnvCheckGridPanel = Ext.extend(Ext.Panel, {
    
    /**
     * @property actionToolbar
     * @type Ext.Toolbar
     */
    actionToolbar: null,
    
    /**
     * @property contextMenu
     * @type Ext.Menu
     */
    contextMenu: null,
    
    /**
     * @private
     */
    layout: 'border',
    border: false,
    
    /**
     * 
     * @cfg grid config 
     */
    gridConfig: {
        autoExpandColumn: 'key'
    },
    
    /**
     * init component
     */
    initComponent: function() {
        
        this.gridConfig.columns = this.getColumns();
        
        this.initActions();
        this.initStore();
        this.initGrid();
        this.initLayout();

        Tine.Setup.EnvCheckGridPanel.superclass.initComponent.call(this);
    },
    
    /**
     * init store
     * @private
     */
    initStore: function() {
        this.store = new Ext.data.JsonStore({
            fields: Tine.Setup.Model.EnvCheck,
            mode: 'local',
            id: 'key',
            remoteSort: false
        });
        
        this.store.on('beforeload', function() {
            if (! this.loadMask) {
                this.loadMask = new Ext.LoadMask(this.el, {msg: this.app.i18n._("Performing Environment Checks...")});
            }
            
            this.loadMask.show();
            
            Ext.Ajax.request({
                params: {
                    method: 'Setup.envCheck'
                },
                scope: this,
                success: function(response) {
                    var data = Ext.util.JSON.decode(response.responseText);
                    Tine.Setup.registry.replace('setupChecks', data);
                    
                    this.store.loadData(data.results);
                    this.loadMask.hide();
                }
            })
            
            return false;
        }, this);
        
        var checkData = Tine.Setup.registry.get('setupChecks').results;
        this.store.loadData(checkData);
    },

    /**
     * init ext grid panel
     * @private
     */
    initGrid: function() {
        // init sel model
        this.selectionModel = new Ext.grid.RowSelectionModel({
            store: this.store
        });
        
        // init view
        var view =  new Ext.grid.GridView({
            autoFill: true,
            forceFit:true,
            ignoreAdd: true
            //emptyText: String.format(i18n._("There could not be found any {0}. Please try to change your filter-criteria, view-options or the {1} you search in."), this.i18nRecordsName, this.i18nContainersName),
            /*
            onLoad: Ext.emptyFn,
            listeners: {
                beforerefresh: function(v) {
                    v.scrollTop = v.scroller.dom.scrollTop;
                },
                refresh: function(v) {
                    // on paging-refreshes (prev/last...) we don't preserv the scroller state
                    if (v.isPagingRefresh) {
                        v.scrollToTop();
                        v.isPagingRefresh = false;
                    } else {
                        v.scroller.dom.scrollTop = v.scrollTop;
                    }
                }
            }
            */
        });
        
        this.grid = new Ext.grid.GridPanel(Ext.applyIf(this.gridConfig, {
            border: false,
            store: this.store,
            sm: this.selectionModel,
            view: view
        }));
    },
    
    getColumns: function() {
        return  [
            {id: 'key',   width: 150, sortable: true, dataIndex: 'key',   header: this.app.i18n._("Check")}, 
            {id: 'value', width: 50, sortable: true, dataIndex: 'value', header: this.app.i18n._("Result"), renderer: this.resultRenderer},
            {id: 'message', width: 600, sortable: true, dataIndex: 'message', header: this.app.i18n._("Message"), renderer: this.messageRenderer}
        ];
    },

    resultRenderer: function(value) {
        var icon = (value) ? 'images/icon-set/icon_ok.svg' : 'images/icon-set/icon_stop.svg';
        return '<img class="setup-envcheck-grid-status" src="' + icon + '">';
    },
    
    messageRenderer: function(value) {
        // overwrite the default renderer to show links correctly
        return value;
    },
    
    initActions: function() {
        // @todo add re-run checks here
        
        this.action_reCheck = new Ext.Action({
            text: this.app.i18n._('Run setup tests'),
            handler: function() {
                this.store.load({});
            },
            iconCls: 'x-tbar-loading',
            scope: this
        });
        
        this.action_ignoreTests = new Ext.Action({
            text: this.app.i18n._('Ignore setup tests'),
            // we are not ready for this button yet:
            //    setup only works with mysql version check ok
            disabled: true,
            iconCls: 'setup_checks_success',
            scope: this,
            handler: function() {
                var checks = Tine.Setup.registry.get('setupChecks');
                checks.success = true;
                Tine.Setup.registry.replace('setupChecks', checks);
                Tine.Setup.registry.replace('checkDB', true);
            }
        });
        /*
        this.action_installApplications = new Ext.Action({
            text: this.app.i18n._('Install application'),
            handler: this.onAlterApplications,
            actionType: 'install',
            iconCls: 'setup_action_install',
            disabled: true,
            scope: this
        });
        
        this.actions = [
            this.action_installApplications,
        ];
        */
        
        this.actionToolbar = new Ext.Toolbar({
            items: [
                this.action_reCheck,
                this.action_ignoreTests
            ]
        });
    },
    
    /**
     * @private
     * 
     * NOTE: Order of items matters! Ext.Layout.Border.SplitRegion.layout() does not
     *       fence the rendering correctly, as such it's impotant, so have the ftb
     *       defined after all other layout items
     */
    initLayout: function() {
        this.items = [{
            region: 'center',
            xtype: 'panel',
            layout: 'fit',
            border: false,
            items: this.grid
        }];
    }
});


/***/ }),

/***/ 795:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 * 
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */

/*global Ext, Tine*/

Ext.ns('Tine', 'Tine.Setup');

/**
 * Setup Configuration Manager
 * 
 * @namespace   Tine.Setup
 * @class       Tine.Setup.ConfigManagerPanel
 * @extends     Tine.Tinebase.widgets.form.ConfigPanel
 * 
 * <p>Configuration Panel</p>
 * <p><pre>
 * </pre></p>
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * 
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Setup.ConfigManagerPanel
 */
Tine.Setup.ConfigManagerPanel = Ext.extend(Tine.Tinebase.widgets.form.ConfigPanel, {

    /**
     * @property idPrefix DOM Id prefix
     * @type String
     */
    idPrefix: null,
    
    /**
     * @private
     * panel cfg
     */
    saveMethod: 'Setup.saveConfig',
    registryKey: 'configData',
    defaults: {
        xtype: 'fieldset',
        autoHeight: 'auto',
        defaults: {width: 300},
        defaultType: 'textfield'
    },
    
    /**
     * session backend DOM Id prefix
     * 
     * @property sessionBackendIdPrefix
     * @type String
     */
    sessionBackendIdPrefix: null,
    
    /**
     * @private
     * field index counter
     */
    tabIndexCounter: 1,
    
    /**
     * @private
     */
    initComponent: function () {
        this.idPrefix                  = Ext.id();
        this.sessionBackendIdPrefix    = this.idPrefix + '-sessionBackend-';
        this.cacheBackendIdPrefix    = this.idPrefix + '-cacheBackend-';
        this.queueBackendIdPrefix    = this.idPrefix + '-queueBackend-';

        Tine.Setup.ConfigManagerPanel.superclass.initComponent.call(this);
    },
    
    /**
     * Change session card layout depending on selected combo box entry
     */
    onChangeSessionBackend: function () {
        this.changeCard(this.sessionBackendCombo, this.sessionBackendIdPrefix);
    },

    /**
     * Change cache card layout depending on selected combo box entry
     */
    onChangeCacheBackend: function () {
        this.changeCard(this.cacheBackendCombo, this.cacheBackendIdPrefix);
    },
    
    /**
     * Change queue card layout depending on selected combo box entry
     */
    onChangeQueueBackend: function () {
        this.changeCard(this.queueBackendCombo, this.queueBackendIdPrefix);
    },
    
    /**
     * Change default ports when database adapter gets changed
     */
    onChangeSqlBackend: function () {
        // @todo change default port
    },
    
    /**
     * @private
     */
    onRender: function (ct, position) {
        Tine.Setup.EmailPanel.superclass.onRender.call(this, ct, position);
        
        this.onChangeSessionBackend.defer(250, this);
    },
    
    /**
     * get tab index for field
     * 
     * @return {Integer}
     */
    getTabIndex: function () {
        return this.tabIndexCounter++;
    },
    
    /**
     * returns config manager form
     * 
     * @private
     * @return {Array} items
     */
    getFormItems: function () {
        // common config for all combos in this setup
        var commonComboConfig = {
            xtype: 'combo',
            listWidth: 300,
            mode: 'local',
            forceSelection: true,
            allowEmpty: false,
            triggerAction: 'all',
            editable: false,
            tabIndex: this.getTabIndex
        };
        
        this.sessionBackendCombo = new Ext.form.ComboBox(Ext.applyIf({
            name: 'session_backend',
            fieldLabel: this.app.i18n._('Backend'),
            value: 'File',
            store: [['File', this.app.i18n._('File')], ['Redis','Redis']],
            listeners: {
                scope: this,
                change: this.onChangeSessionBackend,
                select: this.onChangeSessionBackend
            }
        }, commonComboConfig));

        this.cacheBackendCombo = new Ext.form.ComboBox(Ext.applyIf({
            name: 'caching_backend',
            fieldLabel: this.app.i18n._('Backend'),
            value: 'File',
            store: [['File', this.app.i18n._('File')], ['Redis','Redis'], ['Memcached', 'Memcached']],
            listeners: {
                scope: this,
                change: this.onChangeCacheBackend,
                select: this.onChangeCacheBackend
            }
        }, commonComboConfig));

        this.queueBackendCombo = new Ext.form.ComboBox(Ext.applyIf({
            name: 'actionqueue_backend',
            fieldLabel: this.app.i18n._('Backend'),
            value: 'Redis',
            store: [['Redis','Redis']],
            listeners: {
                scope: this,
                change: this.onChangeQueueBackend,
                select: this.onChangeQueueBackend
            }
        }, commonComboConfig));
        
        this.sqlBackendCombo = new Ext.form.ComboBox(Ext.applyIf({
            name: 'database_adapter',
            fieldLabel: this.app.i18n._('Backend'),
            value: 'pdo_mysql',
            store: [
                ['pdo_mysql', 'MySQL']
            ],
            listeners: {
                scope: this,
                change: this.onChangeSqlBackend,
                select: this.onChangeSqlBackend
            }
        }, commonComboConfig));
        
        return [{
            title: this.app.i18n._('Setup Authentication'),
            defaults: {
                width: 300,
                tabIndex: this.getTabIndex
            },
            items: [{
                name: 'setupuser_username',
                fieldLabel: this.app.i18n._('Username'),
                allowBlank: false,
                listeners: {
                    afterrender: function (field) {
                        field.focus(true, 500);
                    }
                }
            }, {
                name: 'setupuser_password',
                fieldLabel: this.app.i18n._('Password'),
                inputType: 'password',
                allowBlank: false
            }] 
        }, {
            title: this.app.i18n._('Database'),
            id: 'setup-database-group',
            defaults: {
                width: 300,
                tabIndex: this.getTabIndex
            },
            items: [ 
                this.sqlBackendCombo, 
                {
                    name: 'database_host',
                    fieldLabel: this.app.i18n._('Hostname'),
                    allowBlank: false
                }, {
                    xtype: 'numberfield',
                    name: 'database_port',
                    fieldLabel: this.app.i18n._('Port')
                }, {
                    name: 'database_dbname',
                    fieldLabel: this.app.i18n._('Database'),
                    allowBlank: false
                }, {
                    name: 'database_username',
                    fieldLabel: this.app.i18n._('User'),
                    allowBlank: false
                }, {
                    name: 'database_password',
                    fieldLabel: this.app.i18n._('Password'),
                    inputType: 'password'
                }, {
                    name: 'database_tableprefix',
                    fieldLabel: this.app.i18n._('Prefix')
                }
            ]
        }, {
            title: this.app.i18n._('Logging'),
            id: 'setup-logger-group',
            checkboxToggle: true,
            collapsed: true,
            defaults: {
                width: 300,
                tabIndex: this.getTabIndex
            },
            items: [{
                name: 'logger_filename',
                fieldLabel: this.app.i18n._('Filename')
            }, Ext.applyIf({
                name: 'logger_priority',
                fieldLabel: this.app.i18n._('Priority'),
                store: [
                    [0, 'Emergency (0)'],
                    [1, 'Alert (1)'],
                    [2, 'Critical (2)'],
                    [3, 'Error (3)'],
                    [4, 'Warning (4)'],
                    [5, 'Notice (5)'],
                    [6, 'Informational (6)'],
                    [7, 'Debug (7)']
                ]
            }, commonComboConfig)]
        }, {
            title: this.app.i18n._('Caching'),
            id: 'setup-caching-group',
            checkboxToggle: true,
            collapsed: true,
            defaults: {
                width: 300,
                tabIndex: this.getTabIndex
            },
            items: [ {
                xtype: 'numberfield',
                name: 'caching_lifetime',
                fieldLabel: this.app.i18n._('Lifetime (seconds)'),
                minValue: 0,
                maxValue: 3600
            }, this.cacheBackendCombo, 
            {
                id: this.cacheBackendIdPrefix + 'CardLayout',
                xtype: 'panel',
                layout: 'card',
                activeItem: this.cacheBackendIdPrefix + 'File',
                border: false,
                width: '100%',
                defaults: {border: false},
                items: [{
                    id: this.cacheBackendIdPrefix + 'File',
                    layout: 'form',
                    autoHeight: 'auto',
                    defaults: {
                        width: 300,
                        xtype: 'textfield',
                        tabIndex: this.getTabIndex
                    },
                    items: [{
                        name: 'caching_path',
                        fieldLabel: this.app.i18n._('Path')
                    }]
                }, {
                    id: this.cacheBackendIdPrefix + 'Redis',
                    layout: 'form',
                    autoHeight: 'auto',
                    defaults: {
                        width: 300,
                        xtype: 'textfield',
                        tabIndex: this.getTabIndex
                    },
                    items: [{
                        name: 'caching_redis_host',
                        fieldLabel: this.app.i18n._('Hostname'),
                        value: 'localhost'
                    }, {
                        name: 'caching_redis_port',
                        fieldLabel: this.app.i18n._('Port'),
                        xtype: 'numberfield',
                        minValue: 0,
                        value: 6379
                    }]
                }, {
                    id: this.cacheBackendIdPrefix + 'Memcached',
                    layout: 'form',
                    autoHeight: 'auto',
                    defaults: {
                        width: 300,
                        xtype: 'textfield',
                        tabIndex: this.getTabIndex
                    },
                    items: [{
                        name: 'caching_memcached_host',
                        fieldLabel: this.app.i18n._('Hostname'),
                        value: 'localhost'
                    }, {
                        name: 'caching_memcached_port',
                        fieldLabel: this.app.i18n._('Port'),
                        xtype: 'numberfield',
                        minValue: 0,
                        value: 11211
                    }]
                }]
            }]
        }, {
            title: this.app.i18n._('Queue'),
            id: 'setup-actionqueue-group',
            checkboxToggle: true,
            collapsed: true,
            defaults: {
                width: 300,
                tabIndex: this.getTabIndex
            },
            items: [this.queueBackendCombo, 
            {
                id: this.queueBackendIdPrefix + 'CardLayout',
                xtype: 'panel',
                layout: 'card',
                activeItem: this.queueBackendIdPrefix + 'Redis',
                border: false,
                width: '100%',
                defaults: {border: false},
                items: [{
                    // redis config options
                    id: this.queueBackendIdPrefix + 'Redis',
                    layout: 'form',
                    autoHeight: 'auto',
                    defaults: {
                        width: 300,
                        xtype: 'textfield',
                        tabIndex: this.getTabIndex
                    },
                    items: [{
                        name: 'actionqueue_host',
                        fieldLabel: this.app.i18n._('Hostname'),
                        value: 'localhost'
                    }, {
                        name: 'actionqueue_port',
                        fieldLabel: this.app.i18n._('Port'),
                        xtype: 'numberfield',
                        minValue: 0,
                        value: 6379
                    }]
                }]
            }]
        }, {
            title: this.app.i18n._('Session'),
            id: 'setup-session-group',
            defaults: {
                width: 300,
                tabIndex: this.getTabIndex
            },
            items: [{
                name: 'session_lifetime',
                fieldLabel: this.app.i18n._('Lifetime (seconds)'),
                xtype: 'numberfield',
                value: 86400, 
                minValue: 0
            }, this.sessionBackendCombo, 
            {
                id: this.sessionBackendIdPrefix + 'CardLayout',
                xtype: 'panel',
                layout: 'card',
                activeItem: this.sessionBackendIdPrefix + 'File',
                border: false,
                width: '100%',
                defaults: {border: false},
                items: [{
                    // file config options
                    id: this.sessionBackendIdPrefix + 'File',
                    layout: 'form',
                    autoHeight: 'auto',
                    defaults: {
                        width: 300,
                        xtype: 'textfield',
                        tabIndex: this.getTabIndex
                    },
                    items: [{
                        name: 'session_path',
                        fieldLabel: this.app.i18n._('Path')
                    }]
                }, {
                    // redis config options
                    id: this.sessionBackendIdPrefix + 'Redis',
                    layout: 'form',
                    autoHeight: 'auto',
                    defaults: {
                        width: 300,
                        xtype: 'textfield',
                        tabIndex: this.getTabIndex
                    },
                    items: [{
                        name: 'session_host',
                        fieldLabel: this.app.i18n._('Hostname'),
                        value: 'localhost'
                    }, {
                        name: 'session_port',
                        fieldLabel: this.app.i18n._('Port'),
                        xtype: 'numberfield',
                        minValue: 0,
                        value: 6379
                    }]
                }]
            }]
        }, {
            title: this.app.i18n._('Temporary files'),
            id: 'setup-tmpDir-group',
            defaults: {
                width: 300,
                tabIndex: this.getTabIndex
            },
            items: [{
                name: 'tmpdir',
                fieldLabel: this.app.i18n._('Temporary Files Path'),
                value: Tine.Setup.registry.get(this.registryKey).tmpdir
            }]
        }, {
            // TODO this should be not saved in the config.inc.php
            title: this.app.i18n._('Filestore directory'),
            id: 'setup-filesDir-group',
            defaults: {
                width: 300,
                tabIndex: this.getTabIndex
            },
            items: [{
                name: 'filesdir',
                fieldLabel: this.app.i18n._('Filestore Path'),
                value: Tine.Setup.registry.get(this.registryKey)['filesdir']
            }]
        }, {
            // TODO move map panel config to common config panel -> it should not be saved in config.inc.php
            title: this.app.i18n._('Addressbook Map panel'),
            defaults: {
                width: 300,
                tabIndex: this.getTabIndex
            },
            items: [
                Ext.applyIf({
                    name: 'mapPanel',
                    fieldLabel: this.app.i18n._('Map panel'),
                    value: Tine.Setup.registry.get(this.registryKey)['mapPanel'],
                    store: [[0, this.app.i18n._('disabled')], [1,this.app.i18n._('enabled')]]
                }, commonComboConfig)
           ] 
        }];
    },
    
    /**
     * applies registry state to this cmp
     */
    applyRegistryState: function () {
        this.action_saveConfig.setDisabled(! Tine.Setup.registry.get('configWritable'));
        if (! Tine.Setup.registry.get('configWritable')) {
            this.action_saveConfig.setText(this.app.i18n._('Config file is not writable'));
        } else {
            this.action_saveConfig.setText(this.app.i18n._('Save config'));
        }
        
        Ext.getCmp('setup-database-group').setIconClass(Tine.Setup.registry.get('checkDB') ? 'setup_checks_success' : 'setup_checks_fail');
        Ext.getCmp('setup-logger-group').setIconClass(Tine.Setup.registry.get('checkLogger') ? 'setup_checks_success' : 'setup_checks_fail');
        Ext.getCmp('setup-caching-group').setIconClass(Tine.Setup.registry.get('checkCaching') ? 'setup_checks_success' : 'setup_checks_fail');
        Ext.getCmp('setup-actionqueue-group').setIconClass(Tine.Setup.registry.get('checkQueue') ? 'setup_checks_success' : 'setup_checks_fail');
        Ext.getCmp('setup-tmpDir-group').setIconClass(Tine.Setup.registry.get('checkTmpDir') ? 'setup_checks_success' : 'setup_checks_fail');
        Ext.getCmp('setup-session-group').setIconClass(Tine.Setup.registry.get('checkSession') ? 'setup_checks_success' : 'setup_checks_fail');
        Ext.getCmp('setup-filesDir-group').setIconClass(Tine.Setup.registry.get('checkFilesDir') ? 'setup_checks_success' : 'setup_checks_fail');
    },
    
    /**
     * @private
     */
    initActions: function () {
        this.action_downloadConfig = new Ext.Action({
            text: this.app.i18n._('Download config file'),
            iconCls: 'setup_action_download_config',
            scope: this,
            handler: this.onDownloadConfig
            //disabled: true
        });
        
        this.actionToolbarItems = [this.action_downloadConfig];
        
        Tine.Setup.ConfigManagerPanel.superclass.initActions.apply(this, arguments);
    },
    
    onDownloadConfig: function() {
        if (this.isValid()) {
            var configData = this.form2config();
            
            var downloader = new Ext.ux.file.Download({
                url: Tine.Tinebase.tineInit.requestUrl,
                params: {
                    method: 'Setup.downloadConfig',
                    data: Ext.encode(configData)
                }
            });
            downloader.start();
        } else {
            this.alertInvalidData();
        }
    },
    
    isValid: function () {
        var form = this.getForm(),
            result = form.isValid(),
            maxPrefixLength = 10;
        
        // check prefix length
        if (form.findField('database_tableprefix') && 
            form.findField('database_tableprefix').getValue() &&
            form.findField('database_tableprefix').getValue().length > maxPrefixLength)
        {
            form.markInvalid([{
                id: 'database_tableprefix',
                msg: String.format(this.app.i18n._("This prefix is too long. Please choose a prefix no longer than {0} chars."), maxPrefixLength)
            }]);
            result = false;
        }
        return result;
    }
});

/***/ }),

/***/ 796:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 * 
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2015 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */

/*global Ext, Tine*/

Ext.ns('Tine', 'Tine.Setup');
 
/**
 * Setup Authentication Manager
 * 
 * @namespace   Tine.Setup
 * @class       Tine.Setup.AuthenticationPanel
 * @extends     Tine.Tinebase.widgets.form.ConfigPanel
 * 
 * <p>Authentication Panel</p>
 * <p><pre>
 * TODO         move to next step after install?
 * TODO         make default is valid mechanism with 'allowEmpty' work
 * </pre></p>
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 * 
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Setup.AuthenticationPanel
 */
Tine.Setup.AuthenticationPanel = Ext.extend(Tine.Tinebase.widgets.form.ConfigPanel, {
    
    /**
     * @property idPrefix DOM Id prefix
     * @type String
     */
    idPrefix: null,
    
    /**
     * authProviderPrefix DOM Id prefix
     * 
     * @property authProviderIdPrefix
     * @type String
     */
    authProviderIdPrefix: null,
    
    /**
     * accountsStorageIdPrefix DOM Id prefix
     * 
     * @property accountsStorageIdPrefix
     * @type String
     */
    accountsStorageIdPrefix: null,
    
    /**
     * combo box containing the authentication backend selection
     * 
     * @property authenticationBackendCombo
     * @type Ext.form.ComboBox 
     */
    authenticationBackendCombo: null,

    /**
     * combo box containing the accounts storage selection
     * 
     * @property accountsStorageCombo
     * @type Ext.form.ComboBox
     */
    accountsStorageCombo: null,
    
    /**
     * The currently active accounts storage backend
     * 
     * @property originalAccountsStorage
     * @type String
     */
    originalAccountsStorage: null,

    /**
     * @private
     * panel cfg
     */
    saveMethod: 'Setup.saveAuthentication',
    registryKey: 'authenticationData',
    
    /**
     * @private
     * field index counter
     */
    tabIndexCounter: 1,
    
    /**
     * @private
     */
    initComponent: function () {
        this.idPrefix                   = Ext.id();
        this.authProviderIdPrefix       = this.idPrefix + '-authProvider-';
        this.accountsStorageIdPrefix    = this.idPrefix + '-accountsStorage-';
        this.originalAccountsStorage    = (Tine.Setup.registry.get(this.registryKey).accounts) ? Tine.Setup.registry.get(this.registryKey).accounts.backend : 'Sql';
        
        Tine.Setup.AuthenticationPanel.superclass.initComponent.call(this);
    },
    
    /**
     * Change card layout depending on selected combo box entry
     */
    onChangeAuthProvider: function () {
        var authProvider = this.authenticationBackendCombo.getValue();
        
        var cardLayout = Ext.getCmp(this.authProviderIdPrefix + 'CardLayout').getLayout();
        cardLayout.setActiveItem(this.authProviderIdPrefix + authProvider);
    },
    
    /**
     * Change card layout depending on selected combo box entry
     */
    onChangeAccountsStorage: function () {
        var AccountsStorage = this.accountsStorageCombo.getValue();

        if ((AccountsStorage === 'Ldap' || AccountsStorage === 'ActiveDirectory') && AccountsStorage !== this.originalAccountsStorage) {
            Ext.Msg.confirm(this.app.i18n._('Delete all existing users and groups'), this.app.i18n._('Switching from SQL to LDAP will delete all existing User Accounts, Groups and Roles. Do you really want to switch the accounts storage backend to LDAP ?'), function (confirmbtn, value) {
                if (confirmbtn === 'yes') {
                    this.doOnChangeAccountsStorage(AccountsStorage);
                } else {
                    this.accountsStorageCombo.setValue(this.originalAccountsStorage);
                }
            }, this);
        } else {
            this.doOnChangeAccountsStorage(AccountsStorage);
        }
    },
    
    /**
     * Change card layout depending on selected combo box entry
     */
    doOnChangeAccountsStorage: function (AccountsStorage) {
        var cardLayout = Ext.getCmp(this.accountsStorageIdPrefix + 'CardLayout').getLayout();
        
        cardLayout.setActiveItem(this.accountsStorageIdPrefix + AccountsStorage);
        this.originalAccountsStorage = AccountsStorage;
    },
    
    /**
     * @private
     */
    onRender: function (ct, position) {
        Tine.Setup.AuthenticationPanel.superclass.onRender.call(this, ct, position);
        
        this.onChangeAuthProvider.defer(250, this);
        this.onChangeAccountsStorage.defer(250, this);
    },
        
    /**
     * transforms form data into a config object
     * 
     * @hack   smuggle termsAccept in 
     * @return {Object} configData
     */
    form2config: function () {
        var configData = this.supr().form2config.call(this);
        configData.acceptedTermsVersion = Tine.Setup.registry.get('acceptedTermsVersion');
        
        return configData;
    },
    
    /**
     * get tab index for field
     * 
     * @return {Integer}
     */
    getTabIndex: function () {
        return this.tabIndexCounter++;
    },
    
   /**
     * returns config manager form
     * 
     * @private
     * @return {Array} items
     */
    getFormItems: function () {
        var setupRequired = Tine.Setup.registry.get('setupRequired');
        
        // common config for all combos in this setup
        var commonComboConfig = {
            xtype: 'combo',
            listWidth: 300,
            mode: 'local',
            forceSelection: true,
            allowEmpty: false,
            triggerAction: 'all',
            editable: false,
            tabIndex: this.getTabIndex
        };
        
        this.authenticationBackendCombo = new Ext.form.ComboBox(Ext.applyIf({
            name: 'authentication_backend',
            fieldLabel: this.app.i18n._('Backend'),
            store: [['Sql', 'SQL'], ['Ldap', 'LDAP'], ['Imap', 'IMAP'], ['ModSsl', this.app.i18n._('TLS client certificate')]],
            value: 'Sql',
            width: 300,
            listeners: {
                scope: this,
                change: this.onChangeAuthProvider,
                select: this.onChangeAuthProvider
            }
        }, commonComboConfig));
            
        this.accountsStorageCombo = new Ext.form.ComboBox(Ext.applyIf({
            name: 'accounts_backend',
            fieldLabel: this.app.i18n._('Backend'),
            store: [['Sql', 'Sql'], ['Ldap', 'Ldap'], ['ActiveDirectory', 'ActiveDirectory']],
            value: 'Sql',
            width: 300,
            listeners: {
                scope: this,
                change: this.onChangeAccountsStorage,
                select: this.onChangeAccountsStorage
            }
        }, commonComboConfig));
        
        return [{
            xtype: 'fieldset',
            collapsible: true,
            collapsed: !setupRequired,
            autoHeight: true,
            title: this.app.i18n._('Initial Admin User'),
            items: [{
                layout: 'form',
                autoHeight: 'auto',
                border: false,
                defaults: {
                    width: 300,
                    xtype: 'textfield',
                    inputType: 'password',
                    tabIndex: this.getTabIndex
                },
                items: [{
                    name: 'authentication_Sql_adminLoginName',
                    fieldLabel: this.app.i18n._('Initial admin login name'),
                    inputType: 'text',
                    disabled: !setupRequired
                }, {
                    name: 'authentication_Sql_adminPassword',
                    fieldLabel: this.app.i18n._('Initial admin Password'),
                    disabled: !setupRequired
                }, {
                    name: 'authentication_Sql_adminPasswordConfirmation',
                    fieldLabel: this.app.i18n._('Password confirmation'),
                    disabled: !setupRequired
                }]
            }]
        }, {
            xtype: 'fieldset',
            collapsible: false,
            autoHeight: true,
            title: this.app.i18n._('Authentication provider'),
            items: [
                this.authenticationBackendCombo,
                {
                    id: this.authProviderIdPrefix + 'CardLayout',
                    layout: 'card',
                    activeItem: this.authProviderIdPrefix + 'Sql',
                    border: false,
                    defaults: {border: false},
                    items: [{
                        id: this.authProviderIdPrefix + 'Sql',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield',
                            tabIndex: this.getTabIndex
                        },
                        items: [
                            Ext.applyIf({
                                name: 'authentication_Sql_tryUsernameSplit',
                                fieldLabel: this.app.i18n._('Try to split username'),
                                store: [['1', this.app.i18n._('Yes')], ['0', this.app.i18n._('No')]],
                                value: '1'
                            }, commonComboConfig), 
                            Ext.applyIf({
                                name: 'authentication_Sql_accountCanonicalForm',
                                fieldLabel: this.app.i18n._('Account canonical form'),
                                store: [['2', 'ACCTNAME_FORM_USERNAME'], ['3', 'ACCTNAME_FORM_BACKSLASH'], ['4', 'ACCTNAME_FORM_PRINCIPAL']],
                                value: '2'
                            }, commonComboConfig), 
                            {
                                name: 'authentication_Sql_accountDomainName',
                                fieldLabel: this.app.i18n._('Account domain name')
                            }, {
                                name: 'authentication_Sql_accountDomainNameShort',
                                fieldLabel: this.app.i18n._('Account domain short name')
                            }
                        ]
                    }, {
                        id: this.authProviderIdPrefix + 'Ldap',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield',
                            tabIndex: this.getTabIndex
                        },
                        items: [{
                            name: 'authentication_Ldap_host',
                            fieldLabel: this.app.i18n._('Host')
                        }, {
                            name: 'authentication_Ldap_username',
                            fieldLabel: this.app.i18n._('Login name')
                        }, {
                            name: 'authentication_Ldap_password',
                            fieldLabel: this.app.i18n._('Password'),
                            inputType: 'password'
                        },
                        Ext.applyIf({
                            name: 'authentication_Ldap_bindRequiresDn',
                            fieldLabel: this.app.i18n._('Bind requires DN'),
                            store: [['1', this.app.i18n._('Yes')], ['0', this.app.i18n._('No')]],
                            value: '1'
                        }, commonComboConfig),
                        Ext.applyIf({
                            name: 'authentication_Ldap_useStartTls',
                            fieldLabel: this.app.i18n._('Start TLS'),
                            store: [['0', this.app.i18n._('No')], ['1', this.app.i18n._('Yes')]],
                            value: '0'
                        }, commonComboConfig),
                        Ext.applyIf({
                            name: 'authentication_Ldap_useSsl',
                            fieldLabel: this.app.i18n._('SSL'),
                            store: [['0', this.app.i18n._('No')], ['1', this.app.i18n._('Yes')]],
                            value: '0'
                        }, commonComboConfig),
                        {
                            name: 'authentication_Ldap_port',
                            fieldLabel: this.app.i18n._('Port')
                        },
                        {
                            name: 'authentication_Ldap_baseDn',
                            fieldLabel: this.app.i18n._('Base DN')
                        }, {
                            name: 'authentication_Ldap_accountFilterFormat',
                            fieldLabel: this.app.i18n._('Search filter')
                        }, 
                        Ext.applyIf({
                            name: 'authentication_Ldap_tryUsernameSplit',
                            fieldLabel: this.app.i18n._('Try to split username'),
                            store: [['1', this.app.i18n._('Yes')], ['0', this.app.i18n._('No')]],
                            value: '1'
                        }, commonComboConfig),
                        Ext.applyIf({
                            name: 'authentication_Ldap_accountCanonicalForm',
                            fieldLabel: this.app.i18n._('Account canonical form'),
                            store: [['2', 'ACCTNAME_FORM_USERNAME'], ['3', 'ACCTNAME_FORM_BACKSLASH'], ['4', 'ACCTNAME_FORM_PRINCIPAL']],
                            value: '2'
                        }, commonComboConfig), 
                        {
                            name: 'authentication_Ldap_accountDomainName',
                            fieldLabel: this.app.i18n._('Account domain name')
                        }, {
                            name: 'authentication_Ldap_accountDomainNameShort',
                            fieldLabel: this.app.i18n._('Account domain short name')
                        }]
                    }, {
                        id: this.authProviderIdPrefix + 'Imap',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield',
                            tabIndex: this.getTabIndex
                        },
                        items: [{
                            name: 'authentication_Imap_host',
                            fieldLabel: this.app.i18n._('Hostname')
                        }, {
                            name: 'authentication_Imap_port',
                            fieldLabel: this.app.i18n._('Port'),
                            xtype: 'numberfield'
                        }, 
                        Ext.applyIf({
                            fieldLabel: this.app.i18n._('Secure Connection'),
                            name: 'authentication_Imap_ssl',
                            store: [['none', this.app.i18n._('None')], ['tls', this.app.i18n._('TLS')], ['ssl', this.app.i18n._('SSL')]],
                            value: 'none'
                        }, commonComboConfig), 
                        {
                            name: 'authentication_Imap_domain',
                            fieldLabel: this.app.i18n._('Append domain to login name')
                        }
                        ]
                    }, {
                        id: this.authProviderIdPrefix + 'ModSsl',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield',
                            tabIndex: this.getTabIndex
                        },
                        items: [Ext.applyIf({
                            fieldLabel: this.app.i18n._('Certificate validation'),
                            name: 'authentication_ModSsl_validation',
                            store: [['Apache', 'Apache'], ['X509', 'X509'], ['ICPBrasil', 'ICP Brasil']],
                            value: 'Apache'
                        }, commonComboConfig),
                        Ext.applyIf({
                            name: 'authentication_ModSsl_tryUsernameSplit',
                            fieldLabel: this.app.i18n._('Try to split username'),
                            store: [['1', this.app.i18n._('Yes')], ['0', this.app.i18n._('No')]],
                            value: '1'
                        }, commonComboConfig), 
                        {
                            name: 'authentication_ModSsl_casfile',
                            fieldLabel: this.app.i18n._('CA file')
                        }, {
                            name: 'authentication_ModSsl_crlspath',
                            fieldLabel: this.app.i18n._('CRL directory')
                        }
                        ]
                    }]
                }
            ]
        }, {
            xtype: 'fieldset',
            collapsible: false,
            autoHeight: true,
            title: this.app.i18n._('Accounts storage'),
            items: [
                this.accountsStorageCombo,
                {
                    id: this.accountsStorageIdPrefix + 'CardLayout',
                    layout: 'card',
                    activeItem: this.accountsStorageIdPrefix + 'Sql',
                    border: false,
                    defaults: {
                        border: false
                    },
                    items: [{
                        id: this.accountsStorageIdPrefix + 'Sql',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield',
                            tabIndex: this.getTabIndex
                        },
                        items: [{
                            name: 'accounts_Sql_defaultUserGroupName',
                            fieldLabel: this.app.i18n._('Default user group name')
                        }, {
                            name: 'accounts_Sql_defaultAdminGroupName',
                            fieldLabel: this.app.i18n._('Default admin group name')
                        }]
                    },
                        this.getDirectoryOptions('Ldap', commonComboConfig),
                        this.getDirectoryOptions('ActiveDirectory', commonComboConfig)
                    ]
                }
            ]
          }, {
            xtype: 'fieldset',
            collapsible: false,
            autoHeight: true,
            title: this.app.i18n._('Login panel'),
            defaults: {
                width: 300,
                xtype: 'uxspinner',
                tabIndex: this.getTabIndex,
                strategy: {
                    xtype: 'number',
                    minValue: 0,
                    maxValue: 64
                },
                value: 0
            },
            items: [
            Ext.applyIf({
                name: 'saveusername_saveusername',
                fieldLabel: this.app.i18n._('Reuse last username logged'),
                store: [[1, this.app.i18n._('Yes')], [0, this.app.i18n._('No')]],
                value: 0
            }, commonComboConfig)
            ]
        }, {
            xtype: 'fieldset',
            collapsible: false,
            autoHeight: true,
            title: this.app.i18n._('Password Settings'),
            defaults: {
                width: 300,
                xtype: 'uxspinner',
                tabIndex: this.getTabIndex,
                strategy: {
                    xtype: 'number',
                    minValue: 0,
                    maxValue: 64
                },
                value: 0
            },
            items: [
            Ext.applyIf({
                name: 'password_changepw',
                fieldLabel: this.app.i18n._('User can change password'),
                store: [[1, this.app.i18n._('Yes')], [0, this.app.i18n._('No')]],
                value: 1
            }, commonComboConfig),
            Ext.applyIf({
                name: 'password_pwPolicyActive',
                fieldLabel: this.app.i18n._('Enable password policy'),
                store: [[1, this.app.i18n._('Yes')], [0, this.app.i18n._('No')]],
                value: 0
            }, commonComboConfig),
            Ext.applyIf({
                name: 'password_pwPolicyOnlyASCII',
                fieldLabel: this.app.i18n._('Only ASCII'),
                store: [[1, this.app.i18n._('Yes')], [0, this.app.i18n._('No')]],
                value: 0
            }, commonComboConfig), {
                name: 'password_pwPolicyMinLength',
                fieldLabel: this.app.i18n._('Minimum length')
            }, {
                name: 'password_pwPolicyMinWordChars',
                fieldLabel: this.app.i18n._('Minimum word chars')
            }, {
                name: 'password_pwPolicyMinUppercaseChars',
                fieldLabel: this.app.i18n._('Minimum uppercase chars')
            }, {
                name: 'password_pwPolicyMinSpecialChars',
                fieldLabel: this.app.i18n._('Minimum special chars')
            }, {
                name: 'password_pwPolicyMinNumbers',
                fieldLabel: this.app.i18n._('Minimum numbers')
            }, {
                name: 'password_pwPolicyChangeAfter',
                fieldLabel: this.app.i18n._('Change password after ... days'),
                strategy: {
                    xtype: 'number',
                    minValue: 0,
                    maxValue: 365
                },
            },
            Ext.applyIf({
                name: 'password_pwPolicyForbidUsername',
                fieldLabel: this.app.i18n._('Forbid part of username in password'),
                store: [[1, this.app.i18n._('Yes')], [0, this.app.i18n._('No')]],
                value: 0
            }, commonComboConfig)
            ]
        }, {
            xtype: 'fieldset',
            collapsible: false,
            autoHeight: true,
            title: this.app.i18n._('Redirect Settings'),
            defaults: {
                width: 300,
                xtype: 'textfield',
                tabIndex: this.getTabIndex
            },
            items: [{
                name: 'redirectSettings_redirectUrl',
                fieldLabel: this.app.i18n._('Redirect Url (redirect to login screen if empty)')
            }, 
            Ext.applyIf({
                name: 'redirectSettings_redirectAlways',
                fieldLabel: this.app.i18n._('Redirect Always (if No, only redirect after logout)'),
                store: [['1', this.app.i18n._('Yes')], ['0', this.app.i18n._('No')]],
                value: '0'
            }, commonComboConfig), 
            Ext.applyIf({
                name: 'redirectSettings_redirectToReferrer',
                fieldLabel: this.app.i18n._('Redirect to referring site, if exists'),
                store: [['1', this.app.i18n._('Yes')], ['0', this.app.i18n._('No')]],
                value: '0'
            }, commonComboConfig)]
        }];
    },
    
    /**
     * getDirectoryOptions
     * 
     * @param {String} type LDAP or ActiveDirectory
     * @param {Object} commonComboConfig
     */
    getDirectoryOptions: function(type, commonComboConfig)
    {
        return {
            id: this.accountsStorageIdPrefix + type,
            layout: 'form',
            autoHeight: 'auto',
            defaults: {
                width: 300,
                xtype: 'textfield',
                tabIndex: this.getTabIndex
            },
            items: [{
                name: 'accounts_' + type + '_host',
                fieldLabel: this.app.i18n._('Host')
            }, {
                name: 'accounts_' + type + '_username',
                fieldLabel: this.app.i18n._('Login name')
            }, {
                name: 'accounts_' + type + '_password',
                fieldLabel: this.app.i18n._('Password'),
                inputType: 'password'
            }, 
            Ext.applyIf({
                name: 'accounts_' + type + '_bindRequiresDn',
                fieldLabel: this.app.i18n._('Bind requires DN'),
                store: [['1', this.app.i18n._('Yes')], ['0', this.app.i18n._('No')]],
                value: '1'
            }, commonComboConfig),
            Ext.applyIf({
                name: 'accounts_' + type + '_useStartTls',
                fieldLabel: this.app.i18n._('Start TLS'),
                store: [['1', this.app.i18n._('Yes')], ['0', this.app.i18n._('No')]],
                value: '1'
            }, commonComboConfig),
            Ext.applyIf({
                name: 'accounts_' + type + '_useSsl',
                fieldLabel: this.app.i18n._('SSL'),
                store: [['0', this.app.i18n._('No')], ['1', this.app.i18n._('Yes')]],
                value: '0'
            }, commonComboConfig),
            {
                name: 'accounts_' + type + '_port',
                fieldLabel: this.app.i18n._('Port')
            },
            Ext.applyIf({
                hidden: type === 'ActiveDirectory' ,
                name: 'accounts_' + type + '_pwEncType',
                fieldLabel: this.app.i18n._('Password encoding'),
                store: [
                    ['des', this.app.i18n._('des')],
                    ['crypt', this.app.i18n._('crypt')],
                    ['blowfish_crypt', this.app.i18n._('blowfish_crypt')],
                    ['md5_crypt', this.app.i18n._('md5_crypt')],
                    ['ext_crypt', this.app.i18n._('ext_crypt')],
                    ['md5', this.app.i18n._('md5')],
                    ['smd5', this.app.i18n._('smd5')],
                    ['sha', this.app.i18n._('sha')],
                    ['ssha', this.app.i18n._('ssha')],
                    ['ntpassword', this.app.i18n._('ntpassword')],
                    ['plain', this.app.i18n._('plain')]
                ],
                value: 'ssha'
            }, commonComboConfig),
            {
                name: 'accounts_' + type + '_userDn',
                fieldLabel: this.app.i18n._('User DN')
            }, {
                name: 'accounts_' + type + '_userFilter',
                fieldLabel: this.app.i18n._('User Filter')
            }, 
            Ext.applyIf({
                name: 'accounts_' + type + '_userSearchScope',
                fieldLabel: this.app.i18n._('User Search Scope'),
                store: [['1', 'SEARCH_SCOPE_SUB'], ['2', 'SEARCH_SCOPE_ONE']],
                value: '1'
            }, commonComboConfig), 
            {
                name: 'accounts_' + type + '_groupsDn',
                fieldLabel: this.app.i18n._('Groups DN')
            }, {
                name: 'accounts_' + type + '_groupFilter',
                fieldLabel: this.app.i18n._('Group Filter')
            }, 
            Ext.applyIf({
                name: 'accounts_' + type + '_groupSearchScope',
                fieldLabel: this.app.i18n._('Group Search Scope'),
                store: [['1', 'SEARCH_SCOPE_SUB'], ['2', 'SEARCH_SCOPE_ONE']],
                value: '1'
            }, commonComboConfig), 
            Ext.applyIf({
                name: 'accounts_' + type + ((type === 'Ldap') ? '_useRfc2307bis' : '_useRfc2307'),
                fieldLabel: (type === 'Ldap') ? this.app.i18n._('Use Rfc 2307 bis') : this.app.i18n._('Maintain RFC 2307 attributes'),
                store: [['1', this.app.i18n._('Yes')], ['0', this.app.i18n._('No')]],
                value: '0'
            }, commonComboConfig), 
            {
                name: 'accounts_' + type + '_minUserId',
                fieldLabel: this.app.i18n._('Min User Id')
            }, {
                name: 'accounts_' + type + '_maxUserId',
                fieldLabel: this.app.i18n._('Max User Id')
            }, {
                name: 'accounts_' + type + '_minGroupId',
                fieldLabel: this.app.i18n._('Min Group Id')
            }, {
                name: 'accounts_' + type + '_maxGroupId',
                fieldLabel: this.app.i18n._('Max Group Id')
            },
            Ext.applyIf({
                name: 'accounts_' + type + '_groupUUIDAttribute',
                fieldLabel: this.app.i18n._('Group UUID Attribute name'),
                store: (type === 'ActiveDirectory' ? [['objectGUID', 'objectGUID']] : [['entryUUID', 'entryUUID'], ['gidNumber', 'gidNumber']])
            }, commonComboConfig),
            Ext.applyIf({
                name: 'accounts_' + type + '_userUUIDAttribute',
                fieldLabel: this.app.i18n._('User UUID Attribute name'),
                store: (type === 'ActiveDirectory' ? [['objectGUID', 'objectGUID']] : [['entryUUID', 'entryUUID'], ['uidNumber', 'uidNumber']])
            }, commonComboConfig),
            {
                name: 'accounts_' + type + '_defaultUserGroupName',
                fieldLabel: this.app.i18n._('Default user group name')
            }, {
                name: 'accounts_' + type + '_defaultAdminGroupName',
                fieldLabel: this.app.i18n._('Default admin group name')
            },
            Ext.applyIf({
                name: 'accounts_' + type + '_readonly',
                fieldLabel: this.app.i18n._('Readonly access'),
                store: [['0', this.app.i18n._('No')], ['1', this.app.i18n._('Yes')]],
                value: '0'
            }, commonComboConfig)]
        };
    },
    
    /**
     * applies registry state to this cmp
     */
    applyRegistryState: function () {
        this.action_saveConfig.setDisabled(false);
        
        if (Tine.Setup.registry.get('setupRequired')) {
            this.action_saveConfig.setText(this.app.i18n._('Save config and install'));
        } else {
            this.action_saveConfig.setText(this.app.i18n._('Save config'));
            this.getForm().findField('authentication_Sql_adminPassword').setDisabled(true);
            this.getForm().findField('authentication_Sql_adminPasswordConfirmation').setDisabled(true);
            this.getForm().findField('authentication_Sql_adminLoginName').setDisabled(true);
        }
    },
    
    /**
     * checks if form is valid
     * - password fields are equal
     * 
     * @return {Boolean}
     */
    isValid: function () {
        var form = this.getForm();

        var result = form.isValid();
        
        // check if passwords match
        if (this.authenticationBackendCombo.getValue() === 'Sql' && 
            form.findField('authentication_Sql_adminPassword') && 
            form.findField('authentication_Sql_adminPassword').getValue() !== form.findField('authentication_Sql_adminPasswordConfirmation').getValue()) 
        {
            form.markInvalid([{
                id: 'authentication_Sql_adminPasswordConfirmation',
                msg: this.app.i18n._("Passwords don't match")
            }]);
            result = false;
        }
        
        // check if initial username/passwords are set
        if (Tine.Setup.registry.get('setupRequired')
            && form.findField('authentication_Sql_adminLoginName')
            && ! form.findField('authentication_Sql_adminLoginName').disabled) 
        {
            if (Ext.isEmpty(form.findField('authentication_Sql_adminLoginName').getValue())) {
                form.markInvalid([{
                    id: 'authentication_Sql_adminLoginName',
                    msg: this.app.i18n._("Should not be empty")
                }]);
                result = false;
            }
            if (Ext.isEmpty(form.findField('authentication_Sql_adminPassword').getValue())) {
                form.markInvalid([{
                    id: 'authentication_Sql_adminPassword',
                    msg: this.app.i18n._("Should not be empty")
                }]);
                form.markInvalid([{
                    id: 'authentication_Sql_adminPasswordConfirmation',
                    msg: this.app.i18n._("Should not be empty")
                }]);
                result = false;
            }
        }
        
        if (this.accountsStorageCombo.getValue() === 'Sql' && 
               form.findField('accounts_Sql_defaultUserGroupName') && 
               Ext.isEmpty(form.findField('accounts_Sql_defaultUserGroupName').getValue())) 
          {
            form.markInvalid([{
                id: 'accounts_Sql_defaultUserGroupName',
                msg: this.app.i18n._("Should not be empty")
            }]);
            result = false;
        }
        
        if (this.accountsStorageCombo.getValue() === 'Sql' && 
            form.findField('accounts_Sql_defaultAdminGroupName') && 
            Ext.isEmpty(form.findField('accounts_Sql_defaultAdminGroupName').getValue())) 
        {
            form.markInvalid([{
                id: 'accounts_Sql_defaultAdminGroupName',
                msg: this.app.i18n._("Should not be empty")
            }]);
            result = false;
        }
        
        return result;
    }
});


/***/ }),

/***/ 797:
/***/ (function(module, exports) {

/*
 * Tine 2.0
 * 
 * @package     Setup
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Philipp Schüle <p.schuele@metaways.de>
 * @copyright   Copyright (c) 2009-2015 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */

/*global Ext, Tine*/

Ext.ns('Tine', 'Tine.Setup');
 
/**
 * Setup Email Config Manager
 * 
 * @namespace   Tine.Setup
 * @class       Tine.Setup.EmailPanel
 * @extends     Tine.Tinebase.widgets.form.ConfigPanel
 * 
 * <p>Email Config Panel</p>
 * <p><pre>
 * </pre></p>
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Philipp Schuele <p.schuele@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 * 
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Setup.EmailPanel
 */
Tine.Setup.EmailPanel = Ext.extend(Tine.Tinebase.widgets.form.ConfigPanel, {
    
    /**
     * @property idPrefix DOM Id prefix
     * @type String
     */
    idPrefix: null,
    
    /**
     * imapBackend DOM Id prefix
     * 
     * @property imapBackendIdPrefix
     * @type String
     */
    imapBackendIdPrefix: null,
    
    /**
     * combo box containing the imap backend selection
     * 
     * @property imapBackendCombo
     * @type Ext.form.ComboBox 
     */
    imapBackendCombo: null,

    /**
     * smtpBackend DOM Id prefix
     * 
     * @property smtpBackendIdPrefix
     * @type String
     */
    smtpBackendIdPrefix: null,
    
    /**
     * combo box containing the smtp backend selection
     * 
     * @property smtpBackendCombo
     * @type Ext.form.ComboBox 
     */
    smtpBackendCombo: null,

    /**
     * show type before db settings
     * @cfg {Boolean} showType
     */
    showType: false,
    
    /**
     * @private
     * panel cfg
     */
    saveMethod: 'Setup.saveEmailConfig',
    registryKey: 'emailData',
    
    defaults: {
        xtype: 'fieldset',
        autoHeight: 'auto',
        defaults: {width: 300}
    },
    
    /**
     * @private
     */
    initComponent: function () {
        this.idPrefix                  = Ext.id();
        this.imapBackendIdPrefix       = this.idPrefix + '-imapBackend-';
        this.smtpBackendIdPrefix       = this.idPrefix + '-smtpBackend-';

        Tine.Setup.EmailPanel.superclass.initComponent.call(this);
    },
    
    /**
     * Change IMAP card layout depending on selected combo box entry
     */
    onChangeImapBackend: function () {
        this.changeCard(this.imapBackendCombo, this.imapBackendIdPrefix);
    },

    /**
     * Change SMTP card layout depending on selected combo box entry
     */
    onChangeSmtpBackend: function () {
        this.changeCard(this.smtpBackendCombo, this.smtpBackendIdPrefix);
    },

    /**
     * @private
     */
    onRender: function (ct, position) {
        Tine.Setup.EmailPanel.superclass.onRender.call(this, ct, position);
        
        this.onChangeImapBackend.defer(250, this);
        this.onChangeSmtpBackend.defer(250, this);
    },
    
   /**
     * returns config manager form
     * 
     * @private
     * @return {Array} items
     */
    getFormItems: function () {
        
        var backendComboConfig = {
            xtype: 'combo',
            width: 300,
            listWidth: 300,
            mode: 'local',
            forceSelection: true,
            allowEmpty: false,
            triggerAction: 'all',
            editable: false,
            value: 'standard',
            fieldLabel: this.app.i18n._('Backend')
        };
        
        // imap combo
        backendComboConfig.store = [['standard', this.app.i18n._('Standard IMAP')], ['cyrus', 'Cyrus'], ['dovecot_imap', 'Dovecot MySQL'], ['dovecotcombined', 'Dovecot SQL (combined schema)'], ['ldap_univention', 'Univention']];
        backendComboConfig.name = 'imap_backend';
        backendComboConfig.listeners = {
            scope: this,
            change: this.onChangeImapBackend,
            select: this.onChangeImapBackend
        };
        this.imapBackendCombo = new Ext.form.ComboBox(backendComboConfig);
        
        // smtp combo
        backendComboConfig.store = [
            ['standard', this.app.i18n._('Standard SMTP')],
            ['postfix', 'Postfix MySQL'],
            ['postfixcombined', 'Postfix SQL (combined schema)'],
            ['postfixmultiinstance', 'Postfix SQL (multi instance)'],
            ['Ldapsmtpmail', 'Ldap (only mail attribute)'],
            ['ldapSmtpQmail', 'Postfix Ldap (qmail schema)'],
            ['ldap_univention', 'Univention']
        ];
        backendComboConfig.name = 'smtp_backend';
        backendComboConfig.listeners = {
            scope: this,
            change: this.onChangeSmtpBackend,
            select: this.onChangeSmtpBackend
        };
        this.smtpBackendCombo = new Ext.form.ComboBox(backendComboConfig);

        // use backend combo config as common combo config
        var commonComboConfig = backendComboConfig;
        delete commonComboConfig.listeners;
        
        return [{
            title: this.app.i18n._('Imap'),
            id: 'setup-imap-group',
            checkboxToggle: true,
            collapsed: true,
            items: [
                this.imapBackendCombo, 
                {
                    name: 'imap_host',
                    fieldLabel: this.app.i18n._('Hostname'),
                    xtype: 'textfield'
                }, /*{
                    name: 'imap_user',
                    fieldLabel: this.app.i18n._('Username'),
                    xtype: 'textfield'
                }, {
                    name: 'imap_password',
                    fieldLabel: this.app.i18n._('Password'),
                    xtype: 'textfield',
                    inputType: 'password'
                }, */{
                    name: 'imap_port',
                    fieldLabel: this.app.i18n._('Port'),
                    xtype: 'numberfield'
                }, 
                Ext.applyIf({
                    fieldLabel: this.app.i18n._('Secure Connection'),
                    name: 'imap_ssl',
                    value: 'none',
                    store: [['none', this.app.i18n._('None')], ['tls',  this.app.i18n._('TLS')], ['ssl',  this.app.i18n._('SSL')]]
                }, commonComboConfig), {
                    name: 'imap_verifyPeer',
                    fieldLabel: this.app.i18n._('Verify peer Certificate'),
                    checked: true,
                    xtype: 'checkbox'
                },
                Ext.applyIf({
                    name: 'imap_useSystemAccount',
                    fieldLabel: this.app.i18n._('Use system account'),
                    store: [[0, this.app.i18n._('No')], [1, this.app.i18n._('Yes')]],
                    value: 0
                }, commonComboConfig), 
                {
                    name: 'imap_domain',
                    fieldLabel: this.app.i18n._('Append domain to login name'),
                    xtype: 'textfield'
                }, {
                    // TODO disable imap_domain if this is checked
                    name: 'imap_useEmailAsUsername',
                    fieldLabel: this.app.i18n._('Use email address as login name'),
                    xtype: 'checkbox'
                }, {
                    id: this.imapBackendIdPrefix + 'CardLayout',
                    layout: 'card',
                    activeItem: this.imapBackendIdPrefix + 'standard',
                    border: false,
                    width: '100%',
                    defaults: {
                        border: false
                    },
                    items: [{
                        // nothing in here yet
                        id: this.imapBackendIdPrefix + 'standard',
                        layout: 'form',
                        items: []
                    }, {
                        // nothing in here yet
                        id: this.imapBackendIdPrefix + 'ldap_imap',
                        layout: 'form',
                        defaults: {
                            width: 300,
                            xtype: 'textfield'
                        },
                        items: []
                    }, {
                        // cyrus config options
                        id: this.imapBackendIdPrefix + 'cyrus',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield'
                        },
                        items: [{
                            name: 'imap_cyrus_admin',
                            fieldLabel: this.app.i18n._('Cyrus Admin')
                        }, {
                            name: 'imap_cyrus_password',
                            fieldLabel: this.app.i18n._('Cyrus Admin Password'),
                            inputType: 'password'
                        },
                        Ext.applyIf({
                                name: 'imap_cyrus_useProxyAuth',
                                fieldLabel: this.app.i18n._('Use proxy auth'),
                                store: [[0, this.app.i18n._('No')], [1, this.app.i18n._('Yes')]],
                                value: 0
                        }, commonComboConfig)]
                    }, {
                        // dovecot config options
                        id: this.imapBackendIdPrefix + 'dovecot_imap',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield'
                        },
                        items: this.getDbConfigFields('imap', 'dovecot').concat(this.getDovecotExtraConfig('imap'))
                    }, {
                        // dovecot combined with postfix config options
                        id: this.imapBackendIdPrefix + 'dovecotcombined',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield'
                        },
                        items: this.getDbAdapterField('imap', 'dovecotcombined').concat(this.getDbConfigFields('imap', 'dovecotcombined'))
                    }]
                }
            ]
        }, {
            title: this.app.i18n._('Smtp'),
            id: 'setup-smtp-group',
            checkboxToggle:true,
            collapsed: true,
            items: [
                this.smtpBackendCombo,
                {
                    name: 'smtp_hostname',
                    fieldLabel: this.app.i18n._('Hostname'),
                    xtype: 'textfield'
                }, {
                    name: 'smtp_port',
                    fieldLabel: this.app.i18n._('Port'),
                    xtype: 'numberfield'
                }, 
                Ext.applyIf({
                    fieldLabel: this.app.i18n._('Secure Connection'),
                    name: 'smtp_ssl',
                    value: 'none',
                    store: [['none', this.app.i18n._('None')], ['tls', this.app.i18n._('TLS')], ['ssl', this.app.i18n._('SSL')]]
                }, commonComboConfig), {
                    name: 'smtp_verifyPeer',
                    fieldLabel: this.app.i18n._('Verify peer Certificate'),
                    checked: true,
                    xtype: 'checkbox'
                },
                Ext.applyIf({
                    fieldLabel: this.app.i18n._('Authentication'),
                    name: 'smtp_auth',
                    value: 'login',
                    store: [['none', this.app.i18n._('None')], ['login', this.app.i18n._('Login')], ['plain', this.app.i18n._('Plain')]]
                }, commonComboConfig), 
                {
                    name: 'smtp_primarydomain',
                    fieldLabel: this.app.i18n._('Primary Domain'),
                    xtype: 'textfield'
                }, {
                    name: 'smtp_secondarydomains',
                    fieldLabel: this.app.i18n._('Secondary Domains (comma separated)'),
                    xtype: 'textfield'
                }, {
                    name: 'smtp_from',
                    fieldLabel: this.app.i18n._('Notifications service address'),
                    xtype: 'textfield'
                }, {
                    name: 'smtp_username',
                    fieldLabel: this.app.i18n._('Notification Username'),
                    xtype: 'textfield'
                }, {
                    name: 'smtp_password',
                    fieldLabel: this.app.i18n._('Notification Password'),
                    inputType: 'password',
                    xtype: 'textfield'
                }, {
                    name: 'smtp_name',
                    fieldLabel: this.app.i18n._('Notifications local client (hostname or IP address)'),
                    xtype: 'textfield',
                    value: 'localhost'
                }, {
                    id: this.smtpBackendIdPrefix + 'CardLayout',
                    layout: 'card',
                    activeItem: this.smtpBackendIdPrefix + 'standard',
                    border: false,
                    width: '100%',
                    defaults: {
                        border: false
                    },
                    items: [{
                        // nothing in here yet
                        id: this.smtpBackendIdPrefix + 'standard',
                        layout: 'form',
                        items: []
                    }, {
                        // nothing in here yet
                        id: this.smtpBackendIdPrefix + 'ldap_smtp_mail',
                        layout: 'form',
                        items: []
                    }, {
                        // postfix config options
                        id: this.smtpBackendIdPrefix + 'postfix',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield'
                        },
                        items: this.getDbConfigFields('smtp', 'postfix')
                    }, {
                        // postfix config options
                        id: this.smtpBackendIdPrefix + 'postfixmultiinstance',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield'
                        },
                        items: this.getDbConfigFields('smtp', 'postfixmultiinstance')
                    }, {
                        // postfix config options
                        id: this.smtpBackendIdPrefix + 'postfixcombined',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield'
                        },
                        items: []
                    }, {
                        // postfix config options
                        id: this.smtpBackendIdPrefix + 'ldap_smtp',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield'
                        },
                        items: []
                    }, {
                        // postfix ldap qmail user schema config options
                        id: this.smtpBackendIdPrefix + 'ldap_smtp_qmail',
                        layout: 'form',
                        autoHeight: 'auto',
                        defaults: {
                            width: 300,
                            xtype: 'textfield'
                        },
                        items: []
                    }]
                }
             ]
        }, {
            title: this.app.i18n._('SIEVE'),
            id: 'setup-sieve-group',
            checkboxToggle:true,
            collapsed: true,
            items: [{
                name: 'sieve_hostname',
                fieldLabel: this.app.i18n._('Hostname'),
                xtype: 'textfield'
            }, {
                name: 'sieve_port',
                fieldLabel: this.app.i18n._('Port'),
                xtype: 'numberfield'
            }, 
            Ext.applyIf({
                fieldLabel: this.app.i18n._('Secure Connection'),
                name: 'sieve_ssl',
                value: 'none',
                store: [['none', this.app.i18n._('None')], ['tls', this.app.i18n._('TLS')], ['ssl', this.app.i18n._('SSL')]]
            }, commonComboConfig)]
        }];
    },
    
    /**
     * applies registry state to this cmp
     */
    applyRegistryState: function () {
        this.action_saveConfig.setDisabled(!this.isValid());
    },
    
    /**
     * get db adapter field
     * 
     * @param {String} type1 (imap, smtp)
     * @param {String} type2 (dbmail, postfix, ...)
     * @return {Array}
     */
    getDbAdapterField: function (type1, type2) {
        var typeString = (this.showType) ? (Ext.util.Format.capitalize(type2) + ' ') : '';
        
        return [{
            name          : type1 + '_' + type2 + '_adapter',
            fieldLabel    : typeString + this.app.i18n._('Backend'),
            typeAhead     : false,
            triggerAction : 'all',
            lazyRender    : true,
            editable      : false,
            mode          : 'local',
            xtype         : 'combo',
            listWidth     : 300,
            value         : 'pdo_mysql',
            store: [
                ['pdo_mysql', 'MySQL'],
                ['pdo_pgsql', 'PostgreSQL']
            ]
        }];
    },
    
    /**
     * get db config fields
     * 
     * @param {String} type1 (imap, smtp)
     * @param {String} type2 (postfix, ...)
     * @return {Array}
     */
    getDbConfigFields: function (type1, type2) {
        var typeString = (this.showType) ? (Ext.util.Format.capitalize(type2) + ' ') : '';
        
        return [{
            name: type1 + '_' + type2 + '_host',
            fieldLabel: typeString + this.app.i18n._('MySql Hostname')
        }, {
            name: type1 + '_' + type2 + '_dbname',
            fieldLabel: typeString + this.app.i18n._('MySql Database')
        }, {
            name: type1 + '_' + type2 + '_username',
            fieldLabel: typeString + this.app.i18n._('MySql User')
        }, {
            name: type1 + '_' + type2 + '_password',
            fieldLabel: typeString + this.app.i18n._('MySql Password'),
            inputType: 'password'
        }, {
            name: type1 + '_' + type2 + '_port',
            fieldLabel: typeString + this.app.i18n._('MySql Port'),
            value: 3306
        }];
    },
    
    /**
     * get db config fields
     * 
     * @param {String} type1 (imap, smtp)
     * @return {Array}
     */
    getDovecotExtraConfig: function (type1) {
        var typeString = (this.showType) ? 'Dovecot ' : '';
        
        return [{
            name: type1 + '_dovecot_uid',
            fieldLabel: typeString + this.app.i18n._('User or UID')
        }, {
            name: type1 + '_dovecot_gid',
            fieldLabel: typeString + this.app.i18n._('Group or GID')
        }, {
            name: type1 + '_dovecot_home',
            fieldLabel: typeString + this.app.i18n._('Home Template')
        }, {
            fieldLabel: typeString + this.app.i18n._('Password Scheme'),
            name: type1 + '_dovecot_scheme',
            typeAhead     : false,
            triggerAction : 'all',
            lazyRender    : true,
            editable      : false,
            mode          : 'local',
            xtype: 'combo',
            listWidth: 300,
            value: 'SSHA256',
            store: [
                ['PLAIN-MD5',      this.app.i18n._('PLAIN-MD5')],
                ['MD5-CRYPT',    this.app.i18n._('MD5-CRYPT')],
                ['SHA',           this.app.i18n._('SHA1')],
                ['SHA256',       this.app.i18n._('SHA256')],
                ['SSHA256',      this.app.i18n._('SSHA256')],
                ['SHA512',       this.app.i18n._('SHA512')],
                ['SSHA512',       this.app.i18n._('SSHA512')],
                ['PLAIN',        this.app.i18n._('PLAIN')]
            ]
        }];
    }
});


/***/ }),

/***/ 798:
/***/ (function(module, exports, __webpack_require__) {

// style-loader: Adds some css to the DOM by adding a <style> tag

// load the styles
var content = __webpack_require__(799);
if(typeof content === 'string') content = [[module.i, content, '']];
// Prepare cssTransformation
var transform;

var options = {"hmr":true}
options.transform = transform
// add the styles to the DOM
var update = __webpack_require__(1)(content, options);
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
	// When the styles change, update the <style> tags
	if(!content.locals) {
		module.hot.accept("!!../../Tinebase/js/node_modules/css-loader/index.js!./Setup.css", function() {
			var newContent = require("!!../../Tinebase/js/node_modules/css-loader/index.js!./Setup.css");
			if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
			update(newContent);
		});
	}
	// When the module is disposed, remove the <style> tags
	module.hot.dispose(function() { update(); });
}

/***/ }),

/***/ 799:
/***/ (function(module, exports, __webpack_require__) {

exports = module.exports = __webpack_require__(0)(undefined);
// imports


// module
exports.push([module.i, "/*\n * Tine 2.0\n * \n * @package     Setup\n * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3\n * @author      Cornelius Weiss <c.weiss@metaways.de>\n * @copyright   Copyright (c) 2009-2018 Metaways Infosystems GmbH (http://www.metaways.de)\n */\n\n.setup_info {\n    background-image:url(" + __webpack_require__(47) + ") !important;\n}\n\n.setup_action_install {\n    background-image:url(" + __webpack_require__(35) + ") !important;\n}\n\n.setup_action_uninstall {\n    background-image:url(" + __webpack_require__(66) + ") !important;\n}\n\n.setup_action_update {\n    background-image:url(" + __webpack_require__(800) + ") !important;\n}\n\n.setup_checks_success {\n    background-image:url(" + __webpack_require__(48) + ") !important;\n}\n\n.setup_checks_fail {\n    background-image:url(" + __webpack_require__(67) + ") !important;\n}\n\n.setup_authentication_manager {\n    background-image:url(" + __webpack_require__(33) + ") !important;\n}\n\n.setup_config_manager {\n    background-image:url(" + __webpack_require__(12) + ") !important;\n}\n\n.setup_application_manager {\n    background-image:url(" + __webpack_require__(88) + ") !important;\n}\n\n.setup_action_save_config {\n    background-image:url(" + __webpack_require__(801) + ") !important;\n}\n\n.setup_action_download_config {\n    background-image:url(" + __webpack_require__(20) + ") !important;\n}\n\n.setup-envcheck-grid-status {\n    margin-top: -2px;\n    margin-bottom: -2px;\n    width: 18px;\n    height: 18px;\n}", ""]);

// exports


/***/ }),

/***/ 800:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M35.6,21c0-2.6-0.7-5.1-2-7.3s-3.1-4-5.3-5.3s-4.7-2-7.3-2s-5.1,0.7-7.3,2s-4,3.1-5.3,5.3s-2,4.7-2,7.3s0.7,5.1,2,7.3 s3.1,4,5.3,5.3s4.7,2,7.3,2s5.1-0.7,7.3-2s4-3.1,5.3-5.3S35.6,23.6,35.6,21z M38,21c0,3.1-0.8,5.9-2.3,8.5s-3.6,4.7-6.2,6.2 S24.1,38,21,38s-5.9-0.8-8.5-2.3s-4.7-3.6-6.2-6.2S4,24.1,4,21s0.8-5.9,2.3-8.5s3.6-4.7,6.2-6.2S17.9,4,21,4s5.9,0.8,8.5,2.3 s4.7,3.6,6.2,6.2S38,17.9,38,21z M20.8,14.3c-0.2,0-0.3,0.1-0.4,0.2l-8.8,8.8c-0.1,0.1-0.2,0.3-0.2,0.4s0.1,0.3,0.2,0.4l0.9,0.9 c0.1,0.1,0.3,0.2,0.4,0.2s0.3-0.1,0.4-0.2l7.4-7.4l7.4,7.4c0.1,0.1,0.3,0.2,0.4,0.2c0.2,0,0.3-0.1,0.4-0.2l0.9-0.9 c0.1-0.1,0.2-0.3,0.2-0.4s-0.1-0.3-0.2-0.4L21,14.5C21.1,14.4,20.9,14.3,20.8,14.3z'/%3E %3C/svg%3E\""

/***/ }),

/***/ 801:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M14.1,33h14.2v-7.1H14.1V33z M30.6,33H33V16.4c0-0.2-0.1-0.4-0.2-0.7c-0.1-0.3-0.2-0.5-0.4-0.6l-5.2-5.2 c-0.1-0.1-0.3-0.2-0.6-0.4c-0.3-0.1-0.5-0.2-0.7-0.2V17c0,0.5-0.2,0.9-0.5,1.3c-0.3,0.3-0.8,0.5-1.3,0.5H13.5 c-0.5,0-0.9-0.2-1.3-0.5c-0.3-0.3-0.5-0.8-0.5-1.3V9.4H9.4V33h2.4v-7.7c0-0.5,0.2-0.9,0.5-1.3c0.3-0.3,0.8-0.5,1.3-0.5h15.4 c0.5,0,0.9,0.2,1.3,0.5c0.3,0.3,0.5,0.8,0.5,1.3V33z M23.5,15.9V10c0-0.2-0.1-0.3-0.2-0.4c-0.1-0.1-0.3-0.2-0.4-0.2h-3.5 c-0.2,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.3-0.2,0.4v5.9c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h3.5c0.2,0,0.3-0.1,0.4-0.2 C23.5,16.2,23.5,16,23.5,15.9z M35.3,16.4v17.1c0,0.5-0.2,0.9-0.5,1.3c-0.3,0.3-0.8,0.5-1.3,0.5H8.8c-0.5,0-0.9-0.2-1.3-0.5 C7.2,34.5,7,34.1,7,33.6V8.8c0-0.5,0.2-0.9,0.5-1.3S8.3,7,8.8,7h17.1c0.5,0,1,0.1,1.6,0.4c0.6,0.2,1.1,0.5,1.4,0.9l5.2,5.2 c0.3,0.3,0.6,0.8,0.9,1.4S35.3,16,35.3,16.4z'/%3E %3C/svg%3E\""

/***/ }),

/***/ 88:
/***/ (function(module, exports) {

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M31.8,22h2.7c0.5,0,0.8-0.4,0.8-0.8v-8c0-0.5-0.4-0.8-0.8-0.8h-7.2v-1.8c0-1.9-1.6-3.5-3.5-3.5s-3.5,1.6-3.5,3.5v1.8h-7.2 c-0.5,0-0.8,0.4-0.8,0.8v7.2h-1.8c-1.9,0-3.5,1.6-3.5,3.5s1.6,3.5,3.5,3.5h1.8v7.2c0,0.5,0.4,0.8,0.8,0.8h8c0.5,0,0.8-0.4,0.8-0.8 v-2.7c0-1,0.8-1.8,1.8-1.8s1.8,0.8,1.8,1.8v2.7c0,0.5,0.4,0.8,0.8,0.8h8c0.5,0,0.8-0.4,0.8-0.8v-8c0-0.5-0.4-0.8-0.8-0.8h-2.7 c-1,0-1.8-0.8-1.8-1.8S30.8,22,31.8,22z'/%3E %3C/svg%3E\""

/***/ })

/******/ });
});