/*- * Copyright 2016 Vsevolod Stakhov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "lua_common.h" #include "lua_thread_pool.h" #include "utlist.h" /*** * @module rspamd_resolver * This module allows to resolve DNS names from LUA code. All resolving is executed * asynchronously. Here is an example of name resolution: * @example local function symbol_callback(task) local host = 'example.com' local function dns_cb(resolver, to_resolve, results, err, _, authenticated) if not results then rspamd_logger.infox('DNS resolving of %1 failed: %2', host, err) return end for _,r in ipairs(results) do -- r is of type rspamd{ip} here, but it can be converted to string rspamd_logger.infox('Resolved %1 to %2', host, tostring(r)) end end task:get_resolver():resolve_a({task = task, name = host, callback = dns_cb}) end */ static const gchar *M = "rspamd lua dns resolver"; /* Lua bindings */ LUA_FUNCTION_DEF (dns_resolver, init); LUA_FUNCTION_DEF (dns_resolver, resolve_a); LUA_FUNCTION_DEF (dns_resolver, resolve_ptr); LUA_FUNCTION_DEF (dns_resolver, resolve_txt); LUA_FUNCTION_DEF (dns_resolver, resolve_mx); LUA_FUNCTION_DEF (dns_resolver, resolve_ns); LUA_FUNCTION_DEF (dns_resolver, resolve); void lua_push_dns_reply (lua_State *L, const struct rdns_reply *reply); static const struct luaL_reg dns_resolverlib_f[] = { LUA_INTERFACE_DEF (dns_resolver, init), {NULL, NULL} }; static const struct luaL_reg dns_resolverlib_m[] = { LUA_INTERFACE_DEF (dns_resolver, resolve_a), LUA_INTERFACE_DEF (dns_resolver, resolve_ptr), LUA_INTERFACE_DEF (dns_resolver, resolve_txt), LUA_INTERFACE_DEF (dns_resolver, resolve_mx), LUA_INTERFACE_DEF (dns_resolver, resolve_ns), LUA_INTERFACE_DEF (dns_resolver, resolve), {"__tostring", rspamd_lua_class_tostring}, {NULL, NULL} }; struct rspamd_dns_resolver * lua_check_dns_resolver (lua_State * L, gint pos) { void *ud = rspamd_lua_check_udata (L, pos, "rspamd{resolver}"); luaL_argcheck (L, ud != NULL, pos, "'resolver' expected"); return ud ? *((struct rspamd_dns_resolver **)ud) : NULL; } struct lua_dns_cbdata { struct rspamd_task *task; rspamd_mempool_t *pool; struct rspamd_dns_resolver *resolver; gint cbref; gchar *to_resolve; gchar *user_str; struct rspamd_symcache_item *item; struct rspamd_async_session *s; }; static int lua_dns_get_type (lua_State *L, int argno) { int type = RDNS_REQUEST_A; const gchar *strtype; if (lua_type (L, argno) != LUA_TSTRING) { lua_pushvalue (L, argno); lua_gettable (L, lua_upvalueindex (1)); type = lua_tonumber (L, -1); lua_pop (L, 1); if (type == 0) { rspamd_lua_typerror (L, argno, "dns_request_type"); } } else { strtype = lua_tostring (L, argno); if (g_ascii_strcasecmp (strtype, "a") == 0) { type = RDNS_REQUEST_A; } else if (g_ascii_strcasecmp (strtype, "aaaa") == 0) { type = RDNS_REQUEST_AAAA; } else if (g_ascii_strcasecmp (strtype, "mx") == 0) { type = RDNS_REQUEST_MX; } else if (g_ascii_strcasecmp (strtype, "txt") == 0) { type = RDNS_REQUEST_TXT; } else if (g_ascii_strcasecmp (strtype, "ptr") == 0) { type = RDNS_REQUEST_PTR; } else if (g_ascii_strcasecmp (strtype, "soa") == 0) { type = RDNS_REQUEST_SOA; } else { msg_err ("bad DNS type: %s", strtype); } } return type; } static void lua_dns_resolver_callback (struct rdns_reply *reply, gpointer arg) { struct lua_dns_cbdata *cd = arg; struct rspamd_dns_resolver **presolver; lua_State *L; struct lua_callback_state cbs; rspamd_mempool_t *pool; gint err_idx; pool = cd->pool; lua_thread_pool_prepare_callback (cd->resolver->cfg->lua_thread_pool, &cbs); L = cbs.L; lua_pushcfunction (L, &rspamd_lua_traceback); err_idx = lua_gettop (L); lua_rawgeti (L, LUA_REGISTRYINDEX, cd->cbref); presolver = lua_newuserdata (L, sizeof (gpointer)); rspamd_lua_setclass (L, "rspamd{resolver}", -1); *presolver = cd->resolver; lua_pushstring (L, cd->to_resolve); lua_push_dns_reply (L, reply); /* * 1 - resolver * 2 - to_resolve * 3 - entries | nil * 4 - error | nil * 5 - user_str * 6 - reply->authenticated * 7 - server */ if (reply->code != RDNS_RC_NOERROR) { lua_pushnil (L); lua_pushstring (L, rdns_strerror (reply->code)); } if (cd->user_str != NULL) { lua_pushstring (L, cd->user_str); } else { lua_pushnil (L); } lua_pushboolean (L, reply->authenticated); const gchar *servname = rdns_request_get_server (reply->request); if (servname) { lua_pushstring (L, servname); } else { lua_pushnil (L); } if (cd->item) { /* We also need to restore the item in case there are some chains */ rspamd_symcache_set_cur_item (cd->task, cd->item); } if (lua_pcall (L, 7, 0, err_idx) != 0) { msg_err_pool_check ("call to dns callback failed: %s", lua_tostring (L, -1)); } lua_settop (L, err_idx - 1); /* Unref function */ luaL_unref (L, LUA_REGISTRYINDEX, cd->cbref); lua_thread_pool_restore_callback (&cbs); if (cd->item) { rspamd_symcache_item_async_dec_check (cd->task, cd->item, M); } if (!cd->pool) { g_free (cd->to_resolve); g_free (cd->user_str); g_free (cd); } } void lua_push_dns_reply (lua_State *L, const struct rdns_reply *reply) { gint i = 0, naddrs = 0; struct rdns_reply_entry *elt; rspamd_inet_addr_t *addr; if (reply->code == RDNS_RC_NOERROR) { LL_FOREACH (reply->entries, elt) { naddrs ++; } lua_createtable (L, naddrs, 0); LL_FOREACH (reply->entries, elt) { switch (elt->type) { case RDNS_REQUEST_A: addr = rspamd_inet_address_new (AF_INET, &elt->content.a.addr); rspamd_lua_ip_push (L, addr); rspamd_inet_address_free (addr); lua_rawseti (L, -2, ++i); break; case RDNS_REQUEST_AAAA: addr = rspamd_inet_address_new (AF_INET6, &elt->content.aaa.addr); rspamd_lua_ip_push (L, addr); rspamd_inet_address_free (addr); lua_rawseti (L, -2, ++i); break; case RDNS_REQUEST_NS: lua_pushstring (L, elt->content.ns.name); lua_rawseti (L, -2, ++i); break; case RDNS_REQUEST_PTR: lua_pushstring (L, elt->content.ptr.name); lua_rawseti (L, -2, ++i); break; case RDNS_REQUEST_TXT: case RDNS_REQUEST_SPF: lua_pushstring (L, elt->content.txt.data); lua_rawseti (L, -2, ++i); break; case RDNS_REQUEST_MX: /* mx['name'], mx['priority'] */ lua_createtable (L, 0, 2); rspamd_lua_table_set (L, "name", elt->content.mx.name); lua_pushstring (L, "priority"); lua_pushinteger (L, elt->content.mx.priority); lua_settable (L, -3); lua_rawseti (L, -2, ++i); break; case RDNS_REQUEST_SOA: lua_createtable (L, 0, 7); rspamd_lua_table_set (L, "ns", elt->content.soa.mname); rspamd_lua_table_set (L, "contact", elt->content.soa.admin); lua_pushstring (L, "serial"); lua_pushinteger (L, elt->content.soa.serial); lua_settable (L, -3); lua_pushstring (L, "refresh"); lua_pushinteger (L, elt->content.soa.refresh); lua_settable (L, -3); lua_pushstring (L, "retry"); lua_pushinteger (L, elt->content.soa.retry); lua_settable (L, -3); lua_pushstring (L, "expiry"); lua_pushinteger (L, elt->content.soa.expire); lua_settable (L, -3); /* Negative TTL */ lua_pushstring (L, "nx"); lua_pushinteger (L, elt->content.soa.minimum); lua_settable (L, -3); lua_rawseti (L, -2, ++i); break; default: continue; } } lua_pushnil (L); } } /*** * @function rspamd_resolver.init(ev_base, config) * @param {event_base} ev_base event base used for asynchronous events * @param {rspamd_config} config rspamd configuration parameters * @return {rspamd_resolver} new resolver object associated with the specified base */ static int lua_dns_resolver_init (lua_State *L) { struct rspamd_dns_resolver *resolver, **presolver; struct rspamd_config *cfg, **pcfg; struct ev_loop *base, **pbase; /* Check args */ pbase = rspamd_lua_check_udata (L, 1, "rspamd{ev_base}"); luaL_argcheck (L, pbase != NULL, 1, "'ev_base' expected"); base = pbase ? *(pbase) : NULL; pcfg = rspamd_lua_check_udata (L, 2, "rspamd{config}"); luaL_argcheck (L, pcfg != NULL, 2, "'config' expected"); cfg = pcfg ? *(pcfg) : NULL; if (base != NULL && cfg != NULL) { resolver = rspamd_dns_resolver_init (NULL, base, cfg); if (resolver) { presolver = lua_newuserdata (L, sizeof (gpointer)); rspamd_lua_setclass (L, "rspamd{resolver}", -1); *presolver = resolver; } else { lua_pushnil (L); } } else { lua_pushnil (L); } return 1; } static int lua_dns_resolver_resolve_common (lua_State *L, struct rspamd_dns_resolver *resolver, enum rdns_request_type type, int first) { LUA_TRACE_POINT; struct rspamd_async_session *session = NULL; rspamd_mempool_t *pool = NULL; const gchar *to_resolve = NULL, *user_str = NULL; struct lua_dns_cbdata *cbdata; gint cbref = -1, ret; struct rspamd_task *task = NULL; GError *err = NULL; gboolean forced = FALSE; struct rspamd_symcache_item *item = NULL; /* Check arguments */ if (!rspamd_lua_parse_table_arguments (L, first, &err, RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT, "session=U{session};mempool=U{mempool};*name=S;*callback=F;" "option=S;task=U{task};forced=B", &session, &pool, &to_resolve, &cbref, &user_str, &task, &forced)) { if (err) { ret = luaL_error (L, "invalid arguments: %s", err->message); g_error_free (err); return ret; } return luaL_error (L, "invalid arguments"); } if (task) { pool = task->task_pool; session = task->s; item = rspamd_symcache_get_cur_item (task); } if (to_resolve != NULL) { if (pool != NULL) { cbdata = rspamd_mempool_alloc0 (pool, sizeof (struct lua_dns_cbdata)); cbdata->user_str = rspamd_mempool_strdup (pool, user_str); if (type != RDNS_REQUEST_PTR) { cbdata->to_resolve = rspamd_mempool_strdup (pool, to_resolve); } else { char *ptr_str; ptr_str = rdns_generate_ptr_from_str (to_resolve); if (ptr_str == NULL) { msg_err_task_check ("wrong resolve string to PTR request: %s", to_resolve); goto err; } cbdata->to_resolve = rspamd_mempool_strdup (pool, ptr_str); to_resolve = cbdata->to_resolve; free (ptr_str); } } else { cbdata = g_malloc0 (sizeof (struct lua_dns_cbdata)); cbdata->user_str = user_str ? g_strdup (user_str) : NULL; if (type != RDNS_REQUEST_PTR) { cbdata->to_resolve = g_strdup (to_resolve); } else { char *ptr_str; ptr_str = rdns_generate_ptr_from_str (to_resolve); if (ptr_str == NULL) { msg_err_task_check ("wrong resolve string to PTR request: %s", to_resolve); goto err; } cbdata->to_resolve = g_strdup (ptr_str); free (ptr_str); } } cbdata->resolver = resolver; cbdata->cbref = cbref; cbdata->task = task; cbdata->pool = pool; if (task == NULL) { if (rspamd_dns_resolver_request (resolver, session, pool, lua_dns_resolver_callback, cbdata, type, to_resolve)) { lua_pushboolean (L, TRUE); if (session) { cbdata->s = session; } } else { goto err; } } else { /* Fail-safety as this function can, in theory, call * lua_dns_resolver_callback without switching to the event loop */ if (item) { rspamd_symcache_item_async_inc (task, item, M); } if (forced) { ret = rspamd_dns_resolver_request_task_forced (task, lua_dns_resolver_callback, cbdata, type, to_resolve); } else { ret = rspamd_dns_resolver_request_task (task, lua_dns_resolver_callback, cbdata, type, to_resolve); } if (ret) { cbdata->s = session; if (item) { cbdata->item = item; rspamd_symcache_item_async_inc (task, item, M); } /* callback was set up */ lua_pushboolean (L, TRUE); } else { if (item) { rspamd_symcache_item_async_dec_check (task, item, M); } goto err; } if (item) { rspamd_symcache_item_async_dec_check (task, item, M); } } } else { return luaL_error (L, "invalid arguments to lua_resolve"); } return 1; err: if (!pool) { /* Free resources */ g_free (cbdata->to_resolve); g_free (cbdata->user_str); } /* Callback is not called in this case */ if (cbdata->cbref != -1) { luaL_unref (L, LUA_REGISTRYINDEX, cbdata->cbref); } lua_pushnil (L); return 1; } /*** * @method resolver:resolve_a(table) * Resolve A record for a specified host. * Table elements: * * `task` - task element (preferred, required to track dependencies) -or- * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`) * * `mempool` - pool memory pool for storing intermediate data * * `name` - host name to resolve * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)` * * `forced` - true if needed to override notmal limit for DNS requests * @return {boolean} `true` if DNS request has been scheduled */ static int lua_dns_resolver_resolve_a (lua_State *L) { struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1); if (dns_resolver) { return lua_dns_resolver_resolve_common (L, dns_resolver, RDNS_REQUEST_A, 2); } else { lua_pushnil (L); } return 1; } /*** * @method resolver:resolve_ptr(table) * Resolve PTR record for a specified host. * Table elements: * * `task` - task element (preferred, required to track dependencies) -or- * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`) * * `mempool` - pool memory pool for storing intermediate data * * `name` - host name to resolve * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)` * * `forced` - true if needed to override notmal limit for DNS requests * @return {boolean} `true` if DNS request has been scheduled */ static int lua_dns_resolver_resolve_ptr (lua_State *L) { struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1); if (dns_resolver) { return lua_dns_resolver_resolve_common (L, dns_resolver, RDNS_REQUEST_PTR, 2); } else { lua_pushnil (L); } return 1; } /*** * @method resolver:resolve_txt(table) * Resolve TXT record for a specified host. * Table elements: * * `task` - task element (preferred, required to track dependencies) -or- * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`) * * `mempool` - pool memory pool for storing intermediate data * * `name` - host name to resolve * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)` * * `forced` - true if needed to override notmal limit for DNS requests * @return {boolean} `true` if DNS request has been scheduled */ static int lua_dns_resolver_resolve_txt (lua_State *L) { struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1); if (dns_resolver) { return lua_dns_resolver_resolve_common (L, dns_resolver, RDNS_REQUEST_TXT, 2); } else { lua_pushnil (L); } return 1; } /*** * @method resolver:resolve_mx(table) * Resolve MX record for a specified host. * Table elements: * * `task` - task element (preferred, required to track dependencies) -or- * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`) * * `mempool` - pool memory pool for storing intermediate data * * `name` - host name to resolve * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)` * * `forced` - true if needed to override notmal limit for DNS requests * @return {boolean} `true` if DNS request has been scheduled */ static int lua_dns_resolver_resolve_mx (lua_State *L) { struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1); if (dns_resolver) { return lua_dns_resolver_resolve_common (L, dns_resolver, RDNS_REQUEST_MX, 2); } else { lua_pushnil (L); } return 1; } /*** * @method resolver:resolve_ns(table) * Resolve NS records for a specified host. * Table elements: * * `task` - task element (preferred, required to track dependencies) -or- * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`) * * `mempool` - pool memory pool for storing intermediate data * * `name` - host name to resolve * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)` * * `forced` - true if needed to override notmal limit for DNS requests * @return {boolean} `true` if DNS request has been scheduled */ static int lua_dns_resolver_resolve_ns (lua_State *L) { struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1); if (dns_resolver) { return lua_dns_resolver_resolve_common (L, dns_resolver, RDNS_REQUEST_NS, 2); } else { lua_pushnil (L); } return 1; } /* XXX: broken currently */ static int lua_dns_resolver_resolve (lua_State *L) { struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1); int type; type = lua_dns_get_type (L, 2); if (dns_resolver && type != 0) { return lua_dns_resolver_resolve_common (L, dns_resolver, type, 3); } else { lua_pushnil (L); } return 1; } static gint lua_load_dns_resolver (lua_State *L) { lua_newtable (L); luaL_register (L, NULL, dns_resolverlib_f); return 1; } void luaopen_dns_resolver (lua_State * L) { rspamd_lua_new_class (L, "rspamd{resolver}", dns_resolverlib_m); { LUA_ENUM (L, DNS_A, RDNS_REQUEST_A); LUA_ENUM (L, DNS_PTR, RDNS_REQUEST_PTR); LUA_ENUM (L, DNS_MX, RDNS_REQUEST_MX); LUA_ENUM (L, DNS_TXT, RDNS_REQUEST_TXT); LUA_ENUM (L, DNS_SRV, RDNS_REQUEST_SRV); LUA_ENUM (L, DNS_SPF, RDNS_REQUEST_SPF); LUA_ENUM (L, DNS_AAAA, RDNS_REQUEST_AAAA); LUA_ENUM (L, DNS_SOA, RDNS_REQUEST_SOA); } lua_pop (L, 1); rspamd_lua_add_preload (L, "rspamd_resolver", lua_load_dns_resolver); } /47910/stable30 Nextcloud server, a safe home for all your data: https://github.com/nextcloud/serverwww-data
summaryrefslogtreecommitdiffstats
path: root/l10n/de/files_external.po
blob: ba73042a79f05dcaef5aa640d8457372f9e57292 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# 
# Translators:
# arkascha <foss@christian-reiner.info>, 2013
msgid ""
msgstr ""
"Project-Id-Version: ownCloud\n"
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
"POT-Creation-Date: 2013-06-09 01:58+0200\n"
"PO-Revision-Date: 2013-06-08 23:18+0000\n"
"Last-Translator: Mirodin <blobbyjj@ymail.com>\n"
"Language-Team: German <translations@owncloud.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: js/dropbox.js:7 js/dropbox.js:28 js/google.js:16 js/google.js:34
msgid "Access granted"
msgstr "Zugriff gestattet"

#: js/dropbox.js:30 js/dropbox.js:96 js/dropbox.js:102
msgid "Error configuring Dropbox storage"
msgstr "Fehler beim Einrichten von Dropbox"

#: js/dropbox.js:65 js/google.js:66
msgid "Grant access"
msgstr "Zugriff gestatten"

#: js/dropbox.js:101
msgid "Please provide a valid Dropbox app key and secret."
msgstr "Bitte trage einen gültigen Dropbox-App-Key mit Secret ein."

#: js/google.js:36 js/google.js:93
msgid "Error configuring Google Drive storage"
msgstr "Fehler beim Einrichten von Google Drive"

#: lib/config.php:431
msgid ""
"<b>Warning:</b> \"smbclient\" is not installed. Mounting of CIFS/SMB shares "
"is not possible. Please ask your system administrator to install it."
msgstr "<b>Warnung:</b> \"smbclient\" ist nicht installiert. Das Einhängen von CIFS/SMB-Freigaben ist nicht möglich. Bitte Deinen System-Administrator, dies zu installieren."

#: lib/config.php:434
msgid ""
"<b>Warning:</b> The FTP support in PHP is not enabled or installed. Mounting"
" of FTP shares is not possible. Please ask your system administrator to "
"install it."
msgstr "<b>Warnung::</b> Die FTP Unterstützung  von PHP ist nicht aktiviert oder installiert. Bitte wende Dich an Deinen Systemadministrator."

#: lib/config.php:437
msgid ""
"<b>Warning:</b> The Curl support in PHP is not enabled or installed. "
"Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask "
"your system administrator to install it."
msgstr "<b>Warnung:</b> Die Curl-Unterstützung in PHP ist nicht aktiviert oder installiert. Das Einbinden von ownCloud / WebDav der GoogleDrive-Freigaben ist nicht möglich. Bitte Deinen Systemadminstrator um die Installation. "

#: templates/settings.php:3
msgid "External Storage"
msgstr "Externer Speicher"

#: templates/settings.php:9 templates/settings.php:28
msgid "Folder name"
msgstr "Ordnername"

#: templates/settings.php:10
msgid "External storage"
msgstr "Externer Speicher"

#: templates/settings.php:11
msgid "Configuration"
msgstr "Konfiguration"

#: templates/settings.php:12
msgid "Options"
msgstr "Optionen"

#: templates/settings.php:13
msgid "Applicable"
msgstr "Zutreffend"

#: templates/settings.php:33
msgid "Add storage"
msgstr "Speicher hinzufügen"

#: templates/settings.php:90
msgid "None set"
msgstr "Nicht definiert"

#: templates/settings.php:91
msgid "All Users"
msgstr "Alle Benutzer"

#: templates/settings.php:92
msgid "Groups"
msgstr "Gruppen"

#: templates/settings.php:100
msgid "Users"
msgstr "Benutzer"

#: templates/settings.php:113 templates/settings.php:114
#: templates/settings.php:149 templates/settings.php:150
msgid "Delete"
msgstr "Löschen"

#: templates/settings.php:129
msgid "Enable User External Storage"
msgstr "Externen Speicher für Benutzer aktivieren"

#: templates/settings.php:130
msgid "Allow users to mount their own external storage"
msgstr "Erlaubt Benutzern ihre eigenen externen Speicher einzubinden"

#: templates/settings.php:141
msgid "SSL root certificates"
msgstr "SSL-Root-Zertifikate"

#: templates/settings.php:159
msgid "Import Root Certificate"
msgstr "Root-Zertifikate importieren"