').text(s == null ? '' : String(s)).html();
+ }
+
+ disableButtons(true);
+ // Client-side table: the rows come from the same whitelisted payload
+ // the admin JSON route serves (see HostManagement::getPendingAgentList),
+ // fetched once and paged in the browser. There is no server-side
+ // listem() for this class on purpose -- its rows carry key material.
+ var table = $('#dataTable').registerTable(onSelect, {
+ order: [
+ [6, 'desc']
+ ],
+ columns: [
+ {data: 'hostname'},
+ {data: 'reason'},
+ {data: 'os'},
+ {data: 'agentVersion'},
+ {data: 'remoteIP'},
+ {data: 'identity'},
+ {data: 'created'}
+ ],
+ columnDefs: [
+ {
+ // A request bound to an existing host links to it; an
+ // unknown machine shows only the name it reported.
+ render: function (data, type, row) {
+ if (type !== 'display') {
+ return data;
+ }
+ if (row.hostID > 0) {
+ return '
' + esc(data) + '';
+ }
+ return esc(data);
+ },
+ targets: 0
+ },
+ {
+ render: function (data, type, row) {
+ return esc(data) + (row.arch ? '/' + esc(row.arch) : '');
+ },
+ targets: 2
+ },
+ {
+ // What the machine said it is. The serial is what an admin
+ // can check against a label; the UUID is what the server
+ // matched on.
+ render: function (data, type) {
+ var id = data || {};
+ if (type !== 'display') {
+ return (id.system_serial || '') + ' ' + (id.system_uuid || '');
+ }
+ var parts = [];
+ if (id.system_serial) {
+ parts.push(esc(id.system_serial));
+ }
+ if (id.system_uuid) {
+ parts.push('
' + esc(id.system_uuid) + '');
+ }
+ return parts.join('
');
+ },
+ targets: 5
+ }
+ ],
+ rowId: 'id',
+ processing: true,
+ serverSide: false,
+ ajax: {
+ url: '../management/index.php?node='
+ + Common.node
+ + '&sub=getPendingAgentList',
+ type: 'post'
+ }
+ });
+
+ if (Common.search && Common.search.length > 0) {
+ table.search(Common.search).draw();
+ }
+
+ function decide (which, modal, button) {
+ disableButtons(true);
+ var opts = {pending: $.getSelectedIds(table)};
+ opts[which] = 1;
+ $.apiCall(method, action, opts, function(err) {
+ modal.modal('hide');
+ disableButtons(false);
+ // Redraw whatever happened: a partial failure has still
+ // decided some rows, and the error toast names the rest.
+ table.ajax.reload(null, false);
+ });
+ button.prop('disabled', false);
+ }
+
+ approveSelected.on('click', function() {
+ approveModal.modal('show');
+ });
+ confirmApprove.on('click', function() {
+ decide('approvepending', approveModal, confirmApprove);
+ });
+ denySelected.on('click', function() {
+ denyModal.modal('show');
+ });
+ confirmDeny.on('click', function() {
+ decide('denypending', denyModal, confirmDeny);
+ });
+})(jQuery);
diff --git a/packages/web/management/js/fog/printer/fog.printer.export.js b/packages/web/management/js/fog/printer/fog.printer.export.js
index 8ead4332a1..506f796ace 100644
--- a/packages/web/management/js/fog/printer/fog.printer.export.js
+++ b/packages/web/management/js/fog/printer/fog.printer.export.js
@@ -8,10 +8,7 @@
{data: 'config'},
{data: 'configFile', visible: false},
{data: 'ip', visible: false},
- {data: 'pAnon2', visible: false},
- {data: 'pAnon3', visible: false},
- {data: 'pAnon4', visible: false},
- {data: 'pAnon5', visible: false},
+ {data: 'uri', visible: false},
{data: 'associations', visible: false}
]);
})(jQuery);
diff --git a/packages/web/management/js/fog/report/fog.report.file.js b/packages/web/management/js/fog/report/fog.report.file.js
index dd6ea30e2e..d512872f6d 100644
--- a/packages/web/management/js/fog/report/fog.report.file.js
+++ b/packages/web/management/js/fog/report/fog.report.file.js
@@ -373,6 +373,70 @@
}
});
break;
+ // Software Report
+ //
+ // Not serverSide, like the snapin and imaging reports above: the rows
+ // are the same bounded window the "range" fields on screen were drawn
+ // from, so paging them server side would be a second query answering
+ // a slightly different question. Every column is plain text -- the
+ // package id and install details are strings a plugin or an operator
+ // set -- so every column escapes.
+ case 'software report':
+ var softwareReportTable = $('#softwarereport-table'),
+ table = softwareReportTable.registerTable(null, {
+ order: [
+ [7, 'desc']
+ ],
+ buttons: reportFileButtons,
+ columns: [
+ {data: 'hostName', render: $.fn.dataTable.render.text()},
+ {data: 'softwareName', render: $.fn.dataTable.render.text()},
+ {data: 'package', render: $.fn.dataTable.render.text()},
+ {data: 'desired', render: $.fn.dataTable.render.text()},
+ {data: 'installed', render: $.fn.dataTable.render.text()},
+ {data: 'status', render: $.fn.dataTable.render.text()},
+ {data: 'code', render: $.fn.dataTable.render.text()},
+ {data: 'checked', render: $.fn.dataTable.render.text()}
+ ],
+ processing: true,
+ serverSide: false,
+ select: false,
+ ajax: {
+ url: windowedUrl(),
+ type: 'post'
+ }
+ });
+ break;
+ // Installed Software
+ //
+ // Not serverSide, same reasoning as software report above: reportRows()
+ // hands back a plain array with its own MAX_ROWS cap and no DataTables
+ // paging protocol, so there is no server-side page to ask for. No
+ // window either -- "currently installed" is a state, not a range -- but
+ // windowedUrl() is harmless with none of its params present and every
+ // other non-serverSide report here uses it, so this does too rather
+ // than being the one case with a hand-built URL.
+ case 'installed software':
+ var installedSoftwareTable = $('#installedsoftwarereport-table'),
+ table = installedSoftwareTable.registerTable(null, {
+ order: [
+ [2, 'desc']
+ ],
+ buttons: reportFileButtons,
+ columns: [
+ {data: 'name', render: $.fn.dataTable.render.text()},
+ {data: 'version', render: $.fn.dataTable.render.text()},
+ {data: 'hostCount', render: $.fn.dataTable.render.text()}
+ ],
+ processing: true,
+ serverSide: false,
+ select: false,
+ ajax: {
+ url: windowedUrl(),
+ type: 'post'
+ }
+ });
+ break;
// Fleet Report
//
// Ordered by the Days column DESCENDING, which is the report: the
diff --git a/packages/web/management/js/fog/service/fog.service.list.js b/packages/web/management/js/fog/service/fog.service.list.js
index 9a7d0027d4..2b44c4a702 100644
--- a/packages/web/management/js/fog/service/fog.service.list.js
+++ b/packages/web/management/js/fog/service/fog.service.list.js
@@ -6,9 +6,9 @@
// is needed here -- which also removes the old click/submit inconsistency
// that left the user-tracker form wired differently from the rest.
var services = [
- {btn: '#displaymanager-update', form: '#displaymanagerupdate-form'},
{btn: '#autologout-update', form: '#autologoutupdate-form'},
{btn: '#snapinclient-update', form: '#snapinclientupdate-form'},
+ {btn: '#software-update', form: '#softwareupdate-form'},
{btn: '#hostregister-update', form: '#hostregisterupdate-form'},
{btn: '#hostnamechanger-update', form: '#hostnamechangerupdate-form'},
{btn: '#printermanager-update', form: '#printermanagerupdate-form'},
diff --git a/packages/web/management/js/fog/snapin/fog.snapin.export.js b/packages/web/management/js/fog/snapin/fog.snapin.export.js
index 5c912770bb..5967c5a4c3 100644
--- a/packages/web/management/js/fog/snapin/fog.snapin.export.js
+++ b/packages/web/management/js/fog/snapin/fog.snapin.export.js
@@ -15,6 +15,7 @@
{data: 'toReplicate', visible: false},
{data: 'hide', visible: false},
{data: 'timeout', visible: false},
+ {data: 'returnCodes', visible: false},
{data: 'packtype', visible: false},
{data: 'hash', visible: false},
{data: 'size', visible: false},
diff --git a/packages/web/management/js/fog/software/fog.software.add.js b/packages/web/management/js/fog/software/fog.software.add.js
new file mode 100644
index 0000000000..eba7159648
--- /dev/null
+++ b/packages/web/management/js/fog/software/fog.software.add.js
@@ -0,0 +1,17 @@
+(function($) {
+ // Version policy select shows the pinned-version input only when
+ // "Pinned" is chosen; see fog.software.edit.js for the identical wiring
+ // on the General tab. Kept inline on each form rather than centralized
+ // in fog.common.js -- it is three lines and only ever wired here.
+ var createForm = $('#software-create-form');
+
+ function toggleVersionPolicy() {
+ var pinned = createForm.find('[name="versionPolicy"]').val() === 'pinned';
+ createForm.find('.softwareversion-pinned').toggleClass('d-none', !pinned);
+ }
+
+ toggleVersionPolicy();
+ createForm.on('change', '[name="versionPolicy"]', toggleVersionPolicy);
+
+ createForm.wireCreateForm();
+})(jQuery);
diff --git a/packages/web/management/js/fog/software/fog.software.edit.js b/packages/web/management/js/fog/software/fog.software.edit.js
new file mode 100644
index 0000000000..35ff8e4514
--- /dev/null
+++ b/packages/web/management/js/fog/software/fog.software.edit.js
@@ -0,0 +1,75 @@
+(function($) {
+ // ---------------------------------------------------------------
+ // GENERAL TAB
+ $.registerGeneralTab({
+ nameInputSel: '#software',
+ formSel: '#software-general-form'
+ });
+
+ // Version policy select shows the pinned-version input only when
+ // "Pinned" is chosen; see fog.software.add.js for the identical wiring
+ // on the create form.
+ var generalForm = $('#software-general-form');
+
+ function toggleVersionPolicy() {
+ var pinned = generalForm.find('[name="versionPolicy"]').val() === 'pinned';
+ generalForm.find('.softwareversion-pinned').toggleClass('d-none', !pinned);
+ }
+
+ toggleVersionPolicy();
+ generalForm.on('change', '[name="versionPolicy"]', toggleVersionPolicy);
+
+ // ASSOCIATIONS
+ // ---------------------------------------------------------------
+ // HOST TAB
+ var softwareHostsTable = $.registerAssociationTab({
+ slug: 'software-host',
+ item: 'host',
+ sub: 'getHostsList'
+ });
+
+ // ---------------------------------------------------------------
+ // STATUS TAB (read only)
+ var softwareStatusTable = $('#software-status-table').registerTable(null, {
+ columns: [
+ {data: 'hostLink'},
+ $.escapedColumn('installedVersion'),
+ $.escapedColumn('status'),
+ $.escapedColumn('return'),
+ $.escapedColumn('checked'),
+ {
+ data: 'details',
+ render: function(d, t) {
+ var full = d === null ? '' : String(d),
+ clipped = full.length > 200
+ ? full.slice(0, 200) + '…'
+ : full;
+ if (t !== 'display') {
+ return full;
+ }
+ return '
'
+ + $.escapeHtml(clipped)
+ + '';
+ }
+ }
+ ],
+ order: [
+ [4, 'desc']
+ ],
+ rowId: 'id',
+ processing: true,
+ serverSide: true,
+ select: false,
+ ajax: {
+ url: '../management/index.php?node='
+ + Common.node
+ + '&sub=getStatusList&id='
+ + Common.id,
+ type: 'post'
+ }
+ });
+
+ if (Common.search && Common.search.length > 0) {
+ softwareHostsTable.search(Common.search).draw();
+ }
+})(jQuery);
diff --git a/packages/web/management/js/fog/software/fog.software.list.js b/packages/web/management/js/fog/software/fog.software.list.js
new file mode 100644
index 0000000000..14892a4f22
--- /dev/null
+++ b/packages/web/management/js/fog/software/fog.software.list.js
@@ -0,0 +1,116 @@
+(function($) {
+ var deleteSelected = $('#deleteSelected'),
+ createnewBtn = $('#createnew'),
+ createnewModal = $('#createnewModal'),
+ createForm = $('#create-form'),
+ createnewSendBtn = $('#send');
+
+ // Backend labels are hardcoded rather than fetched, matching the design:
+ // one option today (Chocolatey), a second is a row here not a redesign.
+ var backendLabels = {choco: 'Chocolatey'};
+
+ function disableButtons(disable) {
+ deleteSelected.prop('disabled', disable);
+ }
+ function onSelect(selected) {
+ var disabled = selected.count() == 0;
+ disableButtons(disabled);
+ }
+
+ disableButtons(true);
+ var table = $('#dataTable').registerTable(onSelect, {
+ order: [
+ [0, 'asc']
+ ],
+ columns: [
+ {data: 'mainlink'},
+ {data: 'backend'},
+ {data: 'package'},
+ {data: 'version'},
+ {data: 'state'},
+ {data: 'isEnabled'}
+ ],
+ rowId: 'id',
+ columnDefs: [
+ {
+ responsivePriority: -1,
+ targets: 0
+ },
+ {
+ render: function(data, type, row) {
+ return backendLabels[data] || data;
+ },
+ targets: 1
+ },
+ {
+ // '' is any version, 'latest' tracks the source, anything
+ // else is a pinned version string shown as-is.
+ render: function(data, type, row) {
+ if (data === 'latest') {
+ return 'Latest';
+ }
+ if (!data) {
+ return 'Any';
+ }
+ return data;
+ },
+ targets: 3
+ },
+ {
+ render: function(data, type, row) {
+ return $.capitalizeFirstLetter(data || '');
+ },
+ targets: 4
+ },
+ {
+ responsivePriority: 0,
+ render: function(data, type, row) {
+ var enabled = '
';
+ var disabled = '
';
+ if (data > 0) {
+ return enabled;
+ } else {
+ return disabled;
+ }
+ },
+ targets: 5
+ }
+ ],
+ processing: true,
+ serverSide: true,
+ ajax: {
+ url: '../management/index.php?node='+Common.node+'&sub=list',
+ type: 'post'
+ }
+ });
+
+ if (Common.search && Common.search.length > 0) {
+ table.search(Common.search).draw();
+ }
+
+ createnewModal.registerModal(Common.createModalShow, Common.createModalHide);
+ createnewBtn.on('click', function(e) {
+ e.preventDefault();
+ createnewModal.modal('show');
+ });
+ createnewSendBtn.on('click', function(e) {
+ e.preventDefault();
+ createForm.processForm(function(err) {
+ if (err) {
+ return;
+ }
+ table.draw(false);
+ createnewModal.modal('hide');
+ });
+ });
+ deleteSelected.on('click', function() {
+ disableButtons(true);
+ $.deleteSelected(table, function(err) {
+ // if we couldn't delete the items, enable the buttons
+ // as the rows still exist and are selected.
+ if (err) {
+ disableButtons(false);
+ }
+ });
+ });
+})(jQuery);
diff --git a/packages/web/management/languages/de_DE.UTF-8/LC_MESSAGES/messages.po b/packages/web/management/languages/de_DE.UTF-8/LC_MESSAGES/messages.po
index ce9dae6243..15a7630238 100644
--- a/packages/web/management/languages/de_DE.UTF-8/LC_MESSAGES/messages.po
+++ b/packages/web/management/languages/de_DE.UTF-8/LC_MESSAGES/messages.po
@@ -120,6 +120,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -289,6 +293,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, fuzzy, php-format
+msgid "(deleted host %d)"
+msgstr "Ausgewählten MAcs freigeben"
+
msgid "(deleted user)"
msgstr ""
@@ -308,9 +316,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr "Kernel-Argumente"
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
#, fuzzy
msgid "1 Hour"
msgstr "1 Stunde"
@@ -415,6 +429,12 @@ msgstr "Ein Broadcast mit diesem Namen ist bereits vorhanden!"
msgid "A client ID is required"
msgstr "Ein Gruppenname ist erforderlich!"
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
#, fuzzy
msgid "A dmi field must be set!"
msgstr "Schlüsselfeldname muss eine Zeichenfolge sein."
@@ -478,6 +498,9 @@ msgstr "Dieser Benutzername ist bereits vorhanden!"
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
#, fuzzy
msgid "A module already exists with this name!"
msgstr "Eine Rolle mit diesem Namen ist bereits vorhanden!"
@@ -499,6 +522,9 @@ msgstr "Alle Regeln auflisten"
msgid "A permission name is required."
msgstr "Ein Gruppenname ist erforderlich!"
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -521,6 +547,9 @@ msgstr "Ein Drucker mit diesem Namen ist bereits vorhanden!"
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
#, fuzzy
msgid "A role already exists with this name!"
msgstr "Eine Rolle mit diesem Namen ist bereits vorhanden!"
@@ -562,6 +591,10 @@ msgstr "Ein Snapin mit diesem Namen ist bereits vorhanden!"
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+#, fuzzy
+msgid "A software entry already exists with this name!"
+msgstr "Dieser Benutzername ist bereits vorhanden!"
+
#, fuzzy
msgid "A storage group already exists with this name!"
msgstr "Ein Host mit diesem Namen ist bereits vorhanden!"
@@ -698,6 +731,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -928,6 +967,10 @@ msgstr "Standort hinzufügen fehlgeschlagen"
msgid "Add snapin failed!"
msgstr "Snapin hinzufügen fehlgeschlagen"
+#, fuzzy
+msgid "Add software failed!"
+msgstr "Hinzufügen eines Hosts fehlgeschlagen!"
+
#, fuzzy
msgid "Add storage node failed!"
msgstr "Hinzufügen eines Speicherknotens fehlgeschlagen!"
@@ -1012,6 +1055,33 @@ msgstr "Erweitert"
msgid "Advanced Tasks"
msgstr "Erweitert"
+msgid "Agent"
+msgstr ""
+
+#, fuzzy
+msgid "Agent Activity"
+msgstr "Aktiv"
+
+#, fuzzy
+msgid "Agent Approval Success"
+msgstr "Host erfolgreich erstellt"
+
+#, fuzzy
+msgid "Agent Denial Success"
+msgstr "Drucker aktualisiert!"
+
+#, fuzzy
+msgid "Agent Enrollment Tokens"
+msgstr "wurde abgebrochen"
+
+#, fuzzy
+msgid "Agent Tokens"
+msgstr "API-Zugangstoken"
+
+#, fuzzy
+msgid "Agent enrollment tokens"
+msgstr "wurde abgebrochen"
+
msgid "Ago must be boolean"
msgstr "Ago muss boolean sein"
@@ -1028,6 +1098,10 @@ msgstr ""
msgid "All Hosts"
msgstr "Alle Hosts"
+#, fuzzy
+msgid "All Pending Agents"
+msgstr "Ausstehende MACs"
+
#, fuzzy
msgid "All Pending Hosts"
msgstr "Ausstehende Hosts"
@@ -1131,10 +1205,16 @@ msgstr ""
msgid "An SQL error occurred"
msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
#, fuzzy
msgid "An entry already exists with this name!"
msgstr "Dieser Benutzername ist bereits vorhanden!"
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr "Ein Image mit diesem Namen ist bereits vorhanden!"
@@ -1174,6 +1254,10 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+#, fuzzy
+msgid "Any version"
+msgstr "Version"
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1212,18 +1296,36 @@ msgstr ""
msgid "Approve"
msgstr "freigeben"
+#, fuzzy
+msgid "Approve Agent Fail"
+msgstr "freigeben"
+
#, fuzzy
msgid "Approve MAC Fail"
msgstr "freigeben"
+#, fuzzy
+msgid "Approve Pending Agents"
+msgstr "Ausstehende Hosts"
+
#, fuzzy
msgid "Approve Pending Hosts"
msgstr "Ausstehende Hosts"
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
#, fuzzy
msgid "Approve selected"
msgstr "Ausgewählten MAcs freigeben"
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+#, fuzzy
+msgid "Approved selected agents!"
+msgstr "Ausgewählten MAcs freigeben"
+
#, fuzzy
msgid "Approved selected hosts!"
msgstr "Ausgewählten MAcs freigeben"
@@ -1236,6 +1338,9 @@ msgstr "Ausgewählten MAcs freigeben"
msgid "Approving the selected pending hosts."
msgstr "Ausgewählten MAcs freigeben"
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1245,6 +1350,10 @@ msgstr ""
msgid "Area"
msgstr ""
+#, fuzzy
+msgid "Assigned"
+msgstr "zugeordneter Host"
+
#, fuzzy
msgid "Assigned Group"
msgstr "Name der Speichergruppe"
@@ -1307,6 +1416,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1345,6 +1457,9 @@ msgstr "BIOS-Anbieter"
msgid "BIOS Version"
msgstr "BIOS-Version"
+msgid "Backend"
+msgstr ""
+
#, fuzzy
msgid "Bad request."
msgstr "%s ist erforderlich"
@@ -1578,6 +1693,10 @@ msgstr "Stornierter Task"
msgid "Canceled due to new tasking."
msgstr "Abgebrochen aufgrund neuer Aufgabe (Task)"
+#, fuzzy
+msgid "Cannot Run"
+msgstr "Datensatz wurde nicht gefunden, Fehler: %s"
+
#, fuzzy
msgid "Cannot bind to the LDAP server"
msgstr "Anmeldung am LDAP-Server nicht möglich"
@@ -1592,10 +1711,6 @@ msgstr "kann keine Verbindung aufbauen"
msgid "Cannot connect to database"
msgstr "Kann keine Verbindung zur Datenbank herstellen"
-#, fuzzy
-msgid "Cannot connect to ftp server"
-msgstr "Verbindung zum FTP-Server nicht möglich"
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1793,6 +1908,9 @@ msgstr "Keine FOGPage-Klasse für diesen Knoten gefunden"
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+msgid "Checked"
+msgstr ""
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1805,6 +1923,12 @@ msgstr "Prüfe, ob ich der Gruppenmanager bin"
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1976,14 +2100,23 @@ msgstr "Fehler: Herunterladen des Kernels fehlgeschlagen"
msgid "Confirm you would like to download a new kernel"
msgstr "Fehler: Herunterladen des Kernels fehlgeschlagen"
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
#, fuzzy
msgid "Copy from existing"
msgstr "Kopie von bereits existierenden"
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -2057,10 +2190,6 @@ msgstr "Tmp-Datei konnte nicht gelesen werden."
msgid "Could not read local file"
msgstr "Temporäre Datei konnte nicht gelesen werden."
-#, fuzzy
-msgid "Could not read snapin file"
-msgstr "Snapin-Datei konnte nicht gelesen werden."
-
#, fuzzy
msgid "Could not read the database structure"
msgstr "Erstellen eines Snapin-Jobs fehlgeschlagen"
@@ -2157,6 +2286,9 @@ msgstr ""
msgid "Create"
msgstr "Erstellen"
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -2239,6 +2371,10 @@ msgstr "Neue Sites erstellen"
msgid "Create New Snapin"
msgstr "Neue Snapin erstellen"
+#, fuzzy
+msgid "Create New Software"
+msgstr "Neue Sites erstellen"
+
msgid "Create New Storage Group"
msgstr "Neue Storage Group erstellen"
@@ -2286,6 +2422,10 @@ msgstr "Benutzer erfolgreich erstellt"
msgid "Create Users On First Login"
msgstr ""
+#, fuzzy, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr "Benutzer erfolgreich erstellt"
+
#, fuzzy, php-format
msgid "Create a %s"
msgstr "Neue %s erstellen"
@@ -2309,9 +2449,17 @@ msgstr "Benutzer erstellen fehlgeschlagen"
msgid "Create task form success"
msgstr "Benutzer erfolgreich erstellt"
+#, fuzzy
+msgid "Create tasking"
+msgstr "Neues Snapin erstellen"
+
msgid "Create tasking succeeded"
msgstr ""
+#, fuzzy
+msgid "Create token"
+msgstr "Neue %s erstellen"
+
#, fuzzy
msgid "Created"
msgstr "Erstellen"
@@ -2323,6 +2471,10 @@ msgstr "Erstellt von"
msgid "Created Time"
msgstr "Erstellt von"
+#, fuzzy
+msgid "Created by"
+msgstr "Erstellt von"
+
msgid "Created by FOG Reg on"
msgstr "Erstellt von FOG Reg am"
@@ -2451,6 +2603,9 @@ msgstr "Debug Optionen"
msgid "Debug Task"
msgstr "Debug"
+msgid "Decided."
+msgstr ""
+
msgid "Default"
msgstr "Standard"
@@ -2458,15 +2613,6 @@ msgstr "Standard"
msgid "Default Choice"
msgstr "Standard-Eintrag:"
-msgid "Default Height"
-msgstr "Standardhöhe"
-
-msgid "Default Refresh Rate"
-msgstr "Standard-Bildwiederholrate"
-
-msgid "Default Width"
-msgstr "Standardbreite"
-
#, fuzzy
msgid "Default init, ARM64"
msgstr "Standardbreite"
@@ -2551,6 +2697,28 @@ msgstr ""
msgid "Deleting remote file"
msgstr "Remotedatei wird gelöscht"
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+#, fuzzy
+msgid "Denied selected agents!"
+msgstr "Ausgewählten MAcs freigeben"
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy
+msgid "Deny Agent Fail"
+msgstr "Löschen fehlgeschlagen"
+
+#, fuzzy
+msgid "Deny Pending Agents"
+msgstr "Ausstehende MACs"
+
+#, fuzzy
+msgid "Deny selected"
+msgstr "Ausgewählte löschen"
+
msgid "Deploy"
msgstr "Verteilung"
@@ -2567,14 +2735,30 @@ msgstr ""
msgid "Description"
msgstr "Beschreibung"
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+msgid "Desired domain"
+msgstr ""
+
#, fuzzy
msgid "Destroy failed"
msgstr "Zerstörung fehlgeschlagen: %s"
+#, fuzzy
+msgid "Detail"
+msgstr "Details"
+
#, fuzzy
msgid "Details"
msgstr "Details"
+msgid "Device URI"
+msgstr ""
+
#, fuzzy
msgid "Device must be a string"
msgstr "Gerätename muss eine Zeichenfolge sein."
@@ -2588,9 +2772,6 @@ msgstr "Verzeichnis"
msgid "Directory Already Exists"
msgstr "Das Verzeichnis existiert bereits"
-msgid "Directory Cleaner"
-msgstr "Verzeichnis-Bereiniger"
-
#, fuzzy
msgid "Directory Group"
msgstr "Verzeichnis"
@@ -2599,6 +2780,10 @@ msgstr "Verzeichnis"
msgid "Directory Group Name"
msgstr "Verzeichnis"
+#, fuzzy
+msgid "Directory Membership"
+msgstr "Mitgliedschaft"
+
#, fuzzy
msgid "Disable on all hosts"
msgstr "Deaktiviert"
@@ -2715,6 +2900,9 @@ msgstr "Download fehlgeschlagen"
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2734,6 +2922,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr "Bearbeiten"
@@ -2830,6 +3021,10 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+#, fuzzy
+msgid "Enrollment Token"
+msgstr "Pushbullet Accounts"
+
msgid "Enrollment kit"
msgstr ""
@@ -2933,6 +3128,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
#, fuzzy
msgid "Every file was uploaded."
msgstr "Keine Datei wurde hochgeladen"
@@ -2953,6 +3154,14 @@ msgstr "Privater Schlüssel ist fehlgeschlagen"
msgid "Exists item must be boolean"
msgstr "Bestehendes Objekt muss boolean sein"
+#, fuzzy
+msgid "Exit Code"
+msgstr "Snapins exportieren"
+
+#, fuzzy
+msgid "Exit code"
+msgstr "Rückgabewert"
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -3032,9 +3241,32 @@ msgstr "Datenbank importieren"
msgid "External root CA"
msgstr ""
+#, fuzzy
+msgid "Extra arguments"
+msgstr "Snapin läuft mit Argument"
+
msgid "FOG"
msgstr "FOG"
+#, fuzzy
+msgid "FOG Agent capability result"
+msgstr "Keine Datei wurde hochgeladen"
+
+#, fuzzy
+msgid "FOG Agent certificate renewal"
+msgstr "Keine Datei wurde hochgeladen"
+
+#, fuzzy
+msgid "FOG Agent enrollment"
+msgstr "wurde abgebrochen"
+
+#, fuzzy
+msgid "FOG Agent payload"
+msgstr "Keine Datei wurde hochgeladen"
+
+msgid "FOG Agent poll"
+msgstr ""
+
#, fuzzy
msgid "FOG Client"
msgstr "FOG-Client-Wiki"
@@ -3393,6 +3625,9 @@ msgstr "Task gestartet"
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3735,6 +3970,10 @@ msgstr "Host Snapinverlauf"
msgid "Group Snapin History"
msgstr "Snapin-Verlauf"
+#, fuzzy
+msgid "Group Software Assignment"
+msgstr "Host Snapinverlauf"
+
#, fuzzy
msgid "Group Task History"
msgstr "Image-Verlauf"
@@ -3824,9 +4063,15 @@ msgstr "Hardwareinformationen"
msgid "Hardware Report"
msgstr "Hardwareinformationen"
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr "Hash"
+msgid "Hash Mismatch"
+msgstr ""
+
msgid "Have not locked the host for access"
msgstr ""
@@ -3834,10 +4079,6 @@ msgstr ""
msgid "Header is missing the required \"%s\" column"
msgstr ""
-#, fuzzy
-msgid "Height"
-msgstr "Mitternacht"
-
msgid "Height must be 120 pixels."
msgstr "Höhe muss 120 Pixel betragen"
@@ -3910,6 +4151,9 @@ msgstr "Dieser Host ist bereits vorhanden."
msgid "Host %1$s finished deploying image %2$s."
msgstr "Dieser Host ist bereits vorhanden."
+msgid "Host Agent Activity"
+msgstr ""
+
#, fuzzy
msgid "Host Approval Success"
msgstr "Host erfolgreich erstellt"
@@ -3945,10 +4189,6 @@ msgstr "Standard-Eintrag:"
msgid "Host Description"
msgstr "Host-Beschreibung"
-#, fuzzy
-msgid "Host Display Manager Settings"
-msgstr "iPXE Menüeinstellungen"
-
msgid "Host EFI Exit Type"
msgstr "Host-EFI-Exit-Typ"
@@ -4053,10 +4293,6 @@ msgstr "Host-Produkt-Schlüssel"
msgid "Host Registration"
msgstr "Host-Registrierung"
-#, fuzzy
-msgid "Host Screen Resolution"
-msgstr "Host-Registrierung"
-
#, fuzzy
msgid "Host Snapin Associations"
msgstr "zugeordneter Host"
@@ -4065,6 +4301,13 @@ msgstr "zugeordneter Host"
msgid "Host Snapin History"
msgstr "Host Snapinverlauf"
+#, fuzzy
+msgid "Host Software Assignment"
+msgstr "Host Snapinverlauf"
+
+msgid "Host Software Status"
+msgstr ""
+
#, fuzzy
msgid "Host Task History"
msgstr "Image-Verlauf"
@@ -4158,6 +4401,12 @@ msgstr "Host Init"
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
#, fuzzy
msgid "Hosts:"
msgstr "Hosts"
@@ -4222,6 +4471,10 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+#, fuzzy
+msgid "Identity"
+msgstr "Server-Shell"
+
msgid "Identity Provider"
msgstr ""
@@ -4737,6 +4990,10 @@ msgstr "Installierte Plugins"
msgid "Installed Plugins"
msgstr "Installierte Plugins"
+#, fuzzy
+msgid "Installed Software"
+msgstr "Installierte Plugins"
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4823,9 +5080,6 @@ msgstr "Ungültiges Snapin-Tasking-Objekt"
msgid "Invalid Storage Group"
msgstr "Ungültige Speichergruppe"
-msgid "Invalid Storage Node"
-msgstr "Ungültiger Speicherknoten"
-
#, fuzzy
msgid "Invalid Tasking"
msgstr "Ungültiger Vorgang"
@@ -5009,6 +5263,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -5034,6 +5291,9 @@ msgstr "Es weist den Client an, Snapins vom hostdefinierten "
msgid "It will operate based on the fields the area typcially requires."
msgstr ""
+msgid "Join"
+msgstr ""
+
msgid "Join Domain after image task"
msgstr ""
@@ -5237,6 +5497,9 @@ msgstr "Sprache"
msgid "Largest images"
msgstr "Images"
+msgid "Last Agent Check-In"
+msgstr ""
+
#, fuzzy
msgid "Last Captured"
msgstr "Zuletzt hochgeladen"
@@ -5247,15 +5510,16 @@ msgstr ""
msgid "Last Check-In"
msgstr ""
-msgid "Last Client Check-In"
-msgstr ""
-
msgid "Last Deployed"
msgstr "Zuletzt verteilt"
msgid "Last Ping"
msgstr ""
+#, fuzzy
+msgid "Last Seen"
+msgstr "Zuletzt hochgeladen"
+
#, fuzzy
msgid "Last Successful Ping"
msgstr "Erfolgreich"
@@ -5271,6 +5535,10 @@ msgstr ""
msgid "Last deployed"
msgstr "Zuletzt verteilt"
+#, fuzzy
+msgid "Last error"
+msgstr "Fehler"
+
msgid "Last flush"
msgstr ""
@@ -5278,6 +5546,9 @@ msgstr ""
msgid "Last imaged"
msgstr "Images"
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
#, fuzzy
msgid "Latest Alpha Version"
msgstr "Neueste Version"
@@ -5402,6 +5673,10 @@ msgstr "Alle Sitess auflisten"
msgid "List All Snapins"
msgstr "Alle Snapins auflisten"
+#, fuzzy
+msgid "List All Software"
+msgstr "Alle Sitess auflisten"
+
msgid "List All Storage Groups"
msgstr "Alle Storage Groups auflisten"
@@ -5539,6 +5814,9 @@ msgstr "Log-Viewer"
msgid "Log out and sign in as an administrator"
msgstr ""
+msgid "Logged on"
+msgstr ""
+
msgid "Logging"
msgstr ""
@@ -5731,6 +6009,9 @@ msgstr "Max. Größe"
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
#, fuzzy
msgid "Member"
msgstr "Mitglieder"
@@ -5811,6 +6092,10 @@ msgstr "Mitternacht"
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+#, fuzzy
+msgid "Mint an agent enrollment token"
+msgstr "Ausstehende registrierte Hosts"
+
msgid "Minute value is not valid"
msgstr "Minutenwert ist nicht gültig"
@@ -5818,6 +6103,9 @@ msgstr "Minutenwert ist nicht gültig"
msgid "Minutes field is invalid"
msgstr "Minutenwert ist nicht gültig"
+msgid "Missing"
+msgstr ""
+
msgid "Missing a temporary folder"
msgstr "Ein temporärer Ordner fehlt"
@@ -6287,8 +6575,12 @@ msgid "No password is needed. Issue this account a token from its API tab, or fr
msgstr ""
#, fuzzy
-msgid "No plugin tasks to run"
-msgstr "Keine gültigen Tasks gefunden"
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr "Keinen aktiven Task gefunden für Host"
+
+#, fuzzy
+msgid "No plugin tasks to run"
+msgstr "Keine gültigen Tasks gefunden"
#, fuzzy
msgid "No plugin with that id."
@@ -6340,6 +6632,10 @@ msgstr "Snapin geschützt"
msgid "No snapins associated with this group as master"
msgstr "Keine Snapins mit dieser Gruppe als Master verbunden"
+#, fuzzy
+msgid "No storage node can serve the file."
+msgstr "Hinzufügen eines Speicherknotens fehlgeschlagen!"
+
#, fuzzy
msgid "No storage nodes assigned to this storage group"
msgstr "da innerhalb diese Speichergruppe einer aktiviert ist"
@@ -6352,6 +6648,9 @@ msgstr "Ein Host mit diesem Namen ist bereits vorhanden!"
msgid "No storagegroups assigned to this snapin"
msgstr "Die zugewiesene Image Speichergruppe ist nicht gültig."
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -6361,6 +6660,9 @@ msgstr ""
msgid "No such object."
msgstr ""
+msgid "No such token."
+msgstr ""
+
msgid "No such user."
msgstr ""
@@ -6396,6 +6698,9 @@ msgstr ""
msgid "No values passed"
msgstr "Keine Werte übergeben"
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
#, fuzzy
msgid "No viable macs to use"
msgstr "Keine brauchbaren MACS"
@@ -6451,6 +6756,9 @@ msgstr "Icon-Datei nicht gefunden"
msgid "Not Registered Hosts"
msgstr "Nicht registrierte Hosts"
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr "Keine Zahl"
@@ -6588,6 +6896,13 @@ msgstr "Benutzer aktualisiert"
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+#, fuzzy
+msgid "Observed domain"
+msgstr "Allgemeine Informationen"
+
msgid "Off"
msgstr ""
@@ -6644,6 +6959,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr "Eine oder mehrere MACs sind mit einem Host verknüpft"
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -6727,6 +7048,12 @@ msgstr ""
msgid "Operations on %s."
msgstr "Operationsfeld nicht gesetzt: %s"
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -6772,9 +7099,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -6856,6 +7189,10 @@ msgstr ""
msgid "Pending"
msgstr "Ausstehend..."
+#, fuzzy
+msgid "Pending Agents"
+msgstr "Ausstehende MACs"
+
msgid "Pending Hosts"
msgstr "Ausstehende Hosts"
@@ -6873,9 +7210,31 @@ msgstr "Ausstehende MACs"
msgid "Pending Registered Hosts"
msgstr "Ausstehende registrierte Hosts"
+#, fuzzy
+msgid "Pending Registration created by FOG_AGENT"
+msgstr "Ausstehende Registrierung erstellt von FOG_CLIENT"
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr "Ausstehende Registrierung erstellt von FOG_CLIENT"
+#, fuzzy
+msgid "Pending agent"
+msgstr "Ausstehende Hosts"
+
+#, fuzzy
+msgid "Pending agent enrollments"
+msgstr "Ausstehende registrierte Hosts"
+
+#, fuzzy
+msgid "Pending agents"
+msgstr "Ausstehende MACs"
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
#, fuzzy
msgid "Pending host"
msgstr "Ausstehende Hosts"
@@ -6922,6 +7281,16 @@ msgstr "Status"
msgid "Ping cycle complete"
msgstr "wurde abgeschlossen"
+msgid "Pinned"
+msgstr ""
+
+#, fuzzy
+msgid "Placement"
+msgstr "Task-Management"
+
+msgid "Platform"
+msgstr ""
+
msgid "Please Select an option"
msgstr "Bitte wählen Sie eine Option"
@@ -6966,10 +7335,18 @@ msgstr ""
msgid "Please enter a name"
msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
+#, fuzzy
+msgid "Please enter a package id."
+msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
+
#, fuzzy
msgid "Please enter a printer name."
msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
+#, fuzzy
+msgid "Please enter a software name."
+msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
+
#, fuzzy
msgid "Please enter a valid CIDR subnet."
msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
@@ -6983,6 +7360,10 @@ msgstr ""
msgid "Please physically associate"
msgstr "Bitte ordnen Sie physisch"
+#, fuzzy
+msgid "Please select a valid backend."
+msgstr "Wählen Sie ein gültiges Abbild"
+
#, fuzzy
msgid "Please select a valid certificate verification level"
msgstr "Wählen Sie ein gültiges Abbild"
@@ -7003,6 +7384,10 @@ msgstr "Wählen Sie ein gültiges Abbild"
msgid "Please select a valid printer type."
msgstr "Wählen Sie ein gültiges Abbild"
+#, fuzzy
+msgid "Please select a valid state."
+msgstr "Wählen Sie ein gültiges Abbild"
+
#, fuzzy
msgid "Please select an LDAP server!"
msgstr "Bitte wählen Sie eine Option"
@@ -7218,6 +7603,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -7264,6 +7652,10 @@ msgstr "Drucker erstellen fehlgeschlagen!"
msgid "Printer Create Success"
msgstr "Drucker hinzufügen erfolgreich."
+#, fuzzy
+msgid "Printer Deployment"
+msgstr "Druckerverwaltung"
+
msgid "Printer Description"
msgstr "Druckerbeschreibung"
@@ -7421,6 +7813,9 @@ msgstr "Drucker aktualisiert!"
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
msgid "Pushbullet Accounts"
msgstr "Pushbullet Accounts"
@@ -7462,6 +7857,10 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr "Snapin ist geschützt und kann nicht gelöscht werden"
+#, fuzzy
+msgid "Quick tasks"
+msgstr "Aktive Multicast-Tasks"
+
msgid "RESOURCES"
msgstr ""
@@ -7474,6 +7873,9 @@ msgstr "RX"
msgid "Re-Transmit Hello Interval"
msgstr ""
+msgid "Re-check Interval"
+msgstr ""
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -7494,6 +7896,9 @@ msgstr "Ausgewählte löschen"
msgid "Real Time"
msgstr "Datum und Zeit"
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr "Neustarten"
@@ -7522,6 +7927,9 @@ msgstr ""
msgid "Recorded in range"
msgstr "Datensatz wurde nicht gefunden, Fehler: %s"
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
#, fuzzy
msgid "Records"
msgstr "Aktuelle Datensätze"
@@ -7535,10 +7943,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-#, fuzzy
-msgid "Refresh"
-msgstr "Standard-Bildwiederholrate"
-
#, fuzzy
msgid "Refresh Settings Cache"
msgstr "Service-Status"
@@ -7684,6 +8088,10 @@ msgstr "Bericht"
msgid "Report Management"
msgstr "Berichteverwaltung"
+#, fuzzy
+msgid "Reported"
+msgstr "Bericht"
+
msgid "Reports"
msgstr "Berichte"
@@ -7749,9 +8157,16 @@ msgstr ""
msgid "Retention sweep failed"
msgstr "Entfernen fehlgeschlagen"
+msgid "Retry"
+msgstr ""
+
msgid "Return Code"
msgstr "Return-Code"
+#, fuzzy
+msgid "Return Codes"
+msgstr "Return-Code"
+
msgid "Return To Local Login"
msgstr ""
@@ -7762,9 +8177,33 @@ msgstr "Rückgabewert"
msgid "Returning value of key"
msgstr "Wert des Schlüssels zurückgeben"
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+#, fuzzy
+msgid "Revoke an agent enrollment token"
+msgstr "Ausstehende registrierte Hosts"
+
+#, fuzzy
+msgid "Revoke selected"
+msgstr "Ausgewählte entfernen "
+
+#, fuzzy
+msgid "Revoked selected tokens."
+msgstr "Ausgewählten MAcs freigeben"
+
+msgid "Revoked."
+msgstr ""
+
#, fuzzy
msgid "Role"
msgstr "Rollenname"
@@ -7905,6 +8344,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
#, fuzzy
msgid "SQL Error"
msgstr "SQL-Fehler"
@@ -8023,16 +8465,6 @@ msgstr "iPXE-Einstellungen erfolgreich aktualisiert!"
msgid "Scopes"
msgstr ""
-msgid "Screen Height"
-msgstr ""
-
-#, fuzzy
-msgid "Screen Refresh Rate"
-msgstr "Standard-Bildwiederholrate"
-
-msgid "Screen Width"
-msgstr ""
-
msgid "Search"
msgstr "Suche"
@@ -8268,6 +8700,9 @@ msgstr "Ein Host mit diesem Namen ist bereits vorhanden."
msgid "Sessions canceled!"
msgstr "geplante Tasks wurde erfolgreich erstellt"
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -8734,6 +9169,63 @@ msgstr "genutzte Snapins"
msgid "So if you are trying to transmit to remote node A"
msgstr "Wenn Sie also versuchen, an den entfernten Knoten A zu senden,"
+msgid "Software"
+msgstr ""
+
+#, fuzzy
+msgid "Software Create Fail"
+msgstr "Drucker erstellen fehlgeschlagen!"
+
+#, fuzzy
+msgid "Software Create Success"
+msgstr "Drucker hinzufügen erfolgreich."
+
+#, fuzzy
+msgid "Software Host Associations"
+msgstr "zugeordneter Host"
+
+#, fuzzy
+msgid "Software Management"
+msgstr "Speicherverwaltung"
+
+#, fuzzy
+msgid "Software Name"
+msgstr "Sitename"
+
+msgid "Software Order"
+msgstr ""
+
+#, fuzzy
+msgid "Software Report"
+msgstr "Verlaufs-ID"
+
+#, fuzzy
+msgid "Software Status"
+msgstr "Neuen Standort erstellen"
+
+#, fuzzy
+msgid "Software Update Fail"
+msgstr "Drucker-Update fehlgeschlagen!"
+
+#, fuzzy
+msgid "Software Update Success"
+msgstr "Host Aktualisierung erfolgreich!"
+
+#, fuzzy
+msgid "Software added!"
+msgstr "Drucker hinzugefügt"
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+#, fuzzy
+msgid "Software update failed!"
+msgstr "Drucker-Update fehlgeschlagen!"
+
+#, fuzzy
+msgid "Software updated!"
+msgstr "Drucker aktualisiert!"
+
msgid "Some nice description, should be short."
msgstr ""
@@ -8746,6 +9238,9 @@ msgstr "Bereichsvariable muss boolean sein"
msgid "Specified download URL not allowed!"
msgstr ""
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -9499,6 +9994,9 @@ msgstr "Es gibt keine Gruppen auf diesem Server."
msgid "The CA private key is on this server"
msgstr "Es gibt keine Gruppen auf diesem Server."
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -9532,6 +10030,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -9576,6 +10077,9 @@ msgstr " | Datei oder Pfad ist nicht erreichbar"
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -9616,6 +10120,13 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+#, fuzzy
+msgid "The enrollment is no longer pending."
+msgstr "läuft nicht mehr"
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -9643,6 +10154,15 @@ msgstr ""
msgid "The grid key."
msgstr "Fehler beim Erstellen eines Tasks"
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
#, fuzzy
msgid "The identity provider could not be reached"
msgstr "Temporäre Datei konnte nicht gelesen werden."
@@ -9697,9 +10217,16 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+#, fuzzy
+msgid "The item is not a live row of this host."
+msgstr "Keinen aktiven Task gefunden für Host"
+
msgid "The key will be assigned to registered hosts when a"
msgstr "Der Schlüssel wird registrierten Hosts zugewiesen, wenn"
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -9729,12 +10256,21 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
msgid "The path requested is already in use by another image!"
msgstr ""
+msgid "The payload bytes."
+msgstr ""
+
#, fuzzy
msgid "The plugin directory"
msgstr "Home-Verzeichnis speichern"
@@ -9779,6 +10315,13 @@ msgstr ""
msgid "The record could not be written."
msgstr "Temporäre Datei konnte nicht gelesen werden."
+#, fuzzy
+msgid "The renewed certificate, leaf then chain."
+msgstr "Neuen Standort erstellen"
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -9788,6 +10331,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -9799,6 +10345,12 @@ msgstr "Drucker-Update fehlgeschlagen!"
msgid "The selected site no longer exists"
msgstr "läuft nicht mehr"
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -9818,6 +10370,13 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+#, fuzzy
+msgid "The signing helper is not available on this server."
+msgstr "Es gibt keine Gruppen auf diesem Server."
+
#, fuzzy
msgid "The signing request could not be generated"
msgstr "Temporäre Datei konnte nicht gelesen werden."
@@ -9838,6 +10397,10 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+#, fuzzy
+msgid "The token."
+msgstr "CPU-Anzahl"
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -10000,6 +10563,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -10060,10 +10626,16 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, fuzzy, php-format
msgid "This machine already registered as %s"
msgstr "Bereits registriert als"
+msgid "This module has no settings to configure."
+msgstr ""
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -10171,6 +10743,13 @@ msgstr "Zeit bereits vorhanden"
msgid "Time since last imaged"
msgstr ""
+#, fuzzy
+msgid "Timeout"
+msgstr "Zeit"
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -10193,9 +10772,31 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Regel Zuordnung"
+#, fuzzy
+msgid "Token Create Fail"
+msgstr "Drucker erstellen fehlgeschlagen!"
+
+#, fuzzy
+msgid "Token Create Success"
+msgstr "Drucker hinzufügen erfolgreich."
+
+#, fuzzy
+msgid "Token Revoke Fail"
+msgstr "FTP-Verbindung fehlgeschlagen"
+
+#, fuzzy
+msgid "Token Revoke Success"
+msgstr "Drucker hinzufügen erfolgreich."
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
#, fuzzy
msgid "Too many MACs"
msgstr "zu viele MACs"
@@ -10382,6 +10983,9 @@ msgstr "Benutzername Attribut"
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
#, fuzzy
msgid "Unauthenticated."
msgstr "Authentifizieren nicht möglich"
@@ -10432,6 +11036,9 @@ msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
msgid "Unknown action"
msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -10462,6 +11069,9 @@ msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
#, fuzzy
msgid "Unmark selected client ignore"
msgstr "Ausgewählten MAcs freigeben"
@@ -10551,6 +11161,9 @@ msgstr "ausgewählte Images hinzufügen"
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
#, fuzzy
msgid "Upload"
msgstr "Berichte hochladen"
@@ -10663,9 +11276,6 @@ msgstr "Benutzer ist bereits vorhanden"
msgid "User Association"
msgstr "Site Zugehörigkeit"
-msgid "User Cleanup"
-msgstr "Benutzer-Bereinigung"
-
#, fuzzy
msgid "User Count"
msgstr "CPU-Anzahl"
@@ -10751,6 +11361,10 @@ msgstr "Benutzername Attribut"
msgid "User Password"
msgstr "Benutzerpasswort"
+#, fuzzy
+msgid "User Sessions"
+msgstr "Site Zugehörigkeit"
+
msgid "User Tracker"
msgstr "Benutzer-Tracker"
@@ -10833,6 +11447,12 @@ msgstr "Benutzer"
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr "Verwenden der Gruppenübereinstimmungsfunktion,"
@@ -10858,6 +11478,10 @@ msgstr "Version"
msgid "Version information and paging bounds."
msgstr "FOG-Versionsinformationen"
+#, fuzzy
+msgid "Version policy"
+msgstr "Version"
+
#, fuzzy
msgid "Versions"
msgstr "Version"
@@ -10887,6 +11511,9 @@ msgstr "Wake On Lan"
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -10940,12 +11567,18 @@ msgstr "wurde abgebrochen"
msgid "What it does"
msgstr "wurde abgebrochen"
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -10962,6 +11595,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr "Wo bekomme ich Hilfe?"
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -10974,10 +11610,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -11051,6 +11687,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr "Jährlich"
@@ -11173,6 +11812,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
#, fuzzy
msgid "access"
msgstr "Zugang"
@@ -11184,10 +11826,17 @@ msgstr "zusätzliche MACs haben"
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
#, fuzzy
msgid "ago"
msgstr "vor"
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
#, fuzzy
msgid "all current storage nodes"
msgstr "momentanen Speicherknoten löschen."
@@ -11223,6 +11872,13 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+#, fuzzy
+msgid "any version"
+msgstr "Version"
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
#, fuzzy
msgid "architecture not recorded"
msgstr "Temporäre Datei konnte nicht gelesen werden."
@@ -11234,6 +11890,10 @@ msgstr "da der FOG versuchen wird, mit dem Internet zu verbinden, "
msgid "as its primary group"
msgstr "als primäre Gruppe finden"
+#, fuzzy
+msgid "assigned"
+msgstr "zugeordneter Host"
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -11340,6 +12000,9 @@ msgstr "Deaktiviert"
msgid "does not exist and cannot be created"
msgstr "Image ist geschützt und kann nicht gelöscht werden"
+msgid "domain"
+msgstr ""
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -11349,6 +12012,9 @@ msgstr "ob bereits ausgewählt oder hochgeladen"
msgid "either because you have updated"
msgstr "entweder weil Sie aktualisiert haben"
+msgid "empty means never install Chocolatey"
+msgstr ""
+
#, fuzzy
msgid "error"
msgstr "Fehler"
@@ -11356,10 +12022,20 @@ msgstr "Fehler"
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+#, fuzzy
+msgid "failed"
+msgstr "fehlgeschlagen"
+
#, fuzzy
msgid "failed to execute, image file"
msgstr "Löschen der Imagedateien fehlgeschlagen"
@@ -11459,6 +12135,10 @@ msgstr ""
msgid "host"
msgstr "Host"
+#, fuzzy, php-format
+msgid "host \"%s\""
+msgstr "Hosts"
+
#, fuzzy
msgid "host is"
msgstr "Hosts"
@@ -11574,9 +12254,6 @@ msgstr ""
msgid "in"
msgstr "Minuten"
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
@@ -11584,9 +12261,6 @@ msgstr ""
msgid "in minutes"
msgstr "Minuten"
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr "in Sekunden"
@@ -11662,6 +12336,10 @@ msgstr "aktiviert werden."
msgid "keys"
msgstr ""
+#, fuzzy
+msgid "latest"
+msgstr "Replizieren"
+
msgid "leave to keep the current one"
msgstr ""
@@ -11695,6 +12373,10 @@ msgstr "Minuten"
msgid "mismatched"
msgstr ""
+#, fuzzy
+msgid "missing"
+msgstr "Version"
+
msgid "moments from now"
msgstr ""
@@ -11732,6 +12414,10 @@ msgstr ""
msgid "never"
msgstr ""
+#, fuzzy
+msgid "never reported"
+msgstr "Inventar"
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -11764,6 +12450,9 @@ msgstr ""
msgid "not found on this node"
msgstr "auf diesem Knoten nicht gefunden"
+msgid "not joined"
+msgstr ""
+
#, fuzzy
msgid "not reachable"
msgstr "Nicht verfügbar"
@@ -11794,10 +12483,16 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+msgid "off"
+msgstr ""
+
#, fuzzy
msgid "off means an account must already exist"
msgstr "Dieser Host ist bereits vorhanden."
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -11811,6 +12506,9 @@ msgstr ""
msgid "optional"
msgstr "Ort"
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
msgid "or"
msgstr "oder"
@@ -12089,6 +12787,10 @@ msgstr "nicht verfügbar"
msgid "unchanged for"
msgstr "Imaged für"
+#, fuzzy
+msgid "unknown action"
+msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
+
#, fuzzy
msgid "unrecorded"
msgstr "(empfohlen)"
@@ -12323,6 +13025,10 @@ msgstr ""
#~ msgid "Can not redeclare route"
#~ msgstr "Route kann nicht nochmal neu definiert werden"
+#, fuzzy
+#~ msgid "Cannot connect to ftp server"
+#~ msgstr "Verbindung zum FTP-Server nicht möglich"
+
#~ msgid "Check that database is running"
#~ msgstr "Überprüfen Sie, ob die Datenbank ausgeführt wird"
@@ -12330,6 +13036,10 @@ msgstr ""
#~ msgid "Client Module Settings"
#~ msgstr "Client Einstellungen"
+#, fuzzy
+#~ msgid "Could not read snapin file"
+#~ msgstr "Snapin-Datei konnte nicht gelesen werden."
+
#, fuzzy
#~ msgid "Create New Accesscontrol"
#~ msgstr "Neuen Schlüssel erstellen"
@@ -12354,6 +13064,15 @@ msgstr ""
#~ msgid "Database connection unavailable"
#~ msgstr "Pfad ist nicht verfügbar"
+#~ msgid "Default Height"
+#~ msgstr "Standardhöhe"
+
+#~ msgid "Default Refresh Rate"
+#~ msgstr "Standard-Bildwiederholrate"
+
+#~ msgid "Default Width"
+#~ msgstr "Standardbreite"
+
#, fuzzy
#~ msgid "Delete All"
#~ msgstr "Löschen fehlgeschlagen"
@@ -12362,6 +13081,9 @@ msgstr ""
#~ msgid "Deprecated."
#~ msgstr "Erstellen"
+#~ msgid "Directory Cleaner"
+#~ msgstr "Verzeichnis-Bereiniger"
+
#, fuzzy
#~ msgid "Domain joining"
#~ msgstr "Standort senden aktivieren"
@@ -12427,6 +13149,18 @@ msgstr ""
#~ msgid "Export Users"
#~ msgstr "Benutzer exportieren"
+#, fuzzy
+#~ msgid "FOG Agent desired state"
+#~ msgstr "wurde abgebrochen"
+
+#, fuzzy
+#~ msgid "FOG Agent snapin result"
+#~ msgstr "Keine Datei wurde hochgeladen"
+
+#, fuzzy
+#~ msgid "FOG Agent software result"
+#~ msgstr "Keine Datei wurde hochgeladen"
+
#~ msgid "Failed to add/update snapin file"
#~ msgstr "Hinzufügen/aktualisieren eines Snapin-Datei"
@@ -12541,10 +13275,18 @@ msgstr ""
#~ msgid "Group module settings"
#~ msgstr "Gruppeneinstellungen Module"
+#, fuzzy
+#~ msgid "Height"
+#~ msgstr "Mitternacht"
+
#, fuzzy
#~ msgid "History Report"
#~ msgstr "Verlaufs-ID"
+#, fuzzy
+#~ msgid "Host Display Manager Settings"
+#~ msgstr "iPXE Menüeinstellungen"
+
#, fuzzy
#~ msgid "Host Ext"
#~ msgstr "Hostliste"
@@ -12561,6 +13303,10 @@ msgstr ""
#~ msgid "Host Ext Variable"
#~ msgstr "Aktualisierung der Rolle fehlgeschlagen"
+#, fuzzy
+#~ msgid "Host Screen Resolution"
+#~ msgstr "Host-Registrierung"
+
#, fuzzy
#~ msgid "Host Site"
#~ msgstr "Hostliste"
@@ -12664,6 +13410,9 @@ msgstr ""
#~ msgid "Install"
#~ msgstr "Installierte Plugins"
+#~ msgid "Invalid Storage Node"
+#~ msgstr "Ungültiger Speicherknoten"
+
#, fuzzy
#~ msgid "Invalid Type"
#~ msgstr "Ungültiger Typ"
@@ -12687,6 +13436,14 @@ msgstr ""
#~ msgid "LDAP User Filter"
#~ msgstr "LDAP-Server"
+#, fuzzy
+#~ msgid "Last Activity"
+#~ msgstr "Aktiv"
+
+#, fuzzy
+#~ msgid "Last Event"
+#~ msgstr "Zuletzt hochgeladen"
+
#, fuzzy
#~ msgid "Latest SVN Version"
#~ msgstr "Neueste SVN-Version"
@@ -12752,6 +13509,14 @@ msgstr ""
#~ msgid "Not Installed"
#~ msgstr "Installierte Plugins"
+#, fuzzy
+#~ msgid "Not a live task of this host's job."
+#~ msgstr "Keinen aktiven Task gefunden für Host"
+
+#, fuzzy
+#~ msgid "Not an entry in this host's software set."
+#~ msgstr "Keinen aktiven Task gefunden für Host"
+
#, fuzzy
#~ msgid "Pause"
#~ msgstr "Pause"
@@ -12780,9 +13545,13 @@ msgstr ""
#~ msgstr "Host Produktschlüssel"
#, fuzzy
-#~ msgid "Recorded"
+#~ msgid "Recorded."
#~ msgstr "(empfohlen)"
+#, fuzzy
+#~ msgid "Refresh"
+#~ msgstr "Standard-Bildwiederholrate"
+
#~ msgid "Register must be managed from hooks or events"
#~ msgstr "Register muss von Haken oder Ereignissen gemanagt werden"
@@ -12858,6 +13627,10 @@ msgstr ""
#~ msgid "Rule update failed!"
#~ msgstr "Drucker-Update fehlgeschlagen!"
+#, fuzzy
+#~ msgid "Screen Refresh Rate"
+#~ msgstr "Standard-Bildwiederholrate"
+
#, fuzzy
#~ msgid "Serial"
#~ msgstr "Seriennummer"
@@ -12903,8 +13676,16 @@ msgstr ""
#~ msgstr "Dieser Host ist bereits vorhanden."
#, fuzzy
-#~ msgid "The certificate chain"
-#~ msgstr "Neuen Standort erstellen"
+#~ msgid "The desired state."
+#~ msgstr "Fehler beim Erstellen eines Tasks"
+
+#, fuzzy
+#~ msgid "The host this certificate is, and the capabilities this server offers."
+#~ msgstr "Es gibt keine Gruppen auf diesem Server."
+
+#, fuzzy
+#~ msgid "The task was already closed."
+#~ msgstr "Dieser Host ist bereits vorhanden."
#, fuzzy
#~ msgid "There are no "
@@ -12949,6 +13730,10 @@ msgstr ""
#~ msgid "Unable to set user filter."
#~ msgstr "Datei kann zum Lesen nicht geöffnet werden"
+#, fuzzy
+#~ msgid "Unknown status."
+#~ msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
+
#, fuzzy
#~ msgid "Update Master Node"
#~ msgstr "Master-Knoten"
@@ -12961,6 +13746,9 @@ msgstr ""
#~ msgid "Update/Remove printers"
#~ msgstr "Drucker Aktualisieren/Entfernen"
+#~ msgid "User Cleanup"
+#~ msgstr "Benutzer-Bereinigung"
+
#, fuzzy
#~ msgid "User Group Site"
#~ msgstr "Gruppen-Snapins"
@@ -13053,10 +13841,6 @@ msgstr ""
#~ msgid "min (all)"
#~ msgstr "Aktiviert"
-#, fuzzy
-#~ msgid "multicast tasks!"
-#~ msgstr "Aktive Multicast-Tasks"
-
#, fuzzy
#~ msgid "no database to"
#~ msgstr "Keine Datenbank zum"
@@ -13072,7 +13856,3 @@ msgstr ""
#, fuzzy
#~ msgid "username"
#~ msgstr "Benutzername"
-
-#, fuzzy
-#~ msgid "version"
-#~ msgstr "Version"
diff --git a/packages/web/management/languages/en_US.UTF-8/LC_MESSAGES/messages.po b/packages/web/management/languages/en_US.UTF-8/LC_MESSAGES/messages.po
index 4e2829ef2a..80aaaa6c80 100644
--- a/packages/web/management/languages/en_US.UTF-8/LC_MESSAGES/messages.po
+++ b/packages/web/management/languages/en_US.UTF-8/LC_MESSAGES/messages.po
@@ -125,6 +125,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -294,6 +298,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, fuzzy, php-format
+msgid "(deleted host %d)"
+msgstr "Approve selected Hosts"
+
msgid "(deleted user)"
msgstr ""
@@ -313,9 +321,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr "Kernel Arguments"
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
#, fuzzy
msgid "1 Hour"
msgstr "1 hour"
@@ -420,6 +434,12 @@ msgstr "An image already exists with this name!"
msgid "A client ID is required"
msgstr "An image name is required!"
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
#, fuzzy
msgid "A dmi field must be set!"
msgstr "Event must be a string"
@@ -483,6 +503,9 @@ msgstr "An image already exists with this name!"
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
#, fuzzy
msgid "A module already exists with this name!"
msgstr "An image already exists with this name!"
@@ -504,6 +527,9 @@ msgstr "List All %s"
msgid "A permission name is required."
msgstr "An image name is required!"
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -526,6 +552,9 @@ msgstr "An image already exists with this name!"
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
#, fuzzy
msgid "A role already exists with this name!"
msgstr "An image already exists with this name!"
@@ -567,6 +596,10 @@ msgstr "An image already exists with this name!"
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+#, fuzzy
+msgid "A software entry already exists with this name!"
+msgstr "An image already exists with this name!"
+
#, fuzzy
msgid "A storage group already exists with this name!"
msgstr "An image already exists with this name!"
@@ -702,6 +735,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -932,6 +971,10 @@ msgstr "Add snapin failed!"
msgid "Add snapin failed!"
msgstr "Add snapin failed!"
+#, fuzzy
+msgid "Add software failed!"
+msgstr "Add snapin failed!"
+
#, fuzzy
msgid "Add storage node failed!"
msgstr "Add snapin failed!"
@@ -1016,6 +1059,33 @@ msgstr "Advanced"
msgid "Advanced Tasks"
msgstr "Advanced"
+msgid "Agent"
+msgstr ""
+
+#, fuzzy
+msgid "Agent Activity"
+msgstr "Active"
+
+#, fuzzy
+msgid "Agent Approval Success"
+msgstr "Host Created"
+
+#, fuzzy
+msgid "Agent Denial Success"
+msgstr "Printer updated!"
+
+#, fuzzy
+msgid "Agent Enrollment Tokens"
+msgstr "has been successfully updated"
+
+#, fuzzy
+msgid "Agent Tokens"
+msgstr "Access Token"
+
+#, fuzzy
+msgid "Agent enrollment tokens"
+msgstr "has been successfully updated"
+
msgid "Ago must be boolean"
msgstr ""
@@ -1032,6 +1102,10 @@ msgstr ""
msgid "All Hosts"
msgstr "All Hosts"
+#, fuzzy
+msgid "All Pending Agents"
+msgstr "Pending MACs"
+
#, fuzzy
msgid "All Pending Hosts"
msgstr "Pending Hosts"
@@ -1135,10 +1209,16 @@ msgstr ""
msgid "An SQL error occurred"
msgstr "Unknown upload error occurred. Return code: "
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
#, fuzzy
msgid "An entry already exists with this name!"
msgstr "An image already exists with this name!"
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr "An image already exists with this name!"
@@ -1178,6 +1258,10 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+#, fuzzy
+msgid "Any version"
+msgstr "Version"
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1216,18 +1300,36 @@ msgstr ""
msgid "Approve"
msgstr "Host approved"
+#, fuzzy
+msgid "Approve Agent Fail"
+msgstr "Host approved"
+
#, fuzzy
msgid "Approve MAC Fail"
msgstr "Host approved"
+#, fuzzy
+msgid "Approve Pending Agents"
+msgstr "Pending Hosts"
+
#, fuzzy
msgid "Approve Pending Hosts"
msgstr "Pending Hosts"
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
#, fuzzy
msgid "Approve selected"
msgstr "Approve selected Hosts"
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+#, fuzzy
+msgid "Approved selected agents!"
+msgstr "Approve selected Hosts"
+
#, fuzzy
msgid "Approved selected hosts!"
msgstr "Approve selected Hosts"
@@ -1240,6 +1342,9 @@ msgstr "Approve selected Hosts"
msgid "Approving the selected pending hosts."
msgstr "Approve selected Hosts"
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1249,6 +1354,10 @@ msgstr ""
msgid "Area"
msgstr ""
+#, fuzzy
+msgid "Assigned"
+msgstr "No node associated"
+
#, fuzzy
msgid "Assigned Group"
msgstr "Storage Group Name"
@@ -1311,6 +1420,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1349,6 +1461,9 @@ msgstr "BIOS Vendor"
msgid "BIOS Version"
msgstr "BIOS Version"
+msgid "Backend"
+msgstr ""
+
#, fuzzy
msgid "Bad request."
msgstr "%s is required"
@@ -1582,6 +1697,10 @@ msgstr "Cancelled task"
msgid "Canceled due to new tasking."
msgstr "Cancelled due to new tasking."
+#, fuzzy
+msgid "Cannot Run"
+msgstr "Record not found, Error: %s"
+
#, fuzzy
msgid "Cannot bind to the LDAP server"
msgstr "Cannot connect to database"
@@ -1596,10 +1715,6 @@ msgstr "Cannot connect to node."
msgid "Cannot connect to database"
msgstr "Cannot connect to database"
-#, fuzzy
-msgid "Cannot connect to ftp server"
-msgstr "Cannot connect to database"
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1796,6 +1911,9 @@ msgstr "No FOGPage Class found for this node"
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+msgid "Checked"
+msgstr ""
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1808,6 +1926,12 @@ msgstr ""
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1978,14 +2102,23 @@ msgstr "Error: Failed to download kernel"
msgid "Confirm you would like to download a new kernel"
msgstr "Error: Failed to download kernel"
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
#, fuzzy
msgid "Copy from existing"
msgstr "Could not create printer"
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -2059,10 +2192,6 @@ msgstr "Could not read tmp file."
msgid "Could not read local file"
msgstr "Could not read temp file"
-#, fuzzy
-msgid "Could not read snapin file"
-msgstr "Could not read tmp file."
-
#, fuzzy
msgid "Could not read the database structure"
msgstr "Failed to create Snapin Job"
@@ -2159,6 +2288,9 @@ msgstr ""
msgid "Create"
msgstr "Create"
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -2241,6 +2373,10 @@ msgstr ""
msgid "Create New Snapin"
msgstr ""
+#, fuzzy
+msgid "Create New Software"
+msgstr "Create New %s"
+
#, fuzzy
msgid "Create New Storage Group"
msgstr "Storage Group"
@@ -2289,6 +2425,10 @@ msgstr "User created"
msgid "Create Users On First Login"
msgstr ""
+#, fuzzy, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr "User created"
+
#, fuzzy, php-format
msgid "Create a %s"
msgstr "Create New %s"
@@ -2312,9 +2452,17 @@ msgstr "User created"
msgid "Create task form success"
msgstr "User created"
+#, fuzzy
+msgid "Create tasking"
+msgstr "Create New %s"
+
msgid "Create tasking succeeded"
msgstr ""
+#, fuzzy
+msgid "Create token"
+msgstr "Create New %s"
+
#, fuzzy
msgid "Created"
msgstr "Create"
@@ -2326,6 +2474,10 @@ msgstr "Created By"
msgid "Created Time"
msgstr "Created By"
+#, fuzzy
+msgid "Created by"
+msgstr "Created By"
+
msgid "Created by FOG Reg on"
msgstr "Created by FOG Reg on"
@@ -2454,6 +2606,9 @@ msgstr "Debug Options"
msgid "Debug Task"
msgstr "Debug"
+msgid "Decided."
+msgstr ""
+
msgid "Default"
msgstr "Default"
@@ -2461,15 +2616,6 @@ msgstr "Default"
msgid "Default Choice"
msgstr "Default Item:"
-msgid "Default Height"
-msgstr "Default Height"
-
-msgid "Default Refresh Rate"
-msgstr "Default Refresh Rate"
-
-msgid "Default Width"
-msgstr "Default Width"
-
#, fuzzy
msgid "Default init, ARM64"
msgstr "Default Width"
@@ -2554,6 +2700,28 @@ msgstr ""
msgid "Deleting remote file"
msgstr "Menu create failed"
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+#, fuzzy
+msgid "Denied selected agents!"
+msgstr "Approve selected Hosts"
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy
+msgid "Deny Agent Fail"
+msgstr "Delete file data"
+
+#, fuzzy
+msgid "Deny Pending Agents"
+msgstr "Pending MACs"
+
+#, fuzzy
+msgid "Deny selected"
+msgstr "Delete Selected"
+
msgid "Deploy"
msgstr "Deploy"
@@ -2570,14 +2738,30 @@ msgstr ""
msgid "Description"
msgstr "Description"
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+msgid "Desired domain"
+msgstr ""
+
#, fuzzy
msgid "Destroy failed"
msgstr "Destroy failed: %s"
+#, fuzzy
+msgid "Detail"
+msgstr "Snapin Return Detail"
+
#, fuzzy
msgid "Details"
msgstr "Snapin Return Detail"
+msgid "Device URI"
+msgstr ""
+
#, fuzzy
msgid "Device must be a string"
msgstr "Event must be a string"
@@ -2591,9 +2775,6 @@ msgstr "Directory"
msgid "Directory Already Exists"
msgstr "Directory Already Exists"
-msgid "Directory Cleaner"
-msgstr "Directory Cleaner"
-
#, fuzzy
msgid "Directory Group"
msgstr "Directory"
@@ -2602,6 +2783,10 @@ msgstr "Directory"
msgid "Directory Group Name"
msgstr "Directory"
+#, fuzzy
+msgid "Directory Membership"
+msgstr "Membership"
+
#, fuzzy
msgid "Disable on all hosts"
msgstr "Enabled"
@@ -2718,6 +2903,9 @@ msgstr "Download Failed"
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2737,6 +2925,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr "Edit"
@@ -2832,6 +3023,10 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+#, fuzzy
+msgid "Enrollment Token"
+msgstr "Pushbullet Accounts"
+
msgid "Enrollment kit"
msgstr ""
@@ -2935,6 +3130,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
#, fuzzy
msgid "Every file was uploaded."
msgstr "No file was uploaded"
@@ -2955,6 +3156,14 @@ msgstr "Private key failed"
msgid "Exists item must be boolean"
msgstr ""
+#, fuzzy
+msgid "Exit Code"
+msgstr "Export Snapins"
+
+#, fuzzy
+msgid "Exit code"
+msgstr "Return Code"
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -3034,9 +3243,32 @@ msgstr "Date"
msgid "External root CA"
msgstr ""
+#, fuzzy
+msgid "Extra arguments"
+msgstr "Snapin Run With Argument"
+
msgid "FOG"
msgstr "FOG"
+#, fuzzy
+msgid "FOG Agent capability result"
+msgstr "No file was uploaded"
+
+#, fuzzy
+msgid "FOG Agent certificate renewal"
+msgstr "No file was uploaded"
+
+#, fuzzy
+msgid "FOG Agent enrollment"
+msgstr "has been successfully updated"
+
+#, fuzzy
+msgid "FOG Agent payload"
+msgstr "No file was uploaded"
+
+msgid "FOG Agent poll"
+msgstr ""
+
#, fuzzy
msgid "FOG Client"
msgstr "FOG Client Wiki"
@@ -3395,6 +3627,9 @@ msgstr "Task Started"
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3738,6 +3973,10 @@ msgstr "Snapin History"
msgid "Group Snapin History"
msgstr "Snapin History"
+#, fuzzy
+msgid "Group Software Assignment"
+msgstr "Snapin History"
+
#, fuzzy
msgid "Group Task History"
msgstr "Image History"
@@ -3826,9 +4065,15 @@ msgstr "Hardware Information"
msgid "Hardware Report"
msgstr "Hardware Information"
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr ""
+msgid "Hash Mismatch"
+msgstr ""
+
msgid "Have not locked the host for access"
msgstr ""
@@ -3836,10 +4081,6 @@ msgstr ""
msgid "Header is missing the required \"%s\" column"
msgstr ""
-#, fuzzy
-msgid "Height"
-msgstr "Midnight"
-
msgid "Height must be 120 pixels."
msgstr ""
@@ -3912,6 +4153,9 @@ msgstr "Printer already exists"
msgid "Host %1$s finished deploying image %2$s."
msgstr "Printer already exists"
+msgid "Host Agent Activity"
+msgstr ""
+
#, fuzzy
msgid "Host Approval Success"
msgstr "Host Created"
@@ -3947,10 +4191,6 @@ msgstr "Default Item:"
msgid "Host Description"
msgstr "Host Description"
-#, fuzzy
-msgid "Host Display Manager Settings"
-msgstr "Settings"
-
msgid "Host EFI Exit Type"
msgstr "Host EFI Exit Type"
@@ -4055,10 +4295,6 @@ msgstr "Host Product Key"
msgid "Host Registration"
msgstr "Host Registration"
-#, fuzzy
-msgid "Host Screen Resolution"
-msgstr "Host Registration"
-
#, fuzzy
msgid "Host Snapin Associations"
msgstr "No node associated"
@@ -4067,6 +4303,13 @@ msgstr "No node associated"
msgid "Host Snapin History"
msgstr "Snapin History"
+#, fuzzy
+msgid "Host Software Assignment"
+msgstr "Snapin History"
+
+msgid "Host Software Status"
+msgstr ""
+
#, fuzzy
msgid "Host Task History"
msgstr "Image History"
@@ -4160,6 +4403,12 @@ msgstr "Host List"
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
#, fuzzy
msgid "Hosts:"
msgstr "Hosts"
@@ -4224,6 +4473,10 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+#, fuzzy
+msgid "Identity"
+msgstr "Server Shell"
+
msgid "Identity Provider"
msgstr ""
@@ -4739,6 +4992,10 @@ msgstr "Installed Plugins"
msgid "Installed Plugins"
msgstr "Installed Plugins"
+#, fuzzy
+msgid "Installed Software"
+msgstr "Installed Plugins"
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4825,9 +5082,6 @@ msgstr "Invalid Snapin Tasking"
msgid "Invalid Storage Group"
msgstr "Invalid Storage Group"
-msgid "Invalid Storage Node"
-msgstr "Invalid Storage Node"
-
#, fuzzy
msgid "Invalid Tasking"
msgstr "Invalid task"
@@ -5011,6 +5265,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -5036,6 +5293,9 @@ msgstr ""
msgid "It will operate based on the fields the area typcially requires."
msgstr ""
+msgid "Join"
+msgstr ""
+
msgid "Join Domain after image task"
msgstr ""
@@ -5237,6 +5497,9 @@ msgstr "Language"
msgid "Largest images"
msgstr "Images"
+msgid "Last Agent Check-In"
+msgstr ""
+
#, fuzzy
msgid "Last Captured"
msgstr "Host Created"
@@ -5247,15 +5510,16 @@ msgstr ""
msgid "Last Check-In"
msgstr ""
-msgid "Last Client Check-In"
-msgstr ""
-
msgid "Last Deployed"
msgstr "Last Deployed"
msgid "Last Ping"
msgstr ""
+#, fuzzy
+msgid "Last Seen"
+msgstr "Host Created"
+
#, fuzzy
msgid "Last Successful Ping"
msgstr "Successful"
@@ -5271,6 +5535,10 @@ msgstr ""
msgid "Last deployed"
msgstr "Last Deployed"
+#, fuzzy
+msgid "Last error"
+msgstr "Error"
+
msgid "Last flush"
msgstr ""
@@ -5278,6 +5546,9 @@ msgstr ""
msgid "Last imaged"
msgstr "Images"
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
#, fuzzy
msgid "Latest Alpha Version"
msgstr "Latest Version"
@@ -5411,6 +5682,10 @@ msgstr "List All %s"
msgid "List All Snapins"
msgstr "Install Plugins"
+#, fuzzy
+msgid "List All Software"
+msgstr "List All %s"
+
#, fuzzy
msgid "List All Storage Groups"
msgstr "All Storage Groups"
@@ -5551,6 +5826,9 @@ msgstr "Log Viewer"
msgid "Log out and sign in as an administrator"
msgstr ""
+msgid "Logged on"
+msgstr ""
+
msgid "Logging"
msgstr ""
@@ -5743,6 +6021,9 @@ msgstr "Max Size"
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
#, fuzzy
msgid "Member"
msgstr "Members"
@@ -5823,6 +6104,10 @@ msgstr "Midnight"
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+#, fuzzy
+msgid "Mint an agent enrollment token"
+msgstr "Pending Registered Hosts"
+
msgid "Minute value is not valid"
msgstr "Minute value is not valid"
@@ -5830,6 +6115,9 @@ msgstr "Minute value is not valid"
msgid "Minutes field is invalid"
msgstr "Minute value is not valid"
+msgid "Missing"
+msgstr ""
+
msgid "Missing a temporary folder"
msgstr "Missing a temporary folder"
@@ -6298,6 +6586,10 @@ msgstr "No open slots"
msgid "No password is needed. Issue this account a token from its API tab, or from FOG Configuration → API Tokens, once it has been created."
msgstr ""
+#, fuzzy
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr "No Active Task found for Host"
+
#, fuzzy
msgid "No plugin tasks to run"
msgstr "No valid class sent"
@@ -6352,6 +6644,10 @@ msgstr "Snapin updated"
msgid "No snapins associated with this group as master"
msgstr "There are no snapins associated with this host"
+#, fuzzy
+msgid "No storage node can serve the file."
+msgstr "Add snapin failed!"
+
#, fuzzy
msgid "No storage nodes assigned to this storage group"
msgstr "Could not find a Storage Node Is there one enabled within this Storage Group"
@@ -6364,6 +6660,9 @@ msgstr "An image already exists with this name!"
msgid "No storagegroups assigned to this snapin"
msgstr "The image storage group assigned is not valid"
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -6373,6 +6672,9 @@ msgstr ""
msgid "No such object."
msgstr ""
+msgid "No such token."
+msgstr ""
+
msgid "No such user."
msgstr ""
@@ -6408,6 +6710,9 @@ msgstr ""
msgid "No values passed"
msgstr "No values passed"
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
#, fuzzy
msgid "No viable macs to use"
msgstr "Not able to update"
@@ -6463,6 +6768,9 @@ msgstr "Icon File not found"
msgid "Not Registered Hosts"
msgstr "Not Registered Hosts"
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr "Not a number"
@@ -6599,6 +6907,13 @@ msgstr "User updated"
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+#, fuzzy
+msgid "Observed domain"
+msgstr "General Information"
+
msgid "Off"
msgstr ""
@@ -6655,6 +6970,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr "Error, Is an image associated with this host"
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -6738,6 +7059,12 @@ msgstr ""
msgid "Operations on %s."
msgstr "Operation Field not set: %s"
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -6783,9 +7110,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -6867,6 +7200,10 @@ msgstr ""
msgid "Pending"
msgstr "Pending..."
+#, fuzzy
+msgid "Pending Agents"
+msgstr "Pending MACs"
+
msgid "Pending Hosts"
msgstr "Pending Hosts"
@@ -6884,9 +7221,31 @@ msgstr "Pending MACs"
msgid "Pending Registered Hosts"
msgstr "Pending Registered Hosts"
+#, fuzzy
+msgid "Pending Registration created by FOG_AGENT"
+msgstr "Pending Registration created by FOG_CLIENT"
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr "Pending Registration created by FOG_CLIENT"
+#, fuzzy
+msgid "Pending agent"
+msgstr "Pending hosts"
+
+#, fuzzy
+msgid "Pending agent enrollments"
+msgstr "Pending Registered Hosts"
+
+#, fuzzy
+msgid "Pending agents"
+msgstr "Pending macs"
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
#, fuzzy
msgid "Pending host"
msgstr "Pending hosts"
@@ -6933,6 +7292,16 @@ msgstr "Status"
msgid "Ping cycle complete"
msgstr "has been destroyed"
+msgid "Pinned"
+msgstr ""
+
+#, fuzzy
+msgid "Placement"
+msgstr "Task Management"
+
+msgid "Platform"
+msgstr ""
+
msgid "Please Select an option"
msgstr "Please Select an option"
@@ -6977,10 +7346,18 @@ msgstr ""
msgid "Please enter a name"
msgstr "Please enter a valid hostname"
+#, fuzzy
+msgid "Please enter a package id."
+msgstr "Please enter a valid hostname"
+
#, fuzzy
msgid "Please enter a printer name."
msgstr "Please enter a valid hostname"
+#, fuzzy
+msgid "Please enter a software name."
+msgstr "Please enter a valid hostname"
+
#, fuzzy
msgid "Please enter a valid CIDR subnet."
msgstr "Please enter a valid hostname"
@@ -6994,6 +7371,10 @@ msgstr ""
msgid "Please physically associate"
msgstr ""
+#, fuzzy
+msgid "Please select a valid backend."
+msgstr "Select a valid image"
+
#, fuzzy
msgid "Please select a valid certificate verification level"
msgstr "Select a valid image"
@@ -7014,6 +7395,10 @@ msgstr "Select a valid image"
msgid "Please select a valid printer type."
msgstr "Select a valid image"
+#, fuzzy
+msgid "Please select a valid state."
+msgstr "Select a valid image"
+
#, fuzzy
msgid "Please select an LDAP server!"
msgstr "Please select an option"
@@ -7229,6 +7614,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -7275,6 +7663,10 @@ msgstr "Printer update failed!"
msgid "Printer Create Success"
msgstr "Printer already exists"
+#, fuzzy
+msgid "Printer Deployment"
+msgstr "Printer Management"
+
msgid "Printer Description"
msgstr "Printer Description"
@@ -7432,6 +7824,9 @@ msgstr "Printer updated!"
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
msgid "Pushbullet Accounts"
msgstr "Pushbullet Accounts"
@@ -7473,6 +7868,10 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr "Snapin is protected and cannot be deleted"
+#, fuzzy
+msgid "Quick tasks"
+msgstr "Active Multicast Tasks"
+
msgid "RESOURCES"
msgstr ""
@@ -7485,6 +7884,9 @@ msgstr "RX"
msgid "Re-Transmit Hello Interval"
msgstr ""
+msgid "Re-check Interval"
+msgstr ""
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -7505,6 +7907,9 @@ msgstr "Delete Selected"
msgid "Real Time"
msgstr "Host Update Failed"
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr "Reboot"
@@ -7533,6 +7938,9 @@ msgstr ""
msgid "Recorded in range"
msgstr "Record not found, Error: %s"
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
#, fuzzy
msgid "Records"
msgstr "Current Records"
@@ -7546,10 +7954,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-#, fuzzy
-msgid "Refresh"
-msgstr "Default Refresh Rate"
-
#, fuzzy
msgid "Refresh Settings Cache"
msgstr "Service Status"
@@ -7695,6 +8099,10 @@ msgstr "Report"
msgid "Report Management"
msgstr "Report Management"
+#, fuzzy
+msgid "Reported"
+msgstr "Report"
+
msgid "Reports"
msgstr "Reports"
@@ -7760,9 +8168,16 @@ msgstr ""
msgid "Retention sweep failed"
msgstr "Removed"
+msgid "Retry"
+msgstr ""
+
msgid "Return Code"
msgstr "Return Code"
+#, fuzzy
+msgid "Return Codes"
+msgstr "Return Code"
+
msgid "Return To Local Login"
msgstr ""
@@ -7773,9 +8188,33 @@ msgstr "Return Code"
msgid "Returning value of key"
msgstr "Returning value of key"
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+#, fuzzy
+msgid "Revoke an agent enrollment token"
+msgstr "Pending Registered Hosts"
+
+#, fuzzy
+msgid "Revoke selected"
+msgstr "Remove selected snapins"
+
+#, fuzzy
+msgid "Revoked selected tokens."
+msgstr "Approve selected Hosts"
+
+msgid "Revoked."
+msgstr ""
+
#, fuzzy
msgid "Role"
msgstr "Module Name"
@@ -7916,6 +8355,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
#, fuzzy
msgid "SQL Error"
msgstr "SQL Error:"
@@ -8034,16 +8476,6 @@ msgstr "Install / Update Successful!"
msgid "Scopes"
msgstr ""
-msgid "Screen Height"
-msgstr ""
-
-#, fuzzy
-msgid "Screen Refresh Rate"
-msgstr "Default Refresh Rate"
-
-msgid "Screen Width"
-msgstr ""
-
msgid "Search"
msgstr "Search"
@@ -8279,6 +8711,9 @@ msgstr "A hostname with that name already exists."
msgid "Sessions canceled!"
msgstr "has been successfully updated"
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -8745,6 +9180,63 @@ msgstr "Snapins"
msgid "So if you are trying to transmit to remote node A"
msgstr ""
+msgid "Software"
+msgstr ""
+
+#, fuzzy
+msgid "Software Create Fail"
+msgstr "Printer update failed!"
+
+#, fuzzy
+msgid "Software Create Success"
+msgstr "Printer already exists"
+
+#, fuzzy
+msgid "Software Host Associations"
+msgstr "No node associated"
+
+#, fuzzy
+msgid "Software Management"
+msgstr "Storage Management"
+
+#, fuzzy
+msgid "Software Name"
+msgstr "Printer Name"
+
+msgid "Software Order"
+msgstr ""
+
+#, fuzzy
+msgid "Software Report"
+msgstr "Host ID"
+
+#, fuzzy
+msgid "Software Status"
+msgstr "Create New %s"
+
+#, fuzzy
+msgid "Software Update Fail"
+msgstr "Printer update failed!"
+
+#, fuzzy
+msgid "Software Update Success"
+msgstr "Install / Update Successful!"
+
+#, fuzzy
+msgid "Software added!"
+msgstr "Printer Name"
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+#, fuzzy
+msgid "Software update failed!"
+msgstr "Printer update failed!"
+
+#, fuzzy
+msgid "Software updated!"
+msgstr "Printer updated!"
+
msgid "Some nice description, should be short."
msgstr ""
@@ -8757,6 +9249,9 @@ msgstr ""
msgid "Specified download URL not allowed!"
msgstr ""
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -9508,6 +10003,9 @@ msgstr "There are no groups on this server."
msgid "The CA private key is on this server"
msgstr "There are no groups on this server."
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -9541,6 +10039,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -9585,6 +10086,9 @@ msgstr " | File or path cannot be reached"
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -9625,6 +10129,13 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+#, fuzzy
+msgid "The enrollment is no longer pending."
+msgstr " no longer exists"
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -9652,6 +10163,15 @@ msgstr ""
msgid "The grid key."
msgstr "Failed to create task"
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
#, fuzzy
msgid "The identity provider could not be reached"
msgstr "Could not read temp file"
@@ -9706,9 +10226,16 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+#, fuzzy
+msgid "The item is not a live row of this host."
+msgstr "No Active Task found for Host"
+
msgid "The key will be assigned to registered hosts when a"
msgstr ""
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -9738,12 +10265,21 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
msgid "The path requested is already in use by another image!"
msgstr ""
+msgid "The payload bytes."
+msgstr ""
+
#, fuzzy
msgid "The plugin directory"
msgstr "Directory"
@@ -9788,6 +10324,13 @@ msgstr ""
msgid "The record could not be written."
msgstr "Could not read temp file"
+#, fuzzy
+msgid "The renewed certificate, leaf then chain."
+msgstr "Create New %s"
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -9797,6 +10340,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -9808,6 +10354,12 @@ msgstr "Printer update failed!"
msgid "The selected site no longer exists"
msgstr " no longer exists"
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -9827,6 +10379,13 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+#, fuzzy
+msgid "The signing helper is not available on this server."
+msgstr "There are no groups on this server."
+
#, fuzzy
msgid "The signing request could not be generated"
msgstr "Could not read temp file"
@@ -9847,6 +10406,10 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+#, fuzzy
+msgid "The token."
+msgstr "CPU Count"
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -10008,6 +10571,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -10068,10 +10634,16 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, fuzzy, php-format
msgid "This machine already registered as %s"
msgstr "Already registered as"
+msgid "This module has no settings to configure."
+msgstr ""
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -10180,6 +10752,13 @@ msgstr "Time Already Exists"
msgid "Time since last imaged"
msgstr ""
+#, fuzzy
+msgid "Timeout"
+msgstr "Time"
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -10202,9 +10781,31 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Image Association"
+#, fuzzy
+msgid "Token Create Fail"
+msgstr "Printer update failed!"
+
+#, fuzzy
+msgid "Token Create Success"
+msgstr "Printer already exists"
+
+#, fuzzy
+msgid "Token Revoke Fail"
+msgstr "FTP Connection has failed"
+
+#, fuzzy
+msgid "Token Revoke Success"
+msgstr "Printer already exists"
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
#, fuzzy
msgid "Too many MACs"
msgstr "Host Primary MAC"
@@ -10391,6 +10992,9 @@ msgstr "User Name"
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
#, fuzzy
msgid "Unauthenticated."
msgstr "Error contacting server"
@@ -10441,6 +11045,9 @@ msgstr "Unknown upload error occurred. Return code: "
msgid "Unknown action"
msgstr "Unknown upload error occurred. Return code: "
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -10470,6 +11077,9 @@ msgstr "Unknown upload error occurred. Return code: "
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
#, fuzzy
msgid "Unmark selected client ignore"
msgstr "Approve selected Hosts"
@@ -10559,6 +11169,9 @@ msgstr "Remove selected printers"
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
#, fuzzy
msgid "Upload"
msgstr "Upload Reports"
@@ -10671,9 +11284,6 @@ msgstr "User Already Exists"
msgid "User Association"
msgstr "Image Association"
-msgid "User Cleanup"
-msgstr "User Cleanup"
-
#, fuzzy
msgid "User Count"
msgstr "CPU Count"
@@ -10759,6 +11369,10 @@ msgstr "User Name"
msgid "User Password"
msgstr "User Password"
+#, fuzzy
+msgid "User Sessions"
+msgstr "Image Association"
+
msgid "User Tracker"
msgstr "User Tracker"
@@ -10841,6 +11455,12 @@ msgstr "Users"
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr ""
@@ -10866,6 +11486,10 @@ msgstr "Version"
msgid "Version information and paging bounds."
msgstr "FOG Version Information"
+#, fuzzy
+msgid "Version policy"
+msgstr "Version"
+
#, fuzzy
msgid "Versions"
msgstr "Version"
@@ -10895,6 +11519,9 @@ msgstr "Wake on lan?"
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -10948,12 +11575,18 @@ msgstr "has been successfully updated"
msgid "What it does"
msgstr "has been successfully updated"
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -10969,6 +11602,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr ""
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -10981,10 +11617,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -11059,6 +11695,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr "Yearly"
@@ -11181,6 +11820,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
#, fuzzy
msgid "access"
msgstr "Access"
@@ -11192,10 +11834,17 @@ msgstr "Additional MACs"
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
#, fuzzy
msgid "ago"
msgstr " ago"
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
#, fuzzy
msgid "all current storage nodes"
msgstr "Invalid storage node"
@@ -11229,6 +11878,13 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+#, fuzzy
+msgid "any version"
+msgstr "Version"
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
#, fuzzy
msgid "architecture not recorded"
msgstr "Could not read temp file"
@@ -11240,6 +11896,10 @@ msgstr ""
msgid "as its primary group"
msgstr "Update Primary Group"
+#, fuzzy
+msgid "assigned"
+msgstr "No node associated"
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -11346,6 +12006,9 @@ msgstr "Enabled"
msgid "does not exist and cannot be created"
msgstr "Image is protected and cannot be deleted"
+msgid "domain"
+msgstr ""
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -11355,6 +12018,9 @@ msgstr ""
msgid "either because you have updated"
msgstr ""
+msgid "empty means never install Chocolatey"
+msgstr ""
+
#, fuzzy
msgid "error"
msgstr "Error"
@@ -11362,10 +12028,20 @@ msgstr "Error"
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+#, fuzzy
+msgid "failed"
+msgstr "Failed"
+
#, fuzzy
msgid "failed to execute, image file"
msgstr "Failed to delete image files"
@@ -11465,6 +12141,10 @@ msgstr ""
msgid "host"
msgstr "host"
+#, fuzzy, php-format
+msgid "host \"%s\""
+msgstr "host"
+
#, fuzzy
msgid "host is"
msgstr "host"
@@ -11580,9 +12260,6 @@ msgstr ""
msgid "in"
msgstr "minutes"
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
@@ -11590,9 +12267,6 @@ msgstr ""
msgid "in minutes"
msgstr "minutes"
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr ""
@@ -11667,6 +12341,10 @@ msgstr "DMI Key"
msgid "keys"
msgstr ""
+#, fuzzy
+msgid "latest"
+msgstr "Replicate?"
+
msgid "leave to keep the current one"
msgstr ""
@@ -11700,6 +12378,10 @@ msgstr "minutes"
msgid "mismatched"
msgstr ""
+#, fuzzy
+msgid "missing"
+msgstr "Version"
+
msgid "moments from now"
msgstr ""
@@ -11737,6 +12419,10 @@ msgstr ""
msgid "never"
msgstr ""
+#, fuzzy
+msgid "never reported"
+msgstr "Inventory"
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -11769,6 +12455,9 @@ msgstr ""
msgid "not found on this node"
msgstr "Image not found on node"
+msgid "not joined"
+msgstr ""
+
#, fuzzy
msgid "not reachable"
msgstr "Not Available"
@@ -11799,10 +12488,16 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+msgid "off"
+msgstr ""
+
#, fuzzy
msgid "off means an account must already exist"
msgstr "Printer already exists"
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -11816,6 +12511,9 @@ msgstr ""
msgid "optional"
msgstr "Location"
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
msgid "or"
msgstr "or"
@@ -12093,6 +12791,10 @@ msgstr "Not Available"
msgid "unchanged for"
msgstr "Imaged"
+#, fuzzy
+msgid "unknown action"
+msgstr "Unknown upload error occurred. Return code: "
+
msgid "unrecorded"
msgstr ""
@@ -12320,6 +13022,10 @@ msgstr ""
#~ msgid "CA private key"
#~ msgstr "Private key failed"
+#, fuzzy
+#~ msgid "Cannot connect to ftp server"
+#~ msgstr "Cannot connect to database"
+
#~ msgid "Check that database is running"
#~ msgstr "Check that database is running"
@@ -12327,6 +13033,10 @@ msgstr ""
#~ msgid "Client Module Settings"
#~ msgstr "Settings"
+#, fuzzy
+#~ msgid "Could not read snapin file"
+#~ msgstr "Could not read tmp file."
+
#, fuzzy
#~ msgid "Create New Accesscontrol"
#~ msgstr "Create New %s"
@@ -12351,6 +13061,15 @@ msgstr ""
#~ msgid "Database connection unavailable"
#~ msgstr "No hash available"
+#~ msgid "Default Height"
+#~ msgstr "Default Height"
+
+#~ msgid "Default Refresh Rate"
+#~ msgstr "Default Refresh Rate"
+
+#~ msgid "Default Width"
+#~ msgstr "Default Width"
+
#, fuzzy
#~ msgid "Delete All"
#~ msgstr "Delete file data"
@@ -12359,6 +13078,9 @@ msgstr ""
#~ msgid "Deprecated."
#~ msgstr "Create"
+#~ msgid "Directory Cleaner"
+#~ msgstr "Directory Cleaner"
+
#, fuzzy
#~ msgid "Domain joining"
#~ msgstr "Domain name"
@@ -12421,6 +13143,18 @@ msgstr ""
#~ msgid "Export Users"
#~ msgstr "Export Users"
+#, fuzzy
+#~ msgid "FOG Agent desired state"
+#~ msgstr "has been successfully updated"
+
+#, fuzzy
+#~ msgid "FOG Agent snapin result"
+#~ msgstr "No file was uploaded"
+
+#, fuzzy
+#~ msgid "FOG Agent software result"
+#~ msgstr "No file was uploaded"
+
#~ msgid "Failed to add/update snapin file"
#~ msgstr "Failed to add/update snapin file"
@@ -12532,10 +13266,18 @@ msgstr ""
#~ msgid "Group module settings"
#~ msgstr "Update Settings"
+#, fuzzy
+#~ msgid "Height"
+#~ msgstr "Midnight"
+
#, fuzzy
#~ msgid "History Report"
#~ msgstr "Host ID"
+#, fuzzy
+#~ msgid "Host Display Manager Settings"
+#~ msgstr "Settings"
+
#, fuzzy
#~ msgid "Host Ext"
#~ msgstr "Host List"
@@ -12552,6 +13294,10 @@ msgstr ""
#~ msgid "Host Ext Variable"
#~ msgstr "User update failed"
+#, fuzzy
+#~ msgid "Host Screen Resolution"
+#~ msgstr "Host Registration"
+
#, fuzzy
#~ msgid "Host Site"
#~ msgstr "Host List"
@@ -12655,6 +13401,9 @@ msgstr ""
#~ msgid "Install"
#~ msgstr "Installed Plugins"
+#~ msgid "Invalid Storage Node"
+#~ msgstr "Invalid Storage Node"
+
#, fuzzy
#~ msgid "Invalid Type"
#~ msgstr "Invalid type"
@@ -12678,6 +13427,14 @@ msgstr ""
#~ msgid "LDAP User Filter"
#~ msgstr "LDAP Server"
+#, fuzzy
+#~ msgid "Last Activity"
+#~ msgstr "Active"
+
+#, fuzzy
+#~ msgid "Last Event"
+#~ msgstr "Host Created"
+
#, fuzzy
#~ msgid "Latest SVN Version"
#~ msgstr "Latest Version"
@@ -12732,6 +13489,14 @@ msgstr ""
#~ msgid "Not Installed"
#~ msgstr "Installed Plugins"
+#, fuzzy
+#~ msgid "Not a live task of this host's job."
+#~ msgstr "No Active Task found for Host"
+
+#, fuzzy
+#~ msgid "Not an entry in this host's software set."
+#~ msgstr "No Active Task found for Host"
+
#, fuzzy
#~ msgid "Pause"
#~ msgstr "User"
@@ -12759,6 +13524,14 @@ msgstr ""
#~ msgid "Product Keys"
#~ msgstr "Host Product Key"
+#, fuzzy
+#~ msgid "Recorded."
+#~ msgstr "Current Records"
+
+#, fuzzy
+#~ msgid "Refresh"
+#~ msgstr "Default Refresh Rate"
+
#, fuzzy
#~ msgid "Release Version"
#~ msgstr "Latest Version"
@@ -12825,6 +13598,10 @@ msgstr ""
#~ msgid "Rule update failed!"
#~ msgstr "Printer update failed!"
+#, fuzzy
+#~ msgid "Screen Refresh Rate"
+#~ msgstr "Default Refresh Rate"
+
#, fuzzy
#~ msgid "Serial"
#~ msgstr "System Serial"
@@ -12866,8 +13643,16 @@ msgstr ""
#~ msgstr "Printer already exists"
#, fuzzy
-#~ msgid "The certificate chain"
-#~ msgstr "Create New %s"
+#~ msgid "The desired state."
+#~ msgstr "Failed to create task"
+
+#, fuzzy
+#~ msgid "The host this certificate is, and the capabilities this server offers."
+#~ msgstr "There are no groups on this server."
+
+#, fuzzy
+#~ msgid "The task was already closed."
+#~ msgstr "Printer already exists"
#, fuzzy
#~ msgid "There are no "
@@ -12912,6 +13697,10 @@ msgstr ""
#~ msgid "Unable to set user filter."
#~ msgstr "Unable to open file for reading"
+#, fuzzy
+#~ msgid "Unknown status."
+#~ msgstr "Unknown upload error occurred. Return code: "
+
#, fuzzy
#~ msgid "Update Master Node"
#~ msgstr "Master Node"
@@ -12924,6 +13713,9 @@ msgstr ""
#~ msgid "Update/Remove printers"
#~ msgstr "Update Printer"
+#~ msgid "User Cleanup"
+#~ msgstr "User Cleanup"
+
#, fuzzy
#~ msgid "User Group Site"
#~ msgstr "Export Snapins"
@@ -13010,10 +13802,6 @@ msgstr ""
#~ msgid "min (all)"
#~ msgstr "Enabled"
-#, fuzzy
-#~ msgid "multicast tasks!"
-#~ msgstr "Active Multicast Tasks"
-
#, fuzzy
#~ msgid "no database to"
#~ msgstr "No database to work off"
@@ -13029,7 +13817,3 @@ msgstr ""
#, fuzzy
#~ msgid "username"
#~ msgstr "Username"
-
-#, fuzzy
-#~ msgid "version"
-#~ msgstr "Version"
diff --git a/packages/web/management/languages/es_ES.UTF-8/LC_MESSAGES/messages.po b/packages/web/management/languages/es_ES.UTF-8/LC_MESSAGES/messages.po
index 7e28ce0a52..01f60ed7df 100644
--- a/packages/web/management/languages/es_ES.UTF-8/LC_MESSAGES/messages.po
+++ b/packages/web/management/languages/es_ES.UTF-8/LC_MESSAGES/messages.po
@@ -123,6 +123,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -292,6 +296,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, fuzzy, php-format
+msgid "(deleted host %d)"
+msgstr "retirar"
+
msgid "(deleted user)"
msgstr ""
@@ -311,9 +319,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr "Argumentos grupo Kernel"
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
#, fuzzy
msgid "1 Hour"
msgstr "1 hora"
@@ -418,6 +432,12 @@ msgstr "Una imagen ya existe con este nombre!"
msgid "A client ID is required"
msgstr "Se requiere un nombre de imagen!"
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
#, fuzzy
msgid "A dmi field must be set!"
msgstr "Evento debe ser una cadena"
@@ -481,6 +501,9 @@ msgstr "Una imagen ya existe con este nombre!"
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
#, fuzzy
msgid "A module already exists with this name!"
msgstr "Una imagen ya existe con este nombre!"
@@ -502,6 +525,9 @@ msgstr "No disponible"
msgid "A permission name is required."
msgstr "Se requiere un nombre de imagen!"
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -524,6 +550,9 @@ msgstr "Una imagen ya existe con este nombre!"
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
#, fuzzy
msgid "A role already exists with this name!"
msgstr "Una imagen ya existe con este nombre!"
@@ -564,6 +593,10 @@ msgstr "Una imagen ya existe con este nombre!"
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+#, fuzzy
+msgid "A software entry already exists with this name!"
+msgstr "Una imagen ya existe con este nombre!"
+
#, fuzzy
msgid "A storage group already exists with this name!"
msgstr "Una imagen ya existe con este nombre!"
@@ -700,6 +733,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -943,6 +982,10 @@ msgstr "Añadir fallidos SNAPin!"
msgid "Add snapin failed!"
msgstr "Añadir fallidos SNAPin!"
+#, fuzzy
+msgid "Add software failed!"
+msgstr "Añadir fallidos SNAPin!"
+
#, fuzzy
msgid "Add storage node failed!"
msgstr "Añadir fallidos SNAPin!"
@@ -1028,6 +1071,33 @@ msgstr "Avanzado"
msgid "Advanced Tasks"
msgstr "Avanzado"
+msgid "Agent"
+msgstr ""
+
+#, fuzzy
+msgid "Agent Activity"
+msgstr "Activo"
+
+#, fuzzy
+msgid "Agent Approval Success"
+msgstr "Creado"
+
+#, fuzzy
+msgid "Agent Denial Success"
+msgstr "Impresora actualiza!"
+
+#, fuzzy
+msgid "Agent Enrollment Tokens"
+msgstr "se ha actualizado correctamente"
+
+#, fuzzy
+msgid "Agent Tokens"
+msgstr "Nombre de usuario"
+
+#, fuzzy
+msgid "Agent enrollment tokens"
+msgstr "se ha actualizado correctamente"
+
msgid "Ago must be boolean"
msgstr ""
@@ -1045,6 +1115,10 @@ msgstr ""
msgid "All Hosts"
msgstr "Hospedadores"
+#, fuzzy
+msgid "All Pending Agents"
+msgstr "macs pendientes"
+
#, fuzzy
msgid "All Pending Hosts"
msgstr "anfitriones pendientes"
@@ -1149,10 +1223,16 @@ msgstr ""
msgid "An SQL error occurred"
msgstr "Se produjo un error de carga desconocida. Código de retorno: "
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
#, fuzzy
msgid "An entry already exists with this name!"
msgstr "Una imagen ya existe con este nombre!"
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr "Una imagen ya existe con este nombre!"
@@ -1192,6 +1272,10 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+#, fuzzy
+msgid "Any version"
+msgstr "Versión"
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1230,18 +1314,36 @@ msgstr ""
msgid "Approve"
msgstr "Creado"
+#, fuzzy
+msgid "Approve Agent Fail"
+msgstr "Creado"
+
#, fuzzy
msgid "Approve MAC Fail"
msgstr "Creado"
+#, fuzzy
+msgid "Approve Pending Agents"
+msgstr "anfitriones pendientes"
+
#, fuzzy
msgid "Approve Pending Hosts"
msgstr "anfitriones pendientes"
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
#, fuzzy
msgid "Approve selected"
msgstr "retirar"
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+#, fuzzy
+msgid "Approved selected agents!"
+msgstr "retirar"
+
#, fuzzy
msgid "Approved selected hosts!"
msgstr "retirar"
@@ -1254,6 +1356,9 @@ msgstr "retirar"
msgid "Approving the selected pending hosts."
msgstr "retirar"
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1263,6 +1368,10 @@ msgstr ""
msgid "Area"
msgstr ""
+#, fuzzy
+msgid "Assigned"
+msgstr "No nodo asociado"
+
#, fuzzy
msgid "Assigned Group"
msgstr "Nombre del grupo de almacenamiento"
@@ -1324,6 +1433,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1363,6 +1475,9 @@ msgstr "Vendedor del BIOS"
msgid "BIOS Version"
msgstr "Versión de la BIOS"
+msgid "Backend"
+msgstr ""
+
#, fuzzy
msgid "Bad request."
msgstr "%s se requiere"
@@ -1600,6 +1715,10 @@ msgstr "tarea Cancelado"
msgid "Canceled due to new tasking."
msgstr "Cancelada debido a las nuevas tareas a la vez."
+#, fuzzy
+msgid "Cannot Run"
+msgstr "Registro no encontrado, error: %s"
+
#, fuzzy
msgid "Cannot bind to the LDAP server"
msgstr "Error: No se pudo descargar kernel"
@@ -1613,10 +1732,6 @@ msgstr ""
msgid "Cannot connect to database"
msgstr ""
-#, fuzzy
-msgid "Cannot connect to ftp server"
-msgstr "Error: No se pudo descargar kernel"
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1812,6 +1927,9 @@ msgstr ""
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+msgid "Checked"
+msgstr ""
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1824,6 +1942,12 @@ msgstr ""
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1999,14 +2123,23 @@ msgstr "Error: No se pudo descargar kernel"
msgid "Confirm you would like to download a new kernel"
msgstr "Error: No se pudo descargar kernel"
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
#, fuzzy
msgid "Copy from existing"
msgstr "No se pudo crear la impresora"
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -2079,10 +2212,6 @@ msgstr "No se pudo leer el archivo tmp."
msgid "Could not read local file"
msgstr "No se pudo leer el archivo temporal"
-#, fuzzy
-msgid "Could not read snapin file"
-msgstr "No se pudo leer el archivo tmp."
-
#, fuzzy
msgid "Could not read the database structure"
msgstr "No se pudo crear Complemento de empleo"
@@ -2179,6 +2308,9 @@ msgstr ""
msgid "Create"
msgstr "Crear"
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -2261,6 +2393,9 @@ msgstr "Crear nuevo sitio"
msgid "Create New Snapin"
msgstr "Crear nuevo snapin"
+msgid "Create New Software"
+msgstr "Crear nuevo software"
+
msgid "Create New Storage Group"
msgstr "Crear nuevo grupo de almacenamiento"
@@ -2308,6 +2443,10 @@ msgstr "creado por el usuario"
msgid "Create Users On First Login"
msgstr ""
+#, fuzzy, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr "creado por el usuario"
+
#, fuzzy, php-format
msgid "Create a %s"
msgstr "Crear nuevo grupo"
@@ -2331,9 +2470,17 @@ msgstr "creado por el usuario"
msgid "Create task form success"
msgstr "creado por el usuario"
+#, fuzzy
+msgid "Create tasking"
+msgstr "Crear nuevo grupo"
+
msgid "Create tasking succeeded"
msgstr ""
+#, fuzzy
+msgid "Create token"
+msgstr "Crear nuevo grupo"
+
#, fuzzy
msgid "Created"
msgstr "Crear"
@@ -2346,6 +2493,10 @@ msgstr "Creado"
msgid "Created Time"
msgstr "Creado"
+#, fuzzy
+msgid "Created by"
+msgstr "Creado"
+
msgid "Created by FOG Reg on"
msgstr ""
@@ -2478,6 +2629,9 @@ msgstr "Opciones de arranque:"
msgid "Debug Task"
msgstr "Opciones de arranque:"
+msgid "Decided."
+msgstr ""
+
#, fuzzy
msgid "Default"
msgstr "Defecto"
@@ -2486,15 +2640,6 @@ msgstr "Defecto"
msgid "Default Choice"
msgstr "Tema por defecto:"
-msgid "Default Height"
-msgstr "Altura por defecto"
-
-msgid "Default Refresh Rate"
-msgstr "Frecuencia de actualización predeterminado"
-
-msgid "Default Width"
-msgstr "Ancho por defecto"
-
#, fuzzy
msgid "Default init, ARM64"
msgstr "Ancho por defecto"
@@ -2580,6 +2725,28 @@ msgstr ""
msgid "Deleting remote file"
msgstr "Menú Error de creación"
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+#, fuzzy
+msgid "Denied selected agents!"
+msgstr "retirar"
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy
+msgid "Deny Agent Fail"
+msgstr "Eliminar los datos del archivo"
+
+#, fuzzy
+msgid "Deny Pending Agents"
+msgstr "macs pendientes"
+
+#, fuzzy
+msgid "Deny selected"
+msgstr "Eliminar seleccionado"
+
#, fuzzy
msgid "Deploy"
msgstr "última Desplegado"
@@ -2599,13 +2766,28 @@ msgstr ""
msgid "Description"
msgstr "Descripción:"
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+msgid "Desired domain"
+msgstr ""
+
#, fuzzy
msgid "Destroy failed"
msgstr "Destruir fallado: %s"
+msgid "Detail"
+msgstr ""
+
msgid "Details"
msgstr ""
+msgid "Device URI"
+msgstr ""
+
#, fuzzy
msgid "Device must be a string"
msgstr "Evento debe ser una cadena"
@@ -2621,10 +2803,6 @@ msgstr "Directorio"
msgid "Directory Already Exists"
msgstr "nombre de usuario ya existe"
-#, fuzzy
-msgid "Directory Cleaner"
-msgstr "directorios Cleaned"
-
#, fuzzy
msgid "Directory Group"
msgstr "Directorio"
@@ -2633,6 +2811,10 @@ msgstr "Directorio"
msgid "Directory Group Name"
msgstr "Directorio"
+#, fuzzy
+msgid "Directory Membership"
+msgstr "miembros"
+
#, fuzzy
msgid "Disable on all hosts"
msgstr "habilitado"
@@ -2749,6 +2931,9 @@ msgstr "Descarga fracasó"
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2769,6 +2954,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr "Editar"
@@ -2865,6 +3053,10 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+#, fuzzy
+msgid "Enrollment Token"
+msgstr "Gestión de usuarios"
+
msgid "Enrollment kit"
msgstr ""
@@ -2969,6 +3161,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
#, fuzzy
msgid "Every file was uploaded."
msgstr "Ningún archivo fue subido"
@@ -2989,6 +3187,14 @@ msgstr "clave privada fracasó"
msgid "Exists item must be boolean"
msgstr ""
+#, fuzzy
+msgid "Exit Code"
+msgstr "snapins"
+
+#, fuzzy
+msgid "Exit code"
+msgstr "Código de retorno"
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -3069,10 +3275,33 @@ msgstr "Fecha"
msgid "External root CA"
msgstr ""
+#, fuzzy
+msgid "Extra arguments"
+msgstr "Nombre snapin"
+
#, fuzzy
msgid "FOG"
msgstr "En "
+#, fuzzy
+msgid "FOG Agent capability result"
+msgstr "Ningún archivo fue subido"
+
+#, fuzzy
+msgid "FOG Agent certificate renewal"
+msgstr "Ningún archivo fue subido"
+
+#, fuzzy
+msgid "FOG Agent enrollment"
+msgstr "se ha actualizado correctamente"
+
+#, fuzzy
+msgid "FOG Agent payload"
+msgstr "Ningún archivo fue subido"
+
+msgid "FOG Agent poll"
+msgstr ""
+
#, fuzzy
msgid "FOG Client"
msgstr "FOG Wiki Cliente"
@@ -3444,6 +3673,9 @@ msgstr "Nombre de la tarea"
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3788,6 +4020,10 @@ msgstr "Camino snapin"
msgid "Group Snapin History"
msgstr "Camino snapin"
+#, fuzzy
+msgid "Group Software Assignment"
+msgstr "Camino snapin"
+
#, fuzzy
msgid "Group Task History"
msgstr "replicador de imagen"
@@ -3877,9 +4113,15 @@ msgstr "Información general"
msgid "Hardware Report"
msgstr "Información general"
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr ""
+msgid "Hash Mismatch"
+msgstr ""
+
msgid "Have not locked the host for access"
msgstr ""
@@ -3887,10 +4129,6 @@ msgstr ""
msgid "Header is missing the required \"%s\" column"
msgstr ""
-#, fuzzy
-msgid "Height"
-msgstr "Medianoche"
-
msgid "Height must be 120 pixels."
msgstr ""
@@ -3964,6 +4202,9 @@ msgstr "Impresora ya existe"
msgid "Host %1$s finished deploying image %2$s."
msgstr "Impresora ya existe"
+msgid "Host Agent Activity"
+msgstr ""
+
#, fuzzy
msgid "Host Approval Success"
msgstr "Creado"
@@ -4000,10 +4241,6 @@ msgstr "Tema por defecto:"
msgid "Host Description"
msgstr "Descripción del Grupo"
-#, fuzzy
-msgid "Host Display Manager Settings"
-msgstr "Configuración Tecla"
-
#, fuzzy
msgid "Host EFI Exit Type"
msgstr "Grupo EFI Tipo de salida"
@@ -4119,10 +4356,6 @@ msgstr "Clave del producto Grupo"
msgid "Host Registration"
msgstr "Lista de host"
-#, fuzzy
-msgid "Host Screen Resolution"
-msgstr "Lista de host"
-
#, fuzzy
msgid "Host Snapin Associations"
msgstr "No nodo asociado"
@@ -4131,6 +4364,13 @@ msgstr "No nodo asociado"
msgid "Host Snapin History"
msgstr "Camino snapin"
+#, fuzzy
+msgid "Host Software Assignment"
+msgstr "Camino snapin"
+
+msgid "Host Software Status"
+msgstr ""
+
#, fuzzy
msgid "Host Task History"
msgstr "replicador de imagen"
@@ -4226,6 +4466,12 @@ msgstr "ID de host"
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
#, fuzzy
msgid "Hosts:"
msgstr "Hospedadores"
@@ -4292,6 +4538,10 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+#, fuzzy
+msgid "Identity"
+msgstr "servidor TFTP"
+
msgid "Identity Provider"
msgstr ""
@@ -4816,6 +5066,10 @@ msgstr "Instalador inteligente (recomendado)"
msgid "Installed Plugins"
msgstr ""
+#, fuzzy
+msgid "Installed Software"
+msgstr "Instalador inteligente (recomendado)"
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4906,10 +5160,6 @@ msgstr "Tipo de tarea no válida"
msgid "Invalid Storage Group"
msgstr "Grupo de almacenamiento"
-#, fuzzy
-msgid "Invalid Storage Node"
-msgstr "nodo de almacenamiento"
-
#, fuzzy
msgid "Invalid Tasking"
msgstr "tarea no válido"
@@ -5099,6 +5349,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -5124,6 +5377,9 @@ msgstr ""
msgid "It will operate based on the fields the area typcially requires."
msgstr ""
+msgid "Join"
+msgstr ""
+
msgid "Join Domain after image task"
msgstr ""
@@ -5333,6 +5589,9 @@ msgstr ""
msgid "Largest images"
msgstr "Imagen"
+msgid "Last Agent Check-In"
+msgstr ""
+
#, fuzzy
msgid "Last Captured"
msgstr "Creado"
@@ -5343,15 +5602,16 @@ msgstr ""
msgid "Last Check-In"
msgstr ""
-msgid "Last Client Check-In"
-msgstr ""
-
msgid "Last Deployed"
msgstr "última Desplegado"
msgid "Last Ping"
msgstr ""
+#, fuzzy
+msgid "Last Seen"
+msgstr "Creado"
+
#, fuzzy
msgid "Last Successful Ping"
msgstr "Exitoso"
@@ -5367,6 +5627,10 @@ msgstr ""
msgid "Last deployed"
msgstr "última Desplegado"
+#, fuzzy
+msgid "Last error"
+msgstr "Error"
+
msgid "Last flush"
msgstr ""
@@ -5374,6 +5638,9 @@ msgstr ""
msgid "Last imaged"
msgstr "Imagen"
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
#, fuzzy
msgid "Latest Alpha Version"
msgstr "Versión del sistema"
@@ -5502,6 +5769,9 @@ msgstr "Listar todos los sitios"
msgid "List All Snapins"
msgstr "Listar todos los snapins"
+msgid "List All Software"
+msgstr "Listar todo el software"
+
msgid "List All Storage Groups"
msgstr "Listar todos los grupos de almacenamiento"
@@ -5642,6 +5912,9 @@ msgstr "FOG Visor de registro"
msgid "Log out and sign in as an administrator"
msgstr ""
+msgid "Logged on"
+msgstr ""
+
msgid "Logging"
msgstr ""
@@ -5843,6 +6116,9 @@ msgstr "Tamaño máximo:"
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
#, fuzzy
msgid "Member"
msgstr "miembros"
@@ -5923,6 +6199,10 @@ msgstr "Medianoche"
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+#, fuzzy
+msgid "Mint an agent enrollment token"
+msgstr "anfitriones pendientes"
+
#, fuzzy
msgid "Minute value is not valid"
msgstr "tipo de tarea no es válida"
@@ -5931,6 +6211,9 @@ msgstr "tipo de tarea no es válida"
msgid "Minutes field is invalid"
msgstr "tipo de tarea no es válida"
+msgid "Missing"
+msgstr ""
+
msgid "Missing a temporary folder"
msgstr "Falta una carpeta temporal"
@@ -6407,8 +6690,12 @@ msgid "No password is needed. Issue this account a token from its API tab, or fr
msgstr ""
#, fuzzy
-msgid "No plugin tasks to run"
-msgstr "Ninguna clase válida enviado"
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr "No se encontró Clase FOGPage para este nodo"
+
+#, fuzzy
+msgid "No plugin tasks to run"
+msgstr "Ninguna clase válida enviado"
#, fuzzy
msgid "No plugin with that id."
@@ -6461,6 +6748,10 @@ msgstr "Nombre snapin"
msgid "No snapins associated with this group as master"
msgstr "No hay snapins asociados con este anfitrión"
+#, fuzzy
+msgid "No storage node can serve the file."
+msgstr "Añadir fallidos SNAPin!"
+
#, fuzzy
msgid "No storage nodes assigned to this storage group"
msgstr "Grupo de almacenamiento primaria"
@@ -6473,6 +6764,9 @@ msgstr "Una imagen ya existe con este nombre!"
msgid "No storagegroups assigned to this snapin"
msgstr "Marque aquí para ver los grupos no asignado esta imagen"
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -6482,6 +6776,9 @@ msgstr ""
msgid "No such object."
msgstr ""
+msgid "No such token."
+msgstr ""
+
msgid "No such user."
msgstr ""
@@ -6517,6 +6814,9 @@ msgstr ""
msgid "No values passed"
msgstr "No hay valores pasados"
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
#, fuzzy
msgid "No viable macs to use"
msgstr "No es capaz de actualizar"
@@ -6575,6 +6875,9 @@ msgstr "Icono de archivo no encontrado"
msgid "Not Registered Hosts"
msgstr "Registrado"
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr "No un número"
@@ -6711,6 +7014,13 @@ msgstr "el usuario actualiza"
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+#, fuzzy
+msgid "Observed domain"
+msgstr "Información general"
+
msgid "Off"
msgstr ""
@@ -6765,6 +7075,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr "Error, es una imagen asociada con este anfitrión"
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -6848,6 +7164,12 @@ msgstr ""
msgid "Operations on %s."
msgstr "Operación de no activado: %s"
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -6895,9 +7217,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -6979,6 +7307,10 @@ msgstr ""
msgid "Pending"
msgstr "macs pendientes"
+#, fuzzy
+msgid "Pending Agents"
+msgstr "macs pendientes"
+
#, fuzzy
msgid "Pending Hosts"
msgstr "anfitriones pendientes"
@@ -6999,9 +7331,30 @@ msgstr "macs pendientes"
msgid "Pending Registered Hosts"
msgstr "anfitriones pendientes"
+msgid "Pending Registration created by FOG_AGENT"
+msgstr ""
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr ""
+#, fuzzy
+msgid "Pending agent"
+msgstr "anfitriones pendientes"
+
+#, fuzzy
+msgid "Pending agent enrollments"
+msgstr "anfitriones pendientes"
+
+#, fuzzy
+msgid "Pending agents"
+msgstr "macs pendientes"
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
#, fuzzy
msgid "Pending host"
msgstr "anfitriones pendientes"
@@ -7049,6 +7402,16 @@ msgstr "Estado"
msgid "Ping cycle complete"
msgstr "Deben estar cifrados"
+msgid "Pinned"
+msgstr ""
+
+#, fuzzy
+msgid "Placement"
+msgstr "Gestión de usuarios"
+
+msgid "Platform"
+msgstr ""
+
msgid "Please Select an option"
msgstr "Por favor seleccione una opción"
@@ -7093,10 +7456,18 @@ msgstr ""
msgid "Please enter a name"
msgstr "Por favor introduce un nombre de sesión"
+#, fuzzy
+msgid "Please enter a package id."
+msgstr "Por favor introduce un nombre de sesión"
+
#, fuzzy
msgid "Please enter a printer name."
msgstr "Por favor introduce un nombre de sesión"
+#, fuzzy
+msgid "Please enter a software name."
+msgstr "Por favor introduce un nombre de sesión"
+
#, fuzzy
msgid "Please enter a valid CIDR subnet."
msgstr "Por favor introduce un nombre de sesión"
@@ -7111,6 +7482,10 @@ msgstr ""
msgid "Please physically associate"
msgstr ""
+#, fuzzy
+msgid "Please select a valid backend."
+msgstr "Seleccionar una imagen válida"
+
#, fuzzy
msgid "Please select a valid certificate verification level"
msgstr "Seleccionar una imagen válida"
@@ -7131,6 +7506,10 @@ msgstr "Seleccionar una imagen válida"
msgid "Please select a valid printer type."
msgstr "Seleccionar una imagen válida"
+#, fuzzy
+msgid "Please select a valid state."
+msgstr "Seleccionar una imagen válida"
+
#, fuzzy
msgid "Please select an LDAP server!"
msgstr "Por favor seleccione una opción"
@@ -7347,6 +7726,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -7395,6 +7777,10 @@ msgstr "actualización de la impresora ha fallado!"
msgid "Printer Create Success"
msgstr "Impresora ya existe"
+#, fuzzy
+msgid "Printer Deployment"
+msgstr "Sin administración de la impresora"
+
msgid "Printer Description"
msgstr "Descripción de la impresora"
@@ -7554,6 +7940,9 @@ msgstr "Impresora actualiza!"
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
#, fuzzy
msgid "Pushbullet Accounts"
msgstr "Añadir nueva cuenta de usuario"
@@ -7596,6 +7985,10 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr "está protegido, no se permite la eliminación"
+#, fuzzy
+msgid "Quick tasks"
+msgstr "MulticastTask"
+
msgid "RESOURCES"
msgstr ""
@@ -7608,6 +8001,9 @@ msgstr "RX"
msgid "Re-Transmit Hello Interval"
msgstr ""
+msgid "Re-check Interval"
+msgstr ""
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -7628,6 +8024,9 @@ msgstr "Eliminar seleccionado"
msgid "Real Time"
msgstr "Tiempo de actividad del sistema"
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr "Reiniciar"
@@ -7657,6 +8056,9 @@ msgstr ""
msgid "Recorded in range"
msgstr "Registro no encontrado, error: %s"
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
#, fuzzy
msgid "Records"
msgstr "Registros actuales"
@@ -7670,10 +8072,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-#, fuzzy
-msgid "Refresh"
-msgstr "Frecuencia de actualización predeterminado"
-
#, fuzzy
msgid "Refresh Settings Cache"
msgstr "Estado del servicio"
@@ -7822,6 +8220,10 @@ msgstr "Reiniciar"
msgid "Report Management"
msgstr "Gestión de usuarios"
+#, fuzzy
+msgid "Reported"
+msgstr "Reiniciar"
+
#, fuzzy
msgid "Reports"
msgstr "Reiniciar"
@@ -7887,10 +8289,17 @@ msgstr ""
msgid "Retention sweep failed"
msgstr "Remoto"
+msgid "Retry"
+msgstr ""
+
#, fuzzy
msgid "Return Code"
msgstr "Código de retorno"
+#, fuzzy
+msgid "Return Codes"
+msgstr "Código de retorno"
+
msgid "Return To Local Login"
msgstr ""
@@ -7901,9 +8310,33 @@ msgstr "Código de retorno"
msgid "Returning value of key"
msgstr "Volviendo valor de clave"
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+#, fuzzy
+msgid "Revoke an agent enrollment token"
+msgstr "anfitriones pendientes"
+
+#, fuzzy
+msgid "Revoke selected"
+msgstr "Remoto"
+
+#, fuzzy
+msgid "Revoked selected tokens."
+msgstr "retirar"
+
+msgid "Revoked."
+msgstr ""
+
msgid "Role"
msgstr "Rol"
@@ -8043,6 +8476,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
#, fuzzy
msgid "SQL Error"
msgstr "Error"
@@ -8163,16 +8599,6 @@ msgstr "actualización de servicio no pudo"
msgid "Scopes"
msgstr ""
-msgid "Screen Height"
-msgstr ""
-
-#, fuzzy
-msgid "Screen Refresh Rate"
-msgstr "Frecuencia de actualización predeterminado"
-
-msgid "Screen Width"
-msgstr ""
-
msgid "Search"
msgstr "Buscar"
@@ -8410,6 +8836,9 @@ msgstr "Sesión con ese nombre ya existe"
msgid "Sessions canceled!"
msgstr "se ha actualizado correctamente"
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -8886,6 +9315,64 @@ msgstr "snapins"
msgid "So if you are trying to transmit to remote node A"
msgstr ""
+#, fuzzy
+msgid "Software"
+msgstr "Listar todo el software"
+
+#, fuzzy
+msgid "Software Create Fail"
+msgstr "actualización de la impresora ha fallado!"
+
+#, fuzzy
+msgid "Software Create Success"
+msgstr "Impresora ya existe"
+
+#, fuzzy
+msgid "Software Host Associations"
+msgstr "No nodo asociado"
+
+#, fuzzy
+msgid "Software Management"
+msgstr "Gestión de usuarios"
+
+#, fuzzy
+msgid "Software Name"
+msgstr "Nombre de la impresora"
+
+msgid "Software Order"
+msgstr ""
+
+#, fuzzy
+msgid "Software Report"
+msgstr "ID de host"
+
+#, fuzzy
+msgid "Software Status"
+msgstr "Crear nuevo grupo"
+
+#, fuzzy
+msgid "Software Update Fail"
+msgstr "actualización de la impresora ha fallado!"
+
+#, fuzzy
+msgid "Software Update Success"
+msgstr "actualización Valoración falló"
+
+#, fuzzy
+msgid "Software added!"
+msgstr "Nombre de la impresora"
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+#, fuzzy
+msgid "Software update failed!"
+msgstr "actualización de la impresora ha fallado!"
+
+#, fuzzy
+msgid "Software updated!"
+msgstr "Impresora actualiza!"
+
msgid "Some nice description, should be short."
msgstr ""
@@ -8898,6 +9385,9 @@ msgstr ""
msgid "Specified download URL not allowed!"
msgstr ""
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -9671,6 +10161,9 @@ msgstr "No hay grupos en este servidor."
msgid "The CA private key is on this server"
msgstr "No hay grupos en este servidor."
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -9703,6 +10196,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -9747,6 +10243,9 @@ msgstr "No se pudo leer el archivo temporal"
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -9787,6 +10286,12 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+msgid "The enrollment is no longer pending."
+msgstr ""
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -9814,6 +10319,15 @@ msgstr ""
msgid "The grid key."
msgstr "No se pudo crear la tarea"
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
#, fuzzy
msgid "The identity provider could not be reached"
msgstr "No se pudo leer el archivo temporal"
@@ -9869,9 +10383,16 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+#, fuzzy
+msgid "The item is not a live row of this host."
+msgstr "No se encontró Clase FOGPage para este nodo"
+
msgid "The key will be assigned to registered hosts when a"
msgstr ""
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -9901,12 +10422,21 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
msgid "The path requested is already in use by another image!"
msgstr ""
+msgid "The payload bytes."
+msgstr ""
+
#, fuzzy
msgid "The plugin directory"
msgstr "Directorio"
@@ -9952,6 +10482,13 @@ msgstr ""
msgid "The record could not be written."
msgstr "No se pudo leer el archivo temporal"
+#, fuzzy
+msgid "The renewed certificate, leaf then chain."
+msgstr "Crear nuevo grupo"
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -9961,6 +10498,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -9971,6 +10511,12 @@ msgstr "actualización de la impresora ha fallado!"
msgid "The selected site no longer exists"
msgstr ""
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -9990,6 +10536,13 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+#, fuzzy
+msgid "The signing helper is not available on this server."
+msgstr "No hay grupos en este servidor."
+
#, fuzzy
msgid "The signing request could not be generated"
msgstr "No se pudo leer el archivo temporal"
@@ -10010,6 +10563,10 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+#, fuzzy
+msgid "The token."
+msgstr "Contador de la CPU"
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -10173,6 +10730,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -10231,10 +10791,16 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, fuzzy, php-format
msgid "This machine already registered as %s"
msgstr "Impresora ya existe"
+msgid "This module has no settings to configure."
+msgstr ""
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -10342,6 +10908,13 @@ msgstr "nombre de usuario ya existe"
msgid "Time since last imaged"
msgstr ""
+#, fuzzy
+msgid "Timeout"
+msgstr "Hora"
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -10364,9 +10937,31 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Asociación para la imagen"
+#, fuzzy
+msgid "Token Create Fail"
+msgstr "actualización de la impresora ha fallado!"
+
+#, fuzzy
+msgid "Token Create Success"
+msgstr "Impresora ya existe"
+
+#, fuzzy
+msgid "Token Revoke Fail"
+msgstr "Añadir fallidos SNAPin!"
+
+#, fuzzy
+msgid "Token Revoke Success"
+msgstr "Impresora ya existe"
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
msgid "Too many MACs"
msgstr ""
@@ -10550,6 +11145,9 @@ msgstr "Nombre de usuario"
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
#, fuzzy
msgid "Unauthenticated."
msgstr "servidor de ponerse en contacto con el error"
@@ -10601,6 +11199,9 @@ msgstr "Se produjo un error de carga desconocida. Código de retorno: "
msgid "Unknown action"
msgstr "Se produjo un error de carga desconocida. Código de retorno: "
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -10631,6 +11232,9 @@ msgstr "Se produjo un error de carga desconocida. Código de retorno: "
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
#, fuzzy
msgid "Unmark selected client ignore"
msgstr "retirar"
@@ -10720,6 +11324,9 @@ msgstr "Impresora"
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
#, fuzzy
msgid "Upload"
msgstr "Subir archivo"
@@ -10834,9 +11441,6 @@ msgstr "nombre de usuario ya existe"
msgid "User Association"
msgstr "Asociación para la imagen"
-msgid "User Cleanup"
-msgstr ""
-
#, fuzzy
msgid "User Count"
msgstr "Contador de la CPU"
@@ -10921,6 +11525,10 @@ msgstr "Nombre de usuario"
msgid "User Password"
msgstr "Contraseña de usuario"
+#, fuzzy
+msgid "User Sessions"
+msgstr "Asociación para la imagen"
+
#, fuzzy
msgid "User Tracker"
msgstr "Nombre de usuario"
@@ -11007,6 +11615,12 @@ msgstr "Usuario"
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr ""
@@ -11032,6 +11646,10 @@ msgstr "Versión"
msgid "Version information and paging bounds."
msgstr "FOG Información de la versión"
+#, fuzzy
+msgid "Version policy"
+msgstr "Versión"
+
#, fuzzy
msgid "Versions"
msgstr "Versión"
@@ -11061,6 +11679,9 @@ msgstr "¿Activación de la LAN?"
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -11113,12 +11734,18 @@ msgstr "se ha actualizado correctamente"
msgid "What it does"
msgstr "se ha actualizado correctamente"
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -11134,6 +11761,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr ""
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -11146,10 +11776,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -11224,6 +11854,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr "Anual"
@@ -11347,6 +11980,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
#, fuzzy
msgid "access"
msgstr "Exitoso"
@@ -11357,10 +11993,17 @@ msgstr ""
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
#, fuzzy
msgid "ago"
msgstr " hace"
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
#, fuzzy
msgid "all current storage nodes"
msgstr "nodo de almacenamiento no válido"
@@ -11394,6 +12037,13 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+#, fuzzy
+msgid "any version"
+msgstr "Versión"
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
#, fuzzy
msgid "architecture not recorded"
msgstr "No se pudo leer el archivo temporal"
@@ -11405,6 +12055,10 @@ msgstr ""
msgid "as its primary group"
msgstr "Actualización de Grupo Primario"
+#, fuzzy
+msgid "assigned"
+msgstr "No nodo asociado"
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -11511,6 +12165,9 @@ msgstr "habilitado"
msgid "does not exist and cannot be created"
msgstr "está protegido, no se permite la eliminación"
+msgid "domain"
+msgstr ""
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -11520,6 +12177,9 @@ msgstr ""
msgid "either because you have updated"
msgstr ""
+msgid "empty means never install Chocolatey"
+msgstr ""
+
#, fuzzy
msgid "error"
msgstr "Error"
@@ -11527,10 +12187,20 @@ msgstr "Error"
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+#, fuzzy
+msgid "failed"
+msgstr "Ha fallado"
+
#, fuzzy
msgid "failed to execute, image file"
msgstr "No se pudo crear la tarea"
@@ -11631,6 +12301,10 @@ msgstr ""
msgid "host"
msgstr "anfitrión"
+#, fuzzy, php-format
+msgid "host \"%s\""
+msgstr "anfitrión"
+
#, fuzzy
msgid "host is"
msgstr "anfitrión"
@@ -11747,9 +12421,6 @@ msgstr ""
msgid "in"
msgstr "minutos"
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
@@ -11757,9 +12428,6 @@ msgstr ""
msgid "in minutes"
msgstr "minutos"
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr ""
@@ -11833,6 +12501,10 @@ msgstr "DMI clave"
msgid "keys"
msgstr ""
+#, fuzzy
+msgid "latest"
+msgstr "¿Reproducir exactamente?"
+
msgid "leave to keep the current one"
msgstr ""
@@ -11865,6 +12537,10 @@ msgstr "minutos"
msgid "mismatched"
msgstr ""
+#, fuzzy
+msgid "missing"
+msgstr "Versión"
+
msgid "moments from now"
msgstr ""
@@ -11902,6 +12578,10 @@ msgstr ""
msgid "never"
msgstr ""
+#, fuzzy
+msgid "never reported"
+msgstr "ID de inventario"
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -11934,6 +12614,9 @@ msgstr ""
msgid "not found on this node"
msgstr "No se encontró Clase FOGPage para este nodo"
+msgid "not joined"
+msgstr ""
+
#, fuzzy
msgid "not reachable"
msgstr "No disponible"
@@ -11963,10 +12646,16 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+msgid "off"
+msgstr ""
+
#, fuzzy
msgid "off means an account must already exist"
msgstr "Impresora ya existe"
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -11980,6 +12669,9 @@ msgstr ""
msgid "optional"
msgstr "Acción"
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
#, fuzzy
msgid "or"
msgstr "1 hora"
@@ -12255,6 +12947,10 @@ msgstr "No se dispone de hash"
msgid "unchanged for"
msgstr "Imagen"
+#, fuzzy
+msgid "unknown action"
+msgstr "Se produjo un error de carga desconocida. Código de retorno: "
+
msgid "unrecorded"
msgstr ""
@@ -12478,6 +13174,10 @@ msgstr ""
#~ msgid "CA private key"
#~ msgstr "clave privada fracasó"
+#, fuzzy
+#~ msgid "Cannot connect to ftp server"
+#~ msgstr "Error: No se pudo descargar kernel"
+
#, fuzzy
#~ msgid "Check that database is running"
#~ msgstr "Compruebe que la base de datos se está ejecutando"
@@ -12486,6 +13186,10 @@ msgstr ""
#~ msgid "Client Module Settings"
#~ msgstr "Configuración Tecla"
+#, fuzzy
+#~ msgid "Could not read snapin file"
+#~ msgstr "No se pudo leer el archivo tmp."
+
#, fuzzy
#~ msgid "Create New Accesscontrol"
#~ msgstr "Crear nuevo grupo"
@@ -12510,6 +13214,15 @@ msgstr ""
#~ msgid "Database connection unavailable"
#~ msgstr "No se dispone de hash"
+#~ msgid "Default Height"
+#~ msgstr "Altura por defecto"
+
+#~ msgid "Default Refresh Rate"
+#~ msgstr "Frecuencia de actualización predeterminado"
+
+#~ msgid "Default Width"
+#~ msgstr "Ancho por defecto"
+
#, fuzzy
#~ msgid "Delete All"
#~ msgstr "Eliminar los datos del archivo"
@@ -12518,6 +13231,10 @@ msgstr ""
#~ msgid "Deprecated."
#~ msgstr "Crear"
+#, fuzzy
+#~ msgid "Directory Cleaner"
+#~ msgstr "directorios Cleaned"
+
#, fuzzy
#~ msgid "Domain joining"
#~ msgstr "Nombre de dominio"
@@ -12586,6 +13303,18 @@ msgstr ""
#~ msgid "Export Users"
#~ msgstr "Exportar"
+#, fuzzy
+#~ msgid "FOG Agent desired state"
+#~ msgstr "se ha actualizado correctamente"
+
+#, fuzzy
+#~ msgid "FOG Agent snapin result"
+#~ msgstr "Ningún archivo fue subido"
+
+#, fuzzy
+#~ msgid "FOG Agent software result"
+#~ msgstr "Ningún archivo fue subido"
+
#, fuzzy
#~ msgid "Failed to add/update snapin file"
#~ msgstr "No se pudo crear Complemento de empleo"
@@ -12697,10 +13426,18 @@ msgstr ""
#~ msgid "Group module settings"
#~ msgstr "Descripción del Grupo"
+#, fuzzy
+#~ msgid "Height"
+#~ msgstr "Medianoche"
+
#, fuzzy
#~ msgid "History Report"
#~ msgstr "ID de host"
+#, fuzzy
+#~ msgid "Host Display Manager Settings"
+#~ msgstr "Configuración Tecla"
+
#, fuzzy
#~ msgid "Host Ext"
#~ msgstr "Hospedadores"
@@ -12717,6 +13454,10 @@ msgstr ""
#~ msgid "Host Ext Variable"
#~ msgstr "actualización Valoración falló"
+#, fuzzy
+#~ msgid "Host Screen Resolution"
+#~ msgstr "Lista de host"
+
#, fuzzy
#~ msgid "Host Site"
#~ msgstr "Hospedadores"
@@ -12824,6 +13565,10 @@ msgstr ""
#~ msgid "Install"
#~ msgstr "Instalador inteligente (recomendado)"
+#, fuzzy
+#~ msgid "Invalid Storage Node"
+#~ msgstr "nodo de almacenamiento"
+
#, fuzzy
#~ msgid "Invalid Type"
#~ msgstr "tipo no válido"
@@ -12847,6 +13592,14 @@ msgstr ""
#~ msgid "LDAP User Filter"
#~ msgstr "servidor TFTP"
+#, fuzzy
+#~ msgid "Last Activity"
+#~ msgstr "Activo"
+
+#, fuzzy
+#~ msgid "Last Event"
+#~ msgstr "Creado"
+
#, fuzzy
#~ msgid "Latest SVN Version"
#~ msgstr "Versión del sistema"
@@ -12903,6 +13656,14 @@ msgstr ""
#~ msgid "Not Installed"
#~ msgstr "Instalador inteligente (recomendado)"
+#, fuzzy
+#~ msgid "Not a live task of this host's job."
+#~ msgstr "No se encontró Clase FOGPage para este nodo"
+
+#, fuzzy
+#~ msgid "Not an entry in this host's software set."
+#~ msgstr "No se encontró Clase FOGPage para este nodo"
+
#, fuzzy
#~ msgid "Pause"
#~ msgstr "Usuario"
@@ -12922,6 +13683,14 @@ msgstr ""
#~ msgid "Product Keys"
#~ msgstr "Clave del producto Grupo"
+#, fuzzy
+#~ msgid "Recorded."
+#~ msgstr "Registros actuales"
+
+#, fuzzy
+#~ msgid "Refresh"
+#~ msgstr "Frecuencia de actualización predeterminado"
+
#, fuzzy
#~ msgid "Release Version"
#~ msgstr "Versión del sistema"
@@ -12985,6 +13754,10 @@ msgstr ""
#~ msgid "Rule update failed!"
#~ msgstr "actualización de la impresora ha fallado!"
+#, fuzzy
+#~ msgid "Screen Refresh Rate"
+#~ msgstr "Frecuencia de actualización predeterminado"
+
#, fuzzy
#~ msgid "Serial"
#~ msgstr "sistema de serie"
@@ -13026,8 +13799,16 @@ msgstr ""
#~ msgstr "Impresora ya existe"
#, fuzzy
-#~ msgid "The certificate chain"
-#~ msgstr "Crear nuevo grupo"
+#~ msgid "The desired state."
+#~ msgstr "No se pudo crear la tarea"
+
+#, fuzzy
+#~ msgid "The host this certificate is, and the capabilities this server offers."
+#~ msgstr "No hay grupos en este servidor."
+
+#, fuzzy
+#~ msgid "The task was already closed."
+#~ msgstr "Impresora ya existe"
#, fuzzy
#~ msgid "There are no "
@@ -13060,6 +13841,10 @@ msgstr ""
#~ msgid "Unable to set user filter."
#~ msgstr "No se puede abrir archivo para lectura"
+#, fuzzy
+#~ msgid "Unknown status."
+#~ msgstr "Se produjo un error de carga desconocida. Código de retorno: "
+
#, fuzzy
#~ msgid "Update Master Node"
#~ msgstr "nodo de almacenamiento"
@@ -13159,10 +13944,6 @@ msgstr ""
#~ msgid "min (all)"
#~ msgstr "habilitado"
-#, fuzzy
-#~ msgid "multicast tasks!"
-#~ msgstr "MulticastTask"
-
#, fuzzy
#~ msgid "not found on disk"
#~ msgstr "No se encontró Clase FOGPage para este nodo"
@@ -13170,7 +13951,3 @@ msgstr ""
#, fuzzy
#~ msgid "username"
#~ msgstr "Nombre de usuario"
-
-#, fuzzy
-#~ msgid "version"
-#~ msgstr "Versión"
diff --git a/packages/web/management/languages/eu_ES.UTF-8/LC_MESSAGES/messages.po b/packages/web/management/languages/eu_ES.UTF-8/LC_MESSAGES/messages.po
index ae71077dbf..b956a8af26 100644
--- a/packages/web/management/languages/eu_ES.UTF-8/LC_MESSAGES/messages.po
+++ b/packages/web/management/languages/eu_ES.UTF-8/LC_MESSAGES/messages.po
@@ -120,6 +120,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -289,6 +293,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, fuzzy, php-format
+msgid "(deleted host %d)"
+msgstr "Ausgewählten MAcs freigeben"
+
msgid "(deleted user)"
msgstr ""
@@ -308,9 +316,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr "Kernel-Argumente"
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
#, fuzzy
msgid "1 Hour"
msgstr "1 Stunde"
@@ -415,6 +429,12 @@ msgstr "Ein Broadcast mit diesem Namen ist bereits vorhanden!"
msgid "A client ID is required"
msgstr "Ein Gruppenname ist erforderlich!"
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
#, fuzzy
msgid "A dmi field must be set!"
msgstr "Schlüsselfeldname muss eine Zeichenfolge sein."
@@ -478,6 +498,9 @@ msgstr "Dieser Benutzername ist bereits vorhanden!"
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
#, fuzzy
msgid "A module already exists with this name!"
msgstr "Eine Rolle mit diesem Namen ist bereits vorhanden!"
@@ -499,6 +522,9 @@ msgstr "Alle Regeln auflisten"
msgid "A permission name is required."
msgstr "Ein Gruppenname ist erforderlich!"
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -521,6 +547,9 @@ msgstr "Ein Drucker mit diesem Namen ist bereits vorhanden!"
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
#, fuzzy
msgid "A role already exists with this name!"
msgstr "Eine Rolle mit diesem Namen ist bereits vorhanden!"
@@ -562,6 +591,10 @@ msgstr "Ein Snapin mit diesem Namen ist bereits vorhanden!"
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+#, fuzzy
+msgid "A software entry already exists with this name!"
+msgstr "Dieser Benutzername ist bereits vorhanden!"
+
#, fuzzy
msgid "A storage group already exists with this name!"
msgstr "Ein Host mit diesem Namen ist bereits vorhanden!"
@@ -698,6 +731,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -928,6 +967,10 @@ msgstr "Standort hinzufügen fehlgeschlagen"
msgid "Add snapin failed!"
msgstr "Snapin hinzufügen fehlgeschlagen"
+#, fuzzy
+msgid "Add software failed!"
+msgstr "Hinzufügen eines Hosts fehlgeschlagen!"
+
#, fuzzy
msgid "Add storage node failed!"
msgstr "Hinzufügen eines Speicherknotens fehlgeschlagen!"
@@ -1012,6 +1055,33 @@ msgstr "Erweitert"
msgid "Advanced Tasks"
msgstr "Erweitert"
+msgid "Agent"
+msgstr ""
+
+#, fuzzy
+msgid "Agent Activity"
+msgstr "Aktiv"
+
+#, fuzzy
+msgid "Agent Approval Success"
+msgstr "Host erfolgreich erstellt"
+
+#, fuzzy
+msgid "Agent Denial Success"
+msgstr "Drucker aktualisiert!"
+
+#, fuzzy
+msgid "Agent Enrollment Tokens"
+msgstr "wurde abgebrochen"
+
+#, fuzzy
+msgid "Agent Tokens"
+msgstr "API-Zugangstoken"
+
+#, fuzzy
+msgid "Agent enrollment tokens"
+msgstr "wurde abgebrochen"
+
msgid "Ago must be boolean"
msgstr "Ago muss boolean sein"
@@ -1028,6 +1098,10 @@ msgstr ""
msgid "All Hosts"
msgstr "Alle Hosts"
+#, fuzzy
+msgid "All Pending Agents"
+msgstr "Ausstehende MACs"
+
#, fuzzy
msgid "All Pending Hosts"
msgstr "Ausstehende Hosts"
@@ -1131,10 +1205,16 @@ msgstr ""
msgid "An SQL error occurred"
msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
#, fuzzy
msgid "An entry already exists with this name!"
msgstr "Dieser Benutzername ist bereits vorhanden!"
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr "Ein Image mit diesem Namen ist bereits vorhanden!"
@@ -1174,6 +1254,10 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+#, fuzzy
+msgid "Any version"
+msgstr "Version"
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1212,18 +1296,36 @@ msgstr ""
msgid "Approve"
msgstr "freigeben"
+#, fuzzy
+msgid "Approve Agent Fail"
+msgstr "freigeben"
+
#, fuzzy
msgid "Approve MAC Fail"
msgstr "freigeben"
+#, fuzzy
+msgid "Approve Pending Agents"
+msgstr "Ausstehende Hosts"
+
#, fuzzy
msgid "Approve Pending Hosts"
msgstr "Ausstehende Hosts"
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
#, fuzzy
msgid "Approve selected"
msgstr "Ausgewählten MAcs freigeben"
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+#, fuzzy
+msgid "Approved selected agents!"
+msgstr "Ausgewählten MAcs freigeben"
+
#, fuzzy
msgid "Approved selected hosts!"
msgstr "Ausgewählten MAcs freigeben"
@@ -1236,6 +1338,9 @@ msgstr "Ausgewählten MAcs freigeben"
msgid "Approving the selected pending hosts."
msgstr "Ausgewählten MAcs freigeben"
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1245,6 +1350,10 @@ msgstr ""
msgid "Area"
msgstr ""
+#, fuzzy
+msgid "Assigned"
+msgstr "zugeordneter Host"
+
#, fuzzy
msgid "Assigned Group"
msgstr "Name der Speichergruppe"
@@ -1307,6 +1416,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1345,6 +1457,9 @@ msgstr "BIOS-Anbieter"
msgid "BIOS Version"
msgstr "BIOS-Version"
+msgid "Backend"
+msgstr ""
+
#, fuzzy
msgid "Bad request."
msgstr "%s ist erforderlich"
@@ -1578,6 +1693,10 @@ msgstr "Stornierter Task"
msgid "Canceled due to new tasking."
msgstr "Abgebrochen aufgrund neuer Aufgabe (Task)"
+#, fuzzy
+msgid "Cannot Run"
+msgstr "Datensatz wurde nicht gefunden, Fehler: %s"
+
#, fuzzy
msgid "Cannot bind to the LDAP server"
msgstr "Anmeldung am LDAP-Server nicht möglich"
@@ -1592,10 +1711,6 @@ msgstr "kann keine Verbindung aufbauen"
msgid "Cannot connect to database"
msgstr "Kann keine Verbindung zur Datenbank herstellen"
-#, fuzzy
-msgid "Cannot connect to ftp server"
-msgstr "Verbindung zum FTP-Server nicht möglich"
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1793,6 +1908,9 @@ msgstr "Keine FOGPage-Klasse für diesen Knoten gefunden"
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+msgid "Checked"
+msgstr ""
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1805,6 +1923,12 @@ msgstr "Prüfe, ob ich der Gruppenmanager bin"
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1976,14 +2100,23 @@ msgstr "Fehler: Herunterladen des Kernels fehlgeschlagen"
msgid "Confirm you would like to download a new kernel"
msgstr "Fehler: Herunterladen des Kernels fehlgeschlagen"
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
#, fuzzy
msgid "Copy from existing"
msgstr "Kopie von bereits existierenden"
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -2057,10 +2190,6 @@ msgstr "Tmp-Datei konnte nicht gelesen werden."
msgid "Could not read local file"
msgstr "Temporäre Datei konnte nicht gelesen werden."
-#, fuzzy
-msgid "Could not read snapin file"
-msgstr "Snapin-Datei konnte nicht gelesen werden."
-
#, fuzzy
msgid "Could not read the database structure"
msgstr "Erstellen eines Snapin-Jobs fehlgeschlagen"
@@ -2157,6 +2286,9 @@ msgstr ""
msgid "Create"
msgstr "Erstellen"
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -2239,6 +2371,10 @@ msgstr "Neue Sites erstellen"
msgid "Create New Snapin"
msgstr "Neue Snapin erstellen"
+#, fuzzy
+msgid "Create New Software"
+msgstr "Neue Sites erstellen"
+
msgid "Create New Storage Group"
msgstr "Neue Storage Group erstellen"
@@ -2286,6 +2422,10 @@ msgstr "Benutzer erfolgreich erstellt"
msgid "Create Users On First Login"
msgstr ""
+#, fuzzy, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr "Benutzer erfolgreich erstellt"
+
#, fuzzy, php-format
msgid "Create a %s"
msgstr "Neue %s erstellen"
@@ -2309,9 +2449,17 @@ msgstr "Benutzer erstellen fehlgeschlagen"
msgid "Create task form success"
msgstr "Benutzer erfolgreich erstellt"
+#, fuzzy
+msgid "Create tasking"
+msgstr "Neues Snapin erstellen"
+
msgid "Create tasking succeeded"
msgstr ""
+#, fuzzy
+msgid "Create token"
+msgstr "Neue %s erstellen"
+
#, fuzzy
msgid "Created"
msgstr "Erstellen"
@@ -2323,6 +2471,10 @@ msgstr "Erstellt von"
msgid "Created Time"
msgstr "Erstellt von"
+#, fuzzy
+msgid "Created by"
+msgstr "Erstellt von"
+
msgid "Created by FOG Reg on"
msgstr "Erstellt von FOG Reg am"
@@ -2451,6 +2603,9 @@ msgstr "Debug Optionen"
msgid "Debug Task"
msgstr "Debug"
+msgid "Decided."
+msgstr ""
+
msgid "Default"
msgstr "Standard"
@@ -2458,15 +2613,6 @@ msgstr "Standard"
msgid "Default Choice"
msgstr "Standard-Eintrag:"
-msgid "Default Height"
-msgstr "Standardhöhe"
-
-msgid "Default Refresh Rate"
-msgstr "Standard-Bildwiederholrate"
-
-msgid "Default Width"
-msgstr "Standardbreite"
-
#, fuzzy
msgid "Default init, ARM64"
msgstr "Standardbreite"
@@ -2551,6 +2697,28 @@ msgstr ""
msgid "Deleting remote file"
msgstr "Remotedatei wird gelöscht"
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+#, fuzzy
+msgid "Denied selected agents!"
+msgstr "Ausgewählten MAcs freigeben"
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy
+msgid "Deny Agent Fail"
+msgstr "Löschen fehlgeschlagen"
+
+#, fuzzy
+msgid "Deny Pending Agents"
+msgstr "Ausstehende MACs"
+
+#, fuzzy
+msgid "Deny selected"
+msgstr "Ausgewählte löschen"
+
msgid "Deploy"
msgstr "Verteilung"
@@ -2567,14 +2735,30 @@ msgstr ""
msgid "Description"
msgstr "Beschreibung"
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+msgid "Desired domain"
+msgstr ""
+
#, fuzzy
msgid "Destroy failed"
msgstr "Zerstörung fehlgeschlagen: %s"
+#, fuzzy
+msgid "Detail"
+msgstr "Details"
+
#, fuzzy
msgid "Details"
msgstr "Details"
+msgid "Device URI"
+msgstr ""
+
#, fuzzy
msgid "Device must be a string"
msgstr "Gerätename muss eine Zeichenfolge sein."
@@ -2588,9 +2772,6 @@ msgstr "Verzeichnis"
msgid "Directory Already Exists"
msgstr "Das Verzeichnis existiert bereits"
-msgid "Directory Cleaner"
-msgstr "Verzeichnis-Bereiniger"
-
#, fuzzy
msgid "Directory Group"
msgstr "Verzeichnis"
@@ -2599,6 +2780,10 @@ msgstr "Verzeichnis"
msgid "Directory Group Name"
msgstr "Verzeichnis"
+#, fuzzy
+msgid "Directory Membership"
+msgstr "Mitgliedschaft"
+
#, fuzzy
msgid "Disable on all hosts"
msgstr "Deaktiviert"
@@ -2715,6 +2900,9 @@ msgstr "Download fehlgeschlagen"
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2734,6 +2922,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr "Bearbeiten"
@@ -2830,6 +3021,10 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+#, fuzzy
+msgid "Enrollment Token"
+msgstr "Pushbullet Accounts"
+
msgid "Enrollment kit"
msgstr ""
@@ -2933,6 +3128,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
#, fuzzy
msgid "Every file was uploaded."
msgstr "Keine Datei wurde hochgeladen"
@@ -2953,6 +3154,14 @@ msgstr "Privater Schlüssel ist fehlgeschlagen"
msgid "Exists item must be boolean"
msgstr "Bestehendes Objekt muss boolean sein"
+#, fuzzy
+msgid "Exit Code"
+msgstr "Snapins exportieren"
+
+#, fuzzy
+msgid "Exit code"
+msgstr "Rückgabewert"
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -3032,9 +3241,32 @@ msgstr "Datenbank importieren"
msgid "External root CA"
msgstr ""
+#, fuzzy
+msgid "Extra arguments"
+msgstr "Snapin läuft mit Argument"
+
msgid "FOG"
msgstr "FOG"
+#, fuzzy
+msgid "FOG Agent capability result"
+msgstr "Keine Datei wurde hochgeladen"
+
+#, fuzzy
+msgid "FOG Agent certificate renewal"
+msgstr "Keine Datei wurde hochgeladen"
+
+#, fuzzy
+msgid "FOG Agent enrollment"
+msgstr "wurde abgebrochen"
+
+#, fuzzy
+msgid "FOG Agent payload"
+msgstr "Keine Datei wurde hochgeladen"
+
+msgid "FOG Agent poll"
+msgstr ""
+
#, fuzzy
msgid "FOG Client"
msgstr "FOG-Client-Wiki"
@@ -3393,6 +3625,9 @@ msgstr "Task gestartet"
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3735,6 +3970,10 @@ msgstr "Host Snapinverlauf"
msgid "Group Snapin History"
msgstr "Snapin-Verlauf"
+#, fuzzy
+msgid "Group Software Assignment"
+msgstr "Host Snapinverlauf"
+
#, fuzzy
msgid "Group Task History"
msgstr "Image-Verlauf"
@@ -3824,9 +4063,15 @@ msgstr "Hardwareinformationen"
msgid "Hardware Report"
msgstr "Hardwareinformationen"
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr "Hash"
+msgid "Hash Mismatch"
+msgstr ""
+
msgid "Have not locked the host for access"
msgstr ""
@@ -3834,10 +4079,6 @@ msgstr ""
msgid "Header is missing the required \"%s\" column"
msgstr ""
-#, fuzzy
-msgid "Height"
-msgstr "Mitternacht"
-
msgid "Height must be 120 pixels."
msgstr "Höhe muss 120 Pixel betragen"
@@ -3910,6 +4151,9 @@ msgstr "Dieser Host ist bereits vorhanden."
msgid "Host %1$s finished deploying image %2$s."
msgstr "Dieser Host ist bereits vorhanden."
+msgid "Host Agent Activity"
+msgstr ""
+
#, fuzzy
msgid "Host Approval Success"
msgstr "Host erfolgreich erstellt"
@@ -3945,10 +4189,6 @@ msgstr "Standard-Eintrag:"
msgid "Host Description"
msgstr "Host-Beschreibung"
-#, fuzzy
-msgid "Host Display Manager Settings"
-msgstr "iPXE Menüeinstellungen"
-
msgid "Host EFI Exit Type"
msgstr "Host-EFI-Exit-Typ"
@@ -4053,10 +4293,6 @@ msgstr "Host-Produkt-Schlüssel"
msgid "Host Registration"
msgstr "Host-Registrierung"
-#, fuzzy
-msgid "Host Screen Resolution"
-msgstr "Host-Registrierung"
-
#, fuzzy
msgid "Host Snapin Associations"
msgstr "zugeordneter Host"
@@ -4065,6 +4301,13 @@ msgstr "zugeordneter Host"
msgid "Host Snapin History"
msgstr "Host Snapinverlauf"
+#, fuzzy
+msgid "Host Software Assignment"
+msgstr "Host Snapinverlauf"
+
+msgid "Host Software Status"
+msgstr ""
+
#, fuzzy
msgid "Host Task History"
msgstr "Image-Verlauf"
@@ -4158,6 +4401,12 @@ msgstr "Host Init"
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
#, fuzzy
msgid "Hosts:"
msgstr "Hosts"
@@ -4222,6 +4471,10 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+#, fuzzy
+msgid "Identity"
+msgstr "Server-Shell"
+
msgid "Identity Provider"
msgstr ""
@@ -4737,6 +4990,10 @@ msgstr "Installierte Plugins"
msgid "Installed Plugins"
msgstr "Installierte Plugins"
+#, fuzzy
+msgid "Installed Software"
+msgstr "Installierte Plugins"
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4824,9 +5081,6 @@ msgstr "Ungültiges Snapin-Tasking-Objekt"
msgid "Invalid Storage Group"
msgstr "Ungültige Speichergruppe"
-msgid "Invalid Storage Node"
-msgstr "Ungültiger Speicherknoten"
-
#, fuzzy
msgid "Invalid Tasking"
msgstr "Ungültiger Vorgang"
@@ -5010,6 +5264,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -5035,6 +5292,9 @@ msgstr "Es weist den Client an, Snapins vom hostdefinierten "
msgid "It will operate based on the fields the area typcially requires."
msgstr ""
+msgid "Join"
+msgstr ""
+
msgid "Join Domain after image task"
msgstr ""
@@ -5238,6 +5498,9 @@ msgstr "Sprache"
msgid "Largest images"
msgstr "Images"
+msgid "Last Agent Check-In"
+msgstr ""
+
#, fuzzy
msgid "Last Captured"
msgstr "Zuletzt hochgeladen"
@@ -5248,15 +5511,16 @@ msgstr ""
msgid "Last Check-In"
msgstr ""
-msgid "Last Client Check-In"
-msgstr ""
-
msgid "Last Deployed"
msgstr "Zuletzt verteilt"
msgid "Last Ping"
msgstr ""
+#, fuzzy
+msgid "Last Seen"
+msgstr "Zuletzt hochgeladen"
+
#, fuzzy
msgid "Last Successful Ping"
msgstr "Erfolgreich"
@@ -5272,6 +5536,10 @@ msgstr ""
msgid "Last deployed"
msgstr "Zuletzt verteilt"
+#, fuzzy
+msgid "Last error"
+msgstr "Fehler"
+
msgid "Last flush"
msgstr ""
@@ -5279,6 +5547,9 @@ msgstr ""
msgid "Last imaged"
msgstr "Images"
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
#, fuzzy
msgid "Latest Alpha Version"
msgstr "Neueste Version"
@@ -5403,6 +5674,10 @@ msgstr "Alle Sitess auflisten"
msgid "List All Snapins"
msgstr "Alle Snapins auflisten"
+#, fuzzy
+msgid "List All Software"
+msgstr "Alle Sitess auflisten"
+
msgid "List All Storage Groups"
msgstr "Alle Storage Groups auflisten"
@@ -5540,6 +5815,9 @@ msgstr "Log-Viewer"
msgid "Log out and sign in as an administrator"
msgstr ""
+msgid "Logged on"
+msgstr ""
+
msgid "Logging"
msgstr ""
@@ -5732,6 +6010,9 @@ msgstr "Max. Größe"
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
#, fuzzy
msgid "Member"
msgstr "Mitglieder"
@@ -5812,6 +6093,10 @@ msgstr "Mitternacht"
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+#, fuzzy
+msgid "Mint an agent enrollment token"
+msgstr "Ausstehende registrierte Hosts"
+
msgid "Minute value is not valid"
msgstr "Minutenwert ist nicht gültig"
@@ -5819,6 +6104,9 @@ msgstr "Minutenwert ist nicht gültig"
msgid "Minutes field is invalid"
msgstr "Minutenwert ist nicht gültig"
+msgid "Missing"
+msgstr ""
+
msgid "Missing a temporary folder"
msgstr "Ein temporärer Ordner fehlt"
@@ -6288,8 +6576,12 @@ msgid "No password is needed. Issue this account a token from its API tab, or fr
msgstr ""
#, fuzzy
-msgid "No plugin tasks to run"
-msgstr "Keine gültigen Tasks gefunden"
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr "Keinen aktiven Task gefunden für Host"
+
+#, fuzzy
+msgid "No plugin tasks to run"
+msgstr "Keine gültigen Tasks gefunden"
#, fuzzy
msgid "No plugin with that id."
@@ -6341,6 +6633,10 @@ msgstr "Snapin geschützt"
msgid "No snapins associated with this group as master"
msgstr "Keine Snapins mit dieser Gruppe als Master verbunden"
+#, fuzzy
+msgid "No storage node can serve the file."
+msgstr "Hinzufügen eines Speicherknotens fehlgeschlagen!"
+
#, fuzzy
msgid "No storage nodes assigned to this storage group"
msgstr "da innerhalb diese Speichergruppe einer aktiviert ist"
@@ -6353,6 +6649,9 @@ msgstr "Ein Host mit diesem Namen ist bereits vorhanden!"
msgid "No storagegroups assigned to this snapin"
msgstr "Die zugewiesene Image Speichergruppe ist nicht gültig."
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -6362,6 +6661,9 @@ msgstr ""
msgid "No such object."
msgstr ""
+msgid "No such token."
+msgstr ""
+
msgid "No such user."
msgstr ""
@@ -6397,6 +6699,9 @@ msgstr ""
msgid "No values passed"
msgstr "Keine Werte übergeben"
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
#, fuzzy
msgid "No viable macs to use"
msgstr "Keine brauchbaren MACS"
@@ -6452,6 +6757,9 @@ msgstr "Icon-Datei nicht gefunden"
msgid "Not Registered Hosts"
msgstr "Nicht registrierte Hosts"
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr "Keine Zahl"
@@ -6589,6 +6897,13 @@ msgstr "Benutzer aktualisiert"
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+#, fuzzy
+msgid "Observed domain"
+msgstr "Allgemeine Informationen"
+
msgid "Off"
msgstr ""
@@ -6645,6 +6960,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr "Eine oder mehrere MACs sind mit einem Host verknüpft"
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -6728,6 +7049,12 @@ msgstr ""
msgid "Operations on %s."
msgstr "Operationsfeld nicht gesetzt: %s"
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -6773,9 +7100,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -6857,6 +7190,10 @@ msgstr ""
msgid "Pending"
msgstr "Ausstehend..."
+#, fuzzy
+msgid "Pending Agents"
+msgstr "Ausstehende MACs"
+
msgid "Pending Hosts"
msgstr "Ausstehende Hosts"
@@ -6874,9 +7211,31 @@ msgstr "Ausstehende MACs"
msgid "Pending Registered Hosts"
msgstr "Ausstehende registrierte Hosts"
+#, fuzzy
+msgid "Pending Registration created by FOG_AGENT"
+msgstr "Ausstehende Registrierung erstellt von FOG_CLIENT"
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr "Ausstehende Registrierung erstellt von FOG_CLIENT"
+#, fuzzy
+msgid "Pending agent"
+msgstr "Ausstehende Hosts"
+
+#, fuzzy
+msgid "Pending agent enrollments"
+msgstr "Ausstehende registrierte Hosts"
+
+#, fuzzy
+msgid "Pending agents"
+msgstr "Ausstehende MACs"
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
#, fuzzy
msgid "Pending host"
msgstr "Ausstehende Hosts"
@@ -6923,6 +7282,16 @@ msgstr "Status"
msgid "Ping cycle complete"
msgstr "wurde abgeschlossen"
+msgid "Pinned"
+msgstr ""
+
+#, fuzzy
+msgid "Placement"
+msgstr "Task-Management"
+
+msgid "Platform"
+msgstr ""
+
msgid "Please Select an option"
msgstr "Bitte wählen Sie eine Option"
@@ -6967,10 +7336,18 @@ msgstr ""
msgid "Please enter a name"
msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
+#, fuzzy
+msgid "Please enter a package id."
+msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
+
#, fuzzy
msgid "Please enter a printer name."
msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
+#, fuzzy
+msgid "Please enter a software name."
+msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
+
#, fuzzy
msgid "Please enter a valid CIDR subnet."
msgstr "Bitte geben Sie einen gültigen Hostnamen ein"
@@ -6984,6 +7361,10 @@ msgstr ""
msgid "Please physically associate"
msgstr "Bitte ordnen Sie physisch"
+#, fuzzy
+msgid "Please select a valid backend."
+msgstr "Wählen Sie ein gültiges Abbild"
+
#, fuzzy
msgid "Please select a valid certificate verification level"
msgstr "Wählen Sie ein gültiges Abbild"
@@ -7004,6 +7385,10 @@ msgstr "Wählen Sie ein gültiges Abbild"
msgid "Please select a valid printer type."
msgstr "Wählen Sie ein gültiges Abbild"
+#, fuzzy
+msgid "Please select a valid state."
+msgstr "Wählen Sie ein gültiges Abbild"
+
#, fuzzy
msgid "Please select an LDAP server!"
msgstr "Bitte wählen Sie eine Option"
@@ -7219,6 +7604,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -7265,6 +7653,10 @@ msgstr "Drucker erstellen fehlgeschlagen!"
msgid "Printer Create Success"
msgstr "Drucker hinzufügen erfolgreich."
+#, fuzzy
+msgid "Printer Deployment"
+msgstr "Druckerverwaltung"
+
msgid "Printer Description"
msgstr "Druckerbeschreibung"
@@ -7422,6 +7814,9 @@ msgstr "Drucker aktualisiert!"
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
msgid "Pushbullet Accounts"
msgstr "Pushbullet Accounts"
@@ -7463,6 +7858,10 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr "Snapin ist geschützt und kann nicht gelöscht werden"
+#, fuzzy
+msgid "Quick tasks"
+msgstr "Aktive Multicast-Tasks"
+
msgid "RESOURCES"
msgstr ""
@@ -7475,6 +7874,9 @@ msgstr "RX"
msgid "Re-Transmit Hello Interval"
msgstr ""
+msgid "Re-check Interval"
+msgstr ""
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -7495,6 +7897,9 @@ msgstr "Ausgewählte löschen"
msgid "Real Time"
msgstr "Datum und Zeit"
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr "Neustarten"
@@ -7523,6 +7928,9 @@ msgstr ""
msgid "Recorded in range"
msgstr "Datensatz wurde nicht gefunden, Fehler: %s"
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
#, fuzzy
msgid "Records"
msgstr "Aktuelle Datensätze"
@@ -7536,10 +7944,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-#, fuzzy
-msgid "Refresh"
-msgstr "Standard-Bildwiederholrate"
-
#, fuzzy
msgid "Refresh Settings Cache"
msgstr "Service-Status"
@@ -7685,6 +8089,10 @@ msgstr "Bericht"
msgid "Report Management"
msgstr "Berichteverwaltung"
+#, fuzzy
+msgid "Reported"
+msgstr "Bericht"
+
msgid "Reports"
msgstr "Berichte"
@@ -7750,9 +8158,16 @@ msgstr ""
msgid "Retention sweep failed"
msgstr "Entfernen fehlgeschlagen"
+msgid "Retry"
+msgstr ""
+
msgid "Return Code"
msgstr "Return-Code"
+#, fuzzy
+msgid "Return Codes"
+msgstr "Return-Code"
+
msgid "Return To Local Login"
msgstr ""
@@ -7763,9 +8178,33 @@ msgstr "Rückgabewert"
msgid "Returning value of key"
msgstr "Wert des Schlüssels zurückgeben"
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+#, fuzzy
+msgid "Revoke an agent enrollment token"
+msgstr "Ausstehende registrierte Hosts"
+
+#, fuzzy
+msgid "Revoke selected"
+msgstr "Ausgewählte entfernen "
+
+#, fuzzy
+msgid "Revoked selected tokens."
+msgstr "Ausgewählten MAcs freigeben"
+
+msgid "Revoked."
+msgstr ""
+
#, fuzzy
msgid "Role"
msgstr "Rollenname"
@@ -7906,6 +8345,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
#, fuzzy
msgid "SQL Error"
msgstr "SQL-Fehler"
@@ -8024,16 +8466,6 @@ msgstr "iPXE-Einstellungen erfolgreich aktualisiert!"
msgid "Scopes"
msgstr ""
-msgid "Screen Height"
-msgstr ""
-
-#, fuzzy
-msgid "Screen Refresh Rate"
-msgstr "Standard-Bildwiederholrate"
-
-msgid "Screen Width"
-msgstr ""
-
msgid "Search"
msgstr "Suche"
@@ -8269,6 +8701,9 @@ msgstr "Ein Host mit diesem Namen ist bereits vorhanden."
msgid "Sessions canceled!"
msgstr "geplante Tasks wurde erfolgreich erstellt"
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -8735,6 +9170,63 @@ msgstr "genutzte Snapins"
msgid "So if you are trying to transmit to remote node A"
msgstr "Wenn Sie also versuchen, an den entfernten Knoten A zu senden,"
+msgid "Software"
+msgstr ""
+
+#, fuzzy
+msgid "Software Create Fail"
+msgstr "Drucker erstellen fehlgeschlagen!"
+
+#, fuzzy
+msgid "Software Create Success"
+msgstr "Drucker hinzufügen erfolgreich."
+
+#, fuzzy
+msgid "Software Host Associations"
+msgstr "zugeordneter Host"
+
+#, fuzzy
+msgid "Software Management"
+msgstr "Speicherverwaltung"
+
+#, fuzzy
+msgid "Software Name"
+msgstr "Sitename"
+
+msgid "Software Order"
+msgstr ""
+
+#, fuzzy
+msgid "Software Report"
+msgstr "Verlaufs-ID"
+
+#, fuzzy
+msgid "Software Status"
+msgstr "Neuen Standort erstellen"
+
+#, fuzzy
+msgid "Software Update Fail"
+msgstr "Drucker-Update fehlgeschlagen!"
+
+#, fuzzy
+msgid "Software Update Success"
+msgstr "Host Aktualisierung erfolgreich!"
+
+#, fuzzy
+msgid "Software added!"
+msgstr "Drucker hinzugefügt"
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+#, fuzzy
+msgid "Software update failed!"
+msgstr "Drucker-Update fehlgeschlagen!"
+
+#, fuzzy
+msgid "Software updated!"
+msgstr "Drucker aktualisiert!"
+
msgid "Some nice description, should be short."
msgstr ""
@@ -8747,6 +9239,9 @@ msgstr "Bereichsvariable muss boolean sein"
msgid "Specified download URL not allowed!"
msgstr ""
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -9500,6 +9995,9 @@ msgstr "Es gibt keine Gruppen auf diesem Server."
msgid "The CA private key is on this server"
msgstr "Es gibt keine Gruppen auf diesem Server."
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -9533,6 +10031,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -9577,6 +10078,9 @@ msgstr " | Datei oder Pfad ist nicht erreichbar"
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -9617,6 +10121,13 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+#, fuzzy
+msgid "The enrollment is no longer pending."
+msgstr "läuft nicht mehr"
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -9644,6 +10155,15 @@ msgstr ""
msgid "The grid key."
msgstr "Fehler beim Erstellen eines Tasks"
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
#, fuzzy
msgid "The identity provider could not be reached"
msgstr "Temporäre Datei konnte nicht gelesen werden."
@@ -9698,9 +10218,16 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+#, fuzzy
+msgid "The item is not a live row of this host."
+msgstr "Keinen aktiven Task gefunden für Host"
+
msgid "The key will be assigned to registered hosts when a"
msgstr "Der Schlüssel wird registrierten Hosts zugewiesen, wenn"
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -9730,12 +10257,21 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
msgid "The path requested is already in use by another image!"
msgstr ""
+msgid "The payload bytes."
+msgstr ""
+
#, fuzzy
msgid "The plugin directory"
msgstr "Home-Verzeichnis speichern"
@@ -9780,6 +10316,13 @@ msgstr ""
msgid "The record could not be written."
msgstr "Temporäre Datei konnte nicht gelesen werden."
+#, fuzzy
+msgid "The renewed certificate, leaf then chain."
+msgstr "Neuen Standort erstellen"
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -9789,6 +10332,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -9800,6 +10346,12 @@ msgstr "Drucker-Update fehlgeschlagen!"
msgid "The selected site no longer exists"
msgstr "läuft nicht mehr"
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -9819,6 +10371,13 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+#, fuzzy
+msgid "The signing helper is not available on this server."
+msgstr "Es gibt keine Gruppen auf diesem Server."
+
#, fuzzy
msgid "The signing request could not be generated"
msgstr "Temporäre Datei konnte nicht gelesen werden."
@@ -9839,6 +10398,10 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+#, fuzzy
+msgid "The token."
+msgstr "CPU-Anzahl"
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -10001,6 +10564,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -10061,10 +10627,16 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, fuzzy, php-format
msgid "This machine already registered as %s"
msgstr "Bereits registriert als"
+msgid "This module has no settings to configure."
+msgstr ""
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -10172,6 +10744,13 @@ msgstr "Zeit bereits vorhanden"
msgid "Time since last imaged"
msgstr ""
+#, fuzzy
+msgid "Timeout"
+msgstr "Zeit"
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -10194,9 +10773,31 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Regel Zuordnung"
+#, fuzzy
+msgid "Token Create Fail"
+msgstr "Drucker erstellen fehlgeschlagen!"
+
+#, fuzzy
+msgid "Token Create Success"
+msgstr "Drucker hinzufügen erfolgreich."
+
+#, fuzzy
+msgid "Token Revoke Fail"
+msgstr "FTP-Verbindung fehlgeschlagen"
+
+#, fuzzy
+msgid "Token Revoke Success"
+msgstr "Drucker hinzufügen erfolgreich."
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
#, fuzzy
msgid "Too many MACs"
msgstr "zu viele MACs"
@@ -10383,6 +10984,9 @@ msgstr "Benutzername Attribut"
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
#, fuzzy
msgid "Unauthenticated."
msgstr "Authentifizieren nicht möglich"
@@ -10433,6 +11037,9 @@ msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
msgid "Unknown action"
msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -10463,6 +11070,9 @@ msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
#, fuzzy
msgid "Unmark selected client ignore"
msgstr "Ausgewählten MAcs freigeben"
@@ -10552,6 +11162,9 @@ msgstr "ausgewählte Images hinzufügen"
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
#, fuzzy
msgid "Upload"
msgstr "Berichte hochladen"
@@ -10664,9 +11277,6 @@ msgstr "Benutzer ist bereits vorhanden"
msgid "User Association"
msgstr "Site Zugehörigkeit"
-msgid "User Cleanup"
-msgstr "Benutzer-Bereinigung"
-
#, fuzzy
msgid "User Count"
msgstr "CPU-Anzahl"
@@ -10752,6 +11362,10 @@ msgstr "Benutzername Attribut"
msgid "User Password"
msgstr "Benutzerpasswort"
+#, fuzzy
+msgid "User Sessions"
+msgstr "Site Zugehörigkeit"
+
msgid "User Tracker"
msgstr "Benutzer-Tracker"
@@ -10834,6 +11448,12 @@ msgstr "Benutzer"
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr "Verwenden der Gruppenübereinstimmungsfunktion,"
@@ -10859,6 +11479,10 @@ msgstr "Version"
msgid "Version information and paging bounds."
msgstr "FOG-Versionsinformationen"
+#, fuzzy
+msgid "Version policy"
+msgstr "Version"
+
#, fuzzy
msgid "Versions"
msgstr "Version"
@@ -10888,6 +11512,9 @@ msgstr "Wake On Lan"
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -10941,12 +11568,18 @@ msgstr "wurde abgebrochen"
msgid "What it does"
msgstr "wurde abgebrochen"
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -10963,6 +11596,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr "Wo bekomme ich Hilfe?"
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -10975,10 +11611,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -11052,6 +11688,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr "Jährlich"
@@ -11174,6 +11813,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
#, fuzzy
msgid "access"
msgstr "Zugang"
@@ -11185,10 +11827,17 @@ msgstr "zusätzliche MACs haben"
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
#, fuzzy
msgid "ago"
msgstr "vor"
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
#, fuzzy
msgid "all current storage nodes"
msgstr "momentanen Speicherknoten löschen."
@@ -11224,6 +11873,13 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+#, fuzzy
+msgid "any version"
+msgstr "Version"
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
#, fuzzy
msgid "architecture not recorded"
msgstr "Temporäre Datei konnte nicht gelesen werden."
@@ -11235,6 +11891,10 @@ msgstr "da der FOG versuchen wird, mit dem Internet zu verbinden, "
msgid "as its primary group"
msgstr "als primäre Gruppe finden"
+#, fuzzy
+msgid "assigned"
+msgstr "zugeordneter Host"
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -11341,6 +12001,9 @@ msgstr "Deaktiviert"
msgid "does not exist and cannot be created"
msgstr "Image ist geschützt und kann nicht gelöscht werden"
+msgid "domain"
+msgstr ""
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -11350,6 +12013,9 @@ msgstr "ob bereits ausgewählt oder hochgeladen"
msgid "either because you have updated"
msgstr "entweder weil Sie aktualisiert haben"
+msgid "empty means never install Chocolatey"
+msgstr ""
+
#, fuzzy
msgid "error"
msgstr "Fehler"
@@ -11357,10 +12023,20 @@ msgstr "Fehler"
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+#, fuzzy
+msgid "failed"
+msgstr "fehlgeschlagen"
+
#, fuzzy
msgid "failed to execute, image file"
msgstr "Löschen der Imagedateien fehlgeschlagen"
@@ -11460,6 +12136,10 @@ msgstr ""
msgid "host"
msgstr "Host"
+#, fuzzy, php-format
+msgid "host \"%s\""
+msgstr "Hosts"
+
#, fuzzy
msgid "host is"
msgstr "Hosts"
@@ -11575,9 +12255,6 @@ msgstr ""
msgid "in"
msgstr "Minuten"
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
@@ -11585,9 +12262,6 @@ msgstr ""
msgid "in minutes"
msgstr "Minuten"
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr "in Sekunden"
@@ -11663,6 +12337,10 @@ msgstr "aktiviert werden."
msgid "keys"
msgstr ""
+#, fuzzy
+msgid "latest"
+msgstr "Replizieren"
+
msgid "leave to keep the current one"
msgstr ""
@@ -11696,6 +12374,10 @@ msgstr "Minuten"
msgid "mismatched"
msgstr ""
+#, fuzzy
+msgid "missing"
+msgstr "Version"
+
msgid "moments from now"
msgstr ""
@@ -11733,6 +12415,10 @@ msgstr ""
msgid "never"
msgstr ""
+#, fuzzy
+msgid "never reported"
+msgstr "Inventar"
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -11765,6 +12451,9 @@ msgstr ""
msgid "not found on this node"
msgstr "auf diesem Knoten nicht gefunden"
+msgid "not joined"
+msgstr ""
+
#, fuzzy
msgid "not reachable"
msgstr "Nicht verfügbar"
@@ -11795,10 +12484,16 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+msgid "off"
+msgstr ""
+
#, fuzzy
msgid "off means an account must already exist"
msgstr "Dieser Host ist bereits vorhanden."
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -11812,6 +12507,9 @@ msgstr ""
msgid "optional"
msgstr "Ort"
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
msgid "or"
msgstr "oder"
@@ -12090,6 +12788,10 @@ msgstr "nicht verfügbar"
msgid "unchanged for"
msgstr "Imaged für"
+#, fuzzy
+msgid "unknown action"
+msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
+
#, fuzzy
msgid "unrecorded"
msgstr "(empfohlen)"
@@ -12324,6 +13026,10 @@ msgstr ""
#~ msgid "Can not redeclare route"
#~ msgstr "Route kann nicht nochmal neu definiert werden"
+#, fuzzy
+#~ msgid "Cannot connect to ftp server"
+#~ msgstr "Verbindung zum FTP-Server nicht möglich"
+
#~ msgid "Check that database is running"
#~ msgstr "Überprüfen Sie, ob die Datenbank ausgeführt wird"
@@ -12331,6 +13037,10 @@ msgstr ""
#~ msgid "Client Module Settings"
#~ msgstr "Client Einstellungen"
+#, fuzzy
+#~ msgid "Could not read snapin file"
+#~ msgstr "Snapin-Datei konnte nicht gelesen werden."
+
#, fuzzy
#~ msgid "Create New Accesscontrol"
#~ msgstr "Neuen Schlüssel erstellen"
@@ -12355,6 +13065,15 @@ msgstr ""
#~ msgid "Database connection unavailable"
#~ msgstr "Pfad ist nicht verfügbar"
+#~ msgid "Default Height"
+#~ msgstr "Standardhöhe"
+
+#~ msgid "Default Refresh Rate"
+#~ msgstr "Standard-Bildwiederholrate"
+
+#~ msgid "Default Width"
+#~ msgstr "Standardbreite"
+
#, fuzzy
#~ msgid "Delete All"
#~ msgstr "Löschen fehlgeschlagen"
@@ -12363,6 +13082,9 @@ msgstr ""
#~ msgid "Deprecated."
#~ msgstr "Erstellen"
+#~ msgid "Directory Cleaner"
+#~ msgstr "Verzeichnis-Bereiniger"
+
#, fuzzy
#~ msgid "Domain joining"
#~ msgstr "Standort senden aktivieren"
@@ -12428,6 +13150,18 @@ msgstr ""
#~ msgid "Export Users"
#~ msgstr "Benutzer exportieren"
+#, fuzzy
+#~ msgid "FOG Agent desired state"
+#~ msgstr "wurde abgebrochen"
+
+#, fuzzy
+#~ msgid "FOG Agent snapin result"
+#~ msgstr "Keine Datei wurde hochgeladen"
+
+#, fuzzy
+#~ msgid "FOG Agent software result"
+#~ msgstr "Keine Datei wurde hochgeladen"
+
#~ msgid "Failed to add/update snapin file"
#~ msgstr "Hinzufügen/aktualisieren eines Snapin-Datei"
@@ -12542,10 +13276,18 @@ msgstr ""
#~ msgid "Group module settings"
#~ msgstr "Gruppeneinstellungen Module"
+#, fuzzy
+#~ msgid "Height"
+#~ msgstr "Mitternacht"
+
#, fuzzy
#~ msgid "History Report"
#~ msgstr "Verlaufs-ID"
+#, fuzzy
+#~ msgid "Host Display Manager Settings"
+#~ msgstr "iPXE Menüeinstellungen"
+
#, fuzzy
#~ msgid "Host Ext"
#~ msgstr "Hostliste"
@@ -12562,6 +13304,10 @@ msgstr ""
#~ msgid "Host Ext Variable"
#~ msgstr "Aktualisierung der Rolle fehlgeschlagen"
+#, fuzzy
+#~ msgid "Host Screen Resolution"
+#~ msgstr "Host-Registrierung"
+
#, fuzzy
#~ msgid "Host Site"
#~ msgstr "Hostliste"
@@ -12665,6 +13411,9 @@ msgstr ""
#~ msgid "Install"
#~ msgstr "Installierte Plugins"
+#~ msgid "Invalid Storage Node"
+#~ msgstr "Ungültiger Speicherknoten"
+
#, fuzzy
#~ msgid "Invalid Type"
#~ msgstr "Ungültiger Typ"
@@ -12688,6 +13437,14 @@ msgstr ""
#~ msgid "LDAP User Filter"
#~ msgstr "LDAP-Server"
+#, fuzzy
+#~ msgid "Last Activity"
+#~ msgstr "Aktiv"
+
+#, fuzzy
+#~ msgid "Last Event"
+#~ msgstr "Zuletzt hochgeladen"
+
#, fuzzy
#~ msgid "Latest SVN Version"
#~ msgstr "Neueste SVN-Version"
@@ -12753,6 +13510,14 @@ msgstr ""
#~ msgid "Not Installed"
#~ msgstr "Installierte Plugins"
+#, fuzzy
+#~ msgid "Not a live task of this host's job."
+#~ msgstr "Keinen aktiven Task gefunden für Host"
+
+#, fuzzy
+#~ msgid "Not an entry in this host's software set."
+#~ msgstr "Keinen aktiven Task gefunden für Host"
+
#, fuzzy
#~ msgid "Pause"
#~ msgstr "Pause"
@@ -12781,9 +13546,13 @@ msgstr ""
#~ msgstr "Host Produktschlüssel"
#, fuzzy
-#~ msgid "Recorded"
+#~ msgid "Recorded."
#~ msgstr "(empfohlen)"
+#, fuzzy
+#~ msgid "Refresh"
+#~ msgstr "Standard-Bildwiederholrate"
+
#~ msgid "Register must be managed from hooks or events"
#~ msgstr "Register muss von Haken oder Ereignissen gemanagt werden"
@@ -12859,6 +13628,10 @@ msgstr ""
#~ msgid "Rule update failed!"
#~ msgstr "Drucker-Update fehlgeschlagen!"
+#, fuzzy
+#~ msgid "Screen Refresh Rate"
+#~ msgstr "Standard-Bildwiederholrate"
+
#, fuzzy
#~ msgid "Serial"
#~ msgstr "Seriennummer"
@@ -12904,8 +13677,16 @@ msgstr ""
#~ msgstr "Dieser Host ist bereits vorhanden."
#, fuzzy
-#~ msgid "The certificate chain"
-#~ msgstr "Neuen Standort erstellen"
+#~ msgid "The desired state."
+#~ msgstr "Fehler beim Erstellen eines Tasks"
+
+#, fuzzy
+#~ msgid "The host this certificate is, and the capabilities this server offers."
+#~ msgstr "Es gibt keine Gruppen auf diesem Server."
+
+#, fuzzy
+#~ msgid "The task was already closed."
+#~ msgstr "Dieser Host ist bereits vorhanden."
#, fuzzy
#~ msgid "There are no "
@@ -12950,6 +13731,10 @@ msgstr ""
#~ msgid "Unable to set user filter."
#~ msgstr "Datei kann zum Lesen nicht geöffnet werden"
+#, fuzzy
+#~ msgid "Unknown status."
+#~ msgstr "Ein unbekannter Upload-Fehler ist aufgetreten"
+
#, fuzzy
#~ msgid "Update Master Node"
#~ msgstr "Master-Knoten"
@@ -12962,6 +13747,9 @@ msgstr ""
#~ msgid "Update/Remove printers"
#~ msgstr "Drucker Aktualisieren/Entfernen"
+#~ msgid "User Cleanup"
+#~ msgstr "Benutzer-Bereinigung"
+
#, fuzzy
#~ msgid "User Group Site"
#~ msgstr "Gruppen-Snapins"
@@ -13054,10 +13842,6 @@ msgstr ""
#~ msgid "min (all)"
#~ msgstr "Aktiviert"
-#, fuzzy
-#~ msgid "multicast tasks!"
-#~ msgstr "Aktive Multicast-Tasks"
-
#, fuzzy
#~ msgid "no database to"
#~ msgstr "Keine Datenbank zum"
@@ -13073,7 +13857,3 @@ msgstr ""
#, fuzzy
#~ msgid "username"
#~ msgstr "Benutzername"
-
-#, fuzzy
-#~ msgid "version"
-#~ msgstr "Version"
diff --git a/packages/web/management/languages/fr_FR.UTF-8/LC_MESSAGES/messages.po b/packages/web/management/languages/fr_FR.UTF-8/LC_MESSAGES/messages.po
index f12d8aea38..cc9b3b9e59 100644
--- a/packages/web/management/languages/fr_FR.UTF-8/LC_MESSAGES/messages.po
+++ b/packages/web/management/languages/fr_FR.UTF-8/LC_MESSAGES/messages.po
@@ -126,6 +126,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -295,6 +299,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, fuzzy, php-format
+msgid "(deleted host %d)"
+msgstr "Approuver hôtes sélectionnés"
+
msgid "(deleted user)"
msgstr ""
@@ -314,9 +322,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr "Arguments du noyau"
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
#, fuzzy
msgid "1 Hour"
msgstr "1 heure"
@@ -421,6 +435,12 @@ msgstr "Une image existe déjà avec ce nom!"
msgid "A client ID is required"
msgstr "Un nom de l'image est nécessaire!"
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
#, fuzzy
msgid "A dmi field must be set!"
msgstr "Événement doit être une chaîne"
@@ -484,6 +504,9 @@ msgstr "Une image existe déjà avec ce nom!"
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
#, fuzzy
msgid "A module already exists with this name!"
msgstr "Une image existe déjà avec ce nom!"
@@ -505,6 +528,9 @@ msgstr "Lister tous les %s"
msgid "A permission name is required."
msgstr "Un nom de l'image est nécessaire!"
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -527,6 +553,9 @@ msgstr "Une image existe déjà avec ce nom!"
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
#, fuzzy
msgid "A role already exists with this name!"
msgstr "Une image existe déjà avec ce nom!"
@@ -568,6 +597,10 @@ msgstr "Une image existe déjà avec ce nom!"
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+#, fuzzy
+msgid "A software entry already exists with this name!"
+msgstr "Une image existe déjà avec ce nom!"
+
#, fuzzy
msgid "A storage group already exists with this name!"
msgstr "Une image existe déjà avec ce nom!"
@@ -703,6 +736,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -933,6 +972,10 @@ msgstr "Ajouter SnapIn a échoué!"
msgid "Add snapin failed!"
msgstr "Ajouter SnapIn a échoué!"
+#, fuzzy
+msgid "Add software failed!"
+msgstr "Ajouter SnapIn a échoué!"
+
#, fuzzy
msgid "Add storage node failed!"
msgstr "Ajouter SnapIn a échoué!"
@@ -1017,6 +1060,33 @@ msgstr "Avancée"
msgid "Advanced Tasks"
msgstr "Avancée"
+msgid "Agent"
+msgstr ""
+
+#, fuzzy
+msgid "Agent Activity"
+msgstr "actif"
+
+#, fuzzy
+msgid "Agent Approval Success"
+msgstr "hôte Créé"
+
+#, fuzzy
+msgid "Agent Denial Success"
+msgstr "Imprimante mis à jour!"
+
+#, fuzzy
+msgid "Agent Enrollment Tokens"
+msgstr "a été mis à jour avec succès"
+
+#, fuzzy
+msgid "Agent Tokens"
+msgstr "Jeton d'accès"
+
+#, fuzzy
+msgid "Agent enrollment tokens"
+msgstr "a été mis à jour avec succès"
+
msgid "Ago must be boolean"
msgstr ""
@@ -1033,6 +1103,10 @@ msgstr ""
msgid "All Hosts"
msgstr "Tous les hôtes"
+#, fuzzy
+msgid "All Pending Agents"
+msgstr "en attente MACs"
+
#, fuzzy
msgid "All Pending Hosts"
msgstr "Les hôtes en attente"
@@ -1136,10 +1210,16 @@ msgstr ""
msgid "An SQL error occurred"
msgstr "Erreur inconnue de téléchargement a eu lieu. Code de retour: "
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
#, fuzzy
msgid "An entry already exists with this name!"
msgstr "Une image existe déjà avec ce nom!"
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr "Une image existe déjà avec ce nom!"
@@ -1179,6 +1259,10 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+#, fuzzy
+msgid "Any version"
+msgstr "Version"
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1217,18 +1301,36 @@ msgstr ""
msgid "Approve"
msgstr "hôte approuvé"
+#, fuzzy
+msgid "Approve Agent Fail"
+msgstr "hôte approuvé"
+
#, fuzzy
msgid "Approve MAC Fail"
msgstr "hôte approuvé"
+#, fuzzy
+msgid "Approve Pending Agents"
+msgstr "Les hôtes en attente"
+
#, fuzzy
msgid "Approve Pending Hosts"
msgstr "Les hôtes en attente"
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
#, fuzzy
msgid "Approve selected"
msgstr "Approuver hôtes sélectionnés"
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+#, fuzzy
+msgid "Approved selected agents!"
+msgstr "Approuver hôtes sélectionnés"
+
#, fuzzy
msgid "Approved selected hosts!"
msgstr "Approuver hôtes sélectionnés"
@@ -1241,6 +1343,9 @@ msgstr "Approuver hôtes sélectionnés"
msgid "Approving the selected pending hosts."
msgstr "Approuver hôtes sélectionnés"
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1250,6 +1355,10 @@ msgstr ""
msgid "Area"
msgstr ""
+#, fuzzy
+msgid "Assigned"
+msgstr "Aucun noeud associé"
+
#, fuzzy
msgid "Assigned Group"
msgstr "Nom du groupe de stockage"
@@ -1312,6 +1421,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1350,6 +1462,9 @@ msgstr "Vendor BIOS"
msgid "BIOS Version"
msgstr "BIOS Version"
+msgid "Backend"
+msgstr ""
+
#, fuzzy
msgid "Bad request."
msgstr "%s est requis"
@@ -1583,6 +1698,10 @@ msgstr "tâche Annulé"
msgid "Canceled due to new tasking."
msgstr "Annulé en raison de nouvelles tâches."
+#, fuzzy
+msgid "Cannot Run"
+msgstr "Enregistrement non trouvé, Erreur: %s"
+
#, fuzzy
msgid "Cannot bind to the LDAP server"
msgstr "Impossible de se connecter à la base de données"
@@ -1597,10 +1716,6 @@ msgstr "Impossible de se connecter au noeud."
msgid "Cannot connect to database"
msgstr "Impossible de se connecter à la base de données"
-#, fuzzy
-msgid "Cannot connect to ftp server"
-msgstr "Impossible de se connecter à la base de données"
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1797,6 +1912,9 @@ msgstr "Non FOGPage Classe trouvé pour ce noeud"
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+msgid "Checked"
+msgstr ""
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1809,6 +1927,12 @@ msgstr ""
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1980,14 +2104,23 @@ msgstr "Erreur: Impossible de télécharger le noyau"
msgid "Confirm you would like to download a new kernel"
msgstr "Erreur: Impossible de télécharger le noyau"
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
#, fuzzy
msgid "Copy from existing"
msgstr "Impossible de créer l'imprimante"
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -2061,10 +2194,6 @@ msgstr "Impossible de lire le fichier tmp."
msgid "Could not read local file"
msgstr "Impossible de lire le fichier temporaire"
-#, fuzzy
-msgid "Could not read snapin file"
-msgstr "Impossible de lire le fichier tmp."
-
#, fuzzy
msgid "Could not read the database structure"
msgstr "Échec de la création d'emploi Snapin"
@@ -2161,6 +2290,9 @@ msgstr ""
msgid "Create"
msgstr "Créer"
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -2243,6 +2375,9 @@ msgstr "Créer un nouveau site"
msgid "Create New Snapin"
msgstr "Créer un nouveau snapin"
+msgid "Create New Software"
+msgstr "Créer un nouveau logiciel"
+
msgid "Create New Storage Group"
msgstr "Créer un nouveau groupe de stockage"
@@ -2290,6 +2425,10 @@ msgstr "utilisateur créé"
msgid "Create Users On First Login"
msgstr ""
+#, fuzzy, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr "utilisateur créé"
+
#, fuzzy, php-format
msgid "Create a %s"
msgstr "Créer un nouveau %s"
@@ -2313,9 +2452,17 @@ msgstr "utilisateur créé"
msgid "Create task form success"
msgstr "utilisateur créé"
+#, fuzzy
+msgid "Create tasking"
+msgstr "Créer un nouveau %s"
+
msgid "Create tasking succeeded"
msgstr ""
+#, fuzzy
+msgid "Create token"
+msgstr "Créer un nouveau %s"
+
#, fuzzy
msgid "Created"
msgstr "Créer"
@@ -2327,6 +2474,10 @@ msgstr "Créé par"
msgid "Created Time"
msgstr "Créé par"
+#, fuzzy
+msgid "Created by"
+msgstr "Créé par"
+
msgid "Created by FOG Reg on"
msgstr "Créé par FOG Reg sur"
@@ -2455,6 +2606,9 @@ msgstr "Options de débogage"
msgid "Debug Task"
msgstr "Déboguer"
+msgid "Decided."
+msgstr ""
+
msgid "Default"
msgstr "Défaut"
@@ -2462,15 +2616,6 @@ msgstr "Défaut"
msgid "Default Choice"
msgstr "Point par défaut:"
-msgid "Default Height"
-msgstr "Hauteur par défaut"
-
-msgid "Default Refresh Rate"
-msgstr "Par défaut Taux de rafraîchissement"
-
-msgid "Default Width"
-msgstr "Par défaut Largeur"
-
#, fuzzy
msgid "Default init, ARM64"
msgstr "Par défaut Largeur"
@@ -2555,6 +2700,28 @@ msgstr ""
msgid "Deleting remote file"
msgstr "Menu create a échoué"
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+#, fuzzy
+msgid "Denied selected agents!"
+msgstr "Approuver hôtes sélectionnés"
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy
+msgid "Deny Agent Fail"
+msgstr "Supprimer les données de fichiers"
+
+#, fuzzy
+msgid "Deny Pending Agents"
+msgstr "en attente MACs"
+
+#, fuzzy
+msgid "Deny selected"
+msgstr "Supprimer sélectionnée"
+
msgid "Deploy"
msgstr "Déployer"
@@ -2571,14 +2738,30 @@ msgstr ""
msgid "Description"
msgstr "La description"
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+msgid "Desired domain"
+msgstr ""
+
#, fuzzy
msgid "Destroy failed"
msgstr "Destroy a échoué: %s"
+#, fuzzy
+msgid "Detail"
+msgstr "Snapin Retour Détail"
+
#, fuzzy
msgid "Details"
msgstr "Snapin Retour Détail"
+msgid "Device URI"
+msgstr ""
+
#, fuzzy
msgid "Device must be a string"
msgstr "Événement doit être une chaîne"
@@ -2592,9 +2775,6 @@ msgstr "Annuaire"
msgid "Directory Already Exists"
msgstr "Répertoire existe déjà"
-msgid "Directory Cleaner"
-msgstr "Directory Cleaner"
-
#, fuzzy
msgid "Directory Group"
msgstr "Annuaire"
@@ -2603,6 +2783,10 @@ msgstr "Annuaire"
msgid "Directory Group Name"
msgstr "Annuaire"
+#, fuzzy
+msgid "Directory Membership"
+msgstr "Adhésion"
+
#, fuzzy
msgid "Disable on all hosts"
msgstr "Activée"
@@ -2719,6 +2903,9 @@ msgstr "Échec du téléchargement"
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2738,6 +2925,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr "modifier"
@@ -2833,6 +3023,10 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+#, fuzzy
+msgid "Enrollment Token"
+msgstr "Comptes Pushbullet"
+
msgid "Enrollment kit"
msgstr ""
@@ -2936,6 +3130,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
#, fuzzy
msgid "Every file was uploaded."
msgstr "Aucun fichier a été téléchargé"
@@ -2956,6 +3156,14 @@ msgstr "La clé privée a échoué"
msgid "Exists item must be boolean"
msgstr ""
+#, fuzzy
+msgid "Exit Code"
+msgstr "Export SnapIns"
+
+#, fuzzy
+msgid "Exit code"
+msgstr "code de retour"
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -3035,9 +3243,32 @@ msgstr "date"
msgid "External root CA"
msgstr ""
+#, fuzzy
+msgid "Extra arguments"
+msgstr "Snapin Run With Argument"
+
msgid "FOG"
msgstr "BROUILLARD"
+#, fuzzy
+msgid "FOG Agent capability result"
+msgstr "Aucun fichier a été téléchargé"
+
+#, fuzzy
+msgid "FOG Agent certificate renewal"
+msgstr "Aucun fichier a été téléchargé"
+
+#, fuzzy
+msgid "FOG Agent enrollment"
+msgstr "a été mis à jour avec succès"
+
+#, fuzzy
+msgid "FOG Agent payload"
+msgstr "Aucun fichier a été téléchargé"
+
+msgid "FOG Agent poll"
+msgstr ""
+
#, fuzzy
msgid "FOG Client"
msgstr "FOG client Wiki"
@@ -3396,6 +3627,9 @@ msgstr "Tâche Started"
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3739,6 +3973,10 @@ msgstr "snapin Histoire"
msgid "Group Snapin History"
msgstr "snapin Histoire"
+#, fuzzy
+msgid "Group Software Assignment"
+msgstr "snapin Histoire"
+
#, fuzzy
msgid "Group Task History"
msgstr "Histoire de l'image"
@@ -3827,9 +4065,15 @@ msgstr "Informations sur le matériel"
msgid "Hardware Report"
msgstr "Informations sur le matériel"
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr ""
+msgid "Hash Mismatch"
+msgstr ""
+
msgid "Have not locked the host for access"
msgstr ""
@@ -3837,10 +4081,6 @@ msgstr ""
msgid "Header is missing the required \"%s\" column"
msgstr ""
-#, fuzzy
-msgid "Height"
-msgstr "Minuit"
-
msgid "Height must be 120 pixels."
msgstr ""
@@ -3913,6 +4153,9 @@ msgstr "Imprimante existe déjà"
msgid "Host %1$s finished deploying image %2$s."
msgstr "Imprimante existe déjà"
+msgid "Host Agent Activity"
+msgstr ""
+
#, fuzzy
msgid "Host Approval Success"
msgstr "hôte Créé"
@@ -3948,10 +4191,6 @@ msgstr "Point par défaut:"
msgid "Host Description"
msgstr "hôte description de"
-#, fuzzy
-msgid "Host Display Manager Settings"
-msgstr "Paramètres"
-
msgid "Host EFI Exit Type"
msgstr "Hôte EFI Type de sortie"
@@ -4056,10 +4295,6 @@ msgstr "Hôte clé de produit"
msgid "Host Registration"
msgstr "Enregistrement de l'hôte"
-#, fuzzy
-msgid "Host Screen Resolution"
-msgstr "Enregistrement de l'hôte"
-
#, fuzzy
msgid "Host Snapin Associations"
msgstr "Aucun noeud associé"
@@ -4068,6 +4303,13 @@ msgstr "Aucun noeud associé"
msgid "Host Snapin History"
msgstr "snapin Histoire"
+#, fuzzy
+msgid "Host Software Assignment"
+msgstr "snapin Histoire"
+
+msgid "Host Software Status"
+msgstr ""
+
#, fuzzy
msgid "Host Task History"
msgstr "Histoire de l'image"
@@ -4161,6 +4403,12 @@ msgstr "Liste des hôtes"
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
#, fuzzy
msgid "Hosts:"
msgstr "hôtes"
@@ -4225,6 +4473,10 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+#, fuzzy
+msgid "Identity"
+msgstr "serveur Shell"
+
msgid "Identity Provider"
msgstr ""
@@ -4740,6 +4992,10 @@ msgstr "Plugins installés"
msgid "Installed Plugins"
msgstr "Plugins installés"
+#, fuzzy
+msgid "Installed Software"
+msgstr "Plugins installés"
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4826,9 +5082,6 @@ msgstr "Invalid Snapin Tasking"
msgid "Invalid Storage Group"
msgstr "Groupe de stockage non valide"
-msgid "Invalid Storage Node"
-msgstr "Invalid Storage Node"
-
#, fuzzy
msgid "Invalid Tasking"
msgstr "tâche non valide"
@@ -5012,6 +5265,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -5037,6 +5293,9 @@ msgstr ""
msgid "It will operate based on the fields the area typcially requires."
msgstr ""
+msgid "Join"
+msgstr ""
+
msgid "Join Domain after image task"
msgstr ""
@@ -5238,6 +5497,9 @@ msgstr "La langue"
msgid "Largest images"
msgstr "Images"
+msgid "Last Agent Check-In"
+msgstr ""
+
#, fuzzy
msgid "Last Captured"
msgstr "hôte Créé"
@@ -5248,15 +5510,16 @@ msgstr ""
msgid "Last Check-In"
msgstr ""
-msgid "Last Client Check-In"
-msgstr ""
-
msgid "Last Deployed"
msgstr "Dernière Déployé"
msgid "Last Ping"
msgstr ""
+#, fuzzy
+msgid "Last Seen"
+msgstr "hôte Créé"
+
#, fuzzy
msgid "Last Successful Ping"
msgstr "Réussi"
@@ -5272,6 +5535,10 @@ msgstr ""
msgid "Last deployed"
msgstr "Dernière Déployé"
+#, fuzzy
+msgid "Last error"
+msgstr "Erreur"
+
msgid "Last flush"
msgstr ""
@@ -5279,6 +5546,9 @@ msgstr ""
msgid "Last imaged"
msgstr "Images"
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
#, fuzzy
msgid "Latest Alpha Version"
msgstr "Dernière version"
@@ -5403,6 +5673,9 @@ msgstr "Lister tous les sites"
msgid "List All Snapins"
msgstr "Lister tous les snapins"
+msgid "List All Software"
+msgstr "Lister tous les logiciels"
+
msgid "List All Storage Groups"
msgstr "Lister tous les groupes de stockage"
@@ -5539,6 +5812,9 @@ msgstr "Log Viewer"
msgid "Log out and sign in as an administrator"
msgstr ""
+msgid "Logged on"
+msgstr ""
+
msgid "Logging"
msgstr ""
@@ -5731,6 +6007,9 @@ msgstr "Max Taille"
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
#, fuzzy
msgid "Member"
msgstr "Membres"
@@ -5811,6 +6090,10 @@ msgstr "Minuit"
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+#, fuzzy
+msgid "Mint an agent enrollment token"
+msgstr "Dans l'attente des hôtes enregistrés"
+
msgid "Minute value is not valid"
msgstr "valeur de la minute est pas valide"
@@ -5818,6 +6101,9 @@ msgstr "valeur de la minute est pas valide"
msgid "Minutes field is invalid"
msgstr "valeur de la minute est pas valide"
+msgid "Missing"
+msgstr ""
+
msgid "Missing a temporary folder"
msgstr "Manquer un dossier temporaire"
@@ -6285,6 +6571,10 @@ msgstr "Pas de fentes ouvertes"
msgid "No password is needed. Issue this account a token from its API tab, or from FOG Configuration → API Tokens, once it has been created."
msgstr ""
+#, fuzzy
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr "Aucune tâche active trouvée pour Host"
+
#, fuzzy
msgid "No plugin tasks to run"
msgstr "Aucune classe valide envoyé"
@@ -6340,7 +6630,11 @@ msgid "No snapins associated with this group as master"
msgstr "Il n'y a pas snapins associés à cet hôte"
#, fuzzy
-msgid "No storage nodes assigned to this storage group"
+msgid "No storage node can serve the file."
+msgstr "Ajouter SnapIn a échoué!"
+
+#, fuzzy
+msgid "No storage nodes assigned to this storage group"
msgstr "Impossible de trouver un nœud de stockage est-il un permis dans ce groupe de stockage"
#, fuzzy
@@ -6351,6 +6645,9 @@ msgstr "Une image existe déjà avec ce nom!"
msgid "No storagegroups assigned to this snapin"
msgstr "Le groupe de stockage d'images attribuée est non valable"
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -6360,6 +6657,9 @@ msgstr ""
msgid "No such object."
msgstr ""
+msgid "No such token."
+msgstr ""
+
msgid "No such user."
msgstr ""
@@ -6395,6 +6695,9 @@ msgstr ""
msgid "No values passed"
msgstr "Aucune valeur passées"
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
#, fuzzy
msgid "No viable macs to use"
msgstr "Pas en mesure de mettre à jour"
@@ -6450,6 +6753,9 @@ msgstr "Icône Fichier introuvable"
msgid "Not Registered Hosts"
msgstr "Hosts Pas encore inscrit"
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr "Pas un certain nombre"
@@ -6586,6 +6892,13 @@ msgstr "mis à jour l'utilisateur"
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+#, fuzzy
+msgid "Observed domain"
+msgstr "Informations générales"
+
msgid "Off"
msgstr ""
@@ -6642,6 +6955,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr "Erreur, est une image associée à cet hôte"
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -6725,6 +7044,12 @@ msgstr ""
msgid "Operations on %s."
msgstr "Opération pas définie: %s"
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -6770,9 +7095,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -6854,6 +7185,10 @@ msgstr ""
msgid "Pending"
msgstr "En attendant..."
+#, fuzzy
+msgid "Pending Agents"
+msgstr "en attente MACs"
+
msgid "Pending Hosts"
msgstr "Les hôtes en attente"
@@ -6871,9 +7206,31 @@ msgstr "en attente MACs"
msgid "Pending Registered Hosts"
msgstr "Dans l'attente des hôtes enregistrés"
+#, fuzzy
+msgid "Pending Registration created by FOG_AGENT"
+msgstr "Inscription en attente créée par FOG_CLIENT"
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr "Inscription en attente créée par FOG_CLIENT"
+#, fuzzy
+msgid "Pending agent"
+msgstr "hôtes en attente"
+
+#, fuzzy
+msgid "Pending agent enrollments"
+msgstr "Dans l'attente des hôtes enregistrés"
+
+#, fuzzy
+msgid "Pending agents"
+msgstr "macs en attente"
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
#, fuzzy
msgid "Pending host"
msgstr "hôtes en attente"
@@ -6920,6 +7277,16 @@ msgstr "statut"
msgid "Ping cycle complete"
msgstr "a été détruit"
+msgid "Pinned"
+msgstr ""
+
+#, fuzzy
+msgid "Placement"
+msgstr "Gestion des tâches"
+
+msgid "Platform"
+msgstr ""
+
msgid "Please Select an option"
msgstr "Veuillez sélectionner une option"
@@ -6964,10 +7331,18 @@ msgstr ""
msgid "Please enter a name"
msgstr "S'il vous plaît entrer un nom d'hôte valide"
+#, fuzzy
+msgid "Please enter a package id."
+msgstr "S'il vous plaît entrer un nom d'hôte valide"
+
#, fuzzy
msgid "Please enter a printer name."
msgstr "S'il vous plaît entrer un nom d'hôte valide"
+#, fuzzy
+msgid "Please enter a software name."
+msgstr "S'il vous plaît entrer un nom d'hôte valide"
+
#, fuzzy
msgid "Please enter a valid CIDR subnet."
msgstr "S'il vous plaît entrer un nom d'hôte valide"
@@ -6981,6 +7356,10 @@ msgstr ""
msgid "Please physically associate"
msgstr ""
+#, fuzzy
+msgid "Please select a valid backend."
+msgstr "Sélectionnez une image valide"
+
#, fuzzy
msgid "Please select a valid certificate verification level"
msgstr "Sélectionnez une image valide"
@@ -7001,6 +7380,10 @@ msgstr "Sélectionnez une image valide"
msgid "Please select a valid printer type."
msgstr "Sélectionnez une image valide"
+#, fuzzy
+msgid "Please select a valid state."
+msgstr "Sélectionnez une image valide"
+
#, fuzzy
msgid "Please select an LDAP server!"
msgstr "veuillez sélectionner une option"
@@ -7216,6 +7599,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -7262,6 +7648,10 @@ msgstr "mise à jour de l'imprimante a échoué!"
msgid "Printer Create Success"
msgstr "Imprimante existe déjà"
+#, fuzzy
+msgid "Printer Deployment"
+msgstr "Gestion des imprimantes"
+
msgid "Printer Description"
msgstr "Printer description"
@@ -7419,6 +7809,9 @@ msgstr "Imprimante mis à jour!"
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
msgid "Pushbullet Accounts"
msgstr "Comptes Pushbullet"
@@ -7460,6 +7853,10 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr "Snapin est protégé et ne peut être supprimé"
+#, fuzzy
+msgid "Quick tasks"
+msgstr "Tâches Multicast actifs"
+
msgid "RESOURCES"
msgstr ""
@@ -7472,6 +7869,9 @@ msgstr "RX"
msgid "Re-Transmit Hello Interval"
msgstr ""
+msgid "Re-check Interval"
+msgstr ""
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -7492,6 +7892,9 @@ msgstr "Supprimer sélectionnée"
msgid "Real Time"
msgstr "Mise à jour de l'hôte a échoué"
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr "Réinitialiser"
@@ -7520,6 +7923,9 @@ msgstr ""
msgid "Recorded in range"
msgstr "Enregistrement non trouvé, Erreur: %s"
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
#, fuzzy
msgid "Records"
msgstr "Enregistrements courants"
@@ -7533,10 +7939,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-#, fuzzy
-msgid "Refresh"
-msgstr "Par défaut Taux de rafraîchissement"
-
#, fuzzy
msgid "Refresh Settings Cache"
msgstr "État du service"
@@ -7682,6 +8084,10 @@ msgstr "rapport"
msgid "Report Management"
msgstr "Rapport de gestion"
+#, fuzzy
+msgid "Reported"
+msgstr "rapport"
+
msgid "Reports"
msgstr "Rapports"
@@ -7747,9 +8153,16 @@ msgstr ""
msgid "Retention sweep failed"
msgstr "supprimé"
+msgid "Retry"
+msgstr ""
+
msgid "Return Code"
msgstr "code de retour"
+#, fuzzy
+msgid "Return Codes"
+msgstr "code de retour"
+
msgid "Return To Local Login"
msgstr ""
@@ -7760,9 +8173,33 @@ msgstr "code de retour"
msgid "Returning value of key"
msgstr "De retour valeur de clé"
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+#, fuzzy
+msgid "Revoke an agent enrollment token"
+msgstr "Dans l'attente des hôtes enregistrés"
+
+#, fuzzy
+msgid "Revoke selected"
+msgstr "Retirer snapins sélectionnés"
+
+#, fuzzy
+msgid "Revoked selected tokens."
+msgstr "Approuver hôtes sélectionnés"
+
+msgid "Revoked."
+msgstr ""
+
msgid "Role"
msgstr "Rôle"
@@ -7902,6 +8339,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
#, fuzzy
msgid "SQL Error"
msgstr "Erreur SQL:"
@@ -8020,16 +8460,6 @@ msgstr "Installation / Mise à jour réussie!"
msgid "Scopes"
msgstr ""
-msgid "Screen Height"
-msgstr ""
-
-#, fuzzy
-msgid "Screen Refresh Rate"
-msgstr "Par défaut Taux de rafraîchissement"
-
-msgid "Screen Width"
-msgstr ""
-
msgid "Search"
msgstr "Chercher"
@@ -8265,6 +8695,9 @@ msgstr "Un nom d'hôte avec ce nom existe déjà."
msgid "Sessions canceled!"
msgstr "a été mis à jour avec succès"
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -8730,6 +9163,64 @@ msgstr "SnapIns"
msgid "So if you are trying to transmit to remote node A"
msgstr ""
+#, fuzzy
+msgid "Software"
+msgstr "Lister tous les logiciels"
+
+#, fuzzy
+msgid "Software Create Fail"
+msgstr "mise à jour de l'imprimante a échoué!"
+
+#, fuzzy
+msgid "Software Create Success"
+msgstr "Imprimante existe déjà"
+
+#, fuzzy
+msgid "Software Host Associations"
+msgstr "Aucun noeud associé"
+
+#, fuzzy
+msgid "Software Management"
+msgstr "Gestion du stockage"
+
+#, fuzzy
+msgid "Software Name"
+msgstr "Nom de l'imprimante"
+
+msgid "Software Order"
+msgstr ""
+
+#, fuzzy
+msgid "Software Report"
+msgstr "ID d'hôte"
+
+#, fuzzy
+msgid "Software Status"
+msgstr "Créer un nouveau %s"
+
+#, fuzzy
+msgid "Software Update Fail"
+msgstr "mise à jour de l'imprimante a échoué!"
+
+#, fuzzy
+msgid "Software Update Success"
+msgstr "Installation / Mise à jour réussie!"
+
+#, fuzzy
+msgid "Software added!"
+msgstr "Nom de l'imprimante"
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+#, fuzzy
+msgid "Software update failed!"
+msgstr "mise à jour de l'imprimante a échoué!"
+
+#, fuzzy
+msgid "Software updated!"
+msgstr "Imprimante mis à jour!"
+
msgid "Some nice description, should be short."
msgstr ""
@@ -8742,6 +9233,9 @@ msgstr ""
msgid "Specified download URL not allowed!"
msgstr ""
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -9493,6 +9987,9 @@ msgstr "Il n'y a pas de groupes sur ce serveur."
msgid "The CA private key is on this server"
msgstr "Il n'y a pas de groupes sur ce serveur."
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -9526,6 +10023,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -9570,6 +10070,9 @@ msgstr " | Fichier ou chemin ne peut pas être atteint"
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -9610,6 +10113,13 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+#, fuzzy
+msgid "The enrollment is no longer pending."
+msgstr " n'existe plus"
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -9637,6 +10147,15 @@ msgstr ""
msgid "The grid key."
msgstr "Impossible de créer la tâche"
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
#, fuzzy
msgid "The identity provider could not be reached"
msgstr "Impossible de lire le fichier temporaire"
@@ -9691,9 +10210,16 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+#, fuzzy
+msgid "The item is not a live row of this host."
+msgstr "Aucune tâche active trouvée pour Host"
+
msgid "The key will be assigned to registered hosts when a"
msgstr ""
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -9723,12 +10249,21 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
msgid "The path requested is already in use by another image!"
msgstr ""
+msgid "The payload bytes."
+msgstr ""
+
#, fuzzy
msgid "The plugin directory"
msgstr "Annuaire"
@@ -9773,6 +10308,13 @@ msgstr ""
msgid "The record could not be written."
msgstr "Impossible de lire le fichier temporaire"
+#, fuzzy
+msgid "The renewed certificate, leaf then chain."
+msgstr "Créer un nouveau %s"
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -9782,6 +10324,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -9793,6 +10338,12 @@ msgstr "mise à jour de l'imprimante a échoué!"
msgid "The selected site no longer exists"
msgstr " n'existe plus"
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -9812,6 +10363,13 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+#, fuzzy
+msgid "The signing helper is not available on this server."
+msgstr "Il n'y a pas de groupes sur ce serveur."
+
#, fuzzy
msgid "The signing request could not be generated"
msgstr "Impossible de lire le fichier temporaire"
@@ -9832,6 +10390,10 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+#, fuzzy
+msgid "The token."
+msgstr "Nombre de CPU"
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -9993,6 +10555,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -10053,10 +10618,16 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, fuzzy, php-format
msgid "This machine already registered as %s"
msgstr "Déjà inscrit comme"
+msgid "This module has no settings to configure."
+msgstr ""
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -10165,6 +10736,13 @@ msgstr "Temps existe déjà"
msgid "Time since last imaged"
msgstr ""
+#, fuzzy
+msgid "Timeout"
+msgstr "Temps"
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -10187,9 +10765,31 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Association Image"
+#, fuzzy
+msgid "Token Create Fail"
+msgstr "mise à jour de l'imprimante a échoué!"
+
+#, fuzzy
+msgid "Token Create Success"
+msgstr "Imprimante existe déjà"
+
+#, fuzzy
+msgid "Token Revoke Fail"
+msgstr "Connexion FTP a échoué"
+
+#, fuzzy
+msgid "Token Revoke Success"
+msgstr "Imprimante existe déjà"
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
#, fuzzy
msgid "Too many MACs"
msgstr "Hôte MAC primaire"
@@ -10376,6 +10976,9 @@ msgstr "Nom d'utilisateur"
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
#, fuzzy
msgid "Unauthenticated."
msgstr "Erreur serveur contactant"
@@ -10426,6 +11029,9 @@ msgstr "Erreur inconnue de téléchargement a eu lieu. Code de retour: "
msgid "Unknown action"
msgstr "Erreur inconnue de téléchargement a eu lieu. Code de retour: "
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -10456,6 +11062,9 @@ msgstr "Erreur inconnue de téléchargement a eu lieu. Code de retour: "
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
#, fuzzy
msgid "Unmark selected client ignore"
msgstr "Approuver hôtes sélectionnés"
@@ -10545,6 +11154,9 @@ msgstr "Imprimante"
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
#, fuzzy
msgid "Upload"
msgstr "Télécharger Rapports"
@@ -10657,9 +11269,6 @@ msgstr "L'utilisateur existe déjà"
msgid "User Association"
msgstr "Association Image"
-msgid "User Cleanup"
-msgstr "Nettoyage de l'utilisateur"
-
#, fuzzy
msgid "User Count"
msgstr "Nombre de CPU"
@@ -10745,6 +11354,10 @@ msgstr "Nom d'utilisateur"
msgid "User Password"
msgstr "Mot de passe de l'utilisateur"
+#, fuzzy
+msgid "User Sessions"
+msgstr "Association Image"
+
msgid "User Tracker"
msgstr "Tracker utilisateur"
@@ -10827,6 +11440,12 @@ msgstr "Utilisateurs"
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr ""
@@ -10852,6 +11471,10 @@ msgstr "Version"
msgid "Version information and paging bounds."
msgstr "FOG Informations de version"
+#, fuzzy
+msgid "Version policy"
+msgstr "Version"
+
#, fuzzy
msgid "Versions"
msgstr "Version"
@@ -10881,6 +11504,9 @@ msgstr "Wake on lan?"
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -10934,12 +11560,18 @@ msgstr "a été mis à jour avec succès"
msgid "What it does"
msgstr "a été mis à jour avec succès"
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -10955,6 +11587,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr ""
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -10967,10 +11602,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -11045,6 +11680,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr "Annuel"
@@ -11167,6 +11805,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
#, fuzzy
msgid "access"
msgstr "Accès"
@@ -11178,10 +11819,17 @@ msgstr "MACs supplémentaires"
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
#, fuzzy
msgid "ago"
msgstr " depuis"
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
#, fuzzy
msgid "all current storage nodes"
msgstr "nœud de stockage non valide"
@@ -11215,6 +11863,13 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+#, fuzzy
+msgid "any version"
+msgstr "Version"
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
#, fuzzy
msgid "architecture not recorded"
msgstr "Impossible de lire le fichier temporaire"
@@ -11226,6 +11881,10 @@ msgstr ""
msgid "as its primary group"
msgstr "Mise à jour de groupe principal"
+#, fuzzy
+msgid "assigned"
+msgstr "Aucun noeud associé"
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -11332,6 +11991,9 @@ msgstr "Activée"
msgid "does not exist and cannot be created"
msgstr "L'image est protégée et ne peut être supprimé"
+msgid "domain"
+msgstr ""
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -11341,6 +12003,9 @@ msgstr ""
msgid "either because you have updated"
msgstr ""
+msgid "empty means never install Chocolatey"
+msgstr ""
+
#, fuzzy
msgid "error"
msgstr "Erreur"
@@ -11348,10 +12013,20 @@ msgstr "Erreur"
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+#, fuzzy
+msgid "failed"
+msgstr "Échoué"
+
#, fuzzy
msgid "failed to execute, image file"
msgstr "Échec de la suppression des fichiers d'image"
@@ -11451,6 +12126,10 @@ msgstr ""
msgid "host"
msgstr "hôte"
+#, fuzzy, php-format
+msgid "host \"%s\""
+msgstr "hôte"
+
#, fuzzy
msgid "host is"
msgstr "hôte"
@@ -11566,9 +12245,6 @@ msgstr ""
msgid "in"
msgstr "minutes"
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
@@ -11576,9 +12252,6 @@ msgstr ""
msgid "in minutes"
msgstr "minutes"
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr ""
@@ -11653,6 +12326,10 @@ msgstr "DMI Key"
msgid "keys"
msgstr ""
+#, fuzzy
+msgid "latest"
+msgstr "Reproduire?"
+
msgid "leave to keep the current one"
msgstr ""
@@ -11686,6 +12363,10 @@ msgstr "minutes"
msgid "mismatched"
msgstr ""
+#, fuzzy
+msgid "missing"
+msgstr "Version"
+
msgid "moments from now"
msgstr ""
@@ -11723,6 +12404,10 @@ msgstr ""
msgid "never"
msgstr ""
+#, fuzzy
+msgid "never reported"
+msgstr "Inventaire"
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -11755,6 +12440,9 @@ msgstr ""
msgid "not found on this node"
msgstr "Image not found sur le noeud"
+msgid "not joined"
+msgstr ""
+
#, fuzzy
msgid "not reachable"
msgstr "Indisponible"
@@ -11785,10 +12473,16 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+msgid "off"
+msgstr ""
+
#, fuzzy
msgid "off means an account must already exist"
msgstr "Imprimante existe déjà"
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -11802,6 +12496,9 @@ msgstr ""
msgid "optional"
msgstr "Emplacement"
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
msgid "or"
msgstr "ou"
@@ -12079,6 +12776,10 @@ msgstr "Indisponible"
msgid "unchanged for"
msgstr "imager"
+#, fuzzy
+msgid "unknown action"
+msgstr "Erreur inconnue de téléchargement a eu lieu. Code de retour: "
+
msgid "unrecorded"
msgstr ""
@@ -12306,6 +13007,10 @@ msgstr ""
#~ msgid "CA private key"
#~ msgstr "La clé privée a échoué"
+#, fuzzy
+#~ msgid "Cannot connect to ftp server"
+#~ msgstr "Impossible de se connecter à la base de données"
+
#~ msgid "Check that database is running"
#~ msgstr "Vérifiez que la base de données est en cours d'exécution"
@@ -12313,6 +13018,10 @@ msgstr ""
#~ msgid "Client Module Settings"
#~ msgstr "Paramètres"
+#, fuzzy
+#~ msgid "Could not read snapin file"
+#~ msgstr "Impossible de lire le fichier tmp."
+
#, fuzzy
#~ msgid "Create New Accesscontrol"
#~ msgstr "Créer un nouveau %s"
@@ -12337,6 +13046,15 @@ msgstr ""
#~ msgid "Database connection unavailable"
#~ msgstr "Pas de hachage disponible"
+#~ msgid "Default Height"
+#~ msgstr "Hauteur par défaut"
+
+#~ msgid "Default Refresh Rate"
+#~ msgstr "Par défaut Taux de rafraîchissement"
+
+#~ msgid "Default Width"
+#~ msgstr "Par défaut Largeur"
+
#, fuzzy
#~ msgid "Delete All"
#~ msgstr "Supprimer les données de fichiers"
@@ -12345,6 +13063,9 @@ msgstr ""
#~ msgid "Deprecated."
#~ msgstr "Créer"
+#~ msgid "Directory Cleaner"
+#~ msgstr "Directory Cleaner"
+
#, fuzzy
#~ msgid "Domain joining"
#~ msgstr "Nom de domaine"
@@ -12407,6 +13128,18 @@ msgstr ""
#~ msgid "Export Users"
#~ msgstr "Les utilisateurs d'exportation"
+#, fuzzy
+#~ msgid "FOG Agent desired state"
+#~ msgstr "a été mis à jour avec succès"
+
+#, fuzzy
+#~ msgid "FOG Agent snapin result"
+#~ msgstr "Aucun fichier a été téléchargé"
+
+#, fuzzy
+#~ msgid "FOG Agent software result"
+#~ msgstr "Aucun fichier a été téléchargé"
+
#~ msgid "Failed to add/update snapin file"
#~ msgstr "Impossible d'ajouter le fichier de snapin / mise à jour"
@@ -12518,10 +13251,18 @@ msgstr ""
#~ msgid "Group module settings"
#~ msgstr "hôte description de"
+#, fuzzy
+#~ msgid "Height"
+#~ msgstr "Minuit"
+
#, fuzzy
#~ msgid "History Report"
#~ msgstr "ID d'hôte"
+#, fuzzy
+#~ msgid "Host Display Manager Settings"
+#~ msgstr "Paramètres"
+
#, fuzzy
#~ msgid "Host Ext"
#~ msgstr "Liste des hôtes"
@@ -12538,6 +13279,10 @@ msgstr ""
#~ msgid "Host Ext Variable"
#~ msgstr "mise à jour de l'utilisateur a échoué"
+#, fuzzy
+#~ msgid "Host Screen Resolution"
+#~ msgstr "Enregistrement de l'hôte"
+
#, fuzzy
#~ msgid "Host Site"
#~ msgstr "Liste des hôtes"
@@ -12641,6 +13386,9 @@ msgstr ""
#~ msgid "Install"
#~ msgstr "Plugins installés"
+#~ msgid "Invalid Storage Node"
+#~ msgstr "Invalid Storage Node"
+
#, fuzzy
#~ msgid "Invalid Type"
#~ msgstr "Type non valide"
@@ -12664,6 +13412,14 @@ msgstr ""
#~ msgid "LDAP User Filter"
#~ msgstr "Serveur LDAP"
+#, fuzzy
+#~ msgid "Last Activity"
+#~ msgstr "actif"
+
+#, fuzzy
+#~ msgid "Last Event"
+#~ msgstr "hôte Créé"
+
#, fuzzy
#~ msgid "Latest SVN Version"
#~ msgstr "Dernière version"
@@ -12722,6 +13478,14 @@ msgstr ""
#~ msgid "Not Installed"
#~ msgstr "Plugins installés"
+#, fuzzy
+#~ msgid "Not a live task of this host's job."
+#~ msgstr "Aucune tâche active trouvée pour Host"
+
+#, fuzzy
+#~ msgid "Not an entry in this host's software set."
+#~ msgstr "Aucune tâche active trouvée pour Host"
+
#, fuzzy
#~ msgid "Pause"
#~ msgstr "Utilisateur"
@@ -12749,6 +13513,14 @@ msgstr ""
#~ msgid "Product Keys"
#~ msgstr "Hôte clé de produit"
+#, fuzzy
+#~ msgid "Recorded."
+#~ msgstr "Enregistrements courants"
+
+#, fuzzy
+#~ msgid "Refresh"
+#~ msgstr "Par défaut Taux de rafraîchissement"
+
#, fuzzy
#~ msgid "Release Version"
#~ msgstr "Dernière version"
@@ -12815,6 +13587,10 @@ msgstr ""
#~ msgid "Rule update failed!"
#~ msgstr "mise à jour de l'imprimante a échoué!"
+#, fuzzy
+#~ msgid "Screen Refresh Rate"
+#~ msgstr "Par défaut Taux de rafraîchissement"
+
#, fuzzy
#~ msgid "Serial"
#~ msgstr "Serial System"
@@ -12856,8 +13632,16 @@ msgstr ""
#~ msgstr "Imprimante existe déjà"
#, fuzzy
-#~ msgid "The certificate chain"
-#~ msgstr "Créer un nouveau %s"
+#~ msgid "The desired state."
+#~ msgstr "Impossible de créer la tâche"
+
+#, fuzzy
+#~ msgid "The host this certificate is, and the capabilities this server offers."
+#~ msgstr "Il n'y a pas de groupes sur ce serveur."
+
+#, fuzzy
+#~ msgid "The task was already closed."
+#~ msgstr "Imprimante existe déjà"
#, fuzzy
#~ msgid "There are no "
@@ -12902,6 +13686,10 @@ msgstr ""
#~ msgid "Unable to set user filter."
#~ msgstr "Impossible d'ouvrir le fichier pour la lecture"
+#, fuzzy
+#~ msgid "Unknown status."
+#~ msgstr "Erreur inconnue de téléchargement a eu lieu. Code de retour: "
+
#, fuzzy
#~ msgid "Update Master Node"
#~ msgstr "Node Master"
@@ -12914,6 +13702,9 @@ msgstr ""
#~ msgid "Update/Remove printers"
#~ msgstr "Supprimer les imprimantes sélectionnées"
+#~ msgid "User Cleanup"
+#~ msgstr "Nettoyage de l'utilisateur"
+
#, fuzzy
#~ msgid "User Group Site"
#~ msgstr "Export SnapIns"
@@ -13000,10 +13791,6 @@ msgstr ""
#~ msgid "min (all)"
#~ msgstr "Activée"
-#, fuzzy
-#~ msgid "multicast tasks!"
-#~ msgstr "Tâches Multicast actifs"
-
#, fuzzy
#~ msgid "no database to"
#~ msgstr "Aucune base de données de travailler hors"
@@ -13019,7 +13806,3 @@ msgstr ""
#, fuzzy
#~ msgid "username"
#~ msgstr "Nom d'utilisateur"
-
-#, fuzzy
-#~ msgid "version"
-#~ msgstr "Version"
diff --git a/packages/web/management/languages/it_IT.UTF-8/LC_MESSAGES/messages.po b/packages/web/management/languages/it_IT.UTF-8/LC_MESSAGES/messages.po
index d3959cca91..61ea78c68d 100644
--- a/packages/web/management/languages/it_IT.UTF-8/LC_MESSAGES/messages.po
+++ b/packages/web/management/languages/it_IT.UTF-8/LC_MESSAGES/messages.po
@@ -125,6 +125,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -294,6 +298,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, fuzzy, php-format
+msgid "(deleted host %d)"
+msgstr "Approvare MAC selezionati"
+
msgid "(deleted user)"
msgstr ""
@@ -313,9 +321,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr "argomenti del kernel"
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
msgid "1 Hour"
msgstr "1 ora"
@@ -417,6 +431,12 @@ msgstr "Un broadcast esiste già con questo nome!"
msgid "A client ID is required"
msgstr "È richiesto un nome di gruppo!"
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
#, fuzzy
msgid "A dmi field must be set!"
msgstr "Campo chiave deve essere una stringa"
@@ -475,6 +495,9 @@ msgstr "Esiste già un utente con questo nome!"
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
#, fuzzy
msgid "A module already exists with this name!"
msgstr "Esiste già un ruolo con questo nome!"
@@ -496,6 +519,9 @@ msgstr "Elencare tutte le regole"
msgid "A permission name is required."
msgstr "È richiesto un nome di gruppo!"
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -517,6 +543,9 @@ msgstr "Nome stampante già esistente on questo nome!"
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
#, fuzzy
msgid "A role already exists with this name!"
msgstr "Esiste già un ruolo con questo nome!"
@@ -557,6 +586,10 @@ msgstr "Esiste già un snapin con questo nome!"
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+#, fuzzy
+msgid "A software entry already exists with this name!"
+msgstr "Esiste già un utente con questo nome!"
+
#, fuzzy
msgid "A storage group already exists with this name!"
msgstr "Un host già esiste con questo nome!"
@@ -689,6 +722,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -910,6 +949,10 @@ msgstr "Aggiunta posizione non riuscita!"
msgid "Add snapin failed!"
msgstr "Aggiungi snapin non riuscito!"
+#, fuzzy
+msgid "Add software failed!"
+msgstr "Aggiunta host non riuscita!"
+
msgid "Add storage node failed!"
msgstr "Aggiunta nodo di archiviazione fallita!"
@@ -990,6 +1033,33 @@ msgstr "Avanzate"
msgid "Advanced Tasks"
msgstr "Avanzate"
+msgid "Agent"
+msgstr ""
+
+#, fuzzy
+msgid "Agent Activity"
+msgstr "Attivo"
+
+#, fuzzy
+msgid "Agent Approval Success"
+msgstr "Creazione Host con successo"
+
+#, fuzzy
+msgid "Agent Denial Success"
+msgstr "Aggiornamento stampante riuscito"
+
+#, fuzzy
+msgid "Agent Enrollment Tokens"
+msgstr "è stato cancellato"
+
+#, fuzzy
+msgid "Agent Tokens"
+msgstr "API Utente Token"
+
+#, fuzzy
+msgid "Agent enrollment tokens"
+msgstr "è stato cancellato"
+
msgid "Ago must be boolean"
msgstr "Fa deve essere boolean"
@@ -1006,6 +1076,10 @@ msgstr ""
msgid "All Hosts"
msgstr "tutti gli host"
+#, fuzzy
+msgid "All Pending Agents"
+msgstr "sospeso MAC"
+
#, fuzzy
msgid "All Pending Hosts"
msgstr "Host in sospeso"
@@ -1107,10 +1181,16 @@ msgstr ""
msgid "An SQL error occurred"
msgstr "Si è verificato errore di caricamento sconosciuto"
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
#, fuzzy
msgid "An entry already exists with this name!"
msgstr "Esiste già un utente con questo nome!"
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr "Un'immagine esiste già con questo nome!"
@@ -1150,6 +1230,10 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+#, fuzzy
+msgid "Any version"
+msgstr "versione"
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1186,18 +1270,36 @@ msgstr ""
msgid "Approve"
msgstr "Approva"
+#, fuzzy
+msgid "Approve Agent Fail"
+msgstr "Approva"
+
#, fuzzy
msgid "Approve MAC Fail"
msgstr "Approva"
+#, fuzzy
+msgid "Approve Pending Agents"
+msgstr "Host in sospeso"
+
#, fuzzy
msgid "Approve Pending Hosts"
msgstr "Host in sospeso"
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
#, fuzzy
msgid "Approve selected"
msgstr "Approvare MAC selezionati"
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+#, fuzzy
+msgid "Approved selected agents!"
+msgstr "Approvare MAC selezionati"
+
#, fuzzy
msgid "Approved selected hosts!"
msgstr "Approvare MAC selezionati"
@@ -1210,6 +1312,9 @@ msgstr "Approvare MAC selezionati"
msgid "Approving the selected pending hosts."
msgstr "Approvare MAC selezionati"
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1219,6 +1324,10 @@ msgstr ""
msgid "Area"
msgstr ""
+#, fuzzy
+msgid "Assigned"
+msgstr "Host associato"
+
#, fuzzy
msgid "Assigned Group"
msgstr "Nome gruppo di archiviazione"
@@ -1280,6 +1389,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1318,6 +1430,9 @@ msgstr "Venditore BIOS"
msgid "BIOS Version"
msgstr "Versione BIOS"
+msgid "Backend"
+msgstr ""
+
#, fuzzy
msgid "Bad request."
msgstr "è richiesto"
@@ -1543,6 +1658,10 @@ msgstr "compito Annullato"
msgid "Canceled due to new tasking."
msgstr "Annullato a causa della nuova tasking."
+#, fuzzy
+msgid "Cannot Run"
+msgstr "Record non trovato"
+
msgid "Cannot bind to the LDAP server"
msgstr "Impossibile legare al server LDAP"
@@ -1555,9 +1674,6 @@ msgstr "Impossibile connettersi"
msgid "Cannot connect to database"
msgstr "Non è possibile connettersi al database"
-msgid "Cannot connect to ftp server"
-msgstr "Impossibile connettersi al server ftp"
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1753,6 +1869,9 @@ msgstr "Nessun FOGPage Classe trovato per questo nodo"
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+msgid "Checked"
+msgstr ""
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1765,6 +1884,12 @@ msgstr "Controllare se sono il responsabile del gruppo"
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1927,13 +2052,22 @@ msgstr "Errore: Impossibile scaricare il kernel"
msgid "Confirm you would like to download a new kernel"
msgstr "Errore: Impossibile scaricare il kernel"
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
msgid "Copy from existing"
msgstr "Copia da esistenti"
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -2003,9 +2137,6 @@ msgstr "Impossibile leggere il file tmp."
msgid "Could not read local file"
msgstr "Impossibile leggere il file temporaneo"
-msgid "Could not read snapin file"
-msgstr "Impossibile leggere il file snapin"
-
#, fuzzy
msgid "Could not read the database structure"
msgstr "Impossibile creare Snapin lavoro"
@@ -2101,6 +2232,9 @@ msgstr ""
msgid "Create"
msgstr "Creare"
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -2182,6 +2316,10 @@ msgstr "Crea nuovo Siti"
msgid "Create New Snapin"
msgstr "Crea nuovo Snapin"
+#, fuzzy
+msgid "Create New Software"
+msgstr "Crea nuovo Siti"
+
msgid "Create New Storage Group"
msgstr "Crea nuovo Storage Group"
@@ -2229,6 +2367,10 @@ msgstr "Creazione utente riuscita"
msgid "Create Users On First Login"
msgstr ""
+#, fuzzy, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr "Creazione utente riuscita"
+
#, fuzzy, php-format
msgid "Create a %s"
msgstr "Crea nuovo %s"
@@ -2252,9 +2394,17 @@ msgstr "Creazione utente fallita"
msgid "Create task form success"
msgstr "Creazione utente riuscita"
+#, fuzzy
+msgid "Create tasking"
+msgstr "Crea nuovo snapin"
+
msgid "Create tasking succeeded"
msgstr ""
+#, fuzzy
+msgid "Create token"
+msgstr "Crea nuovo %s"
+
#, fuzzy
msgid "Created"
msgstr "Creare"
@@ -2266,6 +2416,10 @@ msgstr "Creato da"
msgid "Created Time"
msgstr "Creato da"
+#, fuzzy
+msgid "Created by"
+msgstr "Creato da"
+
msgid "Created by FOG Reg on"
msgstr "Creato da FOG Reg su"
@@ -2393,6 +2547,9 @@ msgstr "Opzioni di debug"
msgid "Debug Task"
msgstr "mettere a punto"
+msgid "Decided."
+msgstr ""
+
msgid "Default"
msgstr "Predefinito"
@@ -2400,15 +2557,6 @@ msgstr "Predefinito"
msgid "Default Choice"
msgstr "Elemento predefinito:"
-msgid "Default Height"
-msgstr "Altezza di default"
-
-msgid "Default Refresh Rate"
-msgstr "Predefinito: frequenza aggiornamento"
-
-msgid "Default Width"
-msgstr "Larghezza predefinita"
-
#, fuzzy
msgid "Default init, ARM64"
msgstr "Larghezza predefinita"
@@ -2489,6 +2637,28 @@ msgstr ""
msgid "Deleting remote file"
msgstr "Eliminazione di file remoti"
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+#, fuzzy
+msgid "Denied selected agents!"
+msgstr "Approvare MAC selezionati"
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy
+msgid "Deny Agent Fail"
+msgstr "Cancellare i file"
+
+#, fuzzy
+msgid "Deny Pending Agents"
+msgstr "sospeso MAC"
+
+#, fuzzy
+msgid "Deny selected"
+msgstr "Cancella selezionato"
+
msgid "Deploy"
msgstr "Distribuisci"
@@ -2505,13 +2675,29 @@ msgstr ""
msgid "Description"
msgstr "Descrizione"
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+msgid "Desired domain"
+msgstr ""
+
msgid "Destroy failed"
msgstr "Deistruzione fallita"
+#, fuzzy
+msgid "Detail"
+msgstr "Dettagli della macchina"
+
#, fuzzy
msgid "Details"
msgstr "Dettagli della macchina"
+msgid "Device URI"
+msgstr ""
+
msgid "Device must be a string"
msgstr "Dispositivo deve essere una stringa"
@@ -2524,9 +2710,6 @@ msgstr "elenco"
msgid "Directory Already Exists"
msgstr "Directory esiste già"
-msgid "Directory Cleaner"
-msgstr "directory Cleaner"
-
#, fuzzy
msgid "Directory Group"
msgstr "elenco"
@@ -2535,6 +2718,10 @@ msgstr "elenco"
msgid "Directory Group Name"
msgstr "elenco"
+#, fuzzy
+msgid "Directory Membership"
+msgstr "membri"
+
#, fuzzy
msgid "Disable on all hosts"
msgstr "Disabilitato"
@@ -2651,6 +2838,9 @@ msgstr "Scaricamento fallito"
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2670,6 +2860,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr "Modifica"
@@ -2766,6 +2959,10 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+#, fuzzy
+msgid "Enrollment Token"
+msgstr "Pushbullet Conti"
+
msgid "Enrollment kit"
msgstr ""
@@ -2867,6 +3064,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
#, fuzzy
msgid "Every file was uploaded."
msgstr "Nessun file è stato caricato"
@@ -2887,6 +3090,14 @@ msgstr "Chiave privata non è riuscita"
msgid "Exists item must be boolean"
msgstr "Exists deve essere boolean"
+#, fuzzy
+msgid "Exit Code"
+msgstr "Export Snapins"
+
+#, fuzzy
+msgid "Exit code"
+msgstr "Codice di ritorno"
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -2961,9 +3172,32 @@ msgstr "Importa database"
msgid "External root CA"
msgstr ""
+#, fuzzy
+msgid "Extra arguments"
+msgstr "Snap-Run con l'argomento"
+
msgid "FOG"
msgstr "NEBBIA"
+#, fuzzy
+msgid "FOG Agent capability result"
+msgstr "Nessun file è stato caricato"
+
+#, fuzzy
+msgid "FOG Agent certificate renewal"
+msgstr "Nessun file è stato caricato"
+
+#, fuzzy
+msgid "FOG Agent enrollment"
+msgstr "è stato cancellato"
+
+#, fuzzy
+msgid "FOG Agent payload"
+msgstr "Nessun file è stato caricato"
+
+msgid "FOG Agent poll"
+msgstr ""
+
#, fuzzy
msgid "FOG Client"
msgstr "FOG client Wiki"
@@ -3313,6 +3547,9 @@ msgstr "Attività iniziata"
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3648,6 +3885,10 @@ msgstr "Storia Snapin Host"
msgid "Group Snapin History"
msgstr "Storia Snapin"
+#, fuzzy
+msgid "Group Software Assignment"
+msgstr "Storia Snapin Host"
+
#, fuzzy
msgid "Group Task History"
msgstr "Storia immagine"
@@ -3731,9 +3972,15 @@ msgstr "Informazioni sull'hardware"
msgid "Hardware Report"
msgstr "Informazioni sull'hardware"
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr "Hash"
+msgid "Hash Mismatch"
+msgstr ""
+
msgid "Have not locked the host for access"
msgstr ""
@@ -3741,10 +3988,6 @@ msgstr ""
msgid "Header is missing the required \"%s\" column"
msgstr ""
-#, fuzzy
-msgid "Height"
-msgstr "Mezzanotte"
-
msgid "Height must be 120 pixels."
msgstr "Altezza deve essere di 120 pixel."
@@ -3817,6 +4060,9 @@ msgstr "Questo host esiste già"
msgid "Host %1$s finished deploying image %2$s."
msgstr "Questo host esiste già"
+msgid "Host Agent Activity"
+msgstr ""
+
#, fuzzy
msgid "Host Approval Success"
msgstr "Creazione Host con successo"
@@ -3850,10 +4096,6 @@ msgstr "Elemento predefinito:"
msgid "Host Description"
msgstr "Host Descrizione"
-#, fuzzy
-msgid "Host Display Manager Settings"
-msgstr "Impostazioni del menu iPXE"
-
msgid "Host EFI Exit Type"
msgstr "Host EFI Tipo Exit"
@@ -3956,10 +4198,6 @@ msgstr "Tasti del prodotto host"
msgid "Host Registration"
msgstr "registrazione Host"
-#, fuzzy
-msgid "Host Screen Resolution"
-msgstr "registrazione Host"
-
#, fuzzy
msgid "Host Snapin Associations"
msgstr "Host associato"
@@ -3967,6 +4205,13 @@ msgstr "Host associato"
msgid "Host Snapin History"
msgstr "Storia Snapin Host"
+#, fuzzy
+msgid "Host Software Assignment"
+msgstr "Storia Snapin Host"
+
+msgid "Host Software Status"
+msgstr ""
+
#, fuzzy
msgid "Host Task History"
msgstr "Storia immagine"
@@ -4056,6 +4301,12 @@ msgstr "Host Init"
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
#, fuzzy
msgid "Hosts:"
msgstr "host"
@@ -4118,6 +4369,10 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+#, fuzzy
+msgid "Identity"
+msgstr "Server Shell"
+
msgid "Identity Provider"
msgstr ""
@@ -4613,6 +4868,10 @@ msgstr "plugin installati"
msgid "Installed Plugins"
msgstr "plugin installati"
+#, fuzzy
+msgid "Installed Software"
+msgstr "plugin installati"
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4693,9 +4952,6 @@ msgstr "Oggetto Snapin Tasking non valido"
msgid "Invalid Storage Group"
msgstr "Gruppo di archiviazione non valido"
-msgid "Invalid Storage Node"
-msgstr "Non valido Storage Node"
-
#, fuzzy
msgid "Invalid Tasking"
msgstr "Compito non valido!"
@@ -4871,6 +5127,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -4896,6 +5155,9 @@ msgstr "indica al client di scaricare gli snapins da"
msgid "It will operate based on the fields the area typcially requires."
msgstr ""
+msgid "Join"
+msgstr ""
+
msgid "Join Domain after image task"
msgstr ""
@@ -5089,6 +5351,9 @@ msgstr "Lingua"
msgid "Largest images"
msgstr "immagini"
+msgid "Last Agent Check-In"
+msgstr ""
+
msgid "Last Captured"
msgstr "Ultima cattura"
@@ -5098,15 +5363,16 @@ msgstr ""
msgid "Last Check-In"
msgstr ""
-msgid "Last Client Check-In"
-msgstr ""
-
msgid "Last Deployed"
msgstr "Ultima Distribuita"
msgid "Last Ping"
msgstr ""
+#, fuzzy
+msgid "Last Seen"
+msgstr "Ultima cattura"
+
#, fuzzy
msgid "Last Successful Ping"
msgstr "Riuscito"
@@ -5122,6 +5388,10 @@ msgstr ""
msgid "Last deployed"
msgstr "Ultima Distribuita"
+#, fuzzy
+msgid "Last error"
+msgstr "Errore"
+
msgid "Last flush"
msgstr ""
@@ -5129,6 +5399,9 @@ msgstr ""
msgid "Last imaged"
msgstr "immagini"
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
#, fuzzy
msgid "Latest Alpha Version"
msgstr "Ultima versione"
@@ -5245,6 +5518,10 @@ msgstr "Elencare tutti Sitis"
msgid "List All Snapins"
msgstr "Elencare tutti Snapins"
+#, fuzzy
+msgid "List All Software"
+msgstr "Elencare tutti Sitis"
+
msgid "List All Storage Groups"
msgstr "Elencare tutti Storage Groups"
@@ -5373,6 +5650,9 @@ msgstr "Log Viewer"
msgid "Log out and sign in as an administrator"
msgstr ""
+msgid "Logged on"
+msgstr ""
+
msgid "Logging"
msgstr ""
@@ -5563,6 +5843,9 @@ msgstr "Dimensione massima"
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
#, fuzzy
msgid "Member"
msgstr "Utenti"
@@ -5643,6 +5926,10 @@ msgstr "Mezzanotte"
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+#, fuzzy
+msgid "Mint an agent enrollment token"
+msgstr "In attesa di host registrati"
+
msgid "Minute value is not valid"
msgstr "valore dei minuti non è valido"
@@ -5650,6 +5937,9 @@ msgstr "valore dei minuti non è valido"
msgid "Minutes field is invalid"
msgstr "valore dei minuti non è valido"
+msgid "Missing"
+msgstr ""
+
msgid "Missing a temporary folder"
msgstr "Manca una cartella temporanea"
@@ -6107,6 +6397,10 @@ msgstr "Nessuno slot aperti"
msgid "No password is needed. Issue this account a token from its API tab, or from FOG Configuration → API Tokens, once it has been created."
msgstr ""
+#, fuzzy
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr "Nessun compito attivo trovato per Host"
+
#, fuzzy
msgid "No plugin tasks to run"
msgstr "Non sono stati trovati compiti validi"
@@ -6159,6 +6453,10 @@ msgstr "Snapin Protetto"
msgid "No snapins associated with this group as master"
msgstr "Nessun snapins associato a questo gruppo come master"
+#, fuzzy
+msgid "No storage node can serve the file."
+msgstr "Aggiunta nodo di archiviazione fallita!"
+
#, fuzzy
msgid "No storage nodes assigned to this storage group"
msgstr "c'è uno abilitato all'interno di questo gruppo di archiviazione"
@@ -6171,6 +6469,9 @@ msgstr "Un host già esiste con questo nome!"
msgid "No storagegroups assigned to this snapin"
msgstr "Il gruppo di archiviazione immagine assegnato non è valido"
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -6180,6 +6481,9 @@ msgstr ""
msgid "No such object."
msgstr ""
+msgid "No such token."
+msgstr ""
+
msgid "No such user."
msgstr ""
@@ -6213,6 +6517,9 @@ msgstr ""
msgid "No values passed"
msgstr "Nessun valore passato"
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
msgid "No viable macs to use"
msgstr "Nessun MAC valido da usare"
@@ -6265,6 +6572,9 @@ msgstr "File Icona non trovato"
msgid "Not Registered Hosts"
msgstr "Host non registrati"
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr "Non è un numero"
@@ -6401,6 +6711,13 @@ msgstr "Utente aggiornato"
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+#, fuzzy
+msgid "Observed domain"
+msgstr "Informazione generale"
+
msgid "Off"
msgstr ""
@@ -6455,6 +6772,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr "Uno o più MAC sono associati a questo host"
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -6536,6 +6859,12 @@ msgstr ""
msgid "Operations on %s."
msgstr "Campo operazione non impostato"
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -6581,9 +6910,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -6660,6 +6995,10 @@ msgstr ""
msgid "Pending"
msgstr "In attesa di..."
+#, fuzzy
+msgid "Pending Agents"
+msgstr "sospeso MAC"
+
msgid "Pending Hosts"
msgstr "Host in sospeso"
@@ -6677,9 +7016,31 @@ msgstr "sospeso MAC"
msgid "Pending Registered Hosts"
msgstr "In attesa di host registrati"
+#, fuzzy
+msgid "Pending Registration created by FOG_AGENT"
+msgstr "In attesa di registrazione creato da FOG_CLIENT"
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr "In attesa di registrazione creato da FOG_CLIENT"
+#, fuzzy
+msgid "Pending agent"
+msgstr "host in sospeso"
+
+#, fuzzy
+msgid "Pending agent enrollments"
+msgstr "In attesa di host registrati"
+
+#, fuzzy
+msgid "Pending agents"
+msgstr "Mac in attesa"
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
#, fuzzy
msgid "Pending host"
msgstr "host in sospeso"
@@ -6726,6 +7087,16 @@ msgstr "Stato"
msgid "Ping cycle complete"
msgstr "è stato completato"
+msgid "Pinned"
+msgstr ""
+
+#, fuzzy
+msgid "Placement"
+msgstr "Gestione dei compiti"
+
+msgid "Platform"
+msgstr ""
+
msgid "Please Select an option"
msgstr "Per favore selezionate un'opzione"
@@ -6769,10 +7140,18 @@ msgstr ""
msgid "Please enter a name"
msgstr "Si prega di inserire un nome host valido"
+#, fuzzy
+msgid "Please enter a package id."
+msgstr "Si prega di inserire un nome host valido"
+
#, fuzzy
msgid "Please enter a printer name."
msgstr "Si prega di inserire un nome host valido"
+#, fuzzy
+msgid "Please enter a software name."
+msgstr "Si prega di inserire un nome host valido"
+
#, fuzzy
msgid "Please enter a valid CIDR subnet."
msgstr "Si prega di inserire un nome host valido"
@@ -6786,6 +7165,10 @@ msgstr ""
msgid "Please physically associate"
msgstr "Si prega di associare fisicamente"
+#, fuzzy
+msgid "Please select a valid backend."
+msgstr "Selezionare un'immagine valida"
+
#, fuzzy
msgid "Please select a valid certificate verification level"
msgstr "Selezionare un'immagine valida"
@@ -6805,6 +7188,10 @@ msgstr "Selezionare un'immagine valida"
msgid "Please select a valid printer type."
msgstr "Selezionare un'immagine valida"
+#, fuzzy
+msgid "Please select a valid state."
+msgstr "Selezionare un'immagine valida"
+
#, fuzzy
msgid "Please select an LDAP server!"
msgstr "per favore selezionate un'opzione"
@@ -7015,6 +7402,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -7059,6 +7449,10 @@ msgstr "Creazione stampante fallita"
msgid "Printer Create Success"
msgstr "Creazione stampante riuscita"
+#, fuzzy
+msgid "Printer Deployment"
+msgstr "Printer Management"
+
msgid "Printer Description"
msgstr "Descrizione della stampante"
@@ -7212,6 +7606,9 @@ msgstr "aggiornato stampante!"
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
msgid "Pushbullet Accounts"
msgstr "Pushbullet Conti"
@@ -7253,6 +7650,10 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr "Snapin è protetto e non può essere cancellato"
+#, fuzzy
+msgid "Quick tasks"
+msgstr "Compiti multicast attivi"
+
msgid "RESOURCES"
msgstr ""
@@ -7265,6 +7666,9 @@ msgstr "RX"
msgid "Re-Transmit Hello Interval"
msgstr ""
+msgid "Re-check Interval"
+msgstr ""
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -7285,6 +7689,9 @@ msgstr "Cancella selezionato"
msgid "Real Time"
msgstr "Data e Ora"
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr "Riavvio"
@@ -7312,6 +7719,9 @@ msgstr ""
msgid "Recorded in range"
msgstr "Record non trovato"
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
#, fuzzy
msgid "Records"
msgstr "Current Records"
@@ -7325,10 +7735,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-#, fuzzy
-msgid "Refresh"
-msgstr "Predefinito: frequenza aggiornamento"
-
#, fuzzy
msgid "Refresh Settings Cache"
msgstr "Stato servizio"
@@ -7470,6 +7876,10 @@ msgstr "rapporto"
msgid "Report Management"
msgstr "Relazione sulla gestione"
+#, fuzzy
+msgid "Reported"
+msgstr "rapporto"
+
msgid "Reports"
msgstr "Rapporti"
@@ -7533,9 +7943,16 @@ msgstr ""
msgid "Retention sweep failed"
msgstr "Rimozione fallita"
+msgid "Retry"
+msgstr ""
+
msgid "Return Code"
msgstr "Codice di ritorno"
+#, fuzzy
+msgid "Return Codes"
+msgstr "Codice di ritorno"
+
msgid "Return To Local Login"
msgstr ""
@@ -7545,9 +7962,33 @@ msgstr "Codice di ritorno"
msgid "Returning value of key"
msgstr "Tornando valore della chiave"
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+#, fuzzy
+msgid "Revoke an agent enrollment token"
+msgstr "In attesa di host registrati"
+
+#, fuzzy
+msgid "Revoke selected"
+msgstr "Rimuovi i selezionati"
+
+#, fuzzy
+msgid "Revoked selected tokens."
+msgstr "Approvare MAC selezionati"
+
+msgid "Revoked."
+msgstr ""
+
#, fuzzy
msgid "Role"
msgstr "Nome regola"
@@ -7686,6 +8127,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
msgid "SQL Error"
msgstr "Errore SQL:"
@@ -7801,16 +8245,6 @@ msgstr "Impostazioni iPXE aggiornate correttamente!"
msgid "Scopes"
msgstr ""
-msgid "Screen Height"
-msgstr ""
-
-#, fuzzy
-msgid "Screen Refresh Rate"
-msgstr "Predefinito: frequenza aggiornamento"
-
-msgid "Screen Width"
-msgstr ""
-
msgid "Search"
msgstr "Ricerca"
@@ -8041,6 +8475,9 @@ msgstr "Un nome host con questo nome esiste già"
msgid "Sessions canceled!"
msgstr "Attività pianificate create con successo"
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -8483,6 +8920,63 @@ msgstr "Usato Snapin"
msgid "So if you are trying to transmit to remote node A"
msgstr "Quindi, se stai cercando di trasmettere al nodo remoto A"
+msgid "Software"
+msgstr ""
+
+#, fuzzy
+msgid "Software Create Fail"
+msgstr "Creazione stampante fallita"
+
+#, fuzzy
+msgid "Software Create Success"
+msgstr "Creazione stampante riuscita"
+
+#, fuzzy
+msgid "Software Host Associations"
+msgstr "Host associato"
+
+#, fuzzy
+msgid "Software Management"
+msgstr "Storage Management"
+
+#, fuzzy
+msgid "Software Name"
+msgstr "Nome sito"
+
+msgid "Software Order"
+msgstr ""
+
+#, fuzzy
+msgid "Software Report"
+msgstr "Grafico storico"
+
+#, fuzzy
+msgid "Software Status"
+msgstr "Crea nuova posizione"
+
+#, fuzzy
+msgid "Software Update Fail"
+msgstr "Aggiornamento della stampante non riuscito"
+
+#, fuzzy
+msgid "Software Update Success"
+msgstr "Aggiornamento host completato!"
+
+#, fuzzy
+msgid "Software added!"
+msgstr "Stampante aggiunta"
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+#, fuzzy
+msgid "Software update failed!"
+msgstr "Aggiornamento della stampante non è riuscito!"
+
+#, fuzzy
+msgid "Software updated!"
+msgstr "aggiornato stampante!"
+
msgid "Some nice description, should be short."
msgstr ""
@@ -8495,6 +8989,9 @@ msgstr "La variabile spazio deve essere boolean"
msgid "Specified download URL not allowed!"
msgstr ""
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -9214,6 +9711,9 @@ msgstr "Non ci sono gruppi su questo server"
msgid "The CA private key is on this server"
msgstr "Non ci sono gruppi su questo server"
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -9247,6 +9747,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -9291,6 +9794,9 @@ msgstr "Impossibile raggiungere il file o il percorso"
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -9331,6 +9837,13 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+#, fuzzy
+msgid "The enrollment is no longer pending."
+msgstr "non è più in esecuzione"
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -9358,6 +9871,15 @@ msgstr ""
msgid "The grid key."
msgstr "Impossibile creare un'attività"
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
#, fuzzy
msgid "The identity provider could not be reached"
msgstr "Impossibile leggere il file temporaneo"
@@ -9411,9 +9933,16 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+#, fuzzy
+msgid "The item is not a live row of this host."
+msgstr "Nessun compito attivo trovato per Host"
+
msgid "The key will be assigned to registered hosts when a"
msgstr "La chiave verrà assegnata agli host registrati quando una"
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -9443,12 +9972,21 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
msgid "The path requested is already in use by another image!"
msgstr ""
+msgid "The payload bytes."
+msgstr ""
+
#, fuzzy
msgid "The plugin directory"
msgstr "directory"
@@ -9493,6 +10031,13 @@ msgstr ""
msgid "The record could not be written."
msgstr "Impossibile leggere il file temporaneo"
+#, fuzzy
+msgid "The renewed certificate, leaf then chain."
+msgstr "Crea nuova posizione"
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -9502,6 +10047,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -9513,6 +10061,12 @@ msgstr "Aggiornamento della stampante non è riuscito!"
msgid "The selected site no longer exists"
msgstr "non è più in esecuzione"
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -9532,6 +10086,13 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+#, fuzzy
+msgid "The signing helper is not available on this server."
+msgstr "Non ci sono gruppi su questo server"
+
#, fuzzy
msgid "The signing request could not be generated"
msgstr "Impossibile leggere il file temporaneo"
@@ -9552,6 +10113,10 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+#, fuzzy
+msgid "The token."
+msgstr "Conte CPU"
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -9709,6 +10274,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -9768,10 +10336,16 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, fuzzy, php-format
msgid "This machine already registered as %s"
msgstr "Già registrato come"
+msgid "This module has no settings to configure."
+msgstr ""
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -9876,6 +10450,13 @@ msgstr "Ora esiste già"
msgid "Time since last imaged"
msgstr ""
+#, fuzzy
+msgid "Timeout"
+msgstr "Tempo"
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -9898,9 +10479,31 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Regole di associazione"
+#, fuzzy
+msgid "Token Create Fail"
+msgstr "Creazione stampante fallita"
+
+#, fuzzy
+msgid "Token Create Success"
+msgstr "Creazione stampante riuscita"
+
+#, fuzzy
+msgid "Token Revoke Fail"
+msgstr "Connessione FTP non è riuscita"
+
+#, fuzzy
+msgid "Token Revoke Success"
+msgstr "Creazione stampante riuscita"
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
msgid "Too many MACs"
msgstr "Troppi MAC"
@@ -10082,6 +10685,9 @@ msgstr "Attributo nome utente"
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
#, fuzzy
msgid "Unauthenticated."
msgstr "Impossibile contattare il server"
@@ -10130,6 +10736,9 @@ msgstr "Si è verificato errore di caricamento sconosciuto"
msgid "Unknown action"
msgstr "Si è verificato errore di caricamento sconosciuto"
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -10159,6 +10768,9 @@ msgstr "Si è verificato errore di caricamento sconosciuto"
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
#, fuzzy
msgid "Unmark selected client ignore"
msgstr "Approvare MAC selezionati"
@@ -10248,6 +10860,9 @@ msgstr "Aggiungi stampanti selezionate"
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
#, fuzzy
msgid "Upload"
msgstr "Carica Report"
@@ -10359,9 +10974,6 @@ msgstr "L'utente esiste già"
msgid "User Association"
msgstr "Associazione Sito"
-msgid "User Cleanup"
-msgstr "Cleanup utente"
-
#, fuzzy
msgid "User Count"
msgstr "Conte CPU"
@@ -10443,6 +11055,10 @@ msgstr "Attributo nome utente"
msgid "User Password"
msgstr "Password utente"
+#, fuzzy
+msgid "User Sessions"
+msgstr "Associazione Sito"
+
msgid "User Tracker"
msgstr "Tracker utente"
@@ -10519,6 +11135,12 @@ msgstr "utenti"
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr "Utilizzo della funzione di corrispondenza gruppo"
@@ -10544,6 +11166,10 @@ msgstr "Versione"
msgid "Version information and paging bounds."
msgstr "FOG Informazioni sulla versione"
+#, fuzzy
+msgid "Version policy"
+msgstr "Versione"
+
#, fuzzy
msgid "Versions"
msgstr "Versione"
@@ -10570,6 +11196,9 @@ msgstr "Wake On LAN"
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -10620,12 +11249,18 @@ msgstr "è stato cancellato"
msgid "What it does"
msgstr "è stato cancellato"
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -10642,6 +11277,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr "Dove ottenere aiuto"
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -10654,10 +11292,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -10728,6 +11366,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr "Annuale"
@@ -10849,6 +11490,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
#, fuzzy
msgid "access"
msgstr "Accesso"
@@ -10859,9 +11503,16 @@ msgstr "MAC aggiuntivi"
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
msgid "ago"
msgstr "fa"
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
msgid "all current storage nodes"
msgstr "tutti i nodi di archiviazione attivi"
@@ -10895,6 +11546,13 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+#, fuzzy
+msgid "any version"
+msgstr "versione"
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
#, fuzzy
msgid "architecture not recorded"
msgstr "Impossibile leggere il file temporaneo"
@@ -10905,6 +11563,10 @@ msgstr "come FOG proverà ad andare in internet"
msgid "as its primary group"
msgstr "come il suo gruppo primario"
+#, fuzzy
+msgid "assigned"
+msgstr "Host associato"
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -11007,6 +11669,9 @@ msgstr "Disabilitato"
msgid "does not exist and cannot be created"
msgstr "L'immagine è protetta e non può essere cancellato"
+msgid "domain"
+msgstr ""
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -11016,6 +11681,9 @@ msgstr "già selezionati o caricati"
msgid "either because you have updated"
msgstr "Sia perché hai aggiornato"
+msgid "empty means never install Chocolatey"
+msgstr ""
+
#, fuzzy
msgid "error"
msgstr "Errore"
@@ -11023,10 +11691,20 @@ msgstr "Errore"
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+#, fuzzy
+msgid "failed"
+msgstr "Fallito"
+
#, fuzzy
msgid "failed to execute, image file"
msgstr "Impossibile eliminare i file di immagine"
@@ -11121,6 +11799,10 @@ msgstr ""
msgid "host"
msgstr "host"
+#, fuzzy, php-format
+msgid "host \"%s\""
+msgstr "hosts"
+
#, fuzzy
msgid "host is"
msgstr "hosts"
@@ -11228,9 +11910,6 @@ msgstr ""
msgid "in"
msgstr "minuti"
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
@@ -11238,9 +11917,6 @@ msgstr ""
msgid "in minutes"
msgstr "minuti"
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr "in secondi"
@@ -11312,6 +11988,10 @@ msgstr "chiave"
msgid "keys"
msgstr ""
+#, fuzzy
+msgid "latest"
+msgstr "Replicando"
+
msgid "leave to keep the current one"
msgstr ""
@@ -11343,6 +12023,10 @@ msgstr "minuti"
msgid "mismatched"
msgstr ""
+#, fuzzy
+msgid "missing"
+msgstr "Versione"
+
msgid "moments from now"
msgstr ""
@@ -11378,6 +12062,10 @@ msgstr ""
msgid "never"
msgstr ""
+#, fuzzy
+msgid "never reported"
+msgstr "Inventario"
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -11408,6 +12096,9 @@ msgstr ""
msgid "not found on this node"
msgstr "Non trovato su questo nodo"
+msgid "not joined"
+msgstr ""
+
#, fuzzy
msgid "not reachable"
msgstr "Non disponibile"
@@ -11437,10 +12128,16 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+msgid "off"
+msgstr ""
+
#, fuzzy
msgid "off means an account must already exist"
msgstr "Questo host esiste già"
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -11454,6 +12151,9 @@ msgstr ""
msgid "optional"
msgstr "Luogo"
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
msgid "or"
msgstr "o"
@@ -11719,6 +12419,10 @@ msgstr "non disponibile"
msgid "unchanged for"
msgstr "Immagini per"
+#, fuzzy
+msgid "unknown action"
+msgstr "Si è verificato errore di caricamento sconosciuto"
+
#, fuzzy
msgid "unrecorded"
msgstr "Consigliato"
@@ -11947,6 +12651,9 @@ msgstr ""
#~ msgid "Can not redeclare route"
#~ msgstr "Impossibile ridichiarare il percorso"
+#~ msgid "Cannot connect to ftp server"
+#~ msgstr "Impossibile connettersi al server ftp"
+
#~ msgid "Check that database is running"
#~ msgstr "Controllare che database è in esecuzione"
@@ -11954,6 +12661,9 @@ msgstr ""
#~ msgid "Client Module Settings"
#~ msgstr "Impostazioni Client"
+#~ msgid "Could not read snapin file"
+#~ msgstr "Impossibile leggere il file snapin"
+
#, fuzzy
#~ msgid "Create New Accesscontrol"
#~ msgstr "Crea nuovo %s"
@@ -11978,6 +12688,15 @@ msgstr ""
#~ msgid "Database connection unavailable"
#~ msgstr "Percorso non disponibile"
+#~ msgid "Default Height"
+#~ msgstr "Altezza di default"
+
+#~ msgid "Default Refresh Rate"
+#~ msgstr "Predefinito: frequenza aggiornamento"
+
+#~ msgid "Default Width"
+#~ msgstr "Larghezza predefinita"
+
#, fuzzy
#~ msgid "Delete All"
#~ msgstr "Cancellare i file"
@@ -11986,6 +12705,9 @@ msgstr ""
#~ msgid "Deprecated."
#~ msgstr "Creare"
+#~ msgid "Directory Cleaner"
+#~ msgstr "directory Cleaner"
+
#, fuzzy
#~ msgid "Domain joining"
#~ msgstr "Abilita invio posizione "
@@ -12050,6 +12772,18 @@ msgstr ""
#~ msgid "Export Users"
#~ msgstr "Esporta utenti"
+#, fuzzy
+#~ msgid "FOG Agent desired state"
+#~ msgstr "è stato cancellato"
+
+#, fuzzy
+#~ msgid "FOG Agent snapin result"
+#~ msgstr "Nessun file è stato caricato"
+
+#, fuzzy
+#~ msgid "FOG Agent software result"
+#~ msgstr "Nessun file è stato caricato"
+
#~ msgid "Failed to add/update snapin file"
#~ msgstr "Impossibile aggiungere / aggiornare il file snapin"
@@ -12162,10 +12896,18 @@ msgstr ""
#~ msgid "Group module settings"
#~ msgstr "Impostazioni modulo del gruppo"
+#, fuzzy
+#~ msgid "Height"
+#~ msgstr "Mezzanotte"
+
#, fuzzy
#~ msgid "History Report"
#~ msgstr "Grafico storico"
+#, fuzzy
+#~ msgid "Host Display Manager Settings"
+#~ msgstr "Impostazioni del menu iPXE"
+
#, fuzzy
#~ msgid "Host Ext"
#~ msgstr "Lista Host"
@@ -12182,6 +12924,10 @@ msgstr ""
#~ msgid "Host Ext Variable"
#~ msgstr "Aggiornamento ruolo non riuscito"
+#, fuzzy
+#~ msgid "Host Screen Resolution"
+#~ msgstr "registrazione Host"
+
#, fuzzy
#~ msgid "Host Site"
#~ msgstr "Lista Host"
@@ -12283,6 +13029,9 @@ msgstr ""
#~ msgid "Install"
#~ msgstr "plugin installati"
+#~ msgid "Invalid Storage Node"
+#~ msgstr "Non valido Storage Node"
+
#~ msgid "Invalid Type"
#~ msgstr "Tipo non valido"
@@ -12305,6 +13054,14 @@ msgstr ""
#~ msgid "LDAP User Filter"
#~ msgstr "Server LDAP"
+#, fuzzy
+#~ msgid "Last Activity"
+#~ msgstr "Attivo"
+
+#, fuzzy
+#~ msgid "Last Event"
+#~ msgstr "Ultima cattura"
+
#~ msgid "Latest SVN Version"
#~ msgstr "Ultima versione di SVN"
@@ -12369,6 +13126,14 @@ msgstr ""
#~ msgid "Not Installed"
#~ msgstr "plugin installati"
+#, fuzzy
+#~ msgid "Not a live task of this host's job."
+#~ msgstr "Nessun compito attivo trovato per Host"
+
+#, fuzzy
+#~ msgid "Not an entry in this host's software set."
+#~ msgstr "Nessun compito attivo trovato per Host"
+
#~ msgid "Pause"
#~ msgstr "Pausa"
@@ -12395,9 +13160,13 @@ msgstr ""
#~ msgstr "Host Product Key"
#, fuzzy
-#~ msgid "Recorded"
+#~ msgid "Recorded."
#~ msgstr "Consigliato"
+#, fuzzy
+#~ msgid "Refresh"
+#~ msgstr "Predefinito: frequenza aggiornamento"
+
#~ msgid "Register must be managed from hooks or events"
#~ msgstr "Registro deve essere gestito da hook o eventi"
@@ -12470,6 +13239,10 @@ msgstr ""
#~ msgid "Rule update failed!"
#~ msgstr "Aggiornamento della stampante non è riuscito!"
+#, fuzzy
+#~ msgid "Screen Refresh Rate"
+#~ msgstr "Predefinito: frequenza aggiornamento"
+
#, fuzzy
#~ msgid "Serial"
#~ msgstr "Sistema seriale"
@@ -12512,8 +13285,16 @@ msgstr ""
#~ msgstr "Questo host esiste già"
#, fuzzy
-#~ msgid "The certificate chain"
-#~ msgstr "Crea nuova posizione"
+#~ msgid "The desired state."
+#~ msgstr "Impossibile creare un'attività"
+
+#, fuzzy
+#~ msgid "The host this certificate is, and the capabilities this server offers."
+#~ msgstr "Non ci sono gruppi su questo server"
+
+#, fuzzy
+#~ msgid "The task was already closed."
+#~ msgstr "Questo host esiste già"
#, fuzzy
#~ msgid "There are no "
@@ -12555,6 +13336,10 @@ msgstr ""
#~ msgid "Unable to set user filter."
#~ msgstr "Impossibile aprire il file per la lettura"
+#, fuzzy
+#~ msgid "Unknown status."
+#~ msgstr "Si è verificato errore di caricamento sconosciuto"
+
#, fuzzy
#~ msgid "Update Master Node"
#~ msgstr "Maestro Node"
@@ -12566,6 +13351,9 @@ msgstr ""
#~ msgid "Update/Remove printers"
#~ msgstr "Aggiorna/Rimuovi stampanti"
+#~ msgid "User Cleanup"
+#~ msgstr "Cleanup utente"
+
#, fuzzy
#~ msgid "User Group Site"
#~ msgstr "Gruppo Snapins"
@@ -12654,10 +13442,6 @@ msgstr ""
#~ msgid "min (all)"
#~ msgstr "Abilitato"
-#, fuzzy
-#~ msgid "multicast tasks!"
-#~ msgstr "Compiti multicast attivi"
-
#~ msgid "no database to"
#~ msgstr "Nessun database a"
@@ -12672,6 +13456,3 @@ msgstr ""
#, fuzzy
#~ msgid "username"
#~ msgstr "Nome utente"
-
-#~ msgid "version"
-#~ msgstr "versione"
diff --git a/packages/web/management/languages/ja_JP.UTF-8/LC_MESSAGES/messages.po b/packages/web/management/languages/ja_JP.UTF-8/LC_MESSAGES/messages.po
index f2b17101ae..89623dec86 100644
--- a/packages/web/management/languages/ja_JP.UTF-8/LC_MESSAGES/messages.po
+++ b/packages/web/management/languages/ja_JP.UTF-8/LC_MESSAGES/messages.po
@@ -116,6 +116,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -285,6 +289,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, fuzzy, php-format
+msgid "(deleted host %d)"
+msgstr "選択したホストを承認"
+
#, fuzzy
msgid "(deleted user)"
msgstr "選択したユーザーを追加"
@@ -305,9 +313,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr "カーネル引数"
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
msgid "1 Hour"
msgstr "1時間"
@@ -408,6 +422,12 @@ msgstr "この名前のブロードキャストは既に存在します!"
msgid "A client ID is required"
msgstr "名前は必須です!"
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
#, fuzzy
msgid "A dmi field must be set!"
msgstr "名前を設定する必要があります"
@@ -465,6 +485,9 @@ msgstr "この名前のユーザーは既に存在します"
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
#, fuzzy
msgid "A module already exists with this name!"
msgstr "この名前のロールは既に存在します!"
@@ -486,6 +509,9 @@ msgstr "すべてのルールを一覧表示"
msgid "A permission name is required."
msgstr "プリンター名は必須です!"
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -507,6 +533,9 @@ msgstr "この名前のプリンターは既に存在します!"
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
msgid "A role already exists with this name!"
msgstr "この名前のロールは既に存在します!"
@@ -545,6 +574,10 @@ msgstr "この名前のスナップインは既に存在します!"
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+#, fuzzy
+msgid "A software entry already exists with this name!"
+msgstr "この名前のユーザーは既に存在します"
+
#, fuzzy
msgid "A storage group already exists with this name!"
msgstr "この名前のグループは既に存在します!"
@@ -675,6 +708,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -893,6 +932,10 @@ msgstr "ロケーションの追加に失敗しました!"
msgid "Add snapin failed!"
msgstr "スナップインの追加に失敗しました!"
+#, fuzzy
+msgid "Add software failed!"
+msgstr "サイトの追加に失敗しました!"
+
msgid "Add storage node failed!"
msgstr "ストレージノードの追加に失敗しました!"
@@ -971,6 +1014,33 @@ msgstr "詳細"
msgid "Advanced Tasks"
msgstr "詳細"
+msgid "Agent"
+msgstr ""
+
+#, fuzzy
+msgid "Agent Activity"
+msgstr "有効"
+
+#, fuzzy
+msgid "Agent Approval Success"
+msgstr "承認に成功しました"
+
+#, fuzzy
+msgid "Agent Denial Success"
+msgstr "プラグインをインストールしました!"
+
+#, fuzzy
+msgid "Agent Enrollment Tokens"
+msgstr "強制終了されました"
+
+#, fuzzy
+msgid "Agent Tokens"
+msgstr "ユーザー API トークン"
+
+#, fuzzy
+msgid "Agent enrollment tokens"
+msgstr "強制終了されました"
+
msgid "Ago must be boolean"
msgstr "Ago はブール値である必要があります"
@@ -988,6 +1058,10 @@ msgstr "メニュー項目を削除"
msgid "All Hosts"
msgstr "すべてのホスト"
+#, fuzzy
+msgid "All Pending Agents"
+msgstr "保留中 MAC アドレス"
+
#, fuzzy
msgid "All Pending Hosts"
msgstr "保留中ホスト"
@@ -1091,10 +1165,16 @@ msgstr ""
msgid "An SQL error occurred"
msgstr "不明なアップロードエラーが発生しました"
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
#, fuzzy
msgid "An entry already exists with this name!"
msgstr "この名前のプリンターは既に存在します!"
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr "この名前のイメージは既に存在します!"
@@ -1134,6 +1214,10 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+#, fuzzy
+msgid "Any version"
+msgstr "バージョン"
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1170,18 +1254,36 @@ msgstr ""
msgid "Approve"
msgstr "承認"
+#, fuzzy
+msgid "Approve Agent Fail"
+msgstr "MAC アドレスを承認"
+
#, fuzzy
msgid "Approve MAC Fail"
msgstr "MAC アドレスを承認"
+#, fuzzy
+msgid "Approve Pending Agents"
+msgstr "保留中ホスト"
+
#, fuzzy
msgid "Approve Pending Hosts"
msgstr "保留中ホスト"
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
#, fuzzy
msgid "Approve selected"
msgstr "選択したホストを承認"
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+#, fuzzy
+msgid "Approved selected agents!"
+msgstr "選択したホストを承認"
+
#, fuzzy
msgid "Approved selected hosts!"
msgstr "選択したホストを承認"
@@ -1194,6 +1296,9 @@ msgstr "選択したホストを承認"
msgid "Approving the selected pending hosts."
msgstr "選択したホストを承認"
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1203,6 +1308,10 @@ msgstr ""
msgid "Area"
msgstr ""
+#, fuzzy
+msgid "Assigned"
+msgstr "関連付けられたホスト"
+
#, fuzzy
msgid "Assigned Group"
msgstr "管理者グループ"
@@ -1264,6 +1373,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1302,6 +1414,9 @@ msgstr "BIOS ベンダー"
msgid "BIOS Version"
msgstr "BIOS バージョン"
+msgid "Backend"
+msgstr ""
+
#, fuzzy
msgid "Bad request."
msgstr "必須です"
@@ -1525,6 +1640,10 @@ msgstr "キャンセルされたタスク"
msgid "Canceled due to new tasking."
msgstr "新しいタスクによりキャンセルされました。"
+#, fuzzy
+msgid "Cannot Run"
+msgstr "アイコンファイルが見つかりません"
+
msgid "Cannot bind to the LDAP server"
msgstr "LDAP サーバーにバインドできません"
@@ -1537,9 +1656,6 @@ msgstr "接続できません:"
msgid "Cannot connect to database"
msgstr "データベースに接続できません"
-msgid "Cannot connect to ftp server"
-msgstr "FTP サーバーに接続できません"
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1736,6 +1852,10 @@ msgstr "このノードの FOGPage クラスが見つかりません"
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+#, fuzzy
+msgid "Checked"
+msgstr "チェックサム"
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1748,6 +1868,12 @@ msgstr "自身がグループマネージャーか確認しています"
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1911,13 +2037,22 @@ msgstr "エラー: initrd のダウンロードに失敗しました"
msgid "Confirm you would like to download a new kernel"
msgstr "エラー: カーネルのダウンロードに失敗しました"
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
msgid "Copy from existing"
msgstr "既存の項目からコピー"
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -1987,9 +2122,6 @@ msgstr "一時ファイルを読み取れませんでした。"
msgid "Could not read local file"
msgstr "スナップインファイルを読み取れませんでした"
-msgid "Could not read snapin file"
-msgstr "スナップインファイルを読み取れませんでした"
-
#, fuzzy
msgid "Could not read the database structure"
msgstr "スナップインジョブの作成に失敗しました"
@@ -2085,6 +2217,9 @@ msgstr ""
msgid "Create"
msgstr "作成"
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -2166,6 +2301,10 @@ msgstr "新しい サイト を作成"
msgid "Create New Snapin"
msgstr "新しいスナップインを作成"
+#, fuzzy
+msgid "Create New Software"
+msgstr "新しい サイト を作成"
+
msgid "Create New Storage Group"
msgstr "新しい Storage Group を作成"
@@ -2213,6 +2352,10 @@ msgstr "タスクタイプを作成"
msgid "Create Users On First Login"
msgstr ""
+#, fuzzy, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr "タスク状態を作成"
+
#, fuzzy, php-format
msgid "Create a %s"
msgstr "新しい %s を作成"
@@ -2236,10 +2379,18 @@ msgstr "タスク作成対象"
msgid "Create task form success"
msgstr "タスク状態を作成"
+#, fuzzy
+msgid "Create tasking"
+msgstr "新しいスナップインを作成"
+
#, fuzzy
msgid "Create tasking succeeded"
msgstr "タスク状態を作成"
+#, fuzzy
+msgid "Create token"
+msgstr "新しい %s を作成"
+
#, fuzzy
msgid "Created"
msgstr "作成"
@@ -2251,6 +2402,10 @@ msgstr "作成者"
msgid "Created Time"
msgstr "ジョブ作成時刻"
+#, fuzzy
+msgid "Created by"
+msgstr "作成者"
+
msgid "Created by FOG Reg on"
msgstr "FOG Reg により作成:"
@@ -2379,6 +2534,9 @@ msgstr "デバッグオプション"
msgid "Debug Task"
msgstr "デバッグ"
+msgid "Decided."
+msgstr ""
+
msgid "Default"
msgstr "既定"
@@ -2386,15 +2544,6 @@ msgstr "既定"
msgid "Default Choice"
msgstr "既定の項目"
-msgid "Default Height"
-msgstr "既定の高さ"
-
-msgid "Default Refresh Rate"
-msgstr "既定の更新レート"
-
-msgid "Default Width"
-msgstr "既定の幅"
-
#, fuzzy
msgid "Default init, ARM64"
msgstr "既定の幅"
@@ -2474,6 +2623,28 @@ msgstr ""
msgid "Deleting remote file"
msgstr "リモートファイルを削除しています"
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+#, fuzzy
+msgid "Denied selected agents!"
+msgstr "選択したホストを承認"
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy
+msgid "Deny Agent Fail"
+msgstr "削除に失敗しました"
+
+#, fuzzy
+msgid "Deny Pending Agents"
+msgstr "保留中 MAC アドレス"
+
+#, fuzzy
+msgid "Deny selected"
+msgstr "選択項目を削除"
+
msgid "Deploy"
msgstr "展開"
@@ -2490,13 +2661,31 @@ msgstr ""
msgid "Description"
msgstr "説明"
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+#, fuzzy
+msgid "Desired domain"
+msgstr "AD ドメイン"
+
msgid "Destroy failed"
msgstr "解除に失敗しました"
+#, fuzzy
+msgid "Detail"
+msgstr "マシン詳細"
+
#, fuzzy
msgid "Details"
msgstr "マシン詳細"
+#, fuzzy
+msgid "Device URI"
+msgstr "HD デバイス"
+
msgid "Device must be a string"
msgstr "デバイスは文字列で指定してください"
@@ -2509,9 +2698,6 @@ msgstr "ディレクトリ"
msgid "Directory Already Exists"
msgstr "ディレクトリは既に存在します"
-msgid "Directory Cleaner"
-msgstr "ディレクトリクリーナー"
-
#, fuzzy
msgid "Directory Group"
msgstr "ディレクトリ"
@@ -2520,6 +2706,10 @@ msgstr "ディレクトリ"
msgid "Directory Group Name"
msgstr "ディレクトリ"
+#, fuzzy
+msgid "Directory Membership"
+msgstr "ホストメンバーシップ"
+
msgid "Disable on all hosts"
msgstr ""
@@ -2636,6 +2826,9 @@ msgstr "ダウンロードに失敗しました"
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2655,6 +2848,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr "編集"
@@ -2752,6 +2948,10 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+#, fuzzy
+msgid "Enrollment Token"
+msgstr "Pushbullet アカウント"
+
msgid "Enrollment kit"
msgstr ""
@@ -2852,6 +3052,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
#, fuzzy
msgid "Every file was uploaded."
msgstr "ファイルはアップロードされませんでした"
@@ -2872,6 +3078,14 @@ msgstr "秘密鍵の処理に失敗しました"
msgid "Exists item must be boolean"
msgstr "Exists 項目はブール値である必要があります"
+#, fuzzy
+msgid "Exit Code"
+msgstr "ノードを編集"
+
+#, fuzzy
+msgid "Exit code"
+msgstr "戻りコード"
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -2946,9 +3160,32 @@ msgstr "データベースをエクスポート"
msgid "External root CA"
msgstr ""
+#, fuzzy
+msgid "Extra arguments"
+msgstr "スナップイン実行時の引数"
+
msgid "FOG"
msgstr "FOG"
+#, fuzzy
+msgid "FOG Agent capability result"
+msgstr "ファイルはアップロードされませんでした"
+
+#, fuzzy
+msgid "FOG Agent certificate renewal"
+msgstr "ファイルはアップロードされませんでした"
+
+#, fuzzy
+msgid "FOG Agent enrollment"
+msgstr "強制終了されました"
+
+#, fuzzy
+msgid "FOG Agent payload"
+msgstr "ファイルはアップロードされませんでした"
+
+msgid "FOG Agent poll"
+msgstr ""
+
msgid "FOG Client"
msgstr "FOG クライアント"
@@ -3289,6 +3526,9 @@ msgstr "タスク実行に失敗しました"
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3623,6 +3863,10 @@ msgstr "グループ スナップイン"
msgid "Group Snapin History"
msgstr "スナップイン履歴"
+#, fuzzy
+msgid "Group Software Assignment"
+msgstr "グループ スナップイン"
+
#, fuzzy
msgid "Group Task History"
msgstr "イメージ履歴"
@@ -3706,9 +3950,16 @@ msgstr "ハードウェア情報"
msgid "Hardware Report"
msgstr "レポートを作成しますか?"
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr "ハッシュ"
+#, fuzzy
+msgid "Hash Mismatch"
+msgstr "ファイルハッシュが一致しません"
+
msgid "Have not locked the host for access"
msgstr "ホストはアクセス用にロックされていません"
@@ -3716,10 +3967,6 @@ msgstr "ホストはアクセス用にロックされていません"
msgid "Header is missing the required \"%s\" column"
msgstr ""
-#, fuzzy
-msgid "Height"
-msgstr "午前 0 時"
-
msgid "Height must be 120 pixels."
msgstr "高さは 120 ピクセルである必要があります。"
@@ -3792,6 +4039,9 @@ msgstr "このホストは既に存在します"
msgid "Host %1$s finished deploying image %2$s."
msgstr "このホストは既に存在します"
+msgid "Host Agent Activity"
+msgstr ""
+
#, fuzzy
msgid "Host Approval Success"
msgstr "承認に成功しました"
@@ -3825,10 +4075,6 @@ msgstr "既定のプリンターを更新"
msgid "Host Description"
msgstr "ホストの説明"
-#, fuzzy
-msgid "Host Display Manager Settings"
-msgstr "ホストモジュール設定"
-
msgid "Host EFI Exit Type"
msgstr "ホスト EFI 終了方法"
@@ -3929,9 +4175,6 @@ msgstr "ホスト プロダクトキー"
msgid "Host Registration"
msgstr "ホスト登録"
-msgid "Host Screen Resolution"
-msgstr "ホスト画面解像度"
-
#, fuzzy
msgid "Host Snapin Associations"
msgstr "スナップインロケーション"
@@ -3939,6 +4182,14 @@ msgstr "スナップインロケーション"
msgid "Host Snapin History"
msgstr "ホストスナップイン履歴"
+#, fuzzy
+msgid "Host Software Assignment"
+msgstr "グループ スナップイン"
+
+#, fuzzy
+msgid "Host Software Status"
+msgstr "ホスト状態"
+
#, fuzzy
msgid "Host Task History"
msgstr "ホストイメージ履歴"
@@ -4028,6 +4279,12 @@ msgstr "ホスト Init"
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
#, fuzzy
msgid "Hosts:"
msgstr "ホスト"
@@ -4090,6 +4347,10 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+#, fuzzy
+msgid "Identity"
+msgstr "サーバーシェル"
+
msgid "Identity Provider"
msgstr ""
@@ -4580,6 +4841,10 @@ msgstr "インストール/更新"
msgid "Installed Plugins"
msgstr "インストール済みプラグイン"
+#, fuzzy
+msgid "Installed Software"
+msgstr "インストール/更新"
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4659,9 +4924,6 @@ msgstr "無効なスナップインタスクオブジェクト"
msgid "Invalid Storage Group"
msgstr "無効なストレージグループ"
-msgid "Invalid Storage Node"
-msgstr "無効なストレージノード"
-
msgid "Invalid Tasking"
msgstr "無効なタスク"
@@ -4832,6 +5094,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -4859,6 +5124,10 @@ msgstr "クライアントに次の場所からスナップインをダウンロ
msgid "It will operate based on the fields the area typcially requires."
msgstr "通常その領域で必要とされるフィールドに基づいて動作します"
+#, fuzzy
+msgid "Join"
+msgstr "AD 参加"
+
#, fuzzy
msgid "Join Domain after image task"
msgstr "展開後にドメイン参加"
@@ -5051,6 +5320,10 @@ msgstr "言語"
msgid "Largest images"
msgstr "イメージ"
+#, fuzzy
+msgid "Last Agent Check-In"
+msgstr "タスクチェックイン日"
+
msgid "Last Captured"
msgstr "最終キャプチャ"
@@ -5062,16 +5335,16 @@ msgstr "タスクチェックイン日"
msgid "Last Check-In"
msgstr "タスクチェックイン日"
-#, fuzzy
-msgid "Last Client Check-In"
-msgstr "タスクチェックイン日"
-
msgid "Last Deployed"
msgstr "最終展開"
msgid "Last Ping"
msgstr ""
+#, fuzzy
+msgid "Last Seen"
+msgstr "最終キャプチャ"
+
#, fuzzy
msgid "Last Successful Ping"
msgstr "タスクを正常に設定しました"
@@ -5088,6 +5361,10 @@ msgstr "タスクチェックイン日"
msgid "Last deployed"
msgstr "最終展開"
+#, fuzzy
+msgid "Last error"
+msgstr "エラー"
+
msgid "Last flush"
msgstr ""
@@ -5095,6 +5372,9 @@ msgstr ""
msgid "Last imaged"
msgstr "イメージ"
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
#, fuzzy
msgid "Latest Alpha Version"
msgstr "最新バージョン"
@@ -5212,6 +5492,10 @@ msgstr "すべての サイトs を一覧表示"
msgid "List All Snapins"
msgstr "すべての スナップインs を一覧表示"
+#, fuzzy
+msgid "List All Software"
+msgstr "すべての サイトs を一覧表示"
+
msgid "List All Storage Groups"
msgstr "すべての Storage Groups を一覧表示"
@@ -5339,6 +5623,10 @@ msgstr "ログビューアー"
msgid "Log out and sign in as an administrator"
msgstr ""
+#, fuzzy
+msgid "Logged on"
+msgstr "ログイン済み"
+
msgid "Logging"
msgstr ""
@@ -5527,6 +5815,9 @@ msgstr "最大サイズ"
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
#, fuzzy
msgid "Member"
msgstr "メンバー"
@@ -5609,6 +5900,10 @@ msgstr "午前 0 時"
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+#, fuzzy
+msgid "Mint an agent enrollment token"
+msgstr "保留中の登録済みホスト"
+
msgid "Minute value is not valid"
msgstr "分の値が無効です"
@@ -5616,6 +5911,9 @@ msgstr "分の値が無効です"
msgid "Minutes field is invalid"
msgstr "分の値が無効です"
+msgid "Missing"
+msgstr ""
+
msgid "Missing a temporary folder"
msgstr "一時フォルダーがありません"
@@ -6073,6 +6371,10 @@ msgstr "空きスロットがありません"
msgid "No password is needed. Issue this account a token from its API tab, or from FOG Configuration → API Tokens, once it has been created."
msgstr ""
+#, fuzzy
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr "このホストの実行中タスクは見つかりません"
+
#, fuzzy
msgid "No plugin tasks to run"
msgstr "有効なタスクが見つかりません"
@@ -6125,6 +6427,10 @@ msgstr "関連付けられたノードがありません"
msgid "No snapins associated with this group as master"
msgstr "このグループにマスターとして関連付けられたスナップインはありません"
+#, fuzzy
+msgid "No storage node can serve the file."
+msgstr "ストレージノードの更新に失敗しました!"
+
#, fuzzy
msgid "No storage nodes assigned to this storage group"
msgstr "このストレージグループ内に有効なものがあるか"
@@ -6137,6 +6443,9 @@ msgstr "このイメージを削除できる有効なマスターノードがあ
msgid "No storagegroups assigned to this snapin"
msgstr "割り当てられたイメージのストレージグループが無効です"
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -6147,6 +6456,10 @@ msgstr "サイトがありません"
msgid "No such object."
msgstr ""
+#, fuzzy
+msgid "No such token."
+msgstr "サイトがありません"
+
msgid "No such user."
msgstr ""
@@ -6180,6 +6493,9 @@ msgstr ""
msgid "No values passed"
msgstr "値が渡されていません"
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
msgid "No viable macs to use"
msgstr "使用可能な MAC アドレスがありません"
@@ -6231,6 +6547,9 @@ msgstr "見つかりません"
msgid "Not Registered Hosts"
msgstr "未登録ホスト"
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr "数値ではありません"
@@ -6368,6 +6687,13 @@ msgstr "ユーザーを更新しました!"
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+#, fuzzy
+msgid "Observed domain"
+msgstr "サーバー情報"
+
msgid "Off"
msgstr ""
@@ -6422,6 +6748,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr "1 つ以上の MAC アドレスがホストに関連付けられています"
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -6506,6 +6838,12 @@ msgstr ""
msgid "Operations on %s."
msgstr "操作フィールドが設定されていません"
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -6552,9 +6890,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -6631,6 +6975,10 @@ msgstr ""
msgid "Pending"
msgstr "保留中..."
+#, fuzzy
+msgid "Pending Agents"
+msgstr "保留中 MAC アドレス"
+
msgid "Pending Hosts"
msgstr "保留中ホスト"
@@ -6648,9 +6996,31 @@ msgstr "保留中 MAC アドレス"
msgid "Pending Registered Hosts"
msgstr "保留中の登録済みホスト"
+#, fuzzy
+msgid "Pending Registration created by FOG_AGENT"
+msgstr "FOG_CLIENT により保留中の登録が作成されました"
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr "FOG_CLIENT により保留中の登録が作成されました"
+#, fuzzy
+msgid "Pending agent"
+msgstr "保留中ホスト"
+
+#, fuzzy
+msgid "Pending agent enrollments"
+msgstr "保留中の登録済みホスト"
+
+#, fuzzy
+msgid "Pending agents"
+msgstr "保留中 MAC アドレス"
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
#, fuzzy
msgid "Pending host"
msgstr "保留中ホスト"
@@ -6698,6 +7068,17 @@ msgstr "状態"
msgid "Ping cycle complete"
msgstr "完了しました"
+msgid "Pinned"
+msgstr ""
+
+#, fuzzy
+msgid "Placement"
+msgstr "Slack 管理"
+
+#, fuzzy
+msgid "Platform"
+msgstr "クロスプラットフォーム"
+
msgid "Please Select an option"
msgstr "オプションを選択してください"
@@ -6741,10 +7122,18 @@ msgstr ""
msgid "Please enter a name"
msgstr "ホスト名を入力してください"
+#, fuzzy
+msgid "Please enter a package id."
+msgstr "ホスト名を入力してください"
+
#, fuzzy
msgid "Please enter a printer name."
msgstr "ホスト名を入力してください"
+#, fuzzy
+msgid "Please enter a software name."
+msgstr "ホスト名を入力してください"
+
msgid "Please enter a valid CIDR subnet."
msgstr "有効な CIDR サブネットを入力してください。"
@@ -6757,6 +7146,10 @@ msgstr ""
msgid "Please physically associate"
msgstr "物理的に関連付けてください"
+#, fuzzy
+msgid "Please select a valid backend."
+msgstr "有効なイメージを選択してください"
+
#, fuzzy
msgid "Please select a valid certificate verification level"
msgstr "有効な LDAP ポートを選択してください"
@@ -6776,6 +7169,10 @@ msgstr "有効な LDAP ポートを選択してください"
msgid "Please select a valid printer type."
msgstr "有効な LDAP ポートを選択してください"
+#, fuzzy
+msgid "Please select a valid state."
+msgstr "有効なイメージを選択してください"
+
#, fuzzy
msgid "Please select an LDAP server!"
msgstr "使用する LDAP ポートを選択してください"
@@ -6988,6 +7385,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -7031,6 +7431,10 @@ msgstr "プリンターの作成に失敗しました"
msgid "Printer Create Success"
msgstr "プリンターの作成に成功しました"
+#, fuzzy
+msgid "Printer Deployment"
+msgstr "プリンター管理"
+
msgid "Printer Description"
msgstr "プリンターの説明"
@@ -7184,6 +7588,9 @@ msgstr "プリンターを更新しました!"
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
msgid "Pushbullet Accounts"
msgstr "Pushbullet アカウント"
@@ -7224,6 +7631,10 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr "スナップインは保護されているため削除できません"
+#, fuzzy
+msgid "Quick tasks"
+msgstr "マルチキャストタスク"
+
msgid "RESOURCES"
msgstr ""
@@ -7237,6 +7648,10 @@ msgstr "RX"
msgid "Re-Transmit Hello Interval"
msgstr "Hello 送信間隔"
+#, fuzzy
+msgid "Re-check Interval"
+msgstr "Hello 再送信間隔"
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -7257,6 +7672,9 @@ msgstr "関連付けを削除"
msgid "Real Time"
msgstr "日時"
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr "再起動"
@@ -7283,6 +7701,9 @@ msgstr ""
msgid "Recorded in range"
msgstr "レコードが見つかりません"
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
#, fuzzy
msgid "Records"
msgstr "現在のレコード"
@@ -7296,9 +7717,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-msgid "Refresh"
-msgstr ""
-
msgid "Refresh Settings Cache"
msgstr ""
@@ -7439,6 +7857,10 @@ msgstr "レポート"
msgid "Report Management"
msgstr "レポート管理"
+#, fuzzy
+msgid "Reported"
+msgstr "レポート"
+
msgid "Reports"
msgstr "レポート"
@@ -7502,9 +7924,16 @@ msgstr ""
msgid "Retention sweep failed"
msgstr "削除に失敗しました"
+msgid "Retry"
+msgstr ""
+
msgid "Return Code"
msgstr "戻りコード"
+#, fuzzy
+msgid "Return Codes"
+msgstr "戻りコード"
+
msgid "Return To Local Login"
msgstr ""
@@ -7514,9 +7943,33 @@ msgstr "戻りコード"
msgid "Returning value of key"
msgstr "キーの値を返しています"
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+#, fuzzy
+msgid "Revoke an agent enrollment token"
+msgstr "保留中の登録済みホスト"
+
+#, fuzzy
+msgid "Revoke selected"
+msgstr "選択した項目を削除"
+
+#, fuzzy
+msgid "Revoked selected tokens."
+msgstr "選択したルールを削除"
+
+msgid "Revoked."
+msgstr ""
+
#, fuzzy
msgid "Role"
msgstr "ロール"
@@ -7648,6 +8101,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
msgid "SQL Error"
msgstr "SQL エラー"
@@ -7763,18 +8219,6 @@ msgstr "iPXE 設定を更新しました!"
msgid "Scopes"
msgstr ""
-#, fuzzy
-msgid "Screen Height"
-msgstr "画面の高さ(ピクセル)"
-
-#, fuzzy
-msgid "Screen Refresh Rate"
-msgstr "画面のリフレッシュレート(Hz)"
-
-#, fuzzy
-msgid "Screen Width"
-msgstr "画面の幅(ピクセル)"
-
msgid "Search"
msgstr "検索"
@@ -8002,6 +8446,9 @@ msgstr "その名前のセッションは既に存在します"
msgid "Sessions canceled!"
msgstr "キャンセルされました"
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -8436,6 +8883,64 @@ msgstr "使用中のスナップイン"
msgid "So if you are trying to transmit to remote node A"
msgstr "そのため、リモートノード A に送信しようとしている場合"
+msgid "Software"
+msgstr ""
+
+#, fuzzy
+msgid "Software Create Fail"
+msgstr "サイトの作成に失敗しました"
+
+#, fuzzy
+msgid "Software Create Success"
+msgstr "サイトを作成しました"
+
+#, fuzzy
+msgid "Software Host Associations"
+msgstr "サイトの関連付け"
+
+#, fuzzy
+msgid "Software Management"
+msgstr "ストレージ管理"
+
+#, fuzzy
+msgid "Software Name"
+msgstr "サイト名"
+
+#, fuzzy
+msgid "Software Order"
+msgstr "Initrd を保存"
+
+#, fuzzy
+msgid "Software Report"
+msgstr "レポートを作成しますか?"
+
+#, fuzzy
+msgid "Software Status"
+msgstr "ホスト状態"
+
+#, fuzzy
+msgid "Software Update Fail"
+msgstr "サイトの更新に失敗しました"
+
+#, fuzzy
+msgid "Software Update Success"
+msgstr "サイトを更新しました"
+
+#, fuzzy
+msgid "Software added!"
+msgstr "サイトを追加しました!"
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+#, fuzzy
+msgid "Software update failed!"
+msgstr "サイトの更新に失敗しました!"
+
+#, fuzzy
+msgid "Software updated!"
+msgstr "サイトを更新しました!"
+
#, fuzzy
msgid "Some nice description, should be short."
msgstr "説明は必須です"
@@ -8449,6 +8954,9 @@ msgstr "Space 変数はブール値である必要があります"
msgid "Specified download URL not allowed!"
msgstr "指定されたダウンロード URL は許可されていません!"
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -9159,6 +9667,9 @@ msgstr "このサーバーにはグループがありません"
msgid "The CA private key is on this server"
msgstr "このサーバーにはグループがありません"
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -9192,6 +9703,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -9236,6 +9750,9 @@ msgstr "ファイルまたはパスに到達できません"
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -9275,6 +9792,13 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+#, fuzzy
+msgid "The enrollment is no longer pending."
+msgstr "選択したプリンターを追加"
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -9302,6 +9826,15 @@ msgstr ""
msgid "The grid key."
msgstr "タスクの作成に失敗しました"
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
#, fuzzy
msgid "The identity provider could not be reached"
msgstr "強制終了できませんでした"
@@ -9355,9 +9888,16 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+#, fuzzy
+msgid "The item is not a live row of this host."
+msgstr "このホストの実行中タスクは見つかりません"
+
msgid "The key will be assigned to registered hosts when a"
msgstr "キーは、登録済みホストに次の場合割り当てられます"
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -9388,13 +9928,22 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
#, fuzzy
msgid "The path requested is already in use by another image!"
msgstr "これは既に別のイメージで使用されています"
+msgid "The payload bytes."
+msgstr ""
+
#, fuzzy
msgid "The plugin directory"
msgstr "ディレクトリ"
@@ -9439,6 +9988,13 @@ msgstr ""
msgid "The record could not be written."
msgstr "強制終了できませんでした"
+#, fuzzy
+msgid "The renewed certificate, leaf then chain."
+msgstr "新しいロケーションを作成"
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -9448,6 +10004,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -9459,6 +10018,12 @@ msgstr "サイトの更新に失敗しました!"
msgid "The selected site no longer exists"
msgstr "選択したプリンターを追加"
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -9478,6 +10043,13 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+#, fuzzy
+msgid "The signing helper is not available on this server."
+msgstr "このサーバーにはグループがありません"
+
#, fuzzy
msgid "The signing request could not be generated"
msgstr "強制終了できませんでした"
@@ -9499,6 +10071,10 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+#, fuzzy
+msgid "The token."
+msgstr "CPU 数"
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -9656,6 +10232,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -9714,10 +10293,17 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, fuzzy, php-format
msgid "This machine already registered as %s"
msgstr "既に次の名前で登録されています:"
+#, fuzzy
+msgid "This module has no settings to configure."
+msgstr "このモジュールは旧クライアントでのみ使用されます。"
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -9823,6 +10409,12 @@ msgstr "この時刻は既に存在します"
msgid "Time since last imaged"
msgstr ""
+msgid "Timeout"
+msgstr "タイムアウト"
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -9845,9 +10437,31 @@ msgstr ""
msgid "Toggle navigation"
msgstr "ナビゲーション切り替え"
+#, fuzzy
+msgid "Token Create Fail"
+msgstr "ロールの作成に失敗しました"
+
+#, fuzzy
+msgid "Token Create Success"
+msgstr "ロールを作成しました"
+
+#, fuzzy
+msgid "Token Revoke Fail"
+msgstr "FTP 接続に失敗しました"
+
+#, fuzzy
+msgid "Token Revoke Success"
+msgstr "ロールを作成しました"
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
msgid "Too many MACs"
msgstr "MAC アドレスが多すぎます"
@@ -10026,6 +10640,9 @@ msgstr "ユーザー名属性"
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
#, fuzzy
msgid "Unauthenticated."
msgstr "認証できません"
@@ -10075,6 +10692,9 @@ msgstr "不明なデータベースエラー"
msgid "Unknown action"
msgstr "不明なデータベースエラー"
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -10103,6 +10723,9 @@ msgstr "不明なアップロードエラーが発生しました"
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
msgid "Unmark selected client ignore"
msgstr ""
@@ -10192,6 +10815,9 @@ msgstr "選択項目を削除"
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
#, fuzzy
msgid "Upload"
msgstr "レポートをアップロード"
@@ -10305,9 +10931,6 @@ msgstr "ユーザーは既に存在します"
msgid "User Association"
msgstr "ルールの関連付け"
-msgid "User Cleanup"
-msgstr "ユーザークリーンアップ"
-
#, fuzzy
msgid "User Count"
msgstr "CPU 数"
@@ -10389,6 +11012,10 @@ msgstr "ユーザー名属性"
msgid "User Password"
msgstr "ユーザーパスワード"
+#, fuzzy
+msgid "User Sessions"
+msgstr "セッションを開始"
+
msgid "User Tracker"
msgstr "ユーザートラッカー"
@@ -10467,6 +11094,12 @@ msgstr "ユーザー"
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr "グループ照合機能を使用しています"
@@ -10492,6 +11125,10 @@ msgstr "バージョン"
msgid "Version information and paging bounds."
msgstr "FOG バージョン情報"
+#, fuzzy
+msgid "Version policy"
+msgstr "バージョン"
+
#, fuzzy
msgid "Versions"
msgstr "バージョン"
@@ -10517,6 +11154,9 @@ msgstr "Wake on LAN"
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -10567,12 +11207,18 @@ msgstr "強制終了されました"
msgid "What it does"
msgstr "強制終了されました"
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -10589,6 +11235,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr "ヘルプの入手先"
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -10601,10 +11250,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -10667,6 +11316,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr "年単位"
@@ -10796,6 +11448,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
#, fuzzy
msgid "access"
msgstr "アクセス"
@@ -10806,9 +11461,16 @@ msgstr "追加 MAC アドレス"
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
msgid "ago"
msgstr "前"
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
msgid "all current storage nodes"
msgstr "現在のすべてのストレージノード"
@@ -10842,6 +11504,13 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+#, fuzzy
+msgid "any version"
+msgstr "バージョン"
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
#, fuzzy
msgid "architecture not recorded"
msgstr "強制終了できませんでした"
@@ -10852,6 +11521,10 @@ msgstr "FOG がインターネットへ接続を試みるため"
msgid "as its primary group"
msgstr "プライマリグループとして"
+#, fuzzy
+msgid "assigned"
+msgstr "関連付けられたホスト"
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -10950,6 +11623,10 @@ msgstr "無効"
msgid "does not exist and cannot be created"
msgstr "イメージは保護されているため削除できません"
+#, fuzzy
+msgid "domain"
+msgstr "AD ドメイン"
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -10959,6 +11636,9 @@ msgstr "既に選択済み、またはアップロード済み"
msgid "either because you have updated"
msgstr "更新したため、または"
+msgid "empty means never install Chocolatey"
+msgstr ""
+
#, fuzzy
msgid "error"
msgstr "エラー"
@@ -10966,10 +11646,20 @@ msgstr "エラー"
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+#, fuzzy
+msgid "failed"
+msgstr "失敗しました"
+
#, fuzzy
msgid "failed to execute, image file"
msgstr "実行に失敗しました。イメージファイル: "
@@ -11067,6 +11757,10 @@ msgstr "ビットレート"
msgid "host"
msgstr "ホスト"
+#, fuzzy, php-format
+msgid "host \"%s\""
+msgstr "ホスト"
+
#, fuzzy
msgid "host is"
msgstr "ホスト"
@@ -11175,9 +11869,6 @@ msgstr ""
msgid "in"
msgstr "分"
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
@@ -11185,9 +11876,6 @@ msgstr ""
msgid "in minutes"
msgstr "分"
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr "秒単位"
@@ -11259,6 +11947,10 @@ msgstr "キー"
msgid "keys"
msgstr ""
+#, fuzzy
+msgid "latest"
+msgstr "レプリケーションを実行しますか?"
+
#, fuzzy
msgid "leave to keep the current one"
msgstr "各ホストの現在の値を維持する場合は、フィールドを空欄にしてください。"
@@ -11291,6 +11983,10 @@ msgstr "分"
msgid "mismatched"
msgstr ""
+#, fuzzy
+msgid "missing"
+msgstr "バージョン"
+
msgid "moments from now"
msgstr ""
@@ -11326,6 +12022,10 @@ msgstr ""
msgid "never"
msgstr ""
+#, fuzzy
+msgid "never reported"
+msgstr "さらにサポートが必要な場合"
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -11356,6 +12056,9 @@ msgstr ""
msgid "not found on this node"
msgstr "このノード上に見つかりません"
+msgid "not joined"
+msgstr ""
+
#, fuzzy
msgid "not reachable"
msgstr "利用不可"
@@ -11385,10 +12088,17 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+#, fuzzy
+msgid "off"
+msgstr "の"
+
#, fuzzy
msgid "off means an account must already exist"
msgstr "このホストは既に存在します"
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -11402,6 +12112,9 @@ msgstr ""
msgid "optional"
msgstr "ロケーション"
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
msgid "or"
msgstr "または"
@@ -11669,6 +12382,10 @@ msgstr "利用不可"
msgid "unchanged for"
msgstr "イメージ処理対象"
+#, fuzzy
+msgid "unknown action"
+msgstr "不明なデータベースエラー"
+
#, fuzzy
msgid "unrecorded"
msgstr "保護されていません"
@@ -11806,12 +12523,6 @@ msgstr ""
#~ msgid "A subnetgroup already exists with this name!"
#~ msgstr "この名前のサブネットグループは既に存在します!"
-#~ msgid "AD Domain"
-#~ msgstr "AD ドメイン"
-
-#~ msgid "AD Join"
-#~ msgstr "AD 参加"
-
#~ msgid "AD OU"
#~ msgstr "AD OU"
@@ -12007,6 +12718,9 @@ msgstr ""
#~ msgid "Cannot cancel tasks this way"
#~ msgstr "この方法ではタスクをキャンセルできません"
+#~ msgid "Cannot connect to ftp server"
+#~ msgstr "FTP サーバーに接続できません"
+
#~ msgid "Cannot create tasking as image is not enabled"
#~ msgstr "イメージが有効ではないためタスクを作成できません"
@@ -12046,9 +12760,6 @@ msgstr ""
#~ msgid "Checkin Time"
#~ msgstr "チェックイン時刻"
-#~ msgid "Checksum"
-#~ msgstr "チェックサム"
-
#~ msgid "Checksums"
#~ msgstr "チェックサム"
@@ -12079,6 +12790,9 @@ msgstr ""
#~ msgid "Conflicting path/file"
#~ msgstr "競合するパス/ファイル"
+#~ msgid "Could not read snapin file"
+#~ msgstr "スナップインファイルを読み取れませんでした"
+
#~ msgid "Create New Access Control Role"
#~ msgstr "新しいアクセス制御ロールを作成"
@@ -12092,9 +12806,6 @@ msgstr ""
#~ msgid "Create and associate"
#~ msgstr "関連付けられたノードがありません"
-#~ msgid "Cross platform"
-#~ msgstr "クロスプラットフォーム"
-
#~ msgid "Current Associations"
#~ msgstr "現在の関連付け"
@@ -12135,6 +12846,15 @@ msgstr ""
#~ msgid "Date of checkout"
#~ msgstr "貸出日"
+#~ msgid "Default Height"
+#~ msgstr "既定の高さ"
+
+#~ msgid "Default Refresh Rate"
+#~ msgstr "既定の更新レート"
+
+#~ msgid "Default Width"
+#~ msgstr "既定の幅"
+
#~ msgid "Delayed Start"
#~ msgstr "遅延開始"
@@ -12177,6 +12897,9 @@ msgstr ""
#~ msgid "Directories"
#~ msgstr "ディレクトリ"
+#~ msgid "Directory Cleaner"
+#~ msgstr "ディレクトリクリーナー"
+
#~ msgid "Domain Password Legacy"
#~ msgstr "従来のドメインパスワード"
@@ -12314,6 +13037,18 @@ msgstr ""
#~ msgid "FOG 1.2.0 and earlier."
#~ msgstr "FOG 1.2.0 以前。"
+#, fuzzy
+#~ msgid "FOG Agent desired state"
+#~ msgstr "強制終了されました"
+
+#, fuzzy
+#~ msgid "FOG Agent snapin result"
+#~ msgstr "ファイルはアップロードされませんでした"
+
+#, fuzzy
+#~ msgid "FOG Agent software result"
+#~ msgstr "ファイルはアップロードされませんでした"
+
#~ msgid "FOG Client Service Updater"
#~ msgstr "FOG クライアントサービス更新プログラム"
@@ -12551,9 +13286,6 @@ msgstr ""
#~ msgid "Groups are not allowed to schedule upload tasks"
#~ msgstr "グループではアップロードタスクをスケジュールできません"
-#~ msgid "HD Device"
-#~ msgstr "HD デバイス"
-
#~ msgid "HD Firmware"
#~ msgstr "HD ファームウェア"
@@ -12563,6 +13295,10 @@ msgstr ""
#~ msgid "HD Serial"
#~ msgstr "HD シリアル"
+#, fuzzy
+#~ msgid "Height"
+#~ msgstr "午前 0 時"
+
#~ msgid "Hide Menu"
#~ msgstr "メニューを非表示"
@@ -12605,6 +13341,10 @@ msgstr ""
#~ msgid "Host Desc"
#~ msgstr "ホスト説明"
+#, fuzzy
+#~ msgid "Host Display Manager Settings"
+#~ msgstr "ホストモジュール設定"
+
#~ msgid "Host FOG Client Module configuration"
#~ msgstr "ホスト FOG クライアントモジュール設定"
@@ -12626,6 +13366,9 @@ msgstr ""
#~ msgid "Host Printers"
#~ msgstr "ホスト プリンター"
+#~ msgid "Host Screen Resolution"
+#~ msgstr "ホスト画面解像度"
+
#~ msgid "Host Site"
#~ msgstr "ホスト サイト"
@@ -12636,9 +13379,6 @@ msgstr ""
#~ msgid "Host Snapins"
#~ msgstr "ホスト スナップイン"
-#~ msgid "Host Status"
-#~ msgstr "ホスト状態"
-
#~ msgid "Host Status is a plugin that adds a new entry in the Host edit Page"
#~ msgstr "Host Status は、ホスト編集ページに新しい項目を追加するプラグインです"
@@ -12804,6 +13544,9 @@ msgstr ""
#~ msgid "Invalid Plugin Passed"
#~ msgstr "無効なプラグインが渡されました"
+#~ msgid "Invalid Storage Node"
+#~ msgstr "無効なストレージノード"
+
#~ msgid "Invalid Task Type"
#~ msgstr "無効なタスクタイプ"
@@ -12888,6 +13631,14 @@ msgstr ""
#~ msgid "LDAP User Filter"
#~ msgstr "ユーザーフィルター"
+#, fuzzy
+#~ msgid "Last Activity"
+#~ msgstr "有効"
+
+#, fuzzy
+#~ msgid "Last Event"
+#~ msgstr "最終キャプチャ"
+
#~ msgid "Last Updated Time"
#~ msgstr "最終更新時刻"
@@ -13158,12 +13909,20 @@ msgstr ""
#~ msgid "Not Valid"
#~ msgstr "無効"
+#, fuzzy
+#~ msgid "Not a live task of this host's job."
+#~ msgstr "このホストの実行中タスクは見つかりません"
+
#~ msgid "Not able to add"
#~ msgstr "追加できません"
#~ msgid "Not all elements in filter or ports setting are integer"
#~ msgstr "フィルターまたはポート設定のすべての要素が整数ではありません"
+#, fuzzy
+#~ msgid "Not an entry in this host's software set."
+#~ msgstr "このホストの実行中タスクは見つかりません"
+
#~ msgid "Notes"
#~ msgstr "メモ"
@@ -13372,7 +14131,7 @@ msgstr ""
#~ msgstr "ブランド設定を更新しました!"
#, fuzzy
-#~ msgid "Recorded"
+#~ msgid "Recorded."
#~ msgstr "保護されていません"
#~ msgid "Register must be managed from hooks or events"
@@ -13412,9 +14171,6 @@ msgstr ""
#~ msgid "Remove selected printers"
#~ msgstr "選択したプリンターを削除"
-#~ msgid "Remove selected rules"
-#~ msgstr "選択したルールを削除"
-
#~ msgid "Remove selected users"
#~ msgstr "選択したユーザーを削除"
@@ -13446,9 +14202,6 @@ msgstr ""
#~ msgid "Reverse the file: (newest on top)"
#~ msgstr "ファイルを逆順に表示(新しいものを上に)"
-#~ msgid "Rexmit Hello Interval"
-#~ msgstr "Hello 再送信間隔"
-
#~ msgid "Routes should be an array or an instance of Traversable"
#~ msgstr "ルートは配列または Traversable のインスタンスである必要があります"
@@ -13494,6 +14247,18 @@ msgstr ""
#~ msgid "Schedule with shutdown"
#~ msgstr "シャットダウンを含めてスケジュール"
+#, fuzzy
+#~ msgid "Screen Height"
+#~ msgstr "画面の高さ(ピクセル)"
+
+#, fuzzy
+#~ msgid "Screen Refresh Rate"
+#~ msgstr "画面のリフレッシュレート(Hz)"
+
+#, fuzzy
+#~ msgid "Screen Width"
+#~ msgstr "画面の幅(ピクセル)"
+
#~ msgid "Search pattern"
#~ msgstr "検索パターン"
@@ -13614,9 +14379,6 @@ msgstr ""
#~ msgid "Start Date"
#~ msgstr "開始日"
-#~ msgid "Start Session"
-#~ msgstr "セッションを開始"
-
#~ msgid "Static"
#~ msgstr "静的"
@@ -13640,9 +14402,6 @@ msgstr ""
#~ msgid "Storage Node General"
#~ msgstr "ストレージノード全般"
-#~ msgid "Storage Node update failed!"
-#~ msgstr "ストレージノードの更新に失敗しました!"
-
#~ msgid "SubnetGroup General"
#~ msgstr "サブネットグループ全般"
@@ -13697,19 +14456,23 @@ msgstr ""
#~ msgid "The below items are only used for the old client."
#~ msgstr "以下の項目は旧クライアントでのみ使用されます。"
-#, fuzzy
-#~ msgid "The certificate chain"
-#~ msgstr "新しいロケーションを作成"
-
#~ msgid "The clients will checkin with the server from time"
#~ msgstr "クライアントは一定時間ごとにサーバーへチェックインします"
+#, fuzzy
+#~ msgid "The desired state."
+#~ msgstr "タスクの作成に失敗しました"
+
#~ msgid "The following errors occured"
#~ msgstr "次のエラーが発生しました"
#~ msgid "The following errors occurred"
#~ msgstr "次のエラーが発生しました"
+#, fuzzy
+#~ msgid "The host this certificate is, and the capabilities this server offers."
+#~ msgstr "このサーバーにはグループがありません"
+
#~ msgid "The old client is what was distributed with"
#~ msgstr "旧クライアントは次のバージョンまで配布されていました"
@@ -13722,6 +14485,10 @@ msgstr ""
#~ msgid "The old client was distributed with FOG 1.2.0 and earlier."
#~ msgstr "旧クライアントは FOG 1.2.0 以前で配布されていました。"
+#, fuzzy
+#~ msgid "The task was already closed."
+#~ msgstr "このホストは既に存在します"
+
#~ msgid "There are currently"
#~ msgstr "現在"
@@ -13790,9 +14557,6 @@ msgstr ""
#~ msgid "This module is only used on the old client"
#~ msgstr "このモジュールは旧クライアントでのみ使用されます"
-#~ msgid "This module is only used on the old client."
-#~ msgstr "このモジュールは旧クライアントでのみ使用されます。"
-
#~ msgid "This section allows you to customize or alter"
#~ msgstr "このセクションでは各種設定をカスタマイズできます"
@@ -13824,9 +14588,6 @@ msgstr ""
#~ msgid "This will set the configuration level to all hosts in this group"
#~ msgstr "このグループ内のすべてのホストでこの項目をクリアします。"
-#~ msgid "Timeout"
-#~ msgstr "タイムアウト"
-
#~ msgid "Title must be a string"
#~ msgstr "タイトルは文字列で指定してください"
@@ -13852,6 +14613,10 @@ msgstr ""
#~ msgid "Unable to set user filter."
#~ msgstr "サーバー情報を取得できません!"
+#, fuzzy
+#~ msgid "Unknown status."
+#~ msgstr "不明なデータベースエラー"
+
#~ msgid "Update General?"
#~ msgstr "全般設定を更新しますか?"
@@ -13914,6 +14679,9 @@ msgstr ""
#~ msgid "User Change Password"
#~ msgstr "ユーザーパスワードを変更"
+#~ msgid "User Cleanup"
+#~ msgstr "ユーザークリーンアップ"
+
#~ msgid "User General"
#~ msgstr "ユーザー全般"
@@ -14166,9 +14934,6 @@ msgstr ""
#~ msgid "it will enforce login to gain access to the advanced"
#~ msgstr "詳細メニューへアクセスするにはログインが必要になります"
-#~ msgid "logged in"
-#~ msgstr "ログイン済み"
-
#~ msgid "may see the issue and help and/or use the solutions"
#~ msgstr "問題を確認し、支援したり解決策を利用したりできます"
@@ -14184,10 +14949,6 @@ msgstr ""
#~ msgid "more secure"
#~ msgstr "より安全"
-#, fuzzy
-#~ msgid "multicast tasks!"
-#~ msgstr "マルチキャストタスク"
-
#~ msgid "no login will appear"
#~ msgstr "ログイン画面は表示されません"
@@ -14195,9 +14956,6 @@ msgstr ""
#~ msgid "not found on disk"
#~ msgstr "このノード上に見つかりません"
-#~ msgid "of"
-#~ msgstr "の"
-
#~ msgid "on the following pages of this document"
#~ msgstr "このドキュメントの次のページ"
@@ -14286,9 +15044,6 @@ msgstr ""
#~ msgid "username"
#~ msgstr "ユーザー名"
-#~ msgid "version"
-#~ msgstr "バージョン"
-
#~ msgid "where to download the snapin"
#~ msgstr "スナップインのダウンロード元"
diff --git a/packages/web/management/languages/messages.pot b/packages/web/management/languages/messages.pot
index 81dc3dc22d..477be94a5e 100644
--- a/packages/web/management/languages/messages.pot
+++ b/packages/web/management/languages/messages.pot
@@ -101,6 +101,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -270,6 +274,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, php-format
+msgid "(deleted host %d)"
+msgstr ""
+
msgid "(deleted user)"
msgstr ""
@@ -289,9 +297,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr ""
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
msgid "1 Hour"
msgstr ""
@@ -385,6 +399,12 @@ msgstr ""
msgid "A client ID is required"
msgstr ""
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
msgid "A dmi field must be set!"
msgstr ""
@@ -436,6 +456,9 @@ msgstr ""
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
msgid "A module already exists with this name!"
msgstr ""
@@ -454,6 +477,9 @@ msgstr ""
msgid "A permission name is required."
msgstr ""
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -473,6 +499,9 @@ msgstr ""
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
msgid "A role already exists with this name!"
msgstr ""
@@ -508,6 +537,9 @@ msgstr ""
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+msgid "A software entry already exists with this name!"
+msgstr ""
+
msgid "A storage group already exists with this name!"
msgstr ""
@@ -622,6 +654,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -812,6 +850,9 @@ msgstr ""
msgid "Add snapin failed!"
msgstr ""
+msgid "Add software failed!"
+msgstr ""
+
msgid "Add storage node failed!"
msgstr ""
@@ -880,6 +921,27 @@ msgstr ""
msgid "Advanced Tasks"
msgstr ""
+msgid "Agent"
+msgstr ""
+
+msgid "Agent Activity"
+msgstr ""
+
+msgid "Agent Approval Success"
+msgstr ""
+
+msgid "Agent Denial Success"
+msgstr ""
+
+msgid "Agent Enrollment Tokens"
+msgstr ""
+
+msgid "Agent Tokens"
+msgstr ""
+
+msgid "Agent enrollment tokens"
+msgstr ""
+
msgid "Ago must be boolean"
msgstr ""
@@ -896,6 +958,9 @@ msgstr ""
msgid "All Hosts"
msgstr ""
+msgid "All Pending Agents"
+msgstr ""
+
msgid "All Pending Hosts"
msgstr ""
@@ -986,9 +1051,15 @@ msgstr ""
msgid "An SQL error occurred"
msgstr ""
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
msgid "An entry already exists with this name!"
msgstr ""
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr ""
@@ -1025,6 +1096,9 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+msgid "Any version"
+msgstr ""
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1061,15 +1135,30 @@ msgstr ""
msgid "Approve"
msgstr ""
+msgid "Approve Agent Fail"
+msgstr ""
+
msgid "Approve MAC Fail"
msgstr ""
+msgid "Approve Pending Agents"
+msgstr ""
+
msgid "Approve Pending Hosts"
msgstr ""
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
msgid "Approve selected"
msgstr ""
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+msgid "Approved selected agents!"
+msgstr ""
+
msgid "Approved selected hosts!"
msgstr ""
@@ -1079,6 +1168,9 @@ msgstr ""
msgid "Approving the selected pending hosts."
msgstr ""
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1088,6 +1180,9 @@ msgstr ""
msgid "Area"
msgstr ""
+msgid "Assigned"
+msgstr ""
+
msgid "Assigned Group"
msgstr ""
@@ -1139,6 +1234,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1172,6 +1270,9 @@ msgstr ""
msgid "BIOS Version"
msgstr ""
+msgid "Backend"
+msgstr ""
+
msgid "Bad request."
msgstr ""
@@ -1372,6 +1473,9 @@ msgstr ""
msgid "Canceled due to new tasking."
msgstr ""
+msgid "Cannot Run"
+msgstr ""
+
msgid "Cannot bind to the LDAP server"
msgstr ""
@@ -1384,9 +1488,6 @@ msgstr ""
msgid "Cannot connect to database"
msgstr ""
-msgid "Cannot connect to ftp server"
-msgstr ""
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1553,6 +1654,9 @@ msgstr ""
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+msgid "Checked"
+msgstr ""
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1565,6 +1669,12 @@ msgstr ""
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1716,13 +1826,22 @@ msgstr ""
msgid "Confirm you would like to download a new kernel"
msgstr ""
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
msgid "Copy from existing"
msgstr ""
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -1782,9 +1901,6 @@ msgstr ""
msgid "Could not read local file"
msgstr ""
-msgid "Could not read snapin file"
-msgstr ""
-
msgid "Could not read the database structure"
msgstr ""
@@ -1864,6 +1980,9 @@ msgstr ""
msgid "Create"
msgstr ""
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -1934,6 +2053,9 @@ msgstr ""
msgid "Create New Snapin"
msgstr ""
+msgid "Create New Software"
+msgstr ""
+
msgid "Create New Storage Group"
msgstr ""
@@ -1973,6 +2095,10 @@ msgstr ""
msgid "Create Users On First Login"
msgstr ""
+#, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr ""
+
#, php-format
msgid "Create a %s"
msgstr ""
@@ -1992,9 +2118,15 @@ msgstr ""
msgid "Create task form success"
msgstr ""
+msgid "Create tasking"
+msgstr ""
+
msgid "Create tasking succeeded"
msgstr ""
+msgid "Create token"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -2004,6 +2136,9 @@ msgstr ""
msgid "Created Time"
msgstr ""
+msgid "Created by"
+msgstr ""
+
msgid "Created by FOG Reg on"
msgstr ""
@@ -2118,19 +2253,13 @@ msgstr ""
msgid "Debug Task"
msgstr ""
-msgid "Default"
+msgid "Decided."
msgstr ""
-msgid "Default Choice"
-msgstr ""
-
-msgid "Default Height"
-msgstr ""
-
-msgid "Default Refresh Rate"
+msgid "Default"
msgstr ""
-msgid "Default Width"
+msgid "Default Choice"
msgstr ""
msgid "Default init, ARM64"
@@ -2201,6 +2330,24 @@ msgstr ""
msgid "Deleting remote file"
msgstr ""
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+msgid "Denied selected agents!"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deny Agent Fail"
+msgstr ""
+
+msgid "Deny Pending Agents"
+msgstr ""
+
+msgid "Deny selected"
+msgstr ""
+
msgid "Deploy"
msgstr ""
@@ -2216,12 +2363,27 @@ msgstr ""
msgid "Description"
msgstr ""
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+msgid "Desired domain"
+msgstr ""
+
msgid "Destroy failed"
msgstr ""
+msgid "Detail"
+msgstr ""
+
msgid "Details"
msgstr ""
+msgid "Device URI"
+msgstr ""
+
msgid "Device must be a string"
msgstr ""
@@ -2234,15 +2396,15 @@ msgstr ""
msgid "Directory Already Exists"
msgstr ""
-msgid "Directory Cleaner"
-msgstr ""
-
msgid "Directory Group"
msgstr ""
msgid "Directory Group Name"
msgstr ""
+msgid "Directory Membership"
+msgstr ""
+
msgid "Disable on all hosts"
msgstr ""
@@ -2339,6 +2501,9 @@ msgstr ""
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2358,6 +2523,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr ""
@@ -2443,6 +2611,9 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+msgid "Enrollment Token"
+msgstr ""
+
msgid "Enrollment kit"
msgstr ""
@@ -2537,6 +2708,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
msgid "Every file was uploaded."
msgstr ""
@@ -2555,6 +2732,12 @@ msgstr ""
msgid "Exists item must be boolean"
msgstr ""
+msgid "Exit Code"
+msgstr ""
+
+msgid "Exit code"
+msgstr ""
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -2619,9 +2802,27 @@ msgstr ""
msgid "External root CA"
msgstr ""
+msgid "Extra arguments"
+msgstr ""
+
msgid "FOG"
msgstr ""
+msgid "FOG Agent capability result"
+msgstr ""
+
+msgid "FOG Agent certificate renewal"
+msgstr ""
+
+msgid "FOG Agent enrollment"
+msgstr ""
+
+msgid "FOG Agent payload"
+msgstr ""
+
+msgid "FOG Agent poll"
+msgstr ""
+
msgid "FOG Client"
msgstr ""
@@ -2928,6 +3129,9 @@ msgstr ""
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3224,6 +3428,9 @@ msgstr ""
msgid "Group Snapin History"
msgstr ""
+msgid "Group Software Assignment"
+msgstr ""
+
msgid "Group Task History"
msgstr ""
@@ -3296,9 +3503,15 @@ msgstr ""
msgid "Hardware Report"
msgstr ""
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr ""
+msgid "Hash Mismatch"
+msgstr ""
+
msgid "Have not locked the host for access"
msgstr ""
@@ -3306,9 +3519,6 @@ msgstr ""
msgid "Header is missing the required \"%s\" column"
msgstr ""
-msgid "Height"
-msgstr ""
-
msgid "Height must be 120 pixels."
msgstr ""
@@ -3369,6 +3579,9 @@ msgstr ""
msgid "Host %1$s finished deploying image %2$s."
msgstr ""
+msgid "Host Agent Activity"
+msgstr ""
+
msgid "Host Approval Success"
msgstr ""
@@ -3396,9 +3609,6 @@ msgstr ""
msgid "Host Description"
msgstr ""
-msgid "Host Display Manager Settings"
-msgstr ""
-
msgid "Host EFI Exit Type"
msgstr ""
@@ -3486,15 +3696,18 @@ msgstr ""
msgid "Host Registration"
msgstr ""
-msgid "Host Screen Resolution"
-msgstr ""
-
msgid "Host Snapin Associations"
msgstr ""
msgid "Host Snapin History"
msgstr ""
+msgid "Host Software Assignment"
+msgstr ""
+
+msgid "Host Software Status"
+msgstr ""
+
msgid "Host Task History"
msgstr ""
@@ -3573,6 +3786,12 @@ msgstr ""
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
msgid "Hosts:"
msgstr ""
@@ -3631,6 +3850,9 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+msgid "Identity"
+msgstr ""
+
msgid "Identity Provider"
msgstr ""
@@ -4057,6 +4279,9 @@ msgstr ""
msgid "Installed Plugins"
msgstr ""
+msgid "Installed Software"
+msgstr ""
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4133,9 +4358,6 @@ msgstr ""
msgid "Invalid Storage Group"
msgstr ""
-msgid "Invalid Storage Node"
-msgstr ""
-
msgid "Invalid Tasking"
msgstr ""
@@ -4289,6 +4511,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -4313,6 +4538,9 @@ msgstr ""
msgid "It will operate based on the fields the area typcially requires."
msgstr ""
+msgid "Join"
+msgstr ""
+
msgid "Join Domain after image task"
msgstr ""
@@ -4478,6 +4706,9 @@ msgstr ""
msgid "Largest images"
msgstr ""
+msgid "Last Agent Check-In"
+msgstr ""
+
msgid "Last Captured"
msgstr ""
@@ -4487,15 +4718,15 @@ msgstr ""
msgid "Last Check-In"
msgstr ""
-msgid "Last Client Check-In"
-msgstr ""
-
msgid "Last Deployed"
msgstr ""
msgid "Last Ping"
msgstr ""
+msgid "Last Seen"
+msgstr ""
+
msgid "Last Successful Ping"
msgstr ""
@@ -4508,12 +4739,18 @@ msgstr ""
msgid "Last deployed"
msgstr ""
+msgid "Last error"
+msgstr ""
+
msgid "Last flush"
msgstr ""
msgid "Last imaged"
msgstr ""
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
msgid "Latest Alpha Version"
msgstr ""
@@ -4624,6 +4861,9 @@ msgstr ""
msgid "List All Snapins"
msgstr ""
+msgid "List All Software"
+msgstr ""
+
msgid "List All Storage Groups"
msgstr ""
@@ -4738,6 +4978,9 @@ msgstr ""
msgid "Log out and sign in as an administrator"
msgstr ""
+msgid "Logged on"
+msgstr ""
+
msgid "Logging"
msgstr ""
@@ -4900,6 +5143,9 @@ msgstr ""
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
msgid "Member"
msgstr ""
@@ -4969,12 +5215,18 @@ msgstr ""
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+msgid "Mint an agent enrollment token"
+msgstr ""
+
msgid "Minute value is not valid"
msgstr ""
msgid "Minutes field is invalid"
msgstr ""
+msgid "Missing"
+msgstr ""
+
msgid "Missing a temporary folder"
msgstr ""
@@ -5381,6 +5633,9 @@ msgstr ""
msgid "No password is needed. Issue this account a token from its API tab, or from FOG Configuration → API Tokens, once it has been created."
msgstr ""
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr ""
+
msgid "No plugin tasks to run"
msgstr ""
@@ -5426,6 +5681,9 @@ msgstr ""
msgid "No snapins associated with this group as master"
msgstr ""
+msgid "No storage node can serve the file."
+msgstr ""
+
msgid "No storage nodes assigned to this storage group"
msgstr ""
@@ -5435,6 +5693,9 @@ msgstr ""
msgid "No storagegroups assigned to this snapin"
msgstr ""
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -5444,6 +5705,9 @@ msgstr ""
msgid "No such object."
msgstr ""
+msgid "No such token."
+msgstr ""
+
msgid "No such user."
msgstr ""
@@ -5474,6 +5738,9 @@ msgstr ""
msgid "No values passed"
msgstr ""
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
msgid "No viable macs to use"
msgstr ""
@@ -5522,6 +5789,9 @@ msgstr ""
msgid "Not Registered Hosts"
msgstr ""
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr ""
@@ -5639,6 +5909,12 @@ msgstr ""
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+msgid "Observed domain"
+msgstr ""
+
msgid "Off"
msgstr ""
@@ -5690,6 +5966,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr ""
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -5764,6 +6046,12 @@ msgstr ""
msgid "Operations on %s."
msgstr ""
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -5806,9 +6094,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -5878,6 +6172,9 @@ msgstr ""
msgid "Pending"
msgstr ""
+msgid "Pending Agents"
+msgstr ""
+
msgid "Pending Hosts"
msgstr ""
@@ -5893,9 +6190,27 @@ msgstr ""
msgid "Pending Registered Hosts"
msgstr ""
+msgid "Pending Registration created by FOG_AGENT"
+msgstr ""
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr ""
+msgid "Pending agent"
+msgstr ""
+
+msgid "Pending agent enrollments"
+msgstr ""
+
+msgid "Pending agents"
+msgstr ""
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
msgid "Pending host"
msgstr ""
@@ -5935,6 +6250,15 @@ msgstr ""
msgid "Ping cycle complete"
msgstr ""
+msgid "Pinned"
+msgstr ""
+
+msgid "Placement"
+msgstr ""
+
+msgid "Platform"
+msgstr ""
+
msgid "Please Select an option"
msgstr ""
@@ -5975,9 +6299,15 @@ msgstr ""
msgid "Please enter a name"
msgstr ""
+msgid "Please enter a package id."
+msgstr ""
+
msgid "Please enter a printer name."
msgstr ""
+msgid "Please enter a software name."
+msgstr ""
+
msgid "Please enter a valid CIDR subnet."
msgstr ""
@@ -5990,6 +6320,9 @@ msgstr ""
msgid "Please physically associate"
msgstr ""
+msgid "Please select a valid backend."
+msgstr ""
+
msgid "Please select a valid certificate verification level"
msgstr ""
@@ -6005,6 +6338,9 @@ msgstr ""
msgid "Please select a valid printer type."
msgstr ""
+msgid "Please select a valid state."
+msgstr ""
+
msgid "Please select an LDAP server!"
msgstr ""
@@ -6183,6 +6519,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -6222,6 +6561,9 @@ msgstr ""
msgid "Printer Create Success"
msgstr ""
+msgid "Printer Deployment"
+msgstr ""
+
msgid "Printer Description"
msgstr ""
@@ -6354,6 +6696,9 @@ msgstr ""
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
msgid "Pushbullet Accounts"
msgstr ""
@@ -6388,6 +6733,9 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr ""
+msgid "Quick tasks"
+msgstr ""
+
msgid "RESOURCES"
msgstr ""
@@ -6400,6 +6748,9 @@ msgstr ""
msgid "Re-Transmit Hello Interval"
msgstr ""
+msgid "Re-check Interval"
+msgstr ""
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -6418,6 +6769,9 @@ msgstr ""
msgid "Real Time"
msgstr ""
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr ""
@@ -6442,6 +6796,9 @@ msgstr ""
msgid "Recorded in range"
msgstr ""
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
msgid "Records"
msgstr ""
@@ -6454,9 +6811,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-msgid "Refresh"
-msgstr ""
-
msgid "Refresh Settings Cache"
msgstr ""
@@ -6585,6 +6939,9 @@ msgstr ""
msgid "Report Management"
msgstr ""
+msgid "Reported"
+msgstr ""
+
msgid "Reports"
msgstr ""
@@ -6643,9 +7000,15 @@ msgstr ""
msgid "Retention sweep failed"
msgstr ""
+msgid "Retry"
+msgstr ""
+
msgid "Return Code"
msgstr ""
+msgid "Return Codes"
+msgstr ""
+
msgid "Return To Local Login"
msgstr ""
@@ -6655,9 +7018,30 @@ msgstr ""
msgid "Returning value of key"
msgstr ""
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+msgid "Revoke an agent enrollment token"
+msgstr ""
+
+msgid "Revoke selected"
+msgstr ""
+
+msgid "Revoked selected tokens."
+msgstr ""
+
+msgid "Revoked."
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -6775,6 +7159,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
msgid "SQL Error"
msgstr ""
@@ -6877,15 +7264,6 @@ msgstr ""
msgid "Scopes"
msgstr ""
-msgid "Screen Height"
-msgstr ""
-
-msgid "Screen Refresh Rate"
-msgstr ""
-
-msgid "Screen Width"
-msgstr ""
-
msgid "Search"
msgstr ""
@@ -7090,6 +7468,9 @@ msgstr ""
msgid "Sessions canceled!"
msgstr ""
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -7478,6 +7859,51 @@ msgstr ""
msgid "So if you are trying to transmit to remote node A"
msgstr ""
+msgid "Software"
+msgstr ""
+
+msgid "Software Create Fail"
+msgstr ""
+
+msgid "Software Create Success"
+msgstr ""
+
+msgid "Software Host Associations"
+msgstr ""
+
+msgid "Software Management"
+msgstr ""
+
+msgid "Software Name"
+msgstr ""
+
+msgid "Software Order"
+msgstr ""
+
+msgid "Software Report"
+msgstr ""
+
+msgid "Software Status"
+msgstr ""
+
+msgid "Software Update Fail"
+msgstr ""
+
+msgid "Software Update Success"
+msgstr ""
+
+msgid "Software added!"
+msgstr ""
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+msgid "Software update failed!"
+msgstr ""
+
+msgid "Software updated!"
+msgstr ""
+
msgid "Some nice description, should be short."
msgstr ""
@@ -7490,6 +7916,9 @@ msgstr ""
msgid "Specified download URL not allowed!"
msgstr ""
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -8111,6 +8540,9 @@ msgstr ""
msgid "The CA private key is on this server"
msgstr ""
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -8141,6 +8573,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -8183,6 +8618,9 @@ msgstr ""
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -8219,6 +8657,12 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+msgid "The enrollment is no longer pending."
+msgstr ""
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -8243,6 +8687,15 @@ msgstr ""
msgid "The grid key."
msgstr ""
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
msgid "The identity provider could not be reached"
msgstr ""
@@ -8294,9 +8747,15 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+msgid "The item is not a live row of this host."
+msgstr ""
+
msgid "The key will be assigned to registered hosts when a"
msgstr ""
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -8325,12 +8784,21 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
msgid "The path requested is already in use by another image!"
msgstr ""
+msgid "The payload bytes."
+msgstr ""
+
msgid "The plugin directory"
msgstr ""
@@ -8371,6 +8839,12 @@ msgstr ""
msgid "The record could not be written."
msgstr ""
+msgid "The renewed certificate, leaf then chain."
+msgstr ""
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -8380,6 +8854,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -8389,6 +8866,12 @@ msgstr ""
msgid "The selected site no longer exists"
msgstr ""
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -8407,6 +8890,12 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+msgid "The signing helper is not available on this server."
+msgstr ""
+
msgid "The signing request could not be generated"
msgstr ""
@@ -8426,6 +8915,9 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+msgid "The token."
+msgstr ""
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -8577,6 +9069,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -8635,10 +9130,16 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, php-format
msgid "This machine already registered as %s"
msgstr ""
+msgid "This module has no settings to configure."
+msgstr ""
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -8741,6 +9242,12 @@ msgstr ""
msgid "Time since last imaged"
msgstr ""
+msgid "Timeout"
+msgstr ""
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -8762,9 +9269,27 @@ msgstr ""
msgid "Toggle navigation"
msgstr ""
+msgid "Token Create Fail"
+msgstr ""
+
+msgid "Token Create Success"
+msgstr ""
+
+msgid "Token Revoke Fail"
+msgstr ""
+
+msgid "Token Revoke Success"
+msgstr ""
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
msgid "Too many MACs"
msgstr ""
@@ -8919,6 +9444,9 @@ msgstr ""
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
msgid "Unauthenticated."
msgstr ""
@@ -8961,6 +9489,9 @@ msgstr ""
msgid "Unknown action"
msgstr ""
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -8987,6 +9518,9 @@ msgstr ""
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
msgid "Unmark selected client ignore"
msgstr ""
@@ -9062,6 +9596,9 @@ msgstr ""
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
msgid "Upload"
msgstr ""
@@ -9164,9 +9701,6 @@ msgstr ""
msgid "User Association"
msgstr ""
-msgid "User Cleanup"
-msgstr ""
-
msgid "User Count"
msgstr ""
@@ -9233,6 +9767,9 @@ msgstr ""
msgid "User Password"
msgstr ""
+msgid "User Sessions"
+msgstr ""
+
msgid "User Tracker"
msgstr ""
@@ -9302,6 +9839,12 @@ msgstr ""
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr ""
@@ -9326,6 +9869,9 @@ msgstr ""
msgid "Version information and paging bounds."
msgstr ""
+msgid "Version policy"
+msgstr ""
+
msgid "Versions"
msgstr ""
@@ -9350,6 +9896,9 @@ msgstr ""
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -9398,12 +9947,18 @@ msgstr ""
msgid "What it does"
msgstr ""
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -9419,6 +9974,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr ""
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -9431,10 +9989,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -9494,6 +10052,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr ""
@@ -9611,6 +10172,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
msgid "access"
msgstr ""
@@ -9620,9 +10184,16 @@ msgstr ""
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
msgid "ago"
msgstr ""
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
msgid "all current storage nodes"
msgstr ""
@@ -9653,6 +10224,12 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+msgid "any version"
+msgstr ""
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
msgid "architecture not recorded"
msgstr ""
@@ -9662,6 +10239,9 @@ msgstr ""
msgid "as its primary group"
msgstr ""
+msgid "assigned"
+msgstr ""
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -9755,6 +10335,9 @@ msgstr ""
msgid "does not exist and cannot be created"
msgstr ""
+msgid "domain"
+msgstr ""
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -9764,16 +10347,28 @@ msgstr ""
msgid "either because you have updated"
msgstr ""
+msgid "empty means never install Chocolatey"
+msgstr ""
+
msgid "error"
msgstr ""
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+msgid "failed"
+msgstr ""
+
msgid "failed to execute, image file"
msgstr ""
@@ -9858,6 +10453,10 @@ msgstr ""
msgid "host"
msgstr ""
+#, php-format
+msgid "host \"%s\""
+msgstr ""
+
msgid "host is"
msgstr ""
@@ -9952,18 +10551,12 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
msgid "in minutes"
msgstr ""
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr ""
@@ -10031,6 +10624,9 @@ msgstr ""
msgid "keys"
msgstr ""
+msgid "latest"
+msgstr ""
+
msgid "leave to keep the current one"
msgstr ""
@@ -10062,6 +10658,9 @@ msgstr ""
msgid "mismatched"
msgstr ""
+msgid "missing"
+msgstr ""
+
msgid "moments from now"
msgstr ""
@@ -10097,6 +10696,9 @@ msgstr ""
msgid "never"
msgstr ""
+msgid "never reported"
+msgstr ""
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -10127,6 +10729,9 @@ msgstr ""
msgid "not found on this node"
msgstr ""
+msgid "not joined"
+msgstr ""
+
msgid "not reachable"
msgstr ""
@@ -10151,9 +10756,15 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+msgid "off"
+msgstr ""
+
msgid "off means an account must already exist"
msgstr ""
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -10166,6 +10777,9 @@ msgstr ""
msgid "optional"
msgstr ""
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -10416,6 +11030,9 @@ msgstr ""
msgid "unchanged for"
msgstr ""
+msgid "unknown action"
+msgstr ""
+
msgid "unrecorded"
msgstr ""
diff --git a/packages/web/management/languages/pt_BR.UTF-8/LC_MESSAGES/messages.po b/packages/web/management/languages/pt_BR.UTF-8/LC_MESSAGES/messages.po
index ae383410bd..98dd406ddb 100644
--- a/packages/web/management/languages/pt_BR.UTF-8/LC_MESSAGES/messages.po
+++ b/packages/web/management/languages/pt_BR.UTF-8/LC_MESSAGES/messages.po
@@ -125,6 +125,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -294,6 +298,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, fuzzy, php-format
+msgid "(deleted host %d)"
+msgstr "Aprovar Hosts selecionados"
+
msgid "(deleted user)"
msgstr ""
@@ -313,9 +321,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr "Argumentos de kernel"
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
#, fuzzy
msgid "1 Hour"
msgstr "1 hora"
@@ -420,6 +434,12 @@ msgstr "Uma imagem já existe com este nome!"
msgid "A client ID is required"
msgstr "Um nome de imagem é necessário!"
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
#, fuzzy
msgid "A dmi field must be set!"
msgstr "Evento deve ser uma string"
@@ -483,6 +503,9 @@ msgstr "Uma imagem já existe com este nome!"
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
#, fuzzy
msgid "A module already exists with this name!"
msgstr "Uma imagem já existe com este nome!"
@@ -504,6 +527,9 @@ msgstr "Listar todos os %s"
msgid "A permission name is required."
msgstr "Um nome de imagem é necessário!"
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -526,6 +552,9 @@ msgstr "Uma imagem já existe com este nome!"
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
#, fuzzy
msgid "A role already exists with this name!"
msgstr "Uma imagem já existe com este nome!"
@@ -567,6 +596,10 @@ msgstr "Uma imagem já existe com este nome!"
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+#, fuzzy
+msgid "A software entry already exists with this name!"
+msgstr "Uma imagem já existe com este nome!"
+
#, fuzzy
msgid "A storage group already exists with this name!"
msgstr "Uma imagem já existe com este nome!"
@@ -702,6 +735,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -932,6 +971,10 @@ msgstr "Adicionar snap-in falhou!"
msgid "Add snapin failed!"
msgstr "Adicionar snap-in falhou!"
+#, fuzzy
+msgid "Add software failed!"
+msgstr "Adicionar snap-in falhou!"
+
#, fuzzy
msgid "Add storage node failed!"
msgstr "Adicionar snap-in falhou!"
@@ -1016,6 +1059,33 @@ msgstr "avançado"
msgid "Advanced Tasks"
msgstr "avançado"
+msgid "Agent"
+msgstr ""
+
+#, fuzzy
+msgid "Agent Activity"
+msgstr "Ativo"
+
+#, fuzzy
+msgid "Agent Approval Success"
+msgstr "host criado"
+
+#, fuzzy
+msgid "Agent Denial Success"
+msgstr "Impressora atualizado!"
+
+#, fuzzy
+msgid "Agent Enrollment Tokens"
+msgstr "foi atualizado com sucesso"
+
+#, fuzzy
+msgid "Agent Tokens"
+msgstr "token de acesso"
+
+#, fuzzy
+msgid "Agent enrollment tokens"
+msgstr "foi atualizado com sucesso"
+
msgid "Ago must be boolean"
msgstr ""
@@ -1032,6 +1102,10 @@ msgstr ""
msgid "All Hosts"
msgstr "Todos os hosts"
+#, fuzzy
+msgid "All Pending Agents"
+msgstr "pendentes MACs"
+
#, fuzzy
msgid "All Pending Hosts"
msgstr "Anfitriões pendentes"
@@ -1135,10 +1209,16 @@ msgstr ""
msgid "An SQL error occurred"
msgstr "Ocorreu um erro de upload desconhecido. Código de retorno: "
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
#, fuzzy
msgid "An entry already exists with this name!"
msgstr "Uma imagem já existe com este nome!"
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr "Uma imagem já existe com este nome!"
@@ -1178,6 +1258,10 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+#, fuzzy
+msgid "Any version"
+msgstr "Versão"
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1216,18 +1300,36 @@ msgstr ""
msgid "Approve"
msgstr "hospedar aprovado"
+#, fuzzy
+msgid "Approve Agent Fail"
+msgstr "hospedar aprovado"
+
#, fuzzy
msgid "Approve MAC Fail"
msgstr "hospedar aprovado"
+#, fuzzy
+msgid "Approve Pending Agents"
+msgstr "Anfitriões pendentes"
+
#, fuzzy
msgid "Approve Pending Hosts"
msgstr "Anfitriões pendentes"
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
#, fuzzy
msgid "Approve selected"
msgstr "Aprovar Hosts selecionados"
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+#, fuzzy
+msgid "Approved selected agents!"
+msgstr "Aprovar Hosts selecionados"
+
#, fuzzy
msgid "Approved selected hosts!"
msgstr "Aprovar Hosts selecionados"
@@ -1240,6 +1342,9 @@ msgstr "Aprovar Hosts selecionados"
msgid "Approving the selected pending hosts."
msgstr "Aprovar Hosts selecionados"
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1249,6 +1354,10 @@ msgstr ""
msgid "Area"
msgstr ""
+#, fuzzy
+msgid "Assigned"
+msgstr "No nó associado"
+
#, fuzzy
msgid "Assigned Group"
msgstr "Nome do grupo de armazenamento"
@@ -1311,6 +1420,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1349,6 +1461,9 @@ msgstr "BIOS Vendor"
msgid "BIOS Version"
msgstr "Versão do BIOS"
+msgid "Backend"
+msgstr ""
+
#, fuzzy
msgid "Bad request."
msgstr "%s é necessária"
@@ -1582,6 +1697,10 @@ msgstr "tarefa cancelada"
msgid "Canceled due to new tasking."
msgstr "Cancelado devido à nova tarefa."
+#, fuzzy
+msgid "Cannot Run"
+msgstr "Registro não encontrado, erro: %s"
+
#, fuzzy
msgid "Cannot bind to the LDAP server"
msgstr "Não é possível conectar ao banco de dados"
@@ -1596,10 +1715,6 @@ msgstr "Não é possível ligar para o nó."
msgid "Cannot connect to database"
msgstr "Não é possível conectar ao banco de dados"
-#, fuzzy
-msgid "Cannot connect to ftp server"
-msgstr "Não é possível conectar ao banco de dados"
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1796,6 +1911,9 @@ msgstr "Sem FOGPage classe encontrada para este nó"
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+msgid "Checked"
+msgstr ""
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1808,6 +1926,12 @@ msgstr ""
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1979,14 +2103,23 @@ msgstr "Erro: falha ao baixar do kernel"
msgid "Confirm you would like to download a new kernel"
msgstr "Erro: falha ao baixar do kernel"
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
#, fuzzy
msgid "Copy from existing"
msgstr "Não foi possível criar impressora"
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -2060,10 +2193,6 @@ msgstr "Não foi possível ler o arquivo tmp."
msgid "Could not read local file"
msgstr "Não foi possível ler arquivo temporário"
-#, fuzzy
-msgid "Could not read snapin file"
-msgstr "Não foi possível ler o arquivo tmp."
-
#, fuzzy
msgid "Could not read the database structure"
msgstr "Falha ao criar Snapin Job"
@@ -2160,6 +2289,9 @@ msgstr ""
msgid "Create"
msgstr "Crio"
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -2242,6 +2374,10 @@ msgstr "Criar novo minutos"
msgid "Create New Snapin"
msgstr "Criar novo Snapin"
+#, fuzzy
+msgid "Create New Software"
+msgstr "Criar novo minutos"
+
msgid "Create New Storage Group"
msgstr "Criar novo Storage Group"
@@ -2289,6 +2425,10 @@ msgstr "usuário criado"
msgid "Create Users On First Login"
msgstr ""
+#, fuzzy, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr "usuário criado"
+
#, fuzzy, php-format
msgid "Create a %s"
msgstr "Criar novo %s"
@@ -2312,9 +2452,17 @@ msgstr "usuário criado"
msgid "Create task form success"
msgstr "usuário criado"
+#, fuzzy
+msgid "Create tasking"
+msgstr "Criar novo %s"
+
msgid "Create tasking succeeded"
msgstr ""
+#, fuzzy
+msgid "Create token"
+msgstr "Criar novo %s"
+
#, fuzzy
msgid "Created"
msgstr "Crio"
@@ -2326,6 +2474,10 @@ msgstr "Criado por"
msgid "Created Time"
msgstr "Criado por"
+#, fuzzy
+msgid "Created by"
+msgstr "Criado por"
+
msgid "Created by FOG Reg on"
msgstr "Criado por FOG Reg em"
@@ -2454,6 +2606,9 @@ msgstr "Opções de depuração"
msgid "Debug Task"
msgstr "Depurar"
+msgid "Decided."
+msgstr ""
+
msgid "Default"
msgstr "Padrão"
@@ -2461,15 +2616,6 @@ msgstr "Padrão"
msgid "Default Choice"
msgstr "Item padrão:"
-msgid "Default Height"
-msgstr "padrão Altura"
-
-msgid "Default Refresh Rate"
-msgstr "Padrão Refresh Rate"
-
-msgid "Default Width"
-msgstr "Largura padrão"
-
#, fuzzy
msgid "Default init, ARM64"
msgstr "Largura padrão"
@@ -2554,6 +2700,28 @@ msgstr ""
msgid "Deleting remote file"
msgstr "Menu Criar falhou"
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+#, fuzzy
+msgid "Denied selected agents!"
+msgstr "Aprovar Hosts selecionados"
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy
+msgid "Deny Agent Fail"
+msgstr "Apagar dados de arquivo"
+
+#, fuzzy
+msgid "Deny Pending Agents"
+msgstr "pendentes MACs"
+
+#, fuzzy
+msgid "Deny selected"
+msgstr "Delete Selected"
+
msgid "Deploy"
msgstr "implantar"
@@ -2570,14 +2738,30 @@ msgstr ""
msgid "Description"
msgstr "Descrição"
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+msgid "Desired domain"
+msgstr ""
+
#, fuzzy
msgid "Destroy failed"
msgstr "Destrua falhou: %s"
+#, fuzzy
+msgid "Detail"
+msgstr "Detalhe Snapin Retorno"
+
#, fuzzy
msgid "Details"
msgstr "Detalhe Snapin Retorno"
+msgid "Device URI"
+msgstr ""
+
#, fuzzy
msgid "Device must be a string"
msgstr "Evento deve ser uma string"
@@ -2591,9 +2775,6 @@ msgstr "Diretório"
msgid "Directory Already Exists"
msgstr "Diretório já existe"
-msgid "Directory Cleaner"
-msgstr "Cleaner diretório"
-
#, fuzzy
msgid "Directory Group"
msgstr "Diretório"
@@ -2602,6 +2783,10 @@ msgstr "Diretório"
msgid "Directory Group Name"
msgstr "Diretório"
+#, fuzzy
+msgid "Directory Membership"
+msgstr "Membership"
+
#, fuzzy
msgid "Disable on all hosts"
msgstr "ativado"
@@ -2718,6 +2903,9 @@ msgstr "Falha no download"
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2737,6 +2925,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr "Editar"
@@ -2832,6 +3023,10 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+#, fuzzy
+msgid "Enrollment Token"
+msgstr "Contas Pushbullet"
+
msgid "Enrollment kit"
msgstr ""
@@ -2935,6 +3130,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
#, fuzzy
msgid "Every file was uploaded."
msgstr "Nenhum arquivo foi transferido"
@@ -2955,6 +3156,14 @@ msgstr "chave privada falhou"
msgid "Exists item must be boolean"
msgstr ""
+#, fuzzy
+msgid "Exit Code"
+msgstr "exportação Snapins"
+
+#, fuzzy
+msgid "Exit code"
+msgstr "Código de retorno"
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -3034,9 +3243,32 @@ msgstr "Encontro"
msgid "External root CA"
msgstr ""
+#, fuzzy
+msgid "Extra arguments"
+msgstr "Snapin Run com o argumento"
+
msgid "FOG"
msgstr "NÉVOA"
+#, fuzzy
+msgid "FOG Agent capability result"
+msgstr "Nenhum arquivo foi transferido"
+
+#, fuzzy
+msgid "FOG Agent certificate renewal"
+msgstr "Nenhum arquivo foi transferido"
+
+#, fuzzy
+msgid "FOG Agent enrollment"
+msgstr "foi atualizado com sucesso"
+
+#, fuzzy
+msgid "FOG Agent payload"
+msgstr "Nenhum arquivo foi transferido"
+
+msgid "FOG Agent poll"
+msgstr ""
+
#, fuzzy
msgid "FOG Client"
msgstr "FOG Cliente Wiki"
@@ -3395,6 +3627,9 @@ msgstr "tarefa iniciada"
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3738,6 +3973,10 @@ msgstr "História Snapin"
msgid "Group Snapin History"
msgstr "História Snapin"
+#, fuzzy
+msgid "Group Software Assignment"
+msgstr "História Snapin"
+
#, fuzzy
msgid "Group Task History"
msgstr "História imagem"
@@ -3826,9 +4065,15 @@ msgstr "Informações de hardware"
msgid "Hardware Report"
msgstr "Informações de hardware"
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr ""
+msgid "Hash Mismatch"
+msgstr ""
+
msgid "Have not locked the host for access"
msgstr ""
@@ -3836,10 +4081,6 @@ msgstr ""
msgid "Header is missing the required \"%s\" column"
msgstr ""
-#, fuzzy
-msgid "Height"
-msgstr "meia-noite"
-
msgid "Height must be 120 pixels."
msgstr ""
@@ -3912,6 +4153,9 @@ msgstr "Impressora já existe"
msgid "Host %1$s finished deploying image %2$s."
msgstr "Impressora já existe"
+msgid "Host Agent Activity"
+msgstr ""
+
#, fuzzy
msgid "Host Approval Success"
msgstr "host criado"
@@ -3947,10 +4191,6 @@ msgstr "Item padrão:"
msgid "Host Description"
msgstr "anfitrião Descrição"
-#, fuzzy
-msgid "Host Display Manager Settings"
-msgstr "Configurações"
-
msgid "Host EFI Exit Type"
msgstr "Hospedar EFI Tipo Exit"
@@ -4055,10 +4295,6 @@ msgstr "Hospedar de Chave de Produto"
msgid "Host Registration"
msgstr "Registro de acolhimento"
-#, fuzzy
-msgid "Host Screen Resolution"
-msgstr "Registro de acolhimento"
-
#, fuzzy
msgid "Host Snapin Associations"
msgstr "No nó associado"
@@ -4067,6 +4303,13 @@ msgstr "No nó associado"
msgid "Host Snapin History"
msgstr "História Snapin"
+#, fuzzy
+msgid "Host Software Assignment"
+msgstr "História Snapin"
+
+msgid "Host Software Status"
+msgstr ""
+
#, fuzzy
msgid "Host Task History"
msgstr "História imagem"
@@ -4160,6 +4403,12 @@ msgstr "Lista de Host"
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
#, fuzzy
msgid "Hosts:"
msgstr "Hosts"
@@ -4224,6 +4473,10 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+#, fuzzy
+msgid "Identity"
+msgstr "Shell servidor"
+
msgid "Identity Provider"
msgstr ""
@@ -4739,6 +4992,10 @@ msgstr "Plugins instalados"
msgid "Installed Plugins"
msgstr "Plugins instalados"
+#, fuzzy
+msgid "Installed Software"
+msgstr "Plugins instalados"
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4825,9 +5082,6 @@ msgstr "Inválida Snapin Tasking"
msgid "Invalid Storage Group"
msgstr "Grupo de armazenamento inválido"
-msgid "Invalid Storage Node"
-msgstr "Inválida Storage Node"
-
#, fuzzy
msgid "Invalid Tasking"
msgstr "tarefa inválido"
@@ -5011,6 +5265,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -5036,6 +5293,9 @@ msgstr ""
msgid "It will operate based on the fields the area typcially requires."
msgstr ""
+msgid "Join"
+msgstr ""
+
msgid "Join Domain after image task"
msgstr ""
@@ -5237,6 +5497,9 @@ msgstr "Língua"
msgid "Largest images"
msgstr "imagens"
+msgid "Last Agent Check-In"
+msgstr ""
+
#, fuzzy
msgid "Last Captured"
msgstr "host criado"
@@ -5247,15 +5510,16 @@ msgstr ""
msgid "Last Check-In"
msgstr ""
-msgid "Last Client Check-In"
-msgstr ""
-
msgid "Last Deployed"
msgstr "Última Implantado"
msgid "Last Ping"
msgstr ""
+#, fuzzy
+msgid "Last Seen"
+msgstr "host criado"
+
#, fuzzy
msgid "Last Successful Ping"
msgstr "Bem sucedido"
@@ -5271,6 +5535,10 @@ msgstr ""
msgid "Last deployed"
msgstr "Última Implantado"
+#, fuzzy
+msgid "Last error"
+msgstr "Erro"
+
msgid "Last flush"
msgstr ""
@@ -5278,6 +5546,9 @@ msgstr ""
msgid "Last imaged"
msgstr "imagens"
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
#, fuzzy
msgid "Latest Alpha Version"
msgstr "Última versão"
@@ -5402,6 +5673,10 @@ msgstr "Listar todos os minutoss"
msgid "List All Snapins"
msgstr "Listar todos os Snapins"
+#, fuzzy
+msgid "List All Software"
+msgstr "Listar todos os minutoss"
+
msgid "List All Storage Groups"
msgstr "Listar todos os Storage Groups"
@@ -5538,6 +5813,9 @@ msgstr "Visualizador de log"
msgid "Log out and sign in as an administrator"
msgstr ""
+msgid "Logged on"
+msgstr ""
+
msgid "Logging"
msgstr ""
@@ -5730,6 +6008,9 @@ msgstr "Max Size"
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
#, fuzzy
msgid "Member"
msgstr "Membros"
@@ -5810,6 +6091,10 @@ msgstr "meia-noite"
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+#, fuzzy
+msgid "Mint an agent enrollment token"
+msgstr "Enquanto se aguarda hosts registrados"
+
msgid "Minute value is not valid"
msgstr "valor do minuto não é válido"
@@ -5817,6 +6102,9 @@ msgstr "valor do minuto não é válido"
msgid "Minutes field is invalid"
msgstr "valor do minuto não é válido"
+msgid "Missing"
+msgstr ""
+
msgid "Missing a temporary folder"
msgstr "Faltando uma pasta temporária"
@@ -6285,6 +6573,10 @@ msgstr "Não há vagas abertas"
msgid "No password is needed. Issue this account a token from its API tab, or from FOG Configuration → API Tokens, once it has been created."
msgstr ""
+#, fuzzy
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr "Nenhuma tarefa ativa encontrada para o Host"
+
#, fuzzy
msgid "No plugin tasks to run"
msgstr "Nenhuma classe válida enviada"
@@ -6339,6 +6631,10 @@ msgstr "Snapin atualizada"
msgid "No snapins associated with this group as master"
msgstr "Não há snapins associados a este alojamento"
+#, fuzzy
+msgid "No storage node can serve the file."
+msgstr "Adicionar snap-in falhou!"
+
#, fuzzy
msgid "No storage nodes assigned to this storage group"
msgstr "Não foi possível encontrar um nó de armazenamento Existe um ativado dentro deste grupo de armazenamento"
@@ -6351,6 +6647,9 @@ msgstr "Uma imagem já existe com este nome!"
msgid "No storagegroups assigned to this snapin"
msgstr "O grupo de armazenamento de imagens atribuído não é válido"
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -6360,6 +6659,9 @@ msgstr ""
msgid "No such object."
msgstr ""
+msgid "No such token."
+msgstr ""
+
msgid "No such user."
msgstr ""
@@ -6395,6 +6697,9 @@ msgstr ""
msgid "No values passed"
msgstr "Não há valores passados"
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
#, fuzzy
msgid "No viable macs to use"
msgstr "Não é capaz de atualizar"
@@ -6450,6 +6755,9 @@ msgstr "Ícone do Arquivo não encontrado"
msgid "Not Registered Hosts"
msgstr "Hosts não registrada"
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr "Não é um número"
@@ -6586,6 +6894,13 @@ msgstr "usuário atualizada"
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+#, fuzzy
+msgid "Observed domain"
+msgstr "Informação geral"
+
msgid "Off"
msgstr ""
@@ -6642,6 +6957,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr "Erro, é uma imagem associada com este anfitrião"
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -6725,6 +7046,12 @@ msgstr ""
msgid "Operations on %s."
msgstr "Campo operação não definido: %s"
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -6770,9 +7097,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -6854,6 +7187,10 @@ msgstr ""
msgid "Pending"
msgstr "Pendente..."
+#, fuzzy
+msgid "Pending Agents"
+msgstr "pendentes MACs"
+
msgid "Pending Hosts"
msgstr "Anfitriões pendentes"
@@ -6871,9 +7208,31 @@ msgstr "pendentes MACs"
msgid "Pending Registered Hosts"
msgstr "Enquanto se aguarda hosts registrados"
+#, fuzzy
+msgid "Pending Registration created by FOG_AGENT"
+msgstr "Na pendência de Registro criado por FOG_CLIENT"
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr "Na pendência de Registro criado por FOG_CLIENT"
+#, fuzzy
+msgid "Pending agent"
+msgstr "anfitriões pendentes"
+
+#, fuzzy
+msgid "Pending agent enrollments"
+msgstr "Enquanto se aguarda hosts registrados"
+
+#, fuzzy
+msgid "Pending agents"
+msgstr "macs pendentes"
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
#, fuzzy
msgid "Pending host"
msgstr "anfitriões pendentes"
@@ -6920,6 +7279,16 @@ msgstr "estado"
msgid "Ping cycle complete"
msgstr "foi destruído"
+msgid "Pinned"
+msgstr ""
+
+#, fuzzy
+msgid "Placement"
+msgstr "Gestão de tarefas"
+
+msgid "Platform"
+msgstr ""
+
msgid "Please Select an option"
msgstr "Por favor selecione uma opção"
@@ -6964,10 +7333,18 @@ msgstr ""
msgid "Please enter a name"
msgstr "Por favor insira um nome de host válido"
+#, fuzzy
+msgid "Please enter a package id."
+msgstr "Por favor insira um nome de host válido"
+
#, fuzzy
msgid "Please enter a printer name."
msgstr "Por favor insira um nome de host válido"
+#, fuzzy
+msgid "Please enter a software name."
+msgstr "Por favor insira um nome de host válido"
+
#, fuzzy
msgid "Please enter a valid CIDR subnet."
msgstr "Por favor insira um nome de host válido"
@@ -6981,6 +7358,10 @@ msgstr ""
msgid "Please physically associate"
msgstr ""
+#, fuzzy
+msgid "Please select a valid backend."
+msgstr "Selecione uma imagem válida"
+
#, fuzzy
msgid "Please select a valid certificate verification level"
msgstr "Selecione uma imagem válida"
@@ -7001,6 +7382,10 @@ msgstr "Selecione uma imagem válida"
msgid "Please select a valid printer type."
msgstr "Selecione uma imagem válida"
+#, fuzzy
+msgid "Please select a valid state."
+msgstr "Selecione uma imagem válida"
+
#, fuzzy
msgid "Please select an LDAP server!"
msgstr "Por favor selecione uma opção"
@@ -7216,6 +7601,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -7262,6 +7650,10 @@ msgstr "atualização da impressora falhou!"
msgid "Printer Create Success"
msgstr "Impressora já existe"
+#, fuzzy
+msgid "Printer Deployment"
+msgstr "Gerenciamento de impressora"
+
msgid "Printer Description"
msgstr "Descrição Printer"
@@ -7419,6 +7811,9 @@ msgstr "Impressora atualizado!"
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
msgid "Pushbullet Accounts"
msgstr "Contas Pushbullet"
@@ -7460,6 +7855,10 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr "Snapin está protegido e não pode ser excluído"
+#, fuzzy
+msgid "Quick tasks"
+msgstr "Tarefas Multicast ativos"
+
msgid "RESOURCES"
msgstr ""
@@ -7472,6 +7871,9 @@ msgstr "RX"
msgid "Re-Transmit Hello Interval"
msgstr ""
+msgid "Re-check Interval"
+msgstr ""
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -7492,6 +7894,9 @@ msgstr "Delete Selected"
msgid "Real Time"
msgstr "Anfitrião Update Failed"
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr "reinicialização"
@@ -7520,6 +7925,9 @@ msgstr ""
msgid "Recorded in range"
msgstr "Registro não encontrado, erro: %s"
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
#, fuzzy
msgid "Records"
msgstr "Registros atuais"
@@ -7533,10 +7941,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-#, fuzzy
-msgid "Refresh"
-msgstr "Padrão Refresh Rate"
-
#, fuzzy
msgid "Refresh Settings Cache"
msgstr "status do serviço"
@@ -7682,6 +8086,10 @@ msgstr "Relatório"
msgid "Report Management"
msgstr "relatório de Gestão"
+#, fuzzy
+msgid "Reported"
+msgstr "Relatório"
+
msgid "Reports"
msgstr "Relatórios"
@@ -7747,9 +8155,16 @@ msgstr ""
msgid "Retention sweep failed"
msgstr "Removido"
+msgid "Retry"
+msgstr ""
+
msgid "Return Code"
msgstr "Código de retorno"
+#, fuzzy
+msgid "Return Codes"
+msgstr "Código de retorno"
+
msgid "Return To Local Login"
msgstr ""
@@ -7760,9 +8175,33 @@ msgstr "Código de retorno"
msgid "Returning value of key"
msgstr "Retornando valor da chave"
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+#, fuzzy
+msgid "Revoke an agent enrollment token"
+msgstr "Enquanto se aguarda hosts registrados"
+
+#, fuzzy
+msgid "Revoke selected"
+msgstr "Remover snapins selecionados"
+
+#, fuzzy
+msgid "Revoked selected tokens."
+msgstr "Aprovar Hosts selecionados"
+
+msgid "Revoked."
+msgstr ""
+
#, fuzzy
msgid "Role"
msgstr "Nome do módulo"
@@ -7903,6 +8342,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
#, fuzzy
msgid "SQL Error"
msgstr "Erro SQL:"
@@ -8021,16 +8463,6 @@ msgstr "Instalar / Atualizar sucesso!"
msgid "Scopes"
msgstr ""
-msgid "Screen Height"
-msgstr ""
-
-#, fuzzy
-msgid "Screen Refresh Rate"
-msgstr "Padrão Refresh Rate"
-
-msgid "Screen Width"
-msgstr ""
-
msgid "Search"
msgstr "Pesquisa"
@@ -8266,6 +8698,9 @@ msgstr "Um nome de host com esse nome já existe."
msgid "Sessions canceled!"
msgstr "foi atualizado com sucesso"
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -8732,6 +9167,63 @@ msgstr "snapins"
msgid "So if you are trying to transmit to remote node A"
msgstr ""
+msgid "Software"
+msgstr ""
+
+#, fuzzy
+msgid "Software Create Fail"
+msgstr "atualização da impressora falhou!"
+
+#, fuzzy
+msgid "Software Create Success"
+msgstr "Impressora já existe"
+
+#, fuzzy
+msgid "Software Host Associations"
+msgstr "No nó associado"
+
+#, fuzzy
+msgid "Software Management"
+msgstr "Gerenciamento de armazenamento"
+
+#, fuzzy
+msgid "Software Name"
+msgstr "Nome da impressora"
+
+msgid "Software Order"
+msgstr ""
+
+#, fuzzy
+msgid "Software Report"
+msgstr "ID de acolhimento"
+
+#, fuzzy
+msgid "Software Status"
+msgstr "Criar novo %s"
+
+#, fuzzy
+msgid "Software Update Fail"
+msgstr "atualização da impressora falhou!"
+
+#, fuzzy
+msgid "Software Update Success"
+msgstr "Instalar / Atualizar sucesso!"
+
+#, fuzzy
+msgid "Software added!"
+msgstr "Nome da impressora"
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+#, fuzzy
+msgid "Software update failed!"
+msgstr "atualização da impressora falhou!"
+
+#, fuzzy
+msgid "Software updated!"
+msgstr "Impressora atualizado!"
+
msgid "Some nice description, should be short."
msgstr ""
@@ -8744,6 +9236,9 @@ msgstr ""
msgid "Specified download URL not allowed!"
msgstr ""
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -9495,6 +9990,9 @@ msgstr "Não existem grupos neste servidor."
msgid "The CA private key is on this server"
msgstr "Não existem grupos neste servidor."
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -9528,6 +10026,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -9572,6 +10073,9 @@ msgstr " | Arquivo ou o caminho não pode ser alcançado"
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -9612,6 +10116,13 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+#, fuzzy
+msgid "The enrollment is no longer pending."
+msgstr " não existe mais"
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -9639,6 +10150,15 @@ msgstr ""
msgid "The grid key."
msgstr "Falha ao criar tarefa"
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
#, fuzzy
msgid "The identity provider could not be reached"
msgstr "Não foi possível ler arquivo temporário"
@@ -9693,9 +10213,16 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+#, fuzzy
+msgid "The item is not a live row of this host."
+msgstr "Nenhuma tarefa ativa encontrada para o Host"
+
msgid "The key will be assigned to registered hosts when a"
msgstr ""
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -9725,12 +10252,21 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
msgid "The path requested is already in use by another image!"
msgstr ""
+msgid "The payload bytes."
+msgstr ""
+
#, fuzzy
msgid "The plugin directory"
msgstr "Diretório"
@@ -9775,6 +10311,13 @@ msgstr ""
msgid "The record could not be written."
msgstr "Não foi possível ler arquivo temporário"
+#, fuzzy
+msgid "The renewed certificate, leaf then chain."
+msgstr "Criar novo %s"
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -9784,6 +10327,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -9795,6 +10341,12 @@ msgstr "atualização da impressora falhou!"
msgid "The selected site no longer exists"
msgstr " não existe mais"
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -9814,6 +10366,13 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+#, fuzzy
+msgid "The signing helper is not available on this server."
+msgstr "Não existem grupos neste servidor."
+
#, fuzzy
msgid "The signing request could not be generated"
msgstr "Não foi possível ler arquivo temporário"
@@ -9834,6 +10393,10 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+#, fuzzy
+msgid "The token."
+msgstr "Contagem de CPU"
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -9995,6 +10558,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -10055,10 +10621,16 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, fuzzy, php-format
msgid "This machine already registered as %s"
msgstr "Já está registado como"
+msgid "This module has no settings to configure."
+msgstr ""
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -10167,6 +10739,13 @@ msgstr "Tempo já existe"
msgid "Time since last imaged"
msgstr ""
+#, fuzzy
+msgid "Timeout"
+msgstr "Tempo"
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -10189,9 +10768,31 @@ msgstr ""
msgid "Toggle navigation"
msgstr "Associação imagem"
+#, fuzzy
+msgid "Token Create Fail"
+msgstr "atualização da impressora falhou!"
+
+#, fuzzy
+msgid "Token Create Success"
+msgstr "Impressora já existe"
+
+#, fuzzy
+msgid "Token Revoke Fail"
+msgstr "Conexão FTP falhou"
+
+#, fuzzy
+msgid "Token Revoke Success"
+msgstr "Impressora já existe"
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
#, fuzzy
msgid "Too many MACs"
msgstr "Hospedeiro primário MAC"
@@ -10378,6 +10979,9 @@ msgstr "Nome de usuário"
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
#, fuzzy
msgid "Unauthenticated."
msgstr "servidor entrar em contato com erro"
@@ -10428,6 +11032,9 @@ msgstr "Ocorreu um erro de upload desconhecido. Código de retorno: "
msgid "Unknown action"
msgstr "Ocorreu um erro de upload desconhecido. Código de retorno: "
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -10458,6 +11065,9 @@ msgstr "Ocorreu um erro de upload desconhecido. Código de retorno: "
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
#, fuzzy
msgid "Unmark selected client ignore"
msgstr "Aprovar Hosts selecionados"
@@ -10547,6 +11157,9 @@ msgstr "Impressora"
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
#, fuzzy
msgid "Upload"
msgstr "carregar relatórios"
@@ -10659,9 +11272,6 @@ msgstr "Usuário já existe"
msgid "User Association"
msgstr "Associação imagem"
-msgid "User Cleanup"
-msgstr "Limpeza de usuário"
-
#, fuzzy
msgid "User Count"
msgstr "Contagem de CPU"
@@ -10747,6 +11357,10 @@ msgstr "Nome de usuário"
msgid "User Password"
msgstr "Senha do usuário"
+#, fuzzy
+msgid "User Sessions"
+msgstr "Associação imagem"
+
msgid "User Tracker"
msgstr "User tracker"
@@ -10829,6 +11443,12 @@ msgstr "usuários"
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr ""
@@ -10854,6 +11474,10 @@ msgstr "Versão"
msgid "Version information and paging bounds."
msgstr "FOG Informação da versão"
+#, fuzzy
+msgid "Version policy"
+msgstr "Versão"
+
#, fuzzy
msgid "Versions"
msgstr "Versão"
@@ -10883,6 +11507,9 @@ msgstr "Wake on LAN?"
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -10936,12 +11563,18 @@ msgstr "foi atualizado com sucesso"
msgid "What it does"
msgstr "foi atualizado com sucesso"
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -10957,6 +11590,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr ""
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -10969,10 +11605,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -11047,6 +11683,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr "Anual"
@@ -11169,6 +11808,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
#, fuzzy
msgid "access"
msgstr "Acesso"
@@ -11180,10 +11822,17 @@ msgstr "MACs adicionais"
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
#, fuzzy
msgid "ago"
msgstr " atrás"
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
#, fuzzy
msgid "all current storage nodes"
msgstr "nó de armazenamento inválido"
@@ -11217,6 +11866,13 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+#, fuzzy
+msgid "any version"
+msgstr "Versão"
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
#, fuzzy
msgid "architecture not recorded"
msgstr "Não foi possível ler arquivo temporário"
@@ -11228,6 +11884,10 @@ msgstr ""
msgid "as its primary group"
msgstr "Grupo primário de actualização"
+#, fuzzy
+msgid "assigned"
+msgstr "No nó associado"
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -11334,6 +11994,9 @@ msgstr "ativado"
msgid "does not exist and cannot be created"
msgstr "A imagem está protegida e não pode ser excluído"
+msgid "domain"
+msgstr ""
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -11343,6 +12006,9 @@ msgstr ""
msgid "either because you have updated"
msgstr ""
+msgid "empty means never install Chocolatey"
+msgstr ""
+
#, fuzzy
msgid "error"
msgstr "Erro"
@@ -11350,10 +12016,20 @@ msgstr "Erro"
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+#, fuzzy
+msgid "failed"
+msgstr "fracassado"
+
#, fuzzy
msgid "failed to execute, image file"
msgstr "Falha ao excluir arquivos de imagem"
@@ -11453,6 +12129,10 @@ msgstr ""
msgid "host"
msgstr "anfitrião"
+#, fuzzy, php-format
+msgid "host \"%s\""
+msgstr "anfitrião"
+
#, fuzzy
msgid "host is"
msgstr "anfitrião"
@@ -11568,9 +12248,6 @@ msgstr ""
msgid "in"
msgstr "minutos"
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
@@ -11578,9 +12255,6 @@ msgstr ""
msgid "in minutes"
msgstr "minutos"
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr ""
@@ -11655,6 +12329,10 @@ msgstr "DMI Key"
msgid "keys"
msgstr ""
+#, fuzzy
+msgid "latest"
+msgstr "Replicar?"
+
msgid "leave to keep the current one"
msgstr ""
@@ -11688,6 +12366,10 @@ msgstr "minutos"
msgid "mismatched"
msgstr ""
+#, fuzzy
+msgid "missing"
+msgstr "Versão"
+
msgid "moments from now"
msgstr ""
@@ -11725,6 +12407,10 @@ msgstr ""
msgid "never"
msgstr ""
+#, fuzzy
+msgid "never reported"
+msgstr "Inventário"
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -11757,6 +12443,9 @@ msgstr ""
msgid "not found on this node"
msgstr "Imagem não encontrada no nó"
+msgid "not joined"
+msgstr ""
+
#, fuzzy
msgid "not reachable"
msgstr "Não disponível"
@@ -11787,10 +12476,16 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+msgid "off"
+msgstr ""
+
#, fuzzy
msgid "off means an account must already exist"
msgstr "Impressora já existe"
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -11804,6 +12499,9 @@ msgstr ""
msgid "optional"
msgstr "Localização"
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
msgid "or"
msgstr "ou"
@@ -12081,6 +12779,10 @@ msgstr "Não disponível"
msgid "unchanged for"
msgstr "fotografada"
+#, fuzzy
+msgid "unknown action"
+msgstr "Ocorreu um erro de upload desconhecido. Código de retorno: "
+
msgid "unrecorded"
msgstr ""
@@ -12308,6 +13010,10 @@ msgstr ""
#~ msgid "CA private key"
#~ msgstr "chave privada falhou"
+#, fuzzy
+#~ msgid "Cannot connect to ftp server"
+#~ msgstr "Não é possível conectar ao banco de dados"
+
#~ msgid "Check that database is running"
#~ msgstr "Verifique o banco de dados está em execução"
@@ -12315,6 +13021,10 @@ msgstr ""
#~ msgid "Client Module Settings"
#~ msgstr "Configurações"
+#, fuzzy
+#~ msgid "Could not read snapin file"
+#~ msgstr "Não foi possível ler o arquivo tmp."
+
#, fuzzy
#~ msgid "Create New Accesscontrol"
#~ msgstr "Criar novo %s"
@@ -12339,6 +13049,15 @@ msgstr ""
#~ msgid "Database connection unavailable"
#~ msgstr "Nenhum de hash disponíveis"
+#~ msgid "Default Height"
+#~ msgstr "padrão Altura"
+
+#~ msgid "Default Refresh Rate"
+#~ msgstr "Padrão Refresh Rate"
+
+#~ msgid "Default Width"
+#~ msgstr "Largura padrão"
+
#, fuzzy
#~ msgid "Delete All"
#~ msgstr "Apagar dados de arquivo"
@@ -12347,6 +13066,9 @@ msgstr ""
#~ msgid "Deprecated."
#~ msgstr "Crio"
+#~ msgid "Directory Cleaner"
+#~ msgstr "Cleaner diretório"
+
#, fuzzy
#~ msgid "Domain joining"
#~ msgstr "Nome do domínio"
@@ -12409,6 +13131,18 @@ msgstr ""
#~ msgid "Export Users"
#~ msgstr "Usuários de exportação"
+#, fuzzy
+#~ msgid "FOG Agent desired state"
+#~ msgstr "foi atualizado com sucesso"
+
+#, fuzzy
+#~ msgid "FOG Agent snapin result"
+#~ msgstr "Nenhum arquivo foi transferido"
+
+#, fuzzy
+#~ msgid "FOG Agent software result"
+#~ msgstr "Nenhum arquivo foi transferido"
+
#~ msgid "Failed to add/update snapin file"
#~ msgstr "Falha ao adicionar arquivo de snap-in / atualização"
@@ -12520,10 +13254,18 @@ msgstr ""
#~ msgid "Group module settings"
#~ msgstr "anfitrião Descrição"
+#, fuzzy
+#~ msgid "Height"
+#~ msgstr "meia-noite"
+
#, fuzzy
#~ msgid "History Report"
#~ msgstr "ID de acolhimento"
+#, fuzzy
+#~ msgid "Host Display Manager Settings"
+#~ msgstr "Configurações"
+
#, fuzzy
#~ msgid "Host Ext"
#~ msgstr "Lista de Host"
@@ -12540,6 +13282,10 @@ msgstr ""
#~ msgid "Host Ext Variable"
#~ msgstr "atualização do utilizador falhou"
+#, fuzzy
+#~ msgid "Host Screen Resolution"
+#~ msgstr "Registro de acolhimento"
+
#, fuzzy
#~ msgid "Host Site"
#~ msgstr "Lista de Host"
@@ -12643,6 +13389,9 @@ msgstr ""
#~ msgid "Install"
#~ msgstr "Plugins instalados"
+#~ msgid "Invalid Storage Node"
+#~ msgstr "Inválida Storage Node"
+
#, fuzzy
#~ msgid "Invalid Type"
#~ msgstr "tipo inválido"
@@ -12666,6 +13415,14 @@ msgstr ""
#~ msgid "LDAP User Filter"
#~ msgstr "Servidor LDAP"
+#, fuzzy
+#~ msgid "Last Activity"
+#~ msgstr "Ativo"
+
+#, fuzzy
+#~ msgid "Last Event"
+#~ msgstr "host criado"
+
#, fuzzy
#~ msgid "Latest SVN Version"
#~ msgstr "Última versão"
@@ -12724,6 +13481,14 @@ msgstr ""
#~ msgid "Not Installed"
#~ msgstr "Plugins instalados"
+#, fuzzy
+#~ msgid "Not a live task of this host's job."
+#~ msgstr "Nenhuma tarefa ativa encontrada para o Host"
+
+#, fuzzy
+#~ msgid "Not an entry in this host's software set."
+#~ msgstr "Nenhuma tarefa ativa encontrada para o Host"
+
#, fuzzy
#~ msgid "Pause"
#~ msgstr "Do utilizador"
@@ -12751,6 +13516,14 @@ msgstr ""
#~ msgid "Product Keys"
#~ msgstr "Hospedar de Chave de Produto"
+#, fuzzy
+#~ msgid "Recorded."
+#~ msgstr "Registros atuais"
+
+#, fuzzy
+#~ msgid "Refresh"
+#~ msgstr "Padrão Refresh Rate"
+
#, fuzzy
#~ msgid "Release Version"
#~ msgstr "Última versão"
@@ -12817,6 +13590,10 @@ msgstr ""
#~ msgid "Rule update failed!"
#~ msgstr "atualização da impressora falhou!"
+#, fuzzy
+#~ msgid "Screen Refresh Rate"
+#~ msgstr "Padrão Refresh Rate"
+
#, fuzzy
#~ msgid "Serial"
#~ msgstr "Serial sistema"
@@ -12858,8 +13635,16 @@ msgstr ""
#~ msgstr "Impressora já existe"
#, fuzzy
-#~ msgid "The certificate chain"
-#~ msgstr "Criar novo %s"
+#~ msgid "The desired state."
+#~ msgstr "Falha ao criar tarefa"
+
+#, fuzzy
+#~ msgid "The host this certificate is, and the capabilities this server offers."
+#~ msgstr "Não existem grupos neste servidor."
+
+#, fuzzy
+#~ msgid "The task was already closed."
+#~ msgstr "Impressora já existe"
#, fuzzy
#~ msgid "There are no "
@@ -12904,6 +13689,10 @@ msgstr ""
#~ msgid "Unable to set user filter."
#~ msgstr "Não é possível abrir arquivo para leitura"
+#, fuzzy
+#~ msgid "Unknown status."
+#~ msgstr "Ocorreu um erro de upload desconhecido. Código de retorno: "
+
#, fuzzy
#~ msgid "Update Master Node"
#~ msgstr "Nó mestre"
@@ -12916,6 +13705,9 @@ msgstr ""
#~ msgid "Update/Remove printers"
#~ msgstr "Remover impressoras selecionadas"
+#~ msgid "User Cleanup"
+#~ msgstr "Limpeza de usuário"
+
#, fuzzy
#~ msgid "User Group Site"
#~ msgstr "exportação Snapins"
@@ -13002,10 +13794,6 @@ msgstr ""
#~ msgid "min (all)"
#~ msgstr "ativado"
-#, fuzzy
-#~ msgid "multicast tasks!"
-#~ msgstr "Tarefas Multicast ativos"
-
#, fuzzy
#~ msgid "no database to"
#~ msgstr "Nenhum banco de dados para trabalhar fora"
@@ -13021,7 +13809,3 @@ msgstr ""
#, fuzzy
#~ msgid "username"
#~ msgstr "Nome de usuário"
-
-#, fuzzy
-#~ msgid "version"
-#~ msgstr "Versão"
diff --git a/packages/web/management/languages/zh_CN.UTF-8/LC_MESSAGES/messages.po b/packages/web/management/languages/zh_CN.UTF-8/LC_MESSAGES/messages.po
index bae7494026..84656bac7f 100644
--- a/packages/web/management/languages/zh_CN.UTF-8/LC_MESSAGES/messages.po
+++ b/packages/web/management/languages/zh_CN.UTF-8/LC_MESSAGES/messages.po
@@ -125,6 +125,10 @@ msgid_plural "%d days left"
msgstr[0] ""
msgstr[1] ""
+#, php-format
+msgid "%d decided, %d not: %s"
+msgstr ""
+
#, php-format
msgid "%d host(s) are assigned an image they cannot run"
msgstr ""
@@ -294,6 +298,10 @@ msgstr ""
msgid "(all)"
msgstr ""
+#, fuzzy, php-format
+msgid "(deleted host %d)"
+msgstr "批准选定主机"
+
msgid "(deleted user)"
msgstr ""
@@ -313,9 +321,15 @@ msgstr ""
msgid ", Arguments = %s"
msgstr "内核参数"
+msgid "0 checks only when the assigned set changes"
+msgstr ""
+
msgid "0 is a normal snapin, 1 a snapin pack the client extracts before running."
msgstr ""
+msgid "0 logs the user out with no warning"
+msgstr ""
+
#, fuzzy
msgid "1 Hour"
msgstr "1小时"
@@ -420,6 +434,12 @@ msgstr "图像已经存在具有此名称!"
msgid "A client ID is required"
msgstr "图像名是必需的!"
+msgid "A denied agent keeps asking and keeps being refused until it is enrolled with a new key."
+msgstr ""
+
+msgid "A disabled entry stops being managed; it does not remove the package."
+msgstr ""
+
#, fuzzy
msgid "A dmi field must be set!"
msgstr "事件必须是字符串"
@@ -483,6 +503,9 @@ msgstr "图像已经存在具有此名称!"
msgid "A migration step failed. The plugin is left activated and not marked installed."
msgstr ""
+msgid "A missing name, a bad use count, or an expiry that is not in the future."
+msgstr ""
+
#, fuzzy
msgid "A module already exists with this name!"
msgstr "图像已经存在具有此名称!"
@@ -504,6 +527,9 @@ msgstr "列表中的所有%s"
msgid "A permission name is required."
msgstr "图像名是必需的!"
+msgid "A pinned entry needs a version."
+msgstr ""
+
msgid "A plugin is PHP that runs on this server. Only upload one you trust. Nothing is installed until you have seen what the archive contains and confirmed it."
msgstr ""
@@ -526,6 +552,9 @@ msgstr "图像已经存在具有此名称!"
msgid "A request is pending since %s for %s."
msgstr ""
+msgid "A revoked token can never approve an enrollment again."
+msgstr ""
+
#, fuzzy
msgid "A role already exists with this name!"
msgstr "图像已经存在具有此名称!"
@@ -567,6 +596,10 @@ msgstr "图像已经存在具有此名称!"
msgid "A snapin granted here reaches every host in this group, including hosts added later. Granting a snapin does not run it; deploy it from the Tasks tab when you want it to run."
msgstr ""
+#, fuzzy
+msgid "A software entry already exists with this name!"
+msgstr "图像已经存在具有此名称!"
+
#, fuzzy
msgid "A storage group already exists with this name!"
msgstr "图像已经存在具有此名称!"
@@ -702,6 +735,12 @@ msgstr ""
msgid "Aborted due to failure of \"%s\" with exit code %s"
msgstr ""
+msgid "Absent"
+msgstr ""
+
+msgid "Absent removes the package if it is installed."
+msgstr ""
+
msgid "Accepts the same optional filter as a list. Reports the true filtered total and ignores paging."
msgstr ""
@@ -932,6 +971,10 @@ msgstr "添加管理单元失败!"
msgid "Add snapin failed!"
msgstr "添加管理单元失败!"
+#, fuzzy
+msgid "Add software failed!"
+msgstr "添加管理单元失败!"
+
#, fuzzy
msgid "Add storage node failed!"
msgstr "添加管理单元失败!"
@@ -1016,6 +1059,33 @@ msgstr "高级"
msgid "Advanced Tasks"
msgstr "高级"
+msgid "Agent"
+msgstr ""
+
+#, fuzzy
+msgid "Agent Activity"
+msgstr "活性"
+
+#, fuzzy
+msgid "Agent Approval Success"
+msgstr "主机创建"
+
+#, fuzzy
+msgid "Agent Denial Success"
+msgstr "打印机更新!"
+
+#, fuzzy
+msgid "Agent Enrollment Tokens"
+msgstr "已成功更新"
+
+#, fuzzy
+msgid "Agent Tokens"
+msgstr "访问令牌"
+
+#, fuzzy
+msgid "Agent enrollment tokens"
+msgstr "已成功更新"
+
msgid "Ago must be boolean"
msgstr ""
@@ -1032,6 +1102,10 @@ msgstr ""
msgid "All Hosts"
msgstr "所有主机"
+#, fuzzy
+msgid "All Pending Agents"
+msgstr "待定的MAC"
+
#, fuzzy
msgid "All Pending Hosts"
msgstr "待主机"
@@ -1135,10 +1209,16 @@ msgstr ""
msgid "An SQL error occurred"
msgstr "发生未知上传错误。返回代码:"
+msgid "An enrollment token, if the installer was given one."
+msgstr ""
+
#, fuzzy
msgid "An entry already exists with this name!"
msgstr "图像已经存在具有此名称!"
+msgid "An expiry is required. The token approves enrollments until it is spent or expires; revoke it here at any time."
+msgstr ""
+
msgid "An image already exists with this name!"
msgstr "图像已经存在具有此名称!"
@@ -1178,6 +1258,10 @@ msgstr ""
msgid "Answers an empty value when the key has never been set, rather than 404 -- \"no opinion\" is a normal answer here, not a missing resource."
msgstr ""
+#, fuzzy
+msgid "Any version"
+msgstr "版"
+
msgid "Anyone signing in through one of these directory groups is placed in this user group. Membership granted this way is recomputed on every sign in."
msgstr ""
@@ -1216,18 +1300,36 @@ msgstr ""
msgid "Approve"
msgstr "主机批准"
+#, fuzzy
+msgid "Approve Agent Fail"
+msgstr "主机批准"
+
#, fuzzy
msgid "Approve MAC Fail"
msgstr "主机批准"
+#, fuzzy
+msgid "Approve Pending Agents"
+msgstr "待主机"
+
#, fuzzy
msgid "Approve Pending Hosts"
msgstr "待主机"
+msgid "Approve or deny an agent enrollment"
+msgstr ""
+
#, fuzzy
msgid "Approve selected"
msgstr "批准选定主机"
+msgid "Approved but the signer is unavailable; the agent retries."
+msgstr ""
+
+#, fuzzy
+msgid "Approved selected agents!"
+msgstr "批准选定主机"
+
#, fuzzy
msgid "Approved selected hosts!"
msgstr "批准选定主机"
@@ -1240,6 +1342,9 @@ msgstr "批准选定主机"
msgid "Approving the selected pending hosts."
msgstr "批准选定主机"
+msgid "Arch"
+msgstr ""
+
msgid "Architecture"
msgstr ""
@@ -1249,6 +1354,10 @@ msgstr ""
msgid "Area"
msgstr ""
+#, fuzzy
+msgid "Assigned"
+msgstr "无关联的节点"
+
#, fuzzy
msgid "Assigned Group"
msgstr "存储组名称"
@@ -1311,6 +1420,9 @@ msgstr ""
msgid "Authenticated but not permitted."
msgstr ""
+msgid "Authenticated by the client certificate enrollment issued, verified by the web server and bound to the host by its key fingerprint before the route runs; no token or session applies. Records the check-in and answers with the revision of the host's desired state, plus the state itself when the applied revision the agent sent is not current or it asked for it. The revision is opaque: compared for equality, never parsed. A certificate that no longer binds to a live host gets 401, which tells the agent to enroll again. The request may also carry facts about the host -- hardware inventory, the installed-program list -- sent only when their content hash moved or the answer asked; the same conditional as the state, run in the other direction."
+msgstr ""
+
msgid "Authentication missing or invalid."
msgstr ""
@@ -1349,6 +1461,9 @@ msgstr "BIOS供应商"
msgid "BIOS Version"
msgstr "BIOS版本"
+msgid "Backend"
+msgstr ""
+
#, fuzzy
msgid "Bad request."
msgstr "%s是必需的"
@@ -1582,6 +1697,10 @@ msgstr "取消任务"
msgid "Canceled due to new tasking."
msgstr "由于新的任务取消。"
+#, fuzzy
+msgid "Cannot Run"
+msgstr "未发现记录,错误: %s"
+
#, fuzzy
msgid "Cannot bind to the LDAP server"
msgstr "无法连接到数据库"
@@ -1596,10 +1715,6 @@ msgstr "无法连接到节点。"
msgid "Cannot connect to database"
msgstr "无法连接到数据库"
-#, fuzzy
-msgid "Cannot connect to ftp server"
-msgstr "无法连接到数据库"
-
#, php-format
msgid "Cannot delete %1$s because a %2$s still refers to it. Reassign or remove it first."
msgstr ""
@@ -1796,6 +1911,9 @@ msgstr "没有FOGPage类中找到此节点"
msgid "Check this value against what the enrollment tool shows before confirming, whether the certificate reached the client on a USB stick or over the network. That comparison is what stops the wrong key being trusted."
msgstr ""
+msgid "Checked"
+msgstr ""
+
msgid "Checking for expired checked-in tasks..."
msgstr ""
@@ -1808,6 +1926,12 @@ msgstr ""
msgid "Chocolatey (offline source)"
msgstr ""
+msgid "Chocolatey Install Script"
+msgstr ""
+
+msgid "Chocolatey Package Source"
+msgstr ""
+
msgid "Choose a user"
msgstr ""
@@ -1979,14 +2103,23 @@ msgstr "错误:无法下载内核"
msgid "Confirm you would like to download a new kernel"
msgstr "错误:无法下载内核"
+msgid "Converged"
+msgstr ""
+
#, php-format
msgid "Converted %1$d `0` reference(s) to NULL across %2$d column(s)"
msgstr ""
+msgid "Copy"
+msgstr ""
+
#, fuzzy
msgid "Copy from existing"
msgstr "无法创建打印机"
+msgid "Copy it now. It is not stored and cannot be shown again."
+msgstr ""
+
msgid "Copy this token now"
msgstr ""
@@ -2060,10 +2193,6 @@ msgstr "无法读取tmp文件。"
msgid "Could not read local file"
msgstr "无法读取临时文件"
-#, fuzzy
-msgid "Could not read snapin file"
-msgstr "无法读取tmp文件。"
-
#, fuzzy
msgid "Could not read the database structure"
msgstr "无法创建管理单元工作"
@@ -2160,6 +2289,9 @@ msgstr ""
msgid "Create"
msgstr "创建"
+msgid "Create Enrollment Token"
+msgstr ""
+
msgid "Create Immediate Power task"
msgstr ""
@@ -2242,6 +2374,10 @@ msgstr "新建分钟"
msgid "Create New Snapin"
msgstr "新建管理单元"
+#, fuzzy
+msgid "Create New Software"
+msgstr "新建分钟"
+
msgid "Create New Storage Group"
msgstr "新建Storage Group"
@@ -2289,6 +2425,10 @@ msgstr "用户创建"
msgid "Create Users On First Login"
msgstr ""
+#, fuzzy, php-format
+msgid "Create a %1$s task for %2$s?"
+msgstr "用户创建"
+
#, fuzzy, php-format
msgid "Create a %s"
msgstr "新建%s"
@@ -2312,9 +2452,17 @@ msgstr "用户创建"
msgid "Create task form success"
msgstr "用户创建"
+#, fuzzy
+msgid "Create tasking"
+msgstr "新建%s"
+
msgid "Create tasking succeeded"
msgstr ""
+#, fuzzy
+msgid "Create token"
+msgstr "新建%s"
+
#, fuzzy
msgid "Created"
msgstr "创建"
@@ -2326,6 +2474,10 @@ msgstr "由...制作"
msgid "Created Time"
msgstr "由...制作"
+#, fuzzy
+msgid "Created by"
+msgstr "由...制作"
+
msgid "Created by FOG Reg on"
msgstr "创建者FOG上注册"
@@ -2454,6 +2606,9 @@ msgstr "调试选项"
msgid "Debug Task"
msgstr "调试"
+msgid "Decided."
+msgstr ""
+
msgid "Default"
msgstr "默认"
@@ -2461,15 +2616,6 @@ msgstr "默认"
msgid "Default Choice"
msgstr "默认项:"
-msgid "Default Height"
-msgstr "默认高度"
-
-msgid "Default Refresh Rate"
-msgstr "默认刷新频率"
-
-msgid "Default Width"
-msgstr "默认宽度"
-
#, fuzzy
msgid "Default init, ARM64"
msgstr "默认宽度"
@@ -2554,6 +2700,28 @@ msgstr ""
msgid "Deleting remote file"
msgstr "菜单创建失败"
+msgid "Denied by an admin. The agent backs off to hourly."
+msgstr ""
+
+#, fuzzy
+msgid "Denied selected agents!"
+msgstr "批准选定主机"
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy
+msgid "Deny Agent Fail"
+msgstr "删除的文件数据"
+
+#, fuzzy
+msgid "Deny Pending Agents"
+msgstr "待定的MAC"
+
+#, fuzzy
+msgid "Deny selected"
+msgstr "删除所选"
+
msgid "Deploy"
msgstr "部署"
@@ -2570,14 +2738,30 @@ msgstr ""
msgid "Description"
msgstr "描述"
+msgid "Desired"
+msgstr ""
+
+msgid "Desired OU"
+msgstr ""
+
+msgid "Desired domain"
+msgstr ""
+
#, fuzzy
msgid "Destroy failed"
msgstr "摧毁失败: %s"
+#, fuzzy
+msgid "Detail"
+msgstr "管理单元返回详细"
+
#, fuzzy
msgid "Details"
msgstr "管理单元返回详细"
+msgid "Device URI"
+msgstr ""
+
#, fuzzy
msgid "Device must be a string"
msgstr "事件必须是字符串"
@@ -2591,9 +2775,6 @@ msgstr "目录"
msgid "Directory Already Exists"
msgstr "目录已经存在"
-msgid "Directory Cleaner"
-msgstr "目录清洁"
-
#, fuzzy
msgid "Directory Group"
msgstr "目录"
@@ -2602,6 +2783,10 @@ msgstr "目录"
msgid "Directory Group Name"
msgstr "目录"
+#, fuzzy
+msgid "Directory Membership"
+msgstr "籍"
+
#, fuzzy
msgid "Disable on all hosts"
msgstr "启用"
@@ -2718,6 +2903,9 @@ msgstr "下载失败"
msgid "Downloaded file is not a bootable kernel image"
msgstr ""
+msgid "Drift"
+msgstr ""
+
#, php-format
msgid "Drop %s and %s into %s and FOG adopts them -- no setting to edit. Add %s as well if your CA issued intermediates. The installer does the same thing on its next run, so this button only saves you the wait."
msgstr ""
@@ -2737,6 +2925,9 @@ msgstr ""
msgid "Each of these is a public certificate. Downloading one is how you add this server to another machine's trust store, hand an auditor the chain, or check what a client is actually being offered; the SHA-256 is what to compare against a client's trust store when working out why one stopped authenticating. Private keys are deliberately absent -- nothing on this page can read one, and nothing on it can hand one out."
msgstr ""
+msgid "Each selected agent is issued a certificate and collects it on its next check-in."
+msgstr ""
+
msgid "Edit"
msgstr "编辑"
@@ -2832,6 +3023,10 @@ msgstr ""
msgid "Enrolled certificate must be a SHA-256 fingerprint (64 hex characters)"
msgstr ""
+#, fuzzy
+msgid "Enrollment Token"
+msgstr "Pushbullet账户"
+
msgid "Enrollment kit"
msgstr ""
@@ -2935,6 +3130,12 @@ msgstr ""
msgid "Every configured multicast port is already in use"
msgstr ""
+msgid "Every enrollment still waiting for a decision, without the CSR. What the Pending Agents page reads."
+msgstr ""
+
+msgid "Every enrollment token with its remaining uses and expiry, never the token itself. What the Agent Tokens page reads."
+msgstr ""
+
#, fuzzy
msgid "Every file was uploaded."
msgstr "没有文件被上传"
@@ -2955,6 +3156,14 @@ msgstr "私钥失败"
msgid "Exists item must be boolean"
msgstr ""
+#, fuzzy
+msgid "Exit Code"
+msgstr "出口Snapins"
+
+#, fuzzy
+msgid "Exit code"
+msgstr "返回代码"
+
msgid "Expand - walk the chain (any directory)"
msgstr ""
@@ -3034,9 +3243,32 @@ msgstr "日期"
msgid "External root CA"
msgstr ""
+#, fuzzy
+msgid "Extra arguments"
+msgstr "管理单元运行带有参数"
+
msgid "FOG"
msgstr "雾"
+#, fuzzy
+msgid "FOG Agent capability result"
+msgstr "没有文件被上传"
+
+#, fuzzy
+msgid "FOG Agent certificate renewal"
+msgstr "没有文件被上传"
+
+#, fuzzy
+msgid "FOG Agent enrollment"
+msgstr "已成功更新"
+
+#, fuzzy
+msgid "FOG Agent payload"
+msgstr "没有文件被上传"
+
+msgid "FOG Agent poll"
+msgstr ""
+
#, fuzzy
msgid "FOG Client"
msgstr "FOG客户维基"
@@ -3395,6 +3627,9 @@ msgstr "任务开始"
msgid "First Check In"
msgstr ""
+msgid "First Seen"
+msgstr ""
+
msgid "First row is a header"
msgstr ""
@@ -3738,6 +3973,10 @@ msgstr "历史管理单元"
msgid "Group Snapin History"
msgstr "历史管理单元"
+#, fuzzy
+msgid "Group Software Assignment"
+msgstr "历史管理单元"
+
#, fuzzy
msgid "Group Task History"
msgstr "历史形象"
@@ -3826,9 +4065,15 @@ msgstr "硬件信息"
msgid "Hardware Report"
msgstr "硬件信息"
+msgid "Hardware facts, sent only when the agent's own content hash for them moved or the server asked. Absent means nothing new, never nothing there."
+msgstr ""
+
msgid "Hash"
msgstr ""
+msgid "Hash Mismatch"
+msgstr ""
+
msgid "Have not locked the host for access"
msgstr ""
@@ -3836,10 +4081,6 @@ msgstr ""
msgid "Header is missing the required \"%s\" column"
msgstr ""
-#, fuzzy
-msgid "Height"
-msgstr "午夜"
-
msgid "Height must be 120 pixels."
msgstr ""
@@ -3912,6 +4153,9 @@ msgstr "打印机已经存在"
msgid "Host %1$s finished deploying image %2$s."
msgstr "打印机已经存在"
+msgid "Host Agent Activity"
+msgstr ""
+
#, fuzzy
msgid "Host Approval Success"
msgstr "主机创建"
@@ -3947,10 +4191,6 @@ msgstr "默认项:"
msgid "Host Description"
msgstr "主机描述"
-#, fuzzy
-msgid "Host Display Manager Settings"
-msgstr "设置"
-
msgid "Host EFI Exit Type"
msgstr "主持人EFI退出类型"
@@ -4055,10 +4295,6 @@ msgstr "主机产品密钥"
msgid "Host Registration"
msgstr "主机注册"
-#, fuzzy
-msgid "Host Screen Resolution"
-msgstr "主机注册"
-
#, fuzzy
msgid "Host Snapin Associations"
msgstr "无关联的节点"
@@ -4067,6 +4303,13 @@ msgstr "无关联的节点"
msgid "Host Snapin History"
msgstr "历史管理单元"
+#, fuzzy
+msgid "Host Software Assignment"
+msgstr "历史管理单元"
+
+msgid "Host Software Status"
+msgstr ""
+
#, fuzzy
msgid "Host Task History"
msgstr "历史形象"
@@ -4160,6 +4403,12 @@ msgstr "主机列表"
msgid "Hosts registered per day"
msgstr ""
+msgid "Hosts set to use Active Directory, with what each one last reported about itself. An OU difference is not corrected by the legacy client, which only reads the OU when it first joins the machine."
+msgstr ""
+
+msgid "Hosts with printer management switched on, with what each one last reported about itself. A printer in Missing was assigned and is not on the machine."
+msgstr ""
+
#, fuzzy
msgid "Hosts:"
msgstr "主机"
@@ -4224,6 +4473,10 @@ msgstr ""
msgid "Id of the storage group whose master receives the file."
msgstr ""
+#, fuzzy
+msgid "Identity"
+msgstr "服务器外壳"
+
msgid "Identity Provider"
msgstr ""
@@ -4739,6 +4992,10 @@ msgstr "已安装的插件"
msgid "Installed Plugins"
msgstr "已安装的插件"
+#, fuzzy
+msgid "Installed Software"
+msgstr "已安装的插件"
+
msgid "Intel 32 Bit"
msgstr ""
@@ -4825,9 +5082,6 @@ msgstr "无效的管理单元任务处理"
msgid "Invalid Storage Group"
msgstr "无效的存储组"
-msgid "Invalid Storage Node"
-msgstr "无效的存储节点"
-
#, fuzzy
msgid "Invalid Tasking"
msgstr "任务无效"
@@ -5011,6 +5265,9 @@ msgstr ""
msgid "Issued by %s"
msgstr ""
+msgid "Issued. The certificate and the host it binds to."
+msgstr ""
+
msgid "Issuer"
msgstr ""
@@ -5036,6 +5293,9 @@ msgstr ""
msgid "It will operate based on the fields the area typcially requires."
msgstr ""
+msgid "Join"
+msgstr ""
+
msgid "Join Domain after image task"
msgstr ""
@@ -5237,6 +5497,9 @@ msgstr "语言"
msgid "Largest images"
msgstr "图片"
+msgid "Last Agent Check-In"
+msgstr ""
+
#, fuzzy
msgid "Last Captured"
msgstr "主机创建"
@@ -5247,15 +5510,16 @@ msgstr ""
msgid "Last Check-In"
msgstr ""
-msgid "Last Client Check-In"
-msgstr ""
-
msgid "Last Deployed"
msgstr "最后部署"
msgid "Last Ping"
msgstr ""
+#, fuzzy
+msgid "Last Seen"
+msgstr "主机创建"
+
#, fuzzy
msgid "Last Successful Ping"
msgstr "成功"
@@ -5271,6 +5535,10 @@ msgstr ""
msgid "Last deployed"
msgstr "最后部署"
+#, fuzzy
+msgid "Last error"
+msgstr "错误"
+
msgid "Last flush"
msgstr ""
@@ -5278,6 +5546,9 @@ msgstr ""
msgid "Last imaged"
msgstr "图片"
+msgid "Latest (upgrade at each check)"
+msgstr ""
+
#, fuzzy
msgid "Latest Alpha Version"
msgstr "最新版本"
@@ -5402,6 +5673,10 @@ msgstr "列表中的所有分钟s"
msgid "List All Snapins"
msgstr "列表中的所有管理单元s"
+#, fuzzy
+msgid "List All Software"
+msgstr "列表中的所有分钟s"
+
msgid "List All Storage Groups"
msgstr "列表中的所有Storage Groups"
@@ -5538,6 +5813,9 @@ msgstr "日志查看器"
msgid "Log out and sign in as an administrator"
msgstr ""
+msgid "Logged on"
+msgstr ""
+
msgid "Logging"
msgstr ""
@@ -5730,6 +6008,9 @@ msgstr "最大尺寸"
msgid "Maximum rows per class; 0 or absent means no cap."
msgstr ""
+msgid "May be sent with Content-Encoding: gzip; a host's software list is a few hundred KB of JSON and about a tenth of that compressed."
+msgstr ""
+
#, fuzzy
msgid "Member"
msgstr "会员"
@@ -5810,6 +6091,10 @@ msgstr "午夜"
msgid "Minimum time limit for Auto Logout to become active is 5 minutes."
msgstr ""
+#, fuzzy
+msgid "Mint an agent enrollment token"
+msgstr "待注册主机"
+
msgid "Minute value is not valid"
msgstr "分钟值无效"
@@ -5817,7 +6102,10 @@ msgstr "分钟值无效"
msgid "Minutes field is invalid"
msgstr "分钟值无效"
-msgid "Missing a temporary folder"
+msgid "Missing"
+msgstr ""
+
+msgid "Missing a temporary folder"
msgstr "缺少一个临时文件夹"
#, fuzzy
@@ -6285,6 +6573,10 @@ msgstr "没有开口槽"
msgid "No password is needed. Issue this account a token from its API tab, or from FOG Configuration → API Tokens, once it has been created."
msgstr ""
+#, fuzzy
+msgid "No payloads for the capability, or not a live row of this host."
+msgstr "发现主机没有活动任务"
+
#, fuzzy
msgid "No plugin tasks to run"
msgstr "发送无有效类"
@@ -6339,6 +6631,10 @@ msgstr "更新管理单元"
msgid "No snapins associated with this group as master"
msgstr "没有与此主机关联snapins"
+#, fuzzy
+msgid "No storage node can serve the file."
+msgstr "添加管理单元失败!"
+
#, fuzzy
msgid "No storage nodes assigned to this storage group"
msgstr "找不到存储节点是否有什么这个存储组中启用"
@@ -6351,6 +6647,9 @@ msgstr "图像已经存在具有此名称!"
msgid "No storagegroups assigned to this snapin"
msgstr "分配图像存储组无效"
+msgid "No such enrollment, or no such action."
+msgstr ""
+
msgid "No such file in the boot directory."
msgstr ""
@@ -6360,6 +6659,9 @@ msgstr ""
msgid "No such object."
msgstr ""
+msgid "No such token."
+msgstr ""
+
msgid "No such user."
msgstr ""
@@ -6395,6 +6697,9 @@ msgstr ""
msgid "No values passed"
msgstr "没有值传递"
+msgid "No verified client certificate, or one bound to no live host."
+msgstr ""
+
#, fuzzy
msgid "No viable macs to use"
msgstr "不能够更新"
@@ -6450,6 +6755,9 @@ msgstr "图标文件未找到"
msgid "Not Registered Hosts"
msgstr "未注册主机"
+msgid "Not a certificate request, or one for a key other than the one this certificate proved."
+msgstr ""
+
msgid "Not a number"
msgstr "不是一个数字"
@@ -6586,6 +6894,13 @@ msgstr "用户更新"
msgid "OUs"
msgstr ""
+msgid "Observed OU"
+msgstr ""
+
+#, fuzzy
+msgid "Observed domain"
+msgstr "一般信息"
+
msgid "Off"
msgstr ""
@@ -6642,6 +6957,12 @@ msgstr ""
msgid "One or more macs are associated with a host"
msgstr "错误,与此主机关联的图像"
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again at the next check), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
+msgid "One per line, code=class. Classes: success, reboot (installed, reboot to finish), retry (try again next check-in), failed. Empty uses the defaults shown; any code not listed is failed. The defaults are Windows codes: Linux and macOS keep only the low 8 bits of an exit status, so list the code the program can return."
+msgstr ""
+
msgid "One preference."
msgstr ""
@@ -6725,6 +7046,12 @@ msgstr ""
msgid "Operations on %s."
msgstr "操作字段没有设置: %s"
+msgid "Optional. A feed URL, folder or share passed to the package manager as --source. Leave empty for the manager's own configured sources."
+msgstr ""
+
+msgid "Optional. Leave empty to derive it from the type and address above. Examples:"
+msgstr ""
+
msgid "Optional. Pick a type to pre-fill the command fields below; you can still edit them afterward. The Chocolatey entry expects the uploaded file to be a Chocolatey packages.config naming the packages to install."
msgstr ""
@@ -6770,9 +7097,15 @@ msgstr ""
msgid "Over a year"
msgstr ""
+msgid "Over the certificate being renewed: the same gate as poll binds the caller to its host, and the body carries a request for the same key. The answer is the enroll \"issued\" shape. A request for any other key is refused; a key change goes through enroll and an admin."
+msgstr ""
+
msgid "PLUGIN OPTIONS"
msgstr ""
+msgid "Package"
+msgstr ""
+
msgid "Page node is not registered as a permission node"
msgstr ""
@@ -6854,6 +7187,10 @@ msgstr ""
msgid "Pending"
msgstr "待..."
+#, fuzzy
+msgid "Pending Agents"
+msgstr "待定的MAC"
+
msgid "Pending Hosts"
msgstr "待主机"
@@ -6871,9 +7208,31 @@ msgstr "待定的MAC"
msgid "Pending Registered Hosts"
msgstr "待注册主机"
+#, fuzzy
+msgid "Pending Registration created by FOG_AGENT"
+msgstr "通过创建FOG_CLIENT登记待定"
+
msgid "Pending Registration created by FOG_CLIENT"
msgstr "通过创建FOG_CLIENT登记待定"
+#, fuzzy
+msgid "Pending agent"
+msgstr "待主机"
+
+#, fuzzy
+msgid "Pending agent enrollments"
+msgstr "待注册主机"
+
+#, fuzzy
+msgid "Pending agents"
+msgstr "待淅淅沥沥"
+
+msgid "Pending an admin decision. Poll again after retry_after seconds."
+msgstr ""
+
+msgid "Pending enrollment rows."
+msgstr ""
+
#, fuzzy
msgid "Pending host"
msgstr "待主机"
@@ -6920,6 +7279,16 @@ msgstr "状态"
msgid "Ping cycle complete"
msgstr "已被破坏"
+msgid "Pinned"
+msgstr ""
+
+#, fuzzy
+msgid "Placement"
+msgstr "任务管理"
+
+msgid "Platform"
+msgstr ""
+
msgid "Please Select an option"
msgstr "请选择一个选项"
@@ -6964,10 +7333,18 @@ msgstr ""
msgid "Please enter a name"
msgstr "请输入一个有效的主机名"
+#, fuzzy
+msgid "Please enter a package id."
+msgstr "请输入一个有效的主机名"
+
#, fuzzy
msgid "Please enter a printer name."
msgstr "请输入一个有效的主机名"
+#, fuzzy
+msgid "Please enter a software name."
+msgstr "请输入一个有效的主机名"
+
#, fuzzy
msgid "Please enter a valid CIDR subnet."
msgstr "请输入一个有效的主机名"
@@ -6981,6 +7358,10 @@ msgstr ""
msgid "Please physically associate"
msgstr ""
+#, fuzzy
+msgid "Please select a valid backend."
+msgstr "选择一个有效的图像"
+
#, fuzzy
msgid "Please select a valid certificate verification level"
msgstr "选择一个有效的图像"
@@ -7001,6 +7382,10 @@ msgstr "选择一个有效的图像"
msgid "Please select a valid printer type."
msgstr "选择一个有效的图像"
+#, fuzzy
+msgid "Please select a valid state."
+msgstr "选择一个有效的图像"
+
#, fuzzy
msgid "Please select an LDAP server!"
msgstr "请选择一个选项"
@@ -7216,6 +7601,9 @@ msgstr ""
msgid "Preferred over mapping straight to a role: the user group holds the roles, so policy stays in one place and the provider only decides who is in which bucket."
msgstr ""
+msgid "Present"
+msgstr ""
+
msgid "Present means enabled."
msgstr ""
@@ -7262,6 +7650,10 @@ msgstr "打印机更新失败!"
msgid "Printer Create Success"
msgstr "打印机已经存在"
+#, fuzzy
+msgid "Printer Deployment"
+msgstr "打印机管理"
+
msgid "Printer Description"
msgstr "打印机说明"
@@ -7419,6 +7811,9 @@ msgstr "打印机更新!"
msgid "Providers"
msgstr ""
+msgid "Publisher"
+msgstr ""
+
msgid "Pushbullet Accounts"
msgstr "Pushbullet账户"
@@ -7460,6 +7855,10 @@ msgstr ""
msgid "Queued deletion is not active and cannot be canceled"
msgstr "管理单元被保护,不能被删除"
+#, fuzzy
+msgid "Quick tasks"
+msgstr "活动组播任务"
+
msgid "RESOURCES"
msgstr ""
@@ -7472,6 +7871,9 @@ msgstr "RX"
msgid "Re-Transmit Hello Interval"
msgstr ""
+msgid "Re-check Interval"
+msgstr ""
+
msgid "Re-run the installer and read what it prints under \"Publishing Secure Boot variable updates\" -- it names which of the three applied here."
msgstr ""
@@ -7492,6 +7894,9 @@ msgstr "删除所选"
msgid "Real Time"
msgstr "主机更新失败"
+msgid "Reason"
+msgstr ""
+
msgid "Reboot"
msgstr "重启"
@@ -7520,6 +7925,9 @@ msgstr ""
msgid "Recorded in range"
msgstr "未发现记录,错误: %s"
+msgid "Recorded; outcome present for an item report."
+msgstr ""
+
#, fuzzy
msgid "Records"
msgstr "当前记录"
@@ -7533,10 +7941,6 @@ msgstr ""
msgid "Redirect URI"
msgstr ""
-#, fuzzy
-msgid "Refresh"
-msgstr "默认刷新频率"
-
#, fuzzy
msgid "Refresh Settings Cache"
msgstr "服务状态"
@@ -7682,6 +8086,10 @@ msgstr "报告"
msgid "Report Management"
msgstr "报告管理"
+#, fuzzy
+msgid "Reported"
+msgstr "报告"
+
msgid "Reports"
msgstr "报告"
@@ -7747,9 +8155,16 @@ msgstr ""
msgid "Retention sweep failed"
msgstr "去除"
+msgid "Retry"
+msgstr ""
+
msgid "Return Code"
msgstr "返回代码"
+#, fuzzy
+msgid "Return Codes"
+msgstr "返回代码"
+
msgid "Return To Local Login"
msgstr ""
@@ -7760,9 +8175,33 @@ msgstr "返回代码"
msgid "Returning value of key"
msgstr "返回键的值"
+msgid "Returns the token exactly once; only its hash is stored. An expiry is required. uses is how many enrollments it approves, or -1 for unlimited until it expires. Audited as agent.token."
+msgstr ""
+
msgid "Reverse"
msgstr ""
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoke Enrollment Tokens"
+msgstr ""
+
+#, fuzzy
+msgid "Revoke an agent enrollment token"
+msgstr "待注册主机"
+
+#, fuzzy
+msgid "Revoke selected"
+msgstr "删除选定snapins"
+
+#, fuzzy
+msgid "Revoked selected tokens."
+msgstr "批准选定主机"
+
+msgid "Revoked."
+msgstr ""
+
#, fuzzy
msgid "Role"
msgstr "模块名称"
@@ -7903,6 +8342,9 @@ msgstr ""
msgid "SHA-256"
msgstr ""
+msgid "SMBIOS system UUID, system serial, board serial, chassis asset tag and the MAC list, as fog-agent identity prints them."
+msgstr ""
+
#, fuzzy
msgid "SQL Error"
msgstr "SQL错误:"
@@ -8021,16 +8463,6 @@ msgstr "安装/升级成功!"
msgid "Scopes"
msgstr ""
-msgid "Screen Height"
-msgstr ""
-
-#, fuzzy
-msgid "Screen Refresh Rate"
-msgstr "默认刷新频率"
-
-msgid "Screen Width"
-msgstr ""
-
msgid "Search"
msgstr "搜索"
@@ -8266,6 +8698,9 @@ msgstr "使用此名称的主机名已经存在。"
msgid "Sessions canceled!"
msgstr "已成功更新"
+msgid "Sessions open right now, as last reported by each host's agent. A host that has not checked in recently may have logged its user off since."
+msgstr ""
+
msgid "Set Printer as Default for Hosts"
msgstr ""
@@ -8732,6 +9167,63 @@ msgstr "Snapins"
msgid "So if you are trying to transmit to remote node A"
msgstr ""
+msgid "Software"
+msgstr ""
+
+#, fuzzy
+msgid "Software Create Fail"
+msgstr "打印机更新失败!"
+
+#, fuzzy
+msgid "Software Create Success"
+msgstr "打印机已经存在"
+
+#, fuzzy
+msgid "Software Host Associations"
+msgstr "无关联的节点"
+
+#, fuzzy
+msgid "Software Management"
+msgstr "存储管理"
+
+#, fuzzy
+msgid "Software Name"
+msgstr "打印机名称"
+
+msgid "Software Order"
+msgstr ""
+
+#, fuzzy
+msgid "Software Report"
+msgstr "主机ID"
+
+#, fuzzy
+msgid "Software Status"
+msgstr "新建%s"
+
+#, fuzzy
+msgid "Software Update Fail"
+msgstr "打印机更新失败!"
+
+#, fuzzy
+msgid "Software Update Success"
+msgstr "安装/升级成功!"
+
+#, fuzzy
+msgid "Software added!"
+msgstr "打印机名称"
+
+msgid "Software granted here applies to every host in this group, including hosts added later."
+msgstr ""
+
+#, fuzzy
+msgid "Software update failed!"
+msgstr "打印机更新失败!"
+
+#, fuzzy
+msgid "Software updated!"
+msgstr "打印机更新!"
+
msgid "Some nice description, should be short."
msgstr ""
@@ -8744,6 +9236,9 @@ msgstr ""
msgid "Specified download URL not allowed!"
msgstr ""
+msgid "Spooler"
+msgstr ""
+
msgid "Stale"
msgstr ""
@@ -9495,6 +9990,9 @@ msgstr "有此服务器上没有组。"
msgid "The CA private key is on this server"
msgstr "有此服务器上没有组。"
+msgid "The CSR is not a usable P-256 request, or a required field is missing."
+msgstr ""
+
msgid "The Enroll Secure Boot task type does all of this for you: schedule it against a host or a group from Task Scheduling and the client boots FOS, which stages the request itself -- or enrolls outright with nothing to confirm, if the machine is in Setup Mode. The Enroll Secure Boot Key menu item stays for answering a pending request by hand, or for enrolling from local media on a machine FOS cannot boot."
msgstr ""
@@ -9528,6 +10026,9 @@ msgstr ""
msgid "The account on the node itself that FOG signs in as, over SSH to check the node is reachable and over FTP to move images and snapins. Created by the installer, normally \"fogproject\". This is not a FOG web user."
msgstr ""
+msgid "The agent speaks a protocol this server does not."
+msgstr ""
+
msgid "The architecture columns do not exist yet. Run the Database Schema Installer / Updater, then reload this page."
msgstr ""
@@ -9572,6 +10073,9 @@ msgstr "|文件或无法达成通道"
msgid "The breakdowns cover every inventoried machine. The range selects inventory recorded inside it."
msgstr ""
+msgid "The bytes behind one thing under a capability. For snapin, the file for one task of the host's own job; fetching it marks the task in progress. One route for every kind of payload. Same gate as poll."
+msgstr ""
+
msgid "The calling user's preferences."
msgstr ""
@@ -9612,6 +10116,13 @@ msgstr ""
msgid "The default printer for hosts in this group. A host that has its own default keeps it."
msgstr ""
+msgid "The desired state: revision, capabilities, and one block per capability listed. Absent when the agent is current."
+msgstr ""
+
+#, fuzzy
+msgid "The enrollment is no longer pending."
+msgstr "不复存在"
+
msgid "The fields a queued task accepts. Wake-on-lan is this body with wol set, not a route of its own."
msgstr ""
@@ -9639,6 +10150,15 @@ msgstr ""
msgid "The grid key."
msgstr "无法创建任务"
+msgid "The host this certificate is, the revision of its desired state, and the state when it is not what the agent applied."
+msgstr ""
+
+msgid "The host's complete installed-program list, sent on the same terms as inventory. Complete by contract: anything installed and absent from it is marked removed."
+msgstr ""
+
+msgid "The id the package manager knows, e.g. googlechrome."
+msgstr ""
+
#, fuzzy
msgid "The identity provider could not be reached"
msgstr "无法读取临时文件"
@@ -9693,9 +10213,16 @@ msgstr ""
msgid "The issuer must be a full URL"
msgstr ""
+#, fuzzy
+msgid "The item is not a live row of this host."
+msgstr "发现主机没有活动任务"
+
msgid "The key will be assigned to registered hosts when a"
msgstr ""
+msgid "The leaf followed by the agent CA, PEM."
+msgstr ""
+
msgid "The logical sector size of the disk this image was captured from."
msgstr ""
@@ -9725,12 +10252,21 @@ msgstr ""
msgid "The older spelling of /unisearch?q=. An optional trailing integer caps results PER CLASS, not overall, and this route is not paged -- there is no nextUrl to follow. Also reachable as /search."
msgstr ""
+msgid "The order software is applied in when the agent reconciles this host."
+msgstr ""
+
msgid "The order this group's snapins run in. A host runs its own snapins first, then the ones granted here, in this order. Order only changes execution when \"Abort snapin sequence on failure\" is enabled for the task."
msgstr ""
+msgid "The order this group's software is applied in. A host applies its own software first, then the software granted here, in this order."
+msgstr ""
+
msgid "The path requested is already in use by another image!"
msgstr ""
+msgid "The payload bytes."
+msgstr ""
+
#, fuzzy
msgid "The plugin directory"
msgstr "目录"
@@ -9775,6 +10311,13 @@ msgstr ""
msgid "The record could not be written."
msgstr "无法读取临时文件"
+#, fuzzy
+msgid "The renewed certificate, leaf then chain."
+msgstr "新建%s"
+
+msgid "The reported software list is larger than the server accepts."
+msgstr ""
+
msgid "The resource is not in a cancellable state."
msgstr ""
@@ -9784,6 +10327,9 @@ msgstr ""
msgid "The root CA has been imported, but this host's system trust store could not be updated -- so HTTPS calls made on this server will not accept it yet. Re-run the installer, and check the installation log."
msgstr ""
+msgid "The row goes, so the token can never match again. Audited as agent.token."
+msgstr ""
+
msgid "The same rules in prose, for a client reading this at runtime."
msgstr ""
@@ -9795,6 +10341,12 @@ msgstr "打印机更新失败!"
msgid "The selected site no longer exists"
msgstr "不复存在"
+msgid "The server holds no hardware inventory hash for this host and wants the block on the next poll."
+msgstr ""
+
+msgid "The server holds no installed-software hash for this host and wants the list on the next poll."
+msgstr ""
+
msgid "The server refuses to activate this plugin, or the plugin declares no schema() migrations and is already installed, so re-running its installer would drop and recreate its tables. The message says which."
msgstr ""
@@ -9814,6 +10366,13 @@ msgstr ""
msgid "The signed certificate, or full chain, leaf first (PEM)"
msgstr ""
+msgid "The signer is unavailable; nothing changed."
+msgstr ""
+
+#, fuzzy
+msgid "The signing helper is not available on this server."
+msgstr "有此服务器上没有组。"
+
#, fuzzy
msgid "The signing request could not be generated"
msgstr "无法读取临时文件"
@@ -9834,6 +10393,10 @@ msgstr ""
msgid "The term. Because it is a path segment, a term containing / ? # or % cannot travel this way; use /unisearch?q= instead."
msgstr ""
+#, fuzzy
+msgid "The token."
+msgstr "CPU计数"
+
msgid "The trust anchor, published as ca.cert.der. Every fog-client pins this one."
msgstr ""
@@ -9995,6 +10558,9 @@ msgstr ""
msgid "This host last reported UEFI firmware whose Secure Boot state could not be read, so FOS has nowhere to write the certificate."
msgstr ""
+msgid "This host reported that its package manager is not installed. Chocolatey must be installed on the host before software can be managed."
+msgstr ""
+
msgid "This identity is linked to a different FOG account"
msgstr ""
@@ -10055,10 +10621,16 @@ msgstr ""
msgid "This is what MokManager's own View key screen shows after enrolling from the PXE menu -- that route never runs the script above, so check it against this value instead."
msgstr ""
+msgid "This is what hosts report as installed (agent-reported), not the software FOG is configured to install."
+msgstr ""
+
#, fuzzy, php-format
msgid "This machine already registered as %s"
msgstr "已注册为"
+msgid "This module has no settings to configure."
+msgstr ""
+
msgid "This name is not a recognized file in the boot directory."
msgstr ""
@@ -10167,6 +10739,13 @@ msgstr "时间已存在"
msgid "Time since last imaged"
msgstr ""
+#, fuzzy
+msgid "Timeout"
+msgstr "时间"
+
+msgid "Timeout must be a whole number of seconds, zero or more."
+msgstr ""
+
msgid "Title"
msgstr ""
@@ -10189,9 +10768,31 @@ msgstr ""
msgid "Toggle navigation"
msgstr "图像协会"
+#, fuzzy
+msgid "Token Create Fail"
+msgstr "打印机更新失败!"
+
+#, fuzzy
+msgid "Token Create Success"
+msgstr "打印机已经存在"
+
+#, fuzzy
+msgid "Token Revoke Fail"
+msgstr "FTP连接失败"
+
+#, fuzzy
+msgid "Token Revoke Success"
+msgstr "打印机已经存在"
+
+msgid "Token created. Copy it now."
+msgstr ""
+
msgid "Token or user:pass (optional)"
msgstr ""
+msgid "Token rows."
+msgstr ""
+
#, fuzzy
msgid "Too many MACs"
msgstr "主机主MAC"
@@ -10378,6 +10979,9 @@ msgstr "用户名"
msgid "Unauthenticated, and generated per request from this server's live routing and model metadata. Also served at /swagger.json, which is where most tooling looks first."
msgstr ""
+msgid "Unauthenticated, because this is how an agent obtains the client certificate it will authenticate with afterward. The agent posts a certificate signing request and its firmware identity; the server resolves the machine the way iPXE registration does and answers issued, pending or denied. Pending is the normal first answer for a machine nobody has approved yet -- the agent polls until an admin decides on /agent/enrollment/{id}/{action}, an enrollment token pre-approves it, or the server itself imaged the host recently (FOG_AGENT_ENROLL_DEPLOY_WINDOW). A pending agent can do nothing else: without a certificate no other agent route accepts it. Protocol 1."
+msgstr ""
+
#, fuzzy
msgid "Unauthenticated."
msgstr "服务器连接出错"
@@ -10428,6 +11032,9 @@ msgstr "发生未知上传错误。返回代码:"
msgid "Unknown action"
msgstr "发生未知上传错误。返回代码:"
+msgid "Unknown capability or status, or an item for a capability with no item reports."
+msgstr ""
+
#, php-format
msgid "Unknown field for %s: %s"
msgstr ""
@@ -10458,6 +11065,9 @@ msgstr "发生未知上传错误。返回代码:"
msgid "Unless it was declined with"
msgstr ""
+msgid "Unlimited"
+msgstr ""
+
#, fuzzy
msgid "Unmark selected client ignore"
msgstr "批准选定主机"
@@ -10547,6 +11157,9 @@ msgstr "打印机"
msgid "Updated %1$d field(s) on %2$d host(s)."
msgstr ""
+msgid "Upgraded"
+msgstr ""
+
#, fuzzy
msgid "Upload"
msgstr "上传报告"
@@ -10659,9 +11272,6 @@ msgstr "用户已存在"
msgid "User Association"
msgstr "图像协会"
-msgid "User Cleanup"
-msgstr "用户清理"
-
#, fuzzy
msgid "User Count"
msgstr "CPU计数"
@@ -10747,6 +11357,10 @@ msgstr "用户名"
msgid "User Password"
msgstr "用户密码"
+#, fuzzy
+msgid "User Sessions"
+msgstr "图像协会"
+
msgid "User Tracker"
msgstr "用户跟踪"
@@ -10829,6 +11443,12 @@ msgstr "用户"
msgid "Users, user groups and roles as id/name pairs. Each section is gated on that entity's own view permission -- user.view, usergroup.view, role.view -- and comes back EMPTY rather than 403 when the caller lacks it, so this route discloses nothing they could not already list. A caller holding none of the three can still save private filters; there is simply nobody they may name."
msgstr ""
+msgid "Uses"
+msgstr ""
+
+msgid "Uses left"
+msgstr ""
+
msgid "Using the group match function"
msgstr ""
@@ -10854,6 +11474,10 @@ msgstr "版"
msgid "Version information and paging bounds."
msgstr "FOG版本信息"
+#, fuzzy
+msgid "Version policy"
+msgstr "版"
+
#, fuzzy
msgid "Versions"
msgstr "版"
@@ -10883,6 +11507,9 @@ msgstr "网络唤醒?"
msgid "Wake Up"
msgstr ""
+msgid "Warning Before Log Out"
+msgstr ""
+
msgid "Warnings"
msgstr ""
@@ -10936,12 +11563,18 @@ msgstr "已成功更新"
msgid "What it does"
msgstr "已成功更新"
+msgid "What the agent did with one capability at one revision, recorded on the host as agent.result; or, with item, what happened to one thing under the capability (a snapin task, a software entry), answered with the outcome the agent acts on. One route for every kind of report. Same gate as poll."
+msgstr ""
+
msgid "What the browser is shown. Replaced by an ACME renewal where one is configured."
msgstr ""
msgid "What this server itself trusts: FOG's root, plus any root imported below."
msgstr ""
+msgid "What this token is for"
+msgstr ""
+
msgid "What to do next"
msgstr ""
@@ -10957,6 +11590,9 @@ msgstr ""
msgid "Where to get help and guides"
msgstr ""
+msgid "Whether this install collects facts at all (FOG_AGENT_INVENTORY_ENABLED). Always present: an agent cannot tell an absent boolean from a false one, and absent has to mean a server that predates the field rather than one that turned collection off. False stops the agent gathering."
+msgstr ""
+
msgid "Which side of a deploy each architecture may be picked on. An architecture set to Hosts only is not offered on an image, and one set to Images only is not offered on a host. This never affects what a host reports at boot or what a capture records -- only what a person may choose."
msgstr ""
@@ -10969,10 +11605,10 @@ msgstr ""
msgid "Who a filter can be shared with"
msgstr ""
-msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
+msgid "Why it waits: unknown-host, known-host-no-agent, rebind, identity-conflict, reissue."
msgstr ""
-msgid "Width"
+msgid "Why the caller can see it, most specific grant first. A filter reachable several ways is still returned once and reports only the most specific reason."
msgstr ""
msgid "Width must be 650 pixels."
@@ -11047,6 +11683,9 @@ msgstr ""
msgid "Within 30 days"
msgstr ""
+msgid "Y-m-d H:i:s, server time."
+msgstr ""
+
msgid "Yearly"
msgstr "每年"
@@ -11169,6 +11808,9 @@ msgstr ""
msgid "a service account: it may hold API tokens and can never sign in to this interface"
msgstr ""
+msgid "absent"
+msgstr ""
+
#, fuzzy
msgid "access"
msgstr "访问"
@@ -11180,10 +11822,17 @@ msgstr "附加的MAC"
msgid "after"
msgstr ""
+msgid "agent"
+msgstr ""
+
#, fuzzy
msgid "ago"
msgstr "前"
+#, php-format
+msgid "all %1$d hosts in group \"%2$s\""
+msgstr ""
+
#, fuzzy
msgid "all current storage nodes"
msgstr "无效的存储节点"
@@ -11217,6 +11866,13 @@ msgstr ""
msgid "answering 0 for a read that never ran"
msgstr ""
+#, fuzzy
+msgid "any version"
+msgstr "版"
+
+msgid "approve signs the CSR, binds the certificate to the host and takes the host out of pending; deny records the refusal. Either way the agent learns the outcome on its next poll. Audited as agent.enroll."
+msgstr ""
+
#, fuzzy
msgid "architecture not recorded"
msgstr "无法读取临时文件"
@@ -11228,6 +11884,10 @@ msgstr ""
msgid "as its primary group"
msgstr "更新主要组"
+#, fuzzy
+msgid "assigned"
+msgstr "无关联的节点"
+
msgid "attr could not be run -- SELinux may be denying it"
msgstr ""
@@ -11334,6 +11994,9 @@ msgstr "启用"
msgid "does not exist and cannot be created"
msgstr "图像被保护,不能被删除"
+msgid "domain"
+msgstr ""
+
msgid "e.g. nightly inventory script"
msgstr ""
@@ -11343,6 +12006,9 @@ msgstr ""
msgid "either because you have updated"
msgstr ""
+msgid "empty means never install Chocolatey"
+msgstr ""
+
#, fuzzy
msgid "error"
msgstr "错误"
@@ -11350,10 +12016,20 @@ msgstr "错误"
msgid "every column on this table will be treated as untyped"
msgstr ""
+msgid "exclusive"
+msgstr ""
+
#, php-format
msgid "exited abnormally with code %d; canceling task"
msgstr ""
+msgid "extra"
+msgstr ""
+
+#, fuzzy
+msgid "failed"
+msgstr "失败"
+
#, fuzzy
msgid "failed to execute, image file"
msgstr "无法删除图像文件"
@@ -11453,6 +12129,10 @@ msgstr ""
msgid "host"
msgstr "主办"
+#, fuzzy, php-format
+msgid "host \"%s\""
+msgstr "主办"
+
#, fuzzy
msgid "host is"
msgstr "主办"
@@ -11568,9 +12248,6 @@ msgstr ""
msgid "in"
msgstr "分钟"
-msgid "in Hz"
-msgstr ""
-
msgid "in batch row"
msgstr ""
@@ -11578,9 +12255,6 @@ msgstr ""
msgid "in minutes"
msgstr "分钟"
-msgid "in pixels"
-msgstr ""
-
msgid "in seconds"
msgstr ""
@@ -11655,6 +12329,10 @@ msgstr "DMI关键"
msgid "keys"
msgstr ""
+#, fuzzy
+msgid "latest"
+msgstr "复制?"
+
msgid "leave to keep the current one"
msgstr ""
@@ -11688,6 +12366,10 @@ msgstr "分钟"
msgid "mismatched"
msgstr ""
+#, fuzzy
+msgid "missing"
+msgstr "版"
+
msgid "moments from now"
msgstr ""
@@ -11725,6 +12407,10 @@ msgstr ""
msgid "never"
msgstr ""
+#, fuzzy
+msgid "never reported"
+msgstr "库存"
+
msgid "no enabled master node answered the probe"
msgstr ""
@@ -11757,6 +12443,9 @@ msgstr ""
msgid "not found on this node"
msgstr "图片没有节点发现"
+msgid "not joined"
+msgstr ""
+
#, fuzzy
msgid "not reachable"
msgstr "不可用"
@@ -11787,10 +12476,16 @@ msgstr ""
msgid "of how much disk space the image is using."
msgstr ""
+msgid "off"
+msgstr ""
+
#, fuzzy
msgid "off means an account must already exist"
msgstr "打印机已经存在"
+msgid "ok"
+msgstr ""
+
msgid "old"
msgstr ""
@@ -11804,6 +12499,9 @@ msgstr ""
msgid "optional"
msgstr "位置"
+msgid "optional; for an air-gapped or mirrored install"
+msgstr ""
+
msgid "or"
msgstr "要么"
@@ -12081,6 +12779,10 @@ msgstr "不可用"
msgid "unchanged for"
msgstr "成像"
+#, fuzzy
+msgid "unknown action"
+msgstr "发生未知上传错误。返回代码:"
+
msgid "unrecorded"
msgstr ""
@@ -12308,6 +13010,10 @@ msgstr ""
#~ msgid "CA private key"
#~ msgstr "私钥失败"
+#, fuzzy
+#~ msgid "Cannot connect to ftp server"
+#~ msgstr "无法连接到数据库"
+
#~ msgid "Check that database is running"
#~ msgstr "检查数据库运行"
@@ -12315,6 +13021,10 @@ msgstr ""
#~ msgid "Client Module Settings"
#~ msgstr "设置"
+#, fuzzy
+#~ msgid "Could not read snapin file"
+#~ msgstr "无法读取tmp文件。"
+
#, fuzzy
#~ msgid "Create New Accesscontrol"
#~ msgstr "新建%s"
@@ -12339,6 +13049,15 @@ msgstr ""
#~ msgid "Database connection unavailable"
#~ msgstr "没有可用的散列"
+#~ msgid "Default Height"
+#~ msgstr "默认高度"
+
+#~ msgid "Default Refresh Rate"
+#~ msgstr "默认刷新频率"
+
+#~ msgid "Default Width"
+#~ msgstr "默认宽度"
+
#, fuzzy
#~ msgid "Delete All"
#~ msgstr "删除的文件数据"
@@ -12347,6 +13066,9 @@ msgstr ""
#~ msgid "Deprecated."
#~ msgstr "创建"
+#~ msgid "Directory Cleaner"
+#~ msgstr "目录清洁"
+
#, fuzzy
#~ msgid "Domain joining"
#~ msgstr "域名"
@@ -12409,6 +13131,18 @@ msgstr ""
#~ msgid "Export Users"
#~ msgstr "导出用户"
+#, fuzzy
+#~ msgid "FOG Agent desired state"
+#~ msgstr "已成功更新"
+
+#, fuzzy
+#~ msgid "FOG Agent snapin result"
+#~ msgstr "没有文件被上传"
+
+#, fuzzy
+#~ msgid "FOG Agent software result"
+#~ msgstr "没有文件被上传"
+
#~ msgid "Failed to add/update snapin file"
#~ msgstr "无法添加/更新管理单元文件"
@@ -12520,10 +13254,18 @@ msgstr ""
#~ msgid "Group module settings"
#~ msgstr "主机描述"
+#, fuzzy
+#~ msgid "Height"
+#~ msgstr "午夜"
+
#, fuzzy
#~ msgid "History Report"
#~ msgstr "主机ID"
+#, fuzzy
+#~ msgid "Host Display Manager Settings"
+#~ msgstr "设置"
+
#, fuzzy
#~ msgid "Host Ext"
#~ msgstr "主机列表"
@@ -12540,6 +13282,10 @@ msgstr ""
#~ msgid "Host Ext Variable"
#~ msgstr "用户更新失败"
+#, fuzzy
+#~ msgid "Host Screen Resolution"
+#~ msgstr "主机注册"
+
#, fuzzy
#~ msgid "Host Site"
#~ msgstr "主机列表"
@@ -12643,6 +13389,9 @@ msgstr ""
#~ msgid "Install"
#~ msgstr "已安装的插件"
+#~ msgid "Invalid Storage Node"
+#~ msgstr "无效的存储节点"
+
#, fuzzy
#~ msgid "Invalid Type"
#~ msgstr "无效类型"
@@ -12666,6 +13415,14 @@ msgstr ""
#~ msgid "LDAP User Filter"
#~ msgstr "LDAP服务器"
+#, fuzzy
+#~ msgid "Last Activity"
+#~ msgstr "活性"
+
+#, fuzzy
+#~ msgid "Last Event"
+#~ msgstr "主机创建"
+
#, fuzzy
#~ msgid "Latest SVN Version"
#~ msgstr "最新版本"
@@ -12724,6 +13481,14 @@ msgstr ""
#~ msgid "Not Installed"
#~ msgstr "已安装的插件"
+#, fuzzy
+#~ msgid "Not a live task of this host's job."
+#~ msgstr "发现主机没有活动任务"
+
+#, fuzzy
+#~ msgid "Not an entry in this host's software set."
+#~ msgstr "发现主机没有活动任务"
+
#, fuzzy
#~ msgid "Pause"
#~ msgstr "用户"
@@ -12751,6 +13516,14 @@ msgstr ""
#~ msgid "Product Keys"
#~ msgstr "主机产品密钥"
+#, fuzzy
+#~ msgid "Recorded."
+#~ msgstr "当前记录"
+
+#, fuzzy
+#~ msgid "Refresh"
+#~ msgstr "默认刷新频率"
+
#, fuzzy
#~ msgid "Release Version"
#~ msgstr "最新版本"
@@ -12817,6 +13590,10 @@ msgstr ""
#~ msgid "Rule update failed!"
#~ msgstr "打印机更新失败!"
+#, fuzzy
+#~ msgid "Screen Refresh Rate"
+#~ msgstr "默认刷新频率"
+
#, fuzzy
#~ msgid "Serial"
#~ msgstr "系统序列"
@@ -12858,8 +13635,16 @@ msgstr ""
#~ msgstr "打印机已经存在"
#, fuzzy
-#~ msgid "The certificate chain"
-#~ msgstr "新建%s"
+#~ msgid "The desired state."
+#~ msgstr "无法创建任务"
+
+#, fuzzy
+#~ msgid "The host this certificate is, and the capabilities this server offers."
+#~ msgstr "有此服务器上没有组。"
+
+#, fuzzy
+#~ msgid "The task was already closed."
+#~ msgstr "打印机已经存在"
#, fuzzy
#~ msgid "There are no "
@@ -12904,6 +13689,10 @@ msgstr ""
#~ msgid "Unable to set user filter."
#~ msgstr "无法打开文件进行读取"
+#, fuzzy
+#~ msgid "Unknown status."
+#~ msgstr "发生未知上传错误。返回代码:"
+
#, fuzzy
#~ msgid "Update Master Node"
#~ msgstr "主节点"
@@ -12916,6 +13705,9 @@ msgstr ""
#~ msgid "Update/Remove printers"
#~ msgstr "删除选定的打印机"
+#~ msgid "User Cleanup"
+#~ msgstr "用户清理"
+
#, fuzzy
#~ msgid "User Group Site"
#~ msgstr "出口Snapins"
@@ -13002,10 +13794,6 @@ msgstr ""
#~ msgid "min (all)"
#~ msgstr "启用"
-#, fuzzy
-#~ msgid "multicast tasks!"
-#~ msgstr "活动组播任务"
-
#, fuzzy
#~ msgid "no database to"
#~ msgstr "没有数据库工作关闭"
@@ -13021,7 +13809,3 @@ msgstr ""
#, fuzzy
#~ msgid "username"
#~ msgstr "用户名"
-
-#, fuzzy
-#~ msgid "version"
-#~ msgstr "版"
diff --git a/packages/web/service/displaymanager.php b/packages/web/service/displaymanager.php
deleted file mode 100644
index c9d7ccb569..0000000000
--- a/packages/web/service/displaymanager.php
+++ /dev/null
@@ -1,41 +0,0 @@
-
- * @license http://opensource.org/licenses/gpl-3.0 GPLv3
- * @link https://fogproject.org
- */
-
-use FOG\Client\DisplayManager;
-
-/**
- * Display sender for the clients
- *
- * @category DisplayManager
- * @package FOGProject
- * @author Tom Elliott
- * @license http://opensource.org/licenses/gpl-3.0 GPLv3
- * @link https://fogproject.org
- */
-/*
- * A machine entry point: the caller is a booting NIC, FOS, the fog-client
- * or a storage node, none of which can present a credential. Declared per
- * file rather than inferred from the absence of one -- see
- * Authorization::_hasNoPrincipal() for what it licenses and why the
- * distinction matters.
- */
-define('FOG_MACHINE_REQUEST', true);
-
-require '../commons/base.inc.php';
-new DisplayManager(
- true,
- false,
- false,
- false,
- isset($_REQUEST['newService'])
-);
diff --git a/packages/web/src/Agent/DirectoryFacts.php b/packages/web/src/Agent/DirectoryFacts.php
new file mode 100644
index 0000000000..93d9e4ba19
--- /dev/null
+++ b/packages/web/src/Agent/DirectoryFacts.php
@@ -0,0 +1,243 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+use FOG\Router\Route;
+
+/**
+ * Writes a reported membership block onto the host's `hostDirectory` row
+ * (design 0009 section 3).
+ *
+ * A fact report like InventoryFacts, and registered the same way: an entry
+ * in State::FACT_REPORTS and a block in the poll, never a route of its own
+ * (the route rule, protocol-v1.md). The server's hash gate, the
+ * `want_directory` answer and the audit line all come from being in that
+ * registry.
+ *
+ * What it does NOT do is act on the difference. Comparing the observation
+ * against the host's hostADDomain and hostADOU is the report's job, and
+ * moving a computer object between OUs is design 0009 section 5, which
+ * needs a directory credential FOG does not have. This class only records.
+ *
+ * Named DirectoryFacts, not Directory, for the same reason InventoryFacts
+ * is not Inventory: FOG\Items\HostDirectory is the row this writes.
+ *
+ * @category DirectoryMembership
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class DirectoryFacts extends FOGBase
+{
+ /**
+ * The reported keys, mapped to HostDirectory property names.
+ *
+ * A whitelist rather than a filter over the field map, for
+ * InventoryFacts' reason: hdHostID and hdID are the server's, and a
+ * reported block must not be able to reach them.
+ *
+ * @var array
+ */
+ const FIELDS = [
+ 'kind' => 'kind',
+ 'domain' => 'domain',
+ 'netbios' => 'netbios',
+ 'computer_dn' => 'computerDN',
+ 'machine_account' => 'machineAccount',
+ 'site' => 'site'
+ ];
+
+ /**
+ * Longest value stored per column, keyed by property.
+ *
+ * The columns are varchars and MySQL in strict mode refuses an overlong
+ * value, which would fail the whole poll rather than the one field. A
+ * DN is the long one: AD allows well over 255 characters once a few
+ * nested OUs are involved.
+ *
+ * @var array
+ */
+ const WIDTHS = [
+ 'kind' => 32,
+ 'domain' => 255,
+ 'netbios' => 64,
+ 'computerDN' => 1024,
+ 'machineAccount' => 255,
+ 'site' => 255
+ ];
+
+ /**
+ * The kinds a host may report.
+ *
+ * An unrecognized kind is stored as the empty string rather than passed
+ * through: the report groups on it, and a host inventing a value would
+ * put an uncontrolled string into a page an admin reads.
+ *
+ * @var string[]
+ */
+ const KINDS = ['ad', 'entra', 'workgroup', 'none'];
+
+ /**
+ * Records a reported membership block on the host's directory row.
+ *
+ * Upsert: one row per host, replaced in place. Reached only when the
+ * server's hash for the block moved, so every call here is a real
+ * change in what the machine says about itself -- which is why the
+ * audit line is unconditional.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param array $block the reported membership
+ *
+ * @return void
+ */
+ public static function report(Host $Host, array $block)
+ {
+ $hostID = (int)$Host->get('id');
+ $Directory = self::row($hostID);
+
+ $joined = !empty($block['joined']);
+ $Directory->set('joined', $joined ? 1 : 0);
+
+ foreach (self::FIELDS as $key => $field) {
+ $value = substr(
+ trim((string)($block[$key] ?? '')),
+ 0,
+ self::WIDTHS[$field]
+ );
+ if ('kind' === $field && !in_array($value, self::KINDS, true)) {
+ // A host that invents a kind gets none, not its own string.
+ $value = '';
+ }
+ if (!$joined && 'kind' !== $field) {
+ // An unjoined machine has no membership detail, and a stale
+ // domain left on one would compare EQUAL to the desired
+ // value and hide the drift this row exists to show. The
+ // agent already clears these; clearing again here means a
+ // hand-built or older block cannot reintroduce the lie.
+ $value = '';
+ }
+ $Directory->set($field, $value);
+ }
+
+ // Stamped on storageTimeZone() like every other datetime FOG
+ // writes. niceDate() rather than date(): the two clocks differ on
+ // any server whose PHP default zone is not UTC, and mixing them is
+ // what made a one-second user session read as five hours.
+ $Directory->set(
+ 'observedAt',
+ self::niceDate()->setTimezone(self::storageTimeZone())
+ ->format('Y-m-d H:i:s')
+ );
+ $Directory->save();
+
+ // One renderable line, naming what the machine now says rather than
+ // which fields moved: unlike an inventory row, this is three facts
+ // an admin can read in a sentence, and "left CORP" is the sentence
+ // they need to see.
+ Audit::record(
+ [
+ 'type' => 'agent.directory',
+ 'subjectType' => 'host',
+ 'subjectID' => $hostID,
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'affectedCount' => 1,
+ 'text' => substr(
+ 'agent reported directory membership: '
+ . self::describe($Directory),
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+
+ /**
+ * Puts the host's computer object where the host record asks for it
+ * (design 0009 section 5).
+ *
+ * Called from the poll on EVERY check-in, not from report() -- which
+ * runs only when the machine's own report moved. The other thing that
+ * creates drift is an admin editing the host's OU, and that changes
+ * nothing a machine would ever report, so hanging placement off the
+ * report would mean an edited OU never took effect until the machine
+ * happened to change domains. Which is the bug design 0009 exists to
+ * fix, arrived at from the other direction.
+ *
+ * Cheap when there is nothing to do: a host with no row, no desired OU
+ * or no drift returns before any connection is made.
+ *
+ * @param Host $Host the host the certificate bound
+ *
+ * @return void
+ */
+ public static function place(Host $Host)
+ {
+ DirectoryPlacement::ensure($Host, self::row((int)$Host->get('id')));
+ }
+
+ /**
+ * The host's directory row, or a new unsaved one.
+ *
+ * @param int $hostID the host
+ *
+ * @return \FOG\Items\HostDirectory
+ */
+ protected static function row($hostID)
+ {
+ // Route::getIds, the way State::_factStateID looks up its own row.
+ // FOGManagerController has no find(); a manager is the read side of
+ // the route layer, not a repository.
+ $ids = Route::getIds(
+ 'hostdirectory',
+ ['hostID' => (int)$hostID],
+ 'id'
+ );
+ $id = (int)(array_shift($ids) ?: 0);
+ if ($id > 0) {
+ $Directory = new \FOG\Items\HostDirectory($id);
+ if ($Directory->isValid()) {
+ return $Directory;
+ }
+ }
+ return (new \FOG\Items\HostDirectory())->set('hostID', (int)$hostID);
+ }
+
+ /**
+ * One line describing what a host reported, for the audit entry.
+ *
+ * @param \FOG\Items\HostDirectory $Directory the stored row
+ *
+ * @return string
+ */
+ protected static function describe(\FOG\Items\HostDirectory $Directory)
+ {
+ if (!$Directory->get('joined')) {
+ $kind = (string)$Directory->get('kind');
+ return 'not joined' . ('' === $kind ? '' : " ($kind)");
+ }
+ $out = (string)$Directory->get('kind') . ' '
+ . (string)$Directory->get('domain');
+ $container = $Directory->containerDN();
+ if ('' !== $container) {
+ $out .= ' in ' . $container;
+ }
+ return trim($out);
+ }
+}
diff --git a/packages/web/src/Agent/DirectoryJoin.php b/packages/web/src/Agent/DirectoryJoin.php
new file mode 100644
index 0000000000..8ef112a255
--- /dev/null
+++ b/packages/web/src/Agent/DirectoryJoin.php
@@ -0,0 +1,401 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+use FOG\Items\HostDirectory;
+use FOG\Router\Route;
+
+/**
+ * What the agent is told about joining a domain, and what it reports back
+ * (design 0009 section 6).
+ *
+ * The half only the machine can do. Membership is a property of the machine
+ * -- its computer account, its secure channel, its Kerberos keytab -- so it
+ * is the machine that joins, and the server's job is to decide whether it
+ * should and to hand over the credential for exactly as long as that takes.
+ *
+ * The contrast with the legacy client is the whole point of this class.
+ * `Client\HostnameChanger::json()` puts `ADUser` and `ADPass` in the answer
+ * to EVERY check-in of EVERY host with `useAD` set -- joined or not, forever,
+ * in cleartext once the client decrypts it. A joined estate is an estate
+ * where every machine holds a credential that can create computer objects in
+ * the directory, and it holds it permanently, for no reason: it is already
+ * joined.
+ *
+ * Here the credential is sent only to a host the server BELIEVES is not
+ * joined, only while that is true, and not again for an hour after an
+ * attempt. Most hosts in most estates never receive it at all.
+ *
+ * @category DirectoryMembership
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class DirectoryJoin extends FOGBase
+{
+ /**
+ * Seconds before a host is sent the credential again after an attempt.
+ *
+ * Not politeness. A join that fails on a bad password is a FAILED
+ * AUTHENTICATION against somebody's domain controller, and without a
+ * cooldown it is one per host per poll -- which is how a service account
+ * with a lockout policy gets locked out, taking every other host's join
+ * with it. An hour is short enough that fixing the password is not a
+ * long wait and long enough that a fleet cannot trip a lockout.
+ *
+ * It also covers the gap after a SUCCESSFUL join: the machine's own
+ * report of its new membership arrives on a later poll, and until it
+ * does the server would otherwise still believe the host unjoined and
+ * send the credential once more.
+ */
+ const RETRY_AFTER = 3600;
+
+ /**
+ * What the agent may report for a join.
+ *
+ * `refused` is the one worth explaining: it is the agent declining to
+ * act on what it was sent, rather than trying and failing. A machine
+ * already in a DIFFERENT domain is the case that matters -- getting it
+ * to the right one means leaving the wrong one, which resets the
+ * computer account's password and can cost the object its SID, and the
+ * agent will not do that as a side effect of an edit.
+ */
+ const STATUS_JOINED = 'joined';
+ const STATUS_ALREADY_JOINED = 'already_joined';
+ const STATUSES = [
+ 'joined', 'already_joined', 'failed', 'unsupported', 'refused'
+ ];
+
+ /**
+ * The statuses that mean the machine is where it should be, so any
+ * error recorded against it is stale.
+ */
+ const SETTLED_STATUSES = ['joined', 'already_joined'];
+
+ /**
+ * Longest error kept: the column is a varchar(255) because this is a
+ * line an admin reads in a report, not a log.
+ */
+ const MAX_ERROR = 255;
+
+ /**
+ * The join block for a host, or null when there is nothing to send.
+ *
+ * Null is the answer for the overwhelming majority of hosts and every
+ * one of the reasons is a reason NOT to put a credential on a machine:
+ *
+ * - The host is not set to use AD, or names no domain. Nothing to join.
+ * - The host has never reported its membership. The server does not
+ * know whether it is joined, and a credential is not something to
+ * send on a guess. It arrives one poll later, once the machine has
+ * said where it is (facts are recorded after this runs, by design --
+ * see Route::agentPoll).
+ * - The host is already in the domain it should be in. This is the
+ * resting state of a working estate.
+ * - The host is joined to some OTHER domain. The agent would refuse,
+ * so sending the credential would achieve nothing and expose it; the
+ * Directory Membership report shows the mismatch instead.
+ * - An attempt was made within RETRY_AFTER.
+ *
+ * @param Host $Host the principal
+ *
+ * @return array|null
+ */
+ public static function desired(Host $Host)
+ {
+ return self::blockFor($Host, self::observed($Host));
+ }
+
+ /**
+ * The decision, given the host and what it last reported.
+ *
+ * Split from the lookup for the reason ReportManagement splits its
+ * fetch from its emit: the rule about when a credential leaves this
+ * server is the part worth testing, and it needs no database to state.
+ *
+ * @param Host $Host the principal
+ * @param HostDirectory|null $Observed what it last reported, or null
+ *
+ * @return array|null
+ */
+ public static function blockFor(Host $Host, HostDirectory $Observed = null)
+ {
+ if (!(bool)$Host->get('useAD')) {
+ return null;
+ }
+ $domain = trim((string)$Host->get('ADDomain'));
+ if ('' === $domain) {
+ return null;
+ }
+
+ if (null === $Observed) {
+ // Never reported. Ask again next poll, when it has.
+ return null;
+ }
+ if ((bool)$Observed->get('joined')) {
+ // Joined to something. Either it is where it belongs, or it is
+ // somewhere else and the agent would refuse; neither is a
+ // reason to hand over a credential.
+ return null;
+ }
+ if (self::cooling($Observed)) {
+ return null;
+ }
+
+ $user = self::joinUser($Host, $domain);
+ $pass = self::joinPassword($Host);
+ if ('' === $user || '' === $pass) {
+ // No credential to send. Deliberately still returns a block:
+ // the agent reports `refused` with a message naming the missing
+ // fields, which is how an admin finds out. Sending nothing at
+ // all would look identical to a host that is already joined.
+ $user = $pass = '';
+ }
+
+ return [
+ 'domain' => $domain,
+ // The short name where the host's own report supplied it. Used
+ // by the agent only to recognize that it is already in this
+ // domain, never to join.
+ 'netbios' => (string)$Observed->get('netbios'),
+ // The container the object is CREATED in. Semicolons are
+ // stripped the way the legacy client's block does: hostADOU has
+ // always been allowed to hold a list and only the first is a
+ // container.
+ 'ou' => str_replace(';', '', (string)$Host->get('ADOU')),
+ 'username' => $user,
+ 'password' => $pass,
+ // The host's existing "Enforce Hostname | AD Join Reboots"
+ // flag: may the agent reboot to finish the join. The agent's
+ // reboot coordinator still owns the when.
+ 'reboot' => (bool)$Host->get('enforce')
+ ];
+ }
+
+ /**
+ * Records what the agent did about the join.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param int $hostID the host the agent says it is reporting about
+ * @param array $body the reported result
+ *
+ * @throws \RuntimeException with an HTTP code when refused
+ *
+ * @return string the status recorded
+ */
+ public static function report(Host $Host, $hostID, array $body)
+ {
+ // The row a join result is about is the host's own membership, and
+ // the agent addresses it by its host id. Checked rather than
+ // ignored: a host reporting on somebody else's membership is a host
+ // writing a row that is not its own.
+ if ((int)$hostID !== (int)$Host->get('id')) {
+ throw new \RuntimeException('not this host\'s membership', 404);
+ }
+ $status = (string)($body['status'] ?? '');
+ if (!in_array($status, self::STATUSES, true)) {
+ throw new \RuntimeException('unknown status', 400);
+ }
+ $error = self::errorFor($status, (string)($body['details'] ?? ''));
+
+ $Observed = self::observed($Host);
+ if (null === $Observed) {
+ // A result about a host with no membership row. Possible only
+ // if the row was deleted between the state fetch and the
+ // report; the outcome is still worth an audit line, it simply
+ // has nowhere to be stamped.
+ self::_audit($Host, $status, $error);
+ return $status;
+ }
+
+ $Observed
+ // Named for the ATTEMPT, not the join: this is stamped whenever
+ // the agent acted, so a name like hdJoinedAt would claim a join
+ // happened on every occasion one did not -- and it is what the
+ // RETRY_AFTER cooldown reads.
+ ->set('joinAt', self::stamp())
+ ->set('joinError', $error)
+ ->save();
+
+ // An already_joined heartbeat is not news, and it is what a working
+ // estate reports forever. Auditing it would bury the results that
+ // matter.
+ if (self::STATUS_ALREADY_JOINED !== $status) {
+ self::_audit($Host, $status, $error);
+ }
+
+ return $status;
+ }
+
+ /**
+ * The error to record for a reported status.
+ *
+ * A settled status clears whatever was there: an admin chasing a stale
+ * message against a machine that is now joined is worse off than one
+ * chasing none.
+ *
+ * @param string $status the reported status
+ * @param string $error the reported message
+ *
+ * @return string
+ */
+ protected static function errorFor($status, $error)
+ {
+ if (in_array($status, self::SETTLED_STATUSES, true)) {
+ return '';
+ }
+
+ return substr(trim($error), 0, self::MAX_ERROR);
+ }
+
+ /**
+ * Whether an attempt is too recent to make another.
+ *
+ * @param HostDirectory $Observed the membership row
+ *
+ * @return bool
+ */
+ protected static function cooling(HostDirectory $Observed)
+ {
+ $at = trim((string)$Observed->get('joinAt'));
+ // validDate() rather than a literal: there stays one definition of
+ // what an empty date is, and MySQL's zero date is only one of the
+ // shapes an untouched column comes back as.
+ if ('' === $at || !self::validDate($at)) {
+ return false;
+ }
+
+ return (self::niceDate()->getTimestamp()
+ - self::niceDate($at, self::storageTimeZone())->getTimestamp())
+ < self::RETRY_AFTER;
+ }
+
+ /**
+ * The joining account, domain-qualified.
+ *
+ * Same rule the legacy client's block uses, so an admin who has typed
+ * `CORP\svc-join` or `svc-join@corp.example.com` into the host record
+ * gets what they typed, and a bare name is qualified with the domain.
+ * The agent strips the qualifier again for adcli and realm, which want
+ * the bare sAMAccountName -- one spelling on the wire, each consumer
+ * adapting it, rather than the server sending two.
+ *
+ * @param Host $Host the host
+ * @param string $domain the domain being joined
+ *
+ * @return string
+ */
+ protected static function joinUser(Host $Host, $domain)
+ {
+ $user = trim((string)$Host->get('ADUser'));
+ if ('' === $user) {
+ return '';
+ }
+ if (false !== strpos($user, '\\') || false !== strpos($user, '@')) {
+ return $user;
+ }
+
+ return $domain . '\\' . $user;
+ }
+
+ /**
+ * The joining account's password, as typed.
+ *
+ * Reuses DirectoryPlacement's decoder rather than repeating the
+ * three-shape dance a third time. The legacy client's copy in
+ * `Client\HostnameChanger::json()` has the non-strict base64 bug that
+ * one documents -- it is left alone here because changing what the
+ * legacy client is sent is a separate, riskier change.
+ *
+ * @param Host $Host the host
+ *
+ * @return string
+ */
+ protected static function joinPassword(Host $Host)
+ {
+ return DirectoryPlacement::decodeStored((string)$Host->get('ADPass'));
+ }
+
+ /**
+ * The host's reported membership row, or null when it has never
+ * reported.
+ *
+ * @param Host $Host the host
+ *
+ * @return HostDirectory|null
+ */
+ protected static function observed(Host $Host)
+ {
+ $ids = Route::getIds(
+ 'hostdirectory',
+ ['hostID' => (int)$Host->get('id')],
+ 'id'
+ );
+ $id = (int)(array_shift($ids) ?: 0);
+ if ($id < 1) {
+ return null;
+ }
+ $Observed = new HostDirectory($id);
+
+ return $Observed->isValid() ? $Observed : null;
+ }
+
+ /**
+ * Now, in storage time.
+ *
+ * @return string
+ */
+ protected static function stamp()
+ {
+ return self::niceDate()
+ ->setTimezone(self::storageTimeZone())
+ ->format('Y-m-d H:i:s');
+ }
+
+ /**
+ * One audit line for a join result.
+ *
+ * @param Host $Host the host
+ * @param string $status what the agent said it did
+ * @param string $error the message, if any
+ *
+ * @return void
+ */
+ private static function _audit(Host $Host, $status, $error)
+ {
+ Audit::record(
+ [
+ 'type' => 'agent.result',
+ 'subjectType' => 'host',
+ 'subjectID' => (int)$Host->get('id'),
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'text' => substr(
+ sprintf(
+ 'directory join %s%s',
+ $status,
+ '' === $error ? '' : ': ' . $error
+ ),
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+}
diff --git a/packages/web/src/Agent/DirectoryPlacement.php b/packages/web/src/Agent/DirectoryPlacement.php
new file mode 100644
index 0000000000..82d4257a0f
--- /dev/null
+++ b/packages/web/src/Agent/DirectoryPlacement.php
@@ -0,0 +1,319 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+use FOG\Items\HostDirectory;
+use FOG\Net\FOGLdap;
+
+/**
+ * Moves a host's computer object into the OU the host record asks for
+ * (design 0009 section 5).
+ *
+ * The half of directory membership only the directory can do. A computer
+ * object's container is a property of an object in a directory, not of the
+ * machine -- so this is one LDAP Modify DN from the server, with the machine
+ * uninvolved and not necessarily even running.
+ *
+ * What FOG does today instead, because the legacy client never compares an
+ * OU at all: nothing. Editing a host's OU has no effect, forever, and the
+ * workaround an admin is left with is to unjoin and rejoin, which resets the
+ * computer account's password and, where the object is recreated, gives the
+ * machine a new SID -- losing its group memberships, its escrowed BitLocker
+ * keys, its LAPS password and any certificate issued to it.
+ *
+ * Off unless configured. This writes to somebody's directory, so it must
+ * never start working because they upgraded.
+ *
+ * @category DirectoryMembership
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class DirectoryPlacement extends FOGBase
+{
+ /**
+ * Seconds before the directory is consulted again about one host.
+ *
+ * Every attempt is stamped, successful or not, because this bounds two
+ * different things. A failure, first: the ones worth expecting -- the
+ * directory is down, the account lost its rights, the OU was renamed --
+ * do not clear in five minutes, and without a cooldown a broken
+ * directory is dialed once per poll per host forever with every host
+ * paying the connection timeout. And a host that cannot report its own
+ * DN, second: only the directory knows where its object sits, so the
+ * question has to be asked rather than answered from the row, and once
+ * an hour is the price of an OU move landing on a Linux host.
+ *
+ * A host that DOES report its DN is not on this clock while it is where
+ * it belongs -- that comparison is free, so it happens every poll and an
+ * OU change on a Windows host is acted on immediately.
+ */
+ const RETRY_AFTER = 3600;
+
+ /**
+ * Whether placement is switched on and configured.
+ *
+ * @return bool
+ */
+ public static function enabled()
+ {
+ return (bool)self::getSetting('FOG_DIRECTORY_PLACEMENT_ENABLED')
+ && '' !== trim((string)self::getSetting('FOG_DIRECTORY_LDAP_URI'));
+ }
+
+ /**
+ * Places one host's computer object, if it is not already where the host
+ * record says it should be.
+ *
+ * Never throws. It is called from the poll, and a directory problem must
+ * cost the host a recorded error rather than its check-in -- the same
+ * rule the fact reports follow.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param HostDirectory $Directory what the machine reported
+ *
+ * @return void
+ */
+ public static function ensure(Host $Host, HostDirectory $Directory)
+ {
+ try {
+ self::_ensure($Host, $Directory);
+ } catch (\Throwable $e) {
+ // Recorded, not raised. Whatever went wrong here, the host has
+ // still checked in and its facts are still stored.
+ self::_record($Directory, 'placement failed: ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * The body of ensure(), free to fail.
+ *
+ * @param Host $Host the host
+ * @param HostDirectory $Directory the observation
+ *
+ * @return void
+ */
+ private static function _ensure(Host $Host, HostDirectory $Directory)
+ {
+ if (!self::enabled() || !$Host->get('useAD')) {
+ return;
+ }
+ $wantOU = trim((string)$Host->get('ADOU'));
+ if ('' === $wantOU) {
+ // No OU expressed. An admin who never set one is not a machine
+ // in the wrong place, and moving it somewhere would be FOG
+ // inventing an intention.
+ return;
+ }
+ if (!$Directory->get('joined')) {
+ // Not joined: there is no object to move, and creating one is a
+ // join, which is section 6 and needs the machine.
+ return;
+ }
+ if ('' !== $Directory->containerDN() && !$Directory->ouDrifted($wantOU)) {
+ // The host reported its own DN and it is the right one. Nothing
+ // to ask the directory, so no connection and no cooldown: a
+ // healthy Windows fleet never dials LDAP at all.
+ return;
+ }
+ if (self::_cooling($Directory)) {
+ return;
+ }
+
+ $ldap = new FOGLdap();
+ $ok = $ldap->connect(
+ (string)self::getSetting('FOG_DIRECTORY_LDAP_URI'),
+ (string)self::getSetting('FOG_DIRECTORY_BIND_DN'),
+ self::_bindPassword(),
+ (string)self::getSetting('FOG_DIRECTORY_CA_CERT')
+ );
+ if (!$ok) {
+ self::_record($Directory, $ldap->error());
+ return;
+ }
+
+ try {
+ $dn = trim((string)$Directory->get('computerDN'));
+ if ('' === $dn) {
+ // Normal on Linux: no join tool there exposes the DN. The
+ // directory knows, though, and asking it is better than
+ // asking the machine -- it is the authority on where its own
+ // objects live, and it can answer for a machine that is off.
+ $dn = $ldap->findComputer(
+ (string)self::getSetting('FOG_DIRECTORY_BASE_DN'),
+ (string)$Directory->get('machineAccount')
+ );
+ if ('' === $dn) {
+ self::_record($Directory, $ldap->error());
+ return;
+ }
+ // Learned from the directory, so the report stops saying
+ // "unknown" for this host and the free comparison above
+ // works from the next poll on.
+ $Directory->set('computerDN', $dn);
+ if (!$Directory->ouDrifted($wantOU)) {
+ self::_record($Directory, '');
+ return;
+ }
+ }
+ if (!$ldap->moveTo($dn, $wantOU)) {
+ self::_record($Directory, $ldap->error());
+ return;
+ }
+ // Where the object now is, not where we asked it to go: a true
+ // return from ldap_rename is the directory confirming the object
+ // is there. Recording it keeps the next poll's free comparison
+ // correct -- leaving the old DN would make FOG move an object
+ // that has already moved, once every poll forever.
+ $Directory->set(
+ 'computerDN',
+ FOGLdap::rdn($dn) . ',' . $wantOU
+ );
+ } finally {
+ $ldap->close();
+ }
+
+ self::_record($Directory, '');
+
+ Audit::record(
+ [
+ 'type' => 'agent.directory.move',
+ 'subjectType' => 'host',
+ 'subjectID' => (int)$Host->get('id'),
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'affectedCount' => 1,
+ 'text' => substr(
+ 'moved the computer object to ' . $wantOU,
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+
+ /**
+ * Whether this host was consulted about recently enough to leave alone.
+ *
+ * @param HostDirectory $Directory the observation
+ *
+ * @return bool
+ */
+ private static function _cooling(HostDirectory $Directory)
+ {
+ $at = (string)$Directory->get('placementAt');
+ if (!self::validDate($at)) {
+ return false;
+ }
+ return (time() - self::niceDate($at)->getTimestamp()) < self::RETRY_AFTER;
+ }
+
+ /**
+ * Stamps the attempt and stores its outcome.
+ *
+ * An empty error is success. The stamp is written either way, because
+ * it is what the retry cooldown reads.
+ *
+ * @param HostDirectory $Directory the observation
+ * @param string $error the failure, or '' for success
+ *
+ * @return void
+ */
+ private static function _record(HostDirectory $Directory, $error)
+ {
+ $Directory
+ ->set('placementAt', self::stamp())
+ ->set('placementError', substr(trim((string)$error), 0, 255))
+ ->save();
+ }
+
+ /**
+ * Now, on the clock the database stores.
+ *
+ * niceDate() with an explicit storage timezone, not date(): FOG writes
+ * datetimes on storageTimeZone() and reads them back the same way, and
+ * mixing that with PHP's default zone is what made a one-second user
+ * session read as five hours and blanked a report column twice.
+ *
+ * @return string
+ */
+ private static function stamp()
+ {
+ return self::niceDate()
+ ->setTimezone(self::storageTimeZone())
+ ->format('Y-m-d H:i:s');
+ }
+
+ /**
+ * The bind password, as typed.
+ *
+ * Three shapes have to read back, because FOG's own settings accept all
+ * three: what an admin types into the configuration page (raw), what a
+ * script may store (base64), and an aesdecrypt-able value written by an
+ * older tool. aesdecrypt() returns anything without a `|` unchanged, so
+ * it is safe to run over all of them.
+ *
+ * The base64 test is STRICT, deliberately, and this is where the LDAP
+ * plugin's version of this probe goes wrong. It asks
+ * `if ($x = base64_decode($test))`, and non-strict base64_decode does not
+ * fail on a non-base64 string -- it skips the characters outside the
+ * alphabet and decodes whatever is left. Feed it an ordinary password and
+ * it hands back a few bytes of garbage, which mb_detect_encoding will
+ * accept as UTF-8 often enough to matter, and FOG then binds with a
+ * string the admin never typed. Round-tripping the encode is the only
+ * check that actually distinguishes the two.
+ *
+ * @return string
+ */
+ private static function _bindPassword()
+ {
+ return self::decodeStored(
+ (string)self::getSetting('FOG_DIRECTORY_BIND_PASSWORD')
+ );
+ }
+
+ /**
+ * One of FOG's stored secrets, as it was typed.
+ *
+ * Public because DirectoryJoin reads the host's `hostADPass` with the
+ * same three shapes and the same trap; a third copy of the dance is how
+ * the buggy version in `Client\HostnameChanger` came to exist.
+ *
+ * @param string $stored what the column or setting holds
+ *
+ * @return string
+ */
+ public static function decodeStored($stored)
+ {
+ $pass = trim((string)$stored);
+ if ('' === $pass) {
+ return '';
+ }
+ $pass = (string)self::aesdecrypt($pass);
+ $decoded = base64_decode($pass, true);
+ if (false !== $decoded
+ && '' !== $decoded
+ && base64_encode($decoded) === $pass
+ && mb_detect_encoding($decoded, 'utf-8', true)
+ ) {
+ return $decoded;
+ }
+ return $pass;
+ }
+}
diff --git a/packages/web/src/Agent/Enrollment.php b/packages/web/src/Agent/Enrollment.php
new file mode 100644
index 0000000000..9b7adabd5b
--- /dev/null
+++ b/packages/web/src/Agent/Enrollment.php
@@ -0,0 +1,741 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Base\FOGCore;
+use FOG\Base\SmbiosIdentity;
+use FOG\Items\AgentEnrollment;
+use FOG\Items\AgentEnrollToken;
+use FOG\Items\Host;
+use FOG\Items\Inventory;
+use FOG\Managers\HostManager;
+use FOG\Router\Route;
+
+/**
+ * fog-agent enrollment: decides whether a key may act as a host.
+ *
+ * The wire contract is the agent's docs/design/protocol-v1.md. In one
+ * sentence: a stranger presents a firmware identity, a MAC list and a CSR,
+ * and nothing is issued until an admin clicks Approve, a valid enrollment
+ * token was presented, or this server itself imaged that host recently
+ * enough that the deploy counts as the approval.
+ *
+ * Two questions are kept apart on purpose. WHICH host is this is answered by
+ * the SMBIOS tuple and the MACs, the same evidence PXE boot uses, through the
+ * same resolver. IS it that host is answered by the certificate this class
+ * issues, and only after one of the three approvals. The identity is
+ * discoverable by anyone on the network, so it may resolve but never
+ * authenticate; that is why a known host with no agent still waits for a
+ * click unless a token or a deploy vouches for it -- otherwise anyone able
+ * to spoof its firmware values could collect its desired state, which may
+ * carry a directory-join credential.
+ *
+ * Signing follows nodecert.php exactly: the CSR is staged to disk and a
+ * root-owned helper signs it through sudo. This class never reads a CA key
+ * (ADR 0036).
+ *
+ * @category Enrollment
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class Enrollment extends FOGBase
+{
+ const PROTOCOL = 1;
+
+ const REASON_UNKNOWN = 'unknown-host';
+ const REASON_KNOWN = 'known-host-no-agent';
+ const REASON_REBIND = 'rebind';
+ const REASON_CONFLICT = 'identity-conflict';
+ const REASON_REISSUE = 'reissue';
+ const REASON_NO_MAC = 'no-mac';
+
+ const VIA_TOKEN = 'token';
+ const VIA_DEPLOY = 'deploy';
+ const VIA_ADMIN = 'admin';
+
+ /**
+ * Seconds the agent is told to wait before repeating a pending request.
+ */
+ const RETRY_AFTER = 300;
+
+ /**
+ * Agent JSON key => inventory field, in SmbiosIdentity::FIELDS terms.
+ *
+ * @var array
+ */
+ const IDENTITY_MAP = [
+ 'system_uuid' => 'sysuuid',
+ 'system_serial' => 'sysserial',
+ 'board_serial' => 'mbserial',
+ 'chassis_asset' => 'caseasset'
+ ];
+
+ /**
+ * Handles one enroll request.
+ *
+ * @param array $body the decoded JSON body
+ * @param string $remoteIP the caller's address, for the row and the log
+ *
+ * @return array [int HTTP code, array JSON payload]
+ */
+ public static function handle(array $body, $remoteIP)
+ {
+ if ((int)($body['protocol'] ?? 0) !== self::PROTOCOL) {
+ return [426, ['status' => 'unsupported', 'reason' => 'protocol']];
+ }
+ $csr = (string)($body['csr_pem'] ?? '');
+ $fingerprint = self::fingerprint($csr);
+ if (null === $fingerprint) {
+ return [400, ['status' => 'error', 'reason' => 'csr']];
+ }
+ $identity = is_array($body['identity'] ?? null) ? $body['identity'] : [];
+ $macs = self::_macs($identity['macs'] ?? []);
+ $token = trim((string)($body['token'] ?? ''));
+
+ $ids = Route::getIds('agentenrollment', ['fingerprint' => $fingerprint], 'id');
+ $Row = count($ids) ? new AgentEnrollment((int)array_shift($ids)) : null;
+ if ($Row && !$Row->isValid()) {
+ $Row = null;
+ }
+ $now = self::niceDate()->format('Y-m-d H:i:s');
+
+ // A repeat while the answer already exists. The agent polls the same
+ // request every few minutes; the row is the memory of what was
+ // decided about that key, so the decision is answered from it and
+ // never re-derived from the identity, which the caller controls.
+ if ($Row) {
+ $Row->set('updated', $now)
+ ->set('remoteIP', (string)$remoteIP)
+ ->set('agentVersion', (string)($body['agent_version'] ?? ''));
+ switch ($Row->get('state')) {
+ case AgentEnrollment::STATE_DENIED:
+ $Row->save();
+ return [403, ['status' => 'denied', 'reason' => 'admin']];
+ case AgentEnrollment::STATE_ISSUED:
+ $cert = (string)$Row->get('cert');
+ if ($cert !== '') {
+ // Approved since the last poll. Hand it over once.
+ $Row->set('cert', '')->save();
+ return [200, self::_issuedPayload($Row, $cert)];
+ }
+ // Same key, certificate already collected: the agent lost
+ // its certificate but kept its key. Not automatic -- an
+ // admin looks at it, the same as a rebind.
+ $Row->set('state', AgentEnrollment::STATE_PENDING)
+ ->set('reason', self::REASON_REISSUE)
+ ->save();
+ self::_audit($Row, 'waiting: ' . self::REASON_REISSUE);
+ return [202, self::_pendingPayload($Row)];
+ default:
+ // Still pending. The automatic paths are re-checked: a token
+ // may be valid now, or the deploy that vouches for this host
+ // may have finished since the agent first asked.
+ $Row->save();
+ $via = self::_autoApproval($Row, $token);
+ if ($via) {
+ return self::_issueNow($Row, $via, $remoteIP);
+ }
+ return [202, self::_pendingPayload($Row)];
+ }
+ }
+
+ // First contact for this key. Resolve the host the way boot does.
+ list($hostID, $reason) = self::_resolve($identity, $macs);
+
+ $Row = (new AgentEnrollment())
+ ->set('fingerprint', $fingerprint)
+ ->set('csr', $csr)
+ ->set('identity', json_encode($identity))
+ ->set('hostname', (string)($body['hostname'] ?? ''))
+ ->set('os', (string)($body['os'] ?? ''))
+ ->set('arch', (string)($body['arch'] ?? ''))
+ ->set('agentVersion', (string)($body['agent_version'] ?? ''))
+ ->set('remoteIP', (string)$remoteIP)
+ ->set('hostID', $hostID)
+ ->set('reason', $reason)
+ ->set('state', AgentEnrollment::STATE_PENDING)
+ ->set('cert', '')
+ ->set('created', $now)
+ ->set('updated', $now);
+
+ if (0 === $hostID && self::REASON_UNKNOWN === $reason) {
+ // Nobody has seen this machine. It becomes a pending host, the
+ // same thing the current client's auto-registration produces,
+ // so the admin sees it in the one place they already look.
+ // Needs a MAC: a host without a primary MAC is not a host FOG
+ // can address.
+ if (empty($macs)) {
+ $Row->set('reason', self::REASON_NO_MAC)->save();
+ self::_audit($Row, 'waiting: no MAC address reported');
+ return [202, self::_pendingPayload($Row)];
+ }
+ $hostID = self::_createPendingHost($Row, $identity, $macs);
+ $Row->set('hostID', $hostID);
+ }
+ $Row->save();
+
+ $via = self::_autoApproval($Row, $token);
+ if ($via) {
+ return self::_issueNow($Row, $via, $remoteIP);
+ }
+ self::_audit($Row, 'waiting: ' . $Row->get('reason'));
+ return [202, self::_pendingPayload($Row)];
+ }
+
+ /**
+ * An admin approves a pending request: the CSR is signed and the host
+ * bound. The agent collects the certificate on its next poll.
+ *
+ * @param int $id the enrollment row
+ * @param string $by the approving user's name, for the row and the audit
+ *
+ * @throws \RuntimeException with an HTTP code when it cannot be done
+ *
+ * @return AgentEnrollment
+ */
+ public static function approve($id, $by)
+ {
+ $Row = new AgentEnrollment((int)$id);
+ if (!$Row->isValid()) {
+ throw new \RuntimeException('no such enrollment', 404);
+ }
+ if (AgentEnrollment::STATE_PENDING !== $Row->get('state')) {
+ throw new \RuntimeException('enrollment is not pending', 409);
+ }
+ if ((int)$Row->get('hostID') < 1) {
+ throw new \RuntimeException('enrollment is not bound to a host', 409);
+ }
+ $cert = self::_issue($Row, self::VIA_ADMIN, (string)$by);
+ $Row->set('cert', $cert)->save();
+ return $Row;
+ }
+
+ /**
+ * An admin denies a pending request. The key stays denied: repeats of
+ * the same request are answered from the row without re-deciding.
+ *
+ * @param int $id the enrollment row
+ * @param string $by the denying user's name
+ *
+ * @throws \RuntimeException with an HTTP code when it cannot be done
+ *
+ * @return AgentEnrollment
+ */
+ public static function deny($id, $by)
+ {
+ $Row = new AgentEnrollment((int)$id);
+ if (!$Row->isValid()) {
+ throw new \RuntimeException('no such enrollment', 404);
+ }
+ if (AgentEnrollment::STATE_PENDING !== $Row->get('state')) {
+ throw new \RuntimeException('enrollment is not pending', 409);
+ }
+ $Row->set('state', AgentEnrollment::STATE_DENIED)
+ ->set('decided', self::niceDate()->format('Y-m-d H:i:s'))
+ ->set('decidedBy', (string)$by)
+ ->set('decidedVia', self::VIA_ADMIN)
+ ->set('cert', '')
+ ->save();
+ self::_audit($Row, 'denied by ' . $by, (string)$by);
+ return $Row;
+ }
+
+ /**
+ * The sha256 of the CSR's SubjectPublicKeyInfo, hex. Null when the CSR
+ * does not parse or carries no usable key.
+ *
+ * The public key, not the CSR bytes: the same key in two differently
+ * encoded requests must land on the same row, and the certificate a
+ * client later presents is matched to the host by this same value.
+ *
+ * @param string $csrPEM the request
+ *
+ * @return string|null
+ */
+ public static function fingerprint($csrPEM)
+ {
+ if (strpos($csrPEM, '-----BEGIN CERTIFICATE REQUEST-----') === false) {
+ return null;
+ }
+ // Same bytes Principal::verify() hashes out of the issued
+ // certificate, so the binding survives from CSR to client cert.
+ return Principal::spkiFingerprint(@openssl_csr_get_public_key($csrPEM));
+ }
+
+ /**
+ * Resolves the host the request is about.
+ *
+ * Firmware first, under the same setting boot uses (FOG_HOST_IDENTIFY_SMBIOS
+ * off means MAC only), then the MAC list. Both answering with different
+ * hosts is reported, not guessed at: the firmware's answer is kept, as
+ * enforce mode would, and the admin sees the conflict as the reason.
+ *
+ * @param array $identity the identity block from the request
+ * @param array $macs validated MACs
+ *
+ * @return array [int hostID, string reason]
+ */
+ private static function _resolve(array $identity, array $macs)
+ {
+ $smbiosID = null;
+ if ('off' !== FOGCore::getSetting('FOG_HOST_IDENTIFY_SMBIOS')) {
+ $ids = [];
+ foreach (self::IDENTITY_MAP as $key => $field) {
+ $ids[$field] = SmbiosIdentity::canonicalize(
+ (string)($identity[$key] ?? '')
+ );
+ }
+ $smbiosID = HostManager::resolveHostBySmbios($ids);
+ }
+ $macID = 0;
+ if (!empty($macs)) {
+ try {
+ (new HostManager())->getHostByMacAddresses($macs);
+ if (self::$Host->isValid() && !self::$Host->get('pending')) {
+ $macID = (int)self::$Host->get('id');
+ }
+ } catch (\Exception $e) {
+ $macID = 0;
+ }
+ }
+ $hostID = (int)($smbiosID ?: $macID);
+ if ($hostID < 1) {
+ return [0, self::REASON_UNKNOWN];
+ }
+ if ($smbiosID && $macID && (int)$smbiosID !== $macID) {
+ return [(int)$smbiosID, self::REASON_CONFLICT];
+ }
+ $Host = new Host($hostID);
+ if ('' !== (string)$Host->get('agentFingerprint')) {
+ return [$hostID, self::REASON_REBIND];
+ }
+ return [$hostID, self::REASON_KNOWN];
+ }
+
+ /**
+ * The two approvals that need no click. Returns the via, or '' when
+ * the request has to wait for an admin.
+ *
+ * @param AgentEnrollment $Row the request
+ * @param string $token the token presented, if any
+ *
+ * @return string
+ */
+ private static function _autoApproval(AgentEnrollment $Row, $token)
+ {
+ if ('' !== $token && self::_consumeToken($token)) {
+ return self::VIA_TOKEN;
+ }
+ // A deploy vouches only for the host it imaged, and only for a
+ // request that is a first binding or a rebind of that host. It never
+ // resolves a conflict and never creates a host.
+ $hostID = (int)$Row->get('hostID');
+ if ($hostID > 0
+ && in_array($Row->get('reason'), [self::REASON_KNOWN, self::REASON_REBIND], true)
+ && self::_recentDeploy(new Host($hostID))
+ ) {
+ return self::VIA_DEPLOY;
+ }
+ return '';
+ }
+
+ /**
+ * Did this server complete a deploy to the host recently enough?
+ *
+ * hostLastDeploy is written when an imaging task completes, so it is
+ * exactly "this server put an operating system on that machine". The
+ * window is FOG_AGENT_ENROLL_DEPLOY_WINDOW hours; 0 turns the path off.
+ *
+ * @param Host $Host the host
+ *
+ * @return bool
+ */
+ private static function _recentDeploy(Host $Host)
+ {
+ $hours = (int)FOGCore::getSetting('FOG_AGENT_ENROLL_DEPLOY_WINDOW');
+ $deployed = (string)$Host->get('deployed');
+ if ($hours < 1 || !self::validDate($deployed)) {
+ return false;
+ }
+ $when = strtotime($deployed);
+ return $when !== false && (time() - $when) <= $hours * 3600;
+ }
+
+ /**
+ * Validates a token and consumes one use. Only the hash is stored.
+ *
+ * @param string $token the token as presented
+ *
+ * @return bool
+ */
+ private static function _consumeToken($token)
+ {
+ $hash = hash('sha256', $token);
+ $ids = Route::getIds('agentenrolltoken', ['hash' => $hash], 'id');
+ if (!count($ids)) {
+ return false;
+ }
+ $Token = new AgentEnrollToken((int)array_shift($ids));
+ if (!$Token->isValid()) {
+ return false;
+ }
+ $expires = (string)$Token->get('expires');
+ if (self::validDate($expires) && strtotime($expires) < time()) {
+ return false;
+ }
+ $uses = (int)$Token->get('uses');
+ if (0 === $uses) {
+ return false;
+ }
+ if ($uses > 0) {
+ $Token->set('uses', $uses - 1)->save();
+ }
+ return true;
+ }
+
+ /**
+ * Creates the pending host an unknown machine becomes, with an
+ * inventory row carrying the firmware identity so the next boot or
+ * request resolves to it.
+ *
+ * @param AgentEnrollment $Row the request
+ * @param array $identity the identity block
+ * @param array $macs validated MACs, at least one
+ *
+ * @return int the new host id
+ */
+ private static function _createPendingHost(AgentEnrollment $Row, array $identity, array $macs)
+ {
+ $name = (string)$Row->get('hostname');
+ $Probe = new Host();
+ if ('' === $name || !$Probe->isHostnameSafe($name)) {
+ // Fifteen characters, the NetBIOS bound isHostnameSafe enforces.
+ $name = 'agent-' . substr((string)$Row->get('fingerprint'), 0, 8);
+ }
+ $base = $name;
+ $n = 1;
+ while ((new HostManager())->exists($name)) {
+ $suffix = '-' . $n++;
+ $name = substr($base, 0, 15 - strlen($suffix)) . $suffix;
+ }
+ $Host = (new Host())
+ ->set('name', $name)
+ ->set('description', _('Pending Registration created by FOG_AGENT'))
+ ->set('imageID', null)
+ ->set('pending', '1')
+ // The default modules, as Boot\Registration and the host add
+ // form attach them: Resolver::resolveModules() has no default
+ // tier, so a host created without these has every capability
+ // off until an admin visits its Modules tab. Found when the
+ // first agent-created host polled and got no capabilities.
+ ->set('modules', Route::getIds('module', ['isDefault' => 1]))
+ ->addPriMAC(array_shift($macs));
+ $Host->save();
+ $hostID = (int)$Host->get('id');
+ // After save, not before: addMAC() writes the hostMAC rows
+ // immediately with whatever id the object holds, and an unsaved
+ // host holds none -- the batch guard in FOGManagerController then
+ // rejects the empty hostID and the whole enroll dies with a 500.
+ // addPriMAC() is different: it only stages the primary, and
+ // Host::save() writes that row itself once the id exists.
+ if (!empty($macs)) {
+ $Host->addMAC($macs);
+ }
+
+ $ids = [];
+ foreach (self::IDENTITY_MAP as $key => $field) {
+ $ids[$field] = SmbiosIdentity::canonicalize((string)($identity[$key] ?? ''));
+ }
+ $usable = SmbiosIdentity::usable($ids);
+ if (!empty($usable)) {
+ $Inventory = (new Inventory())->set('hostID', $hostID);
+ foreach ($usable as $field => $value) {
+ $Inventory->set($field, $value);
+ }
+ $Inventory->save();
+ }
+ return $hostID;
+ }
+
+ /**
+ * An enrolled agent renews its certificate over its own mTLS session.
+ *
+ * Same key only. The presented certificate proved the caller holds the
+ * key bound to this host, and the request is signed for that same key,
+ * so nothing an admin decided changes: the binding, the host, the
+ * subject. A different key is a new claim on the machine and goes
+ * through enroll, where it pends as a rebind for an admin. The old
+ * certificate is not revoked -- it binds to the same key and expires on
+ * its own -- and there is nothing to revoke it with; the binding is the
+ * only thing the server checks.
+ *
+ * @param Host $Host the principal the gate bound
+ * @param string $csrPEM the request, for the bound key
+ *
+ * @throws \RuntimeException with an HTTP code when refused
+ *
+ * @return string the leaf followed by the issuing chain, PEM
+ */
+ public static function renew(Host $Host, $csrPEM)
+ {
+ $fingerprint = self::fingerprint((string)$csrPEM);
+ if (null === $fingerprint) {
+ throw new \RuntimeException('csr_pem is not a certificate request', 400);
+ }
+ if (!hash_equals((string)$Host->get('agentFingerprint'), $fingerprint)) {
+ throw new \RuntimeException('the request is not for the key this certificate proved', 400);
+ }
+ list($leaf, $chain) = self::_sign((string)$csrPEM, (int)$Host->get('id'));
+ $parsed = openssl_x509_parse($leaf);
+ $notAfter = is_array($parsed) && isset($parsed['validTo_time_t'])
+ ? gmdate('Y-m-d H:i:s', (int)$parsed['validTo_time_t'])
+ : null;
+ // The manager rather than Host::save(), as agentPoll does: a save
+ // rewrites the MAC association, and renewal is a routine call.
+ (new HostManager())->update(
+ ['id' => (int)$Host->get('id')],
+ '',
+ [
+ 'agentNotAfter' => $notAfter,
+ 'agentCheckin' => self::niceDate()->format('Y-m-d H:i:s')
+ ]
+ );
+ Audit::record(
+ [
+ 'type' => 'agent.enroll',
+ 'subjectType' => 'host',
+ 'subjectID' => (int)$Host->get('id'),
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'text' => sprintf(
+ 'certificate renewed to %s, key %s',
+ (string)$notAfter,
+ substr($fingerprint, 0, 16)
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ return $leaf . $chain;
+ }
+
+ /**
+ * Issues on an automatic path and answers the agent in the same
+ * request.
+ *
+ * @param AgentEnrollment $Row the request
+ * @param string $via token or deploy
+ * @param string $remoteIP the caller
+ *
+ * @return array [int, array]
+ */
+ private static function _issueNow(AgentEnrollment $Row, $via, $remoteIP)
+ {
+ try {
+ $cert = self::_issue($Row, $via, '');
+ } catch (\RuntimeException $e) {
+ error_log(
+ sprintf(
+ 'FOG agent enroll: signing for host %d from %s failed: %s',
+ (int)$Row->get('hostID'),
+ $remoteIP,
+ $e->getMessage()
+ )
+ );
+ return [503, ['status' => 'error', 'reason' => 'signing']];
+ }
+ // Collected in this response; nothing left in the row to hand out.
+ $Row->set('cert', '')->save();
+ return [200, self::_issuedPayload($Row, $cert)];
+ }
+
+ /**
+ * Signs the stored CSR for the bound host, binds the fingerprint to the
+ * host, marks the row issued and audits it. Returns the PEM the agent
+ * gets: the leaf followed by the issuing chain.
+ *
+ * A pending host approved this way stops being pending: approving the
+ * agent is approving the machine.
+ *
+ * @param AgentEnrollment $Row the request
+ * @param string $via token, deploy or admin
+ * @param string $by the admin, or '' on an automatic path
+ *
+ * @throws \RuntimeException when the helper refuses
+ *
+ * @return string
+ */
+ private static function _issue(AgentEnrollment $Row, $via, $by)
+ {
+ $hostID = (int)$Row->get('hostID');
+ $Host = new Host($hostID);
+ if (!$Host->isValid()) {
+ throw new \RuntimeException('host no longer exists', 409);
+ }
+ list($leaf, $chain) = self::_sign((string)$Row->get('csr'), $hostID);
+ $parsed = openssl_x509_parse($leaf);
+ $notAfter = is_array($parsed) && isset($parsed['validTo_time_t'])
+ ? gmdate('Y-m-d H:i:s', (int)$parsed['validTo_time_t'])
+ : null;
+ $now = self::niceDate()->format('Y-m-d H:i:s');
+
+ $Host->set('agentFingerprint', (string)$Row->get('fingerprint'))
+ ->set('agentNotAfter', $notAfter)
+ ->set('agentVersion', (string)$Row->get('agentVersion'))
+ ->set('agentCheckin', $now);
+ if ($Host->get('pending')) {
+ $Host->set('pending', '0');
+ }
+ $Host->save();
+
+ $Row->set('state', AgentEnrollment::STATE_ISSUED)
+ ->set('decided', $now)
+ ->set('decidedBy', (string)$by)
+ ->set('decidedVia', $via)
+ ->save();
+ self::_audit(
+ $Row,
+ sprintf('issued via %s, key %s', $via, substr((string)$Row->get('fingerprint'), 0, 16)),
+ (string)$by
+ );
+ return $leaf . $chain;
+ }
+
+ /**
+ * The staging-and-sudo handshake nodecert.php uses, for the agent type.
+ * The helper builds the subject from the host id it reads out of the
+ * staged file; nothing in the CSR's subject is used.
+ *
+ * @param string $csr the request, PEM
+ * @param int $hostID the host to name in the certificate
+ *
+ * @throws \RuntimeException when the helper refuses
+ *
+ * @return array [leaf PEM, chain PEM]
+ */
+ private static function _sign($csr, $hostID)
+ {
+ $staging = FOG_BASE_DIR . DS . 'nodecert-staging';
+ if (!is_dir($staging) || !is_writable($staging)) {
+ throw new \RuntimeException('agent certificate issuance is not configured', 503);
+ }
+ $reqid = bin2hex(openssl_random_pseudo_bytes(16));
+ $csrfile = $staging . DS . $reqid . '.csr';
+ $hostfile = $staging . DS . $reqid . '.agent';
+ $outfile = $staging . DS . $reqid . '.pem';
+ $chainfile = $staging . DS . $reqid . '.chain';
+ file_put_contents($csrfile, $csr);
+ file_put_contents($hostfile, (int)$hostID . "\n");
+ $cmd = 'sudo -n '
+ . escapeshellarg(rtrim(FOG_BASE_DIR, DS) . '/bin/fog-sign-node-cert')
+ . ' agent ' . escapeshellarg($reqid) . ' 2>&1';
+ $output = shell_exec($cmd);
+ $leaf = file_exists($outfile) ? file_get_contents($outfile) : '';
+ $chain = file_exists($chainfile) ? file_get_contents($chainfile) : '';
+ foreach ([$csrfile, $hostfile, $outfile, $chainfile] as $tmp) {
+ if (file_exists($tmp)) {
+ unlink($tmp);
+ }
+ }
+ if (!$leaf) {
+ throw new \RuntimeException(trim((string)$output) ?: 'signing failed', 503);
+ }
+ return [$leaf, $chain];
+ }
+
+ /**
+ * Validated, lower-cased, de-duplicated MACs from the request.
+ *
+ * @param mixed $macs whatever the agent sent
+ *
+ * @return array
+ */
+ private static function _macs($macs)
+ {
+ $out = [];
+ foreach ((array)$macs as $mac) {
+ $mac = strtolower(trim((string)$mac));
+ if (filter_var($mac, FILTER_VALIDATE_MAC)) {
+ $out[$mac] = $mac;
+ }
+ }
+ return array_values($out);
+ }
+
+ /**
+ * The 202 body.
+ *
+ * @param AgentEnrollment $Row the request
+ *
+ * @return array
+ */
+ private static function _pendingPayload(AgentEnrollment $Row)
+ {
+ return [
+ 'status' => 'pending',
+ 'reason' => (string)$Row->get('reason'),
+ 'retry_after' => self::RETRY_AFTER
+ ];
+ }
+
+ /**
+ * The 200 body.
+ *
+ * @param AgentEnrollment $Row the request
+ * @param string $cert leaf plus chain, PEM
+ *
+ * @return array
+ */
+ private static function _issuedPayload(AgentEnrollment $Row, $cert)
+ {
+ $Host = new Host((int)$Row->get('hostID'));
+ return [
+ 'status' => 'issued',
+ 'host_id' => (int)$Row->get('hostID'),
+ 'certificate_pem' => $cert,
+ 'not_after' => (string)$Host->get('agentNotAfter')
+ ];
+ }
+
+ /**
+ * Every decision leaves a row. An agent that was let in without a
+ * trail is the thing an admin cannot answer questions about later.
+ *
+ * @param AgentEnrollment $Row the request
+ * @param string $text what happened
+ * @param string $by the admin, or '' for the agent itself
+ *
+ * @return void
+ */
+ private static function _audit(AgentEnrollment $Row, $text, $by = '')
+ {
+ $hostID = (int)$Row->get('hostID');
+ $label = $hostID > 0 ? (string)(new Host($hostID))->get('name') : (string)$Row->get('hostname');
+ $row = [
+ 'type' => 'agent.enroll',
+ 'subjectType' => 'host',
+ 'subjectID' => $hostID,
+ 'subjectLabel' => $label,
+ 'renderable' => 1,
+ 'text' => $text
+ ];
+ if ('' === $by) {
+ $row['authSource'] = Audit::SOURCE_ANONYMOUS;
+ }
+ Audit::record($row);
+ }
+}
diff --git a/packages/web/src/Agent/InventoryFacts.php b/packages/web/src/Agent/InventoryFacts.php
new file mode 100644
index 0000000000..0a318b6ddd
--- /dev/null
+++ b/packages/web/src/Agent/InventoryFacts.php
@@ -0,0 +1,128 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+use FOG\Items\Inventory;
+
+/**
+ * Writes a reported hardware block into FOG's existing `inventory` row
+ * (design 0006 section 3).
+ *
+ * The table is reused rather than replaced: the Host "Inventory" tab and
+ * the Hardware report already read it, so an agent-reported machine and an
+ * FOS-imaged one look the same to every consumer. What is not reused is the
+ * legacy transport -- base64 form fields authenticated by a MAC address --
+ * because the agent already has an mTLS channel bound to exactly one host.
+ *
+ * Named InventoryFacts, not Inventory, to stay distinct from
+ * FOG\Items\Inventory, which is the row this writes.
+ *
+ * @category Inventory
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class InventoryFacts extends FOGBase
+{
+ /**
+ * The only properties an agent may set.
+ *
+ * A whitelist, not a filter over the class's field map: `inventory`
+ * also carries `primaryUser`, `other1`, `other2` and `deleteDate`,
+ * which are an admin's to set. Passing a reported block straight into
+ * set() would let a host rewrite its own asset tags.
+ *
+ * @var string[]
+ */
+ const FIELDS = [
+ 'sysman', 'sysproduct', 'sysversion', 'sysserial', 'sysuuid',
+ 'systype', 'biosvendor', 'biosversion', 'biosdate',
+ 'mbman', 'mbproductname', 'mbversion', 'mbserial', 'mbasset',
+ 'cpuman', 'cpuversion', 'cpucurrent', 'cpumax', 'mem',
+ 'hdmodel', 'hdserial', 'hdfirmware',
+ 'caseman', 'casever', 'caseserial', 'caseasset',
+ 'gpuvendors', 'gpuproducts'
+ ];
+
+ /**
+ * Longest value stored for any one property. The columns are varchars
+ * and MySQL in strict mode refuses an overlong value, failing the whole
+ * poll; truncating keeps a hostile or merely odd DMI string from
+ * costing the host its check-in.
+ */
+ const MAX_VALUE = 250;
+
+ /**
+ * Records a reported hardware block on the host's inventory row.
+ *
+ * Upsert rather than insert: a host has exactly one inventory row, and
+ * enrollment has usually already created it with the four SMBIOS
+ * identity fields. Only the whitelisted properties move.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param array $block the reported properties
+ *
+ * @return void
+ */
+ public static function report(Host $Host, array $block)
+ {
+ $hostID = (int)$Host->get('id');
+ $Inventory = $Host->get('inventory');
+ if (!$Inventory instanceof \FOG\Items\Inventory
+ || !$Inventory->isValid()
+ ) {
+ $Inventory = (new Inventory())->set('hostID', $hostID);
+ }
+ $changed = [];
+ foreach (self::FIELDS as $field) {
+ if (!array_key_exists($field, $block)) {
+ continue;
+ }
+ $value = substr(trim((string)$block[$field]), 0, self::MAX_VALUE);
+ if ((string)$Inventory->get($field) === $value) {
+ continue;
+ }
+ $changed[] = $field;
+ $Inventory->set($field, $value);
+ }
+ if (empty($changed)) {
+ return;
+ }
+ $Inventory->save();
+ // One renderable line on the host, so a disk swap or a BIOS update
+ // shows up where an admin already looks for what changed. The
+ // field names, not the values: an inventory row is a page of
+ // strings and the audit text is not the place to copy it.
+ Audit::record(
+ [
+ 'type' => 'agent.inventory',
+ 'subjectType' => 'host',
+ 'subjectID' => $hostID,
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'affectedCount' => count($changed),
+ 'text' => substr(
+ 'agent reported inventory: ' . implode(', ', $changed),
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+}
diff --git a/packages/web/src/Agent/NetworkFacts.php b/packages/web/src/Agent/NetworkFacts.php
new file mode 100644
index 0000000000..49856a615f
--- /dev/null
+++ b/packages/web/src/Agent/NetworkFacts.php
@@ -0,0 +1,299 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+
+/**
+ * Reconciles a reported network block into `hostNetwork` (design 0011
+ * section 3).
+ *
+ * A fact report like InventoryFacts, registered the same way: an entry in
+ * State::FACT_REPORTS and a block in the poll, never a route of its own
+ * (the route rule, protocol-v1.md).
+ *
+ * The contrast to draw is with `hosts.hostIP`, which this does not replace.
+ * hostIP is one address with no prefix and no interface behind it, resolved
+ * whenever FOG last looked; these rows are the machine's own account of its
+ * links. The difference matters because a prefix is what turns an address
+ * into a LINK, and "which awake machine is on the same link as this
+ * sleeping one" is the question the wake relay is built out of.
+ *
+ * There is deliberately no audit line here. Interfaces move whenever a
+ * laptop changes desk, a VPN comes up or a container engine starts, and an
+ * audit entry per event would bury the results that matter under noise
+ * nobody asked for.
+ *
+ * @category WakeRelay
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class NetworkFacts extends FOGBase
+{
+ /**
+ * Most interface addresses accepted from one host.
+ *
+ * A machine running containers legitimately carries dozens, so this is
+ * generous rather than tight. It is here because the list is input from
+ * an enrolled but otherwise untrusted host: a machine claiming a
+ * million interfaces must fail this check rather than the database.
+ */
+ const MAX_INTERFACES = 128;
+
+ /**
+ * Column widths, so an overlong value is truncated here rather than
+ * failing the insert under strict mode and costing the host its poll.
+ */
+ const WIDTHS = [
+ 'name' => 255,
+ 'mac' => 17,
+ 'ipv4' => 15,
+ 'network' => 15,
+ 'broadcast' => 15
+ ];
+
+ /**
+ * Records the host's current interfaces.
+ *
+ * The list is complete by contract: any address currently recorded for
+ * this host and absent from it is gone. That is why the agent sends no
+ * block at all when it could not read its interfaces -- an empty list
+ * here means "this machine is on no link", and would clear every row it
+ * has (design 0006 section 6).
+ *
+ * @param Host $Host the host the certificate bound
+ * @param array $block the reported network block
+ *
+ * @throws \RuntimeException with an HTTP code when refused
+ *
+ * @return void
+ */
+ public static function report(Host $Host, array $block)
+ {
+ $list = $block['interfaces'] ?? [];
+ if (!is_array($list)) {
+ $list = [];
+ }
+ if (count($list) > self::MAX_INTERFACES) {
+ throw new \RuntimeException('interface list too large', 413);
+ }
+
+ $hostID = (int)$Host->get('id');
+ $incoming = self::clean($list);
+ $now = self::niceDate()->setTimezone(self::storageTimeZone())
+ ->format('Y-m-d H:i:s');
+
+ // Replace the set, in one transaction so nothing observes the
+ // intermediate empty state -- which matters more here than it does
+ // for printers, because a wake relay running against the empty
+ // moment would conclude the estate had no machine on any link.
+ self::$DB->query('START TRANSACTION');
+ try {
+ self::$DB->query(
+ 'DELETE FROM `hostNetwork` WHERE `hnHostID`=:host',
+ [],
+ [':host' => $hostID]
+ );
+ self::insert($hostID, $incoming, $now);
+ self::$DB->query('COMMIT');
+ } catch (\Exception $e) {
+ self::$DB->query('ROLLBACK');
+ throw $e;
+ }
+ }
+
+ /**
+ * Normalizes the reported list, keyed by interface name and address.
+ *
+ * Keying deduplicates: a host reporting the same address twice would
+ * otherwise hit the unique index mid-insert and roll back the whole
+ * poll.
+ *
+ * Every address is validated here rather than trusted. The agent
+ * computes the network and the broadcast itself, and this is the class
+ * that decides whether to believe it -- so both are RECOMPUTED from the
+ * address and prefix, and the reported values are discarded. A host
+ * that claimed a network address it is not on would otherwise be a host
+ * that could join any link's relay group it liked.
+ *
+ * @param array $list the reported interfaces
+ *
+ * @return array key => normalized row
+ */
+ private static function clean(array $list)
+ {
+ $out = [];
+ foreach ($list as $entry) {
+ if (!is_array($entry)) {
+ continue;
+ }
+ $row = [];
+ foreach (self::WIDTHS as $field => $width) {
+ $row[$field] = substr(
+ trim((string)($entry[$field] ?? '')),
+ 0,
+ $width
+ );
+ }
+ $prefix = (int)($entry['prefix'] ?? 0);
+ if ('' === $row['name'] || $prefix < 0 || $prefix > 32) {
+ continue;
+ }
+ $long = self::ipToLong($row['ipv4']);
+ if (null === $long) {
+ // Not an IPv4 address. Dropped rather than stored: a row
+ // with no address is on no link, so nothing reads it.
+ continue;
+ }
+ $row['prefix'] = $prefix;
+ $row['network'] = self::networkFor($long, $prefix);
+ $row['broadcast'] = self::broadcastFor($long, $prefix);
+ $row['mac'] = strtolower($row['mac']);
+ $row['up'] = !empty($entry['up']) ? 1 : 0;
+ $row['wireless'] = !empty($entry['wireless']) ? 1 : 0;
+ $out[$row['name'] . '|' . $row['ipv4']] = $row;
+ }
+
+ return $out;
+ }
+
+ /**
+ * An IPv4 address as an unsigned 32-bit integer, or null.
+ *
+ * ip2long() alone is not the check: it accepts shortened forms like
+ * `10.1` that no interface reports, so the round trip through long2ip
+ * is what pins the value to the dotted quad the agent sent.
+ *
+ * @param string $ip the address
+ *
+ * @return int|null
+ */
+ protected static function ipToLong($ip)
+ {
+ $long = ip2long($ip);
+ if (false === $long || long2ip($long) !== $ip) {
+ return null;
+ }
+
+ return $long;
+ }
+
+ /**
+ * The network address for an address and prefix.
+ *
+ * @param int $long the address
+ * @param int $prefix the prefix length
+ *
+ * @return string
+ */
+ protected static function networkFor($long, $prefix)
+ {
+ return long2ip($long & self::mask($prefix));
+ }
+
+ /**
+ * The broadcast address, empty where the link has none.
+ *
+ * A /31 is a point-to-point pair (RFC 3021) and a /32 is a host route;
+ * neither has a broadcast address, and the all-ones address on a /31
+ * names the peer rather than the link.
+ *
+ * @param int $long the address
+ * @param int $prefix the prefix length
+ *
+ * @return string
+ */
+ protected static function broadcastFor($long, $prefix)
+ {
+ if ($prefix >= 31) {
+ return '';
+ }
+
+ return long2ip($long | (~self::mask($prefix) & 0xFFFFFFFF));
+ }
+
+ /**
+ * The netmask for a prefix length, as an integer.
+ *
+ * A /0 is spelled out rather than shifted: `-1 << 32` is undefined
+ * across platforms and PHP gives back -1, which would make every host
+ * in the estate share one link.
+ *
+ * @param int $prefix the prefix length
+ *
+ * @return int
+ */
+ protected static function mask($prefix)
+ {
+ if ($prefix <= 0) {
+ return 0;
+ }
+
+ return (-1 << (32 - $prefix)) & 0xFFFFFFFF;
+ }
+
+ /**
+ * Inserts the reported interfaces.
+ *
+ * One statement rather than a row at a time, for PrinterFacts' reason:
+ * a container host with fifty interfaces would otherwise cost fifty
+ * round trips on every poll where anything moved.
+ *
+ * @param int $hostID the host
+ * @param array $incoming key => normalized row
+ * @param string $now the timestamp for this reconcile
+ *
+ * @return void
+ */
+ private static function insert($hostID, array $incoming, $now)
+ {
+ if (empty($incoming)) {
+ return;
+ }
+ $values = [];
+ $binds = [];
+ $i = 0;
+ foreach ($incoming as $row) {
+ // A distinct placeholder name per value rather than reusing one
+ // for the host id and the timestamp: a real prepared statement
+ // binds each name once, and a driver that is not emulating them
+ // rejects the repeat with a bound-parameter count error.
+ $p = ':r' . $i++ . '_';
+ $values[] = '(' . $p . 'h,' . $p . 'n,' . $p . 'm,' . $p . 'i,'
+ . $p . 'p,' . $p . 'w,' . $p . 'b,' . $p . 'u,' . $p . 'l,'
+ . $p . 'o)';
+ $binds[$p . 'h'] = (int)$hostID;
+ $binds[$p . 'n'] = $row['name'];
+ $binds[$p . 'm'] = $row['mac'];
+ $binds[$p . 'i'] = $row['ipv4'];
+ $binds[$p . 'p'] = $row['prefix'];
+ $binds[$p . 'w'] = $row['network'];
+ $binds[$p . 'b'] = $row['broadcast'];
+ $binds[$p . 'u'] = $row['up'];
+ $binds[$p . 'l'] = $row['wireless'];
+ $binds[$p . 'o'] = $now;
+ }
+ self::$DB->query(
+ 'INSERT INTO `hostNetwork` '
+ . '(`hnHostID`,`hnName`,`hnMAC`,`hnIPv4`,`hnPrefix`,`hnNetwork`,'
+ . '`hnBroadcast`,`hnUp`,`hnWireless`,`hnObservedAt`) VALUES '
+ . implode(',', $values),
+ [],
+ $binds
+ );
+ }
+}
diff --git a/packages/web/src/Agent/Principal.php b/packages/web/src/Agent/Principal.php
new file mode 100644
index 0000000000..541c7db64c
--- /dev/null
+++ b/packages/web/src/Agent/Principal.php
@@ -0,0 +1,140 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+namespace FOG\Agent;
+
+/**
+ * Turns the web server's client-certificate variables into a key
+ * fingerprint the router can bind to a host.
+ *
+ * Deliberately NOT a FOGBase: it touches no globals and no database, so
+ * tests/agent-principal.test.php can drive it with certificates minted on
+ * the spot and prove what it refuses. The host lookup is the router's.
+ *
+ * Two checks, both required, and the second is why this class exists:
+ *
+ * 1. The web server said SUCCESS. nginx and Apache both verify the chain
+ * and the validity dates before PHP ever runs; SSL_CLIENT_VERIFY is
+ * how they say so.
+ * 2. PHP verifies the chain AGAIN, against the agent CA bundle and for
+ * the client-auth purpose. The web server's trust file is whatever
+ * the vhost was written with -- on an Apache install it is also the
+ * server's own chain, and an external-CA install can point it
+ * anywhere -- so "the server accepted it" does not prove "the FOG
+ * Agent CA issued it". This check does, and it costs one X509
+ * verification per request.
+ *
+ * The binding is the SPKI fingerprint, the same sha256 of the public key
+ * that enrollment stored on the host, so a certificate whose key is not
+ * the enrolled key is not this host's agent whatever its subject says.
+ *
+ * @category Principal
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class Principal
+{
+ /**
+ * The audit authSource for a write the client certificate authorized.
+ * Not anonymous: the caller proved a key the server bound to a host.
+ */
+ const AUTH_SOURCE = 'agent';
+
+ /**
+ * sha256 of a public key's SPKI, as enrollment stores it on the host.
+ *
+ * One definition, shared by the CSR side (Enrollment::fingerprint) and
+ * the certificate side (verify) so the two can never drift apart.
+ *
+ * @param mixed $pub the public key (resource before PHP 8, object after), or false
+ *
+ * @return string|null the hex fingerprint, null for an unusable key
+ */
+ public static function spkiFingerprint($pub)
+ {
+ if (false === $pub) {
+ return null;
+ }
+ $details = openssl_pkey_get_details($pub);
+ if (!is_array($details) || empty($details['key'])) {
+ return null;
+ }
+ return hash('sha256', (string)$details['key']);
+ }
+
+ /**
+ * The PEM the web server handed over, in the form openssl wants.
+ *
+ * nginx's $ssl_client_escaped_cert is URL-encoded (its raw variant
+ * would break the fastcgi record on newlines); Apache's SSL_CLIENT_CERT
+ * is plain PEM. Tell them apart by the newline: plain PEM always has
+ * one after its BEGIN line, the escaped form carries %0A instead.
+ * NOT by "-----BEGIN" -- URL escaping leaves dashes and letters alone,
+ * so that marker survives escaping and tells you nothing.
+ *
+ * @param string $raw the variable as received
+ *
+ * @return string
+ */
+ public static function pem($raw)
+ {
+ $raw = (string)$raw;
+ if (false === strpos($raw, "\n")) {
+ $raw = rawurldecode($raw);
+ }
+ return $raw;
+ }
+
+ /**
+ * Verifies the calling agent's certificate.
+ *
+ * @param array $server the request's $_SERVER
+ * @param string $bundle path to the agent CA bundle (agent CA + root)
+ *
+ * @return array|null ['fingerprint' => sha256 hex, 'not_after' =>
+ * unix time] or null when anything is not right.
+ * Null carries no reason on purpose: the caller
+ * answers 401 either way, and the reasons are only
+ * interesting to someone with the server's logs.
+ */
+ public static function verify(array $server, $bundle)
+ {
+ if ('SUCCESS' !== (string)($server['SSL_CLIENT_VERIFY'] ?? '')) {
+ return null;
+ }
+ $pem = self::pem((string)($server['SSL_CLIENT_CERT'] ?? ''));
+ if ('' === $pem || !is_readable($bundle)) {
+ return null;
+ }
+ $cert = @openssl_x509_read($pem);
+ if (false === $cert) {
+ return null;
+ }
+ // Chain, dates and the client-auth purpose, against OUR CA. This
+ // is check 2 in the class comment and it must stay independent
+ // of what the vhost trusts.
+ if (true !== openssl_x509_checkpurpose($cert, X509_PURPOSE_SSL_CLIENT, [$bundle])) {
+ return null;
+ }
+ $parsed = openssl_x509_parse($cert);
+ $fingerprint = self::spkiFingerprint(@openssl_pkey_get_public($cert));
+ if (null === $fingerprint || !is_array($parsed)) {
+ return null;
+ }
+ return [
+ 'fingerprint' => $fingerprint,
+ 'not_after' => (int)($parsed['validTo_time_t'] ?? 0),
+ ];
+ }
+}
diff --git a/packages/web/src/Agent/PrinterFacts.php b/packages/web/src/Agent/PrinterFacts.php
new file mode 100644
index 0000000000..54ed34edea
--- /dev/null
+++ b/packages/web/src/Agent/PrinterFacts.php
@@ -0,0 +1,335 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+
+/**
+ * Reconciles a reported printer block into `hostSpooler` and `hostPrinter`
+ * (design 0010 sections 3 and 4).
+ *
+ * A fact report like InventoryFacts, and registered the same way: an entry
+ * in State::FACT_REPORTS and a block in the poll, never a route of its own
+ * (the route rule, protocol-v1.md).
+ *
+ * The contrast to draw is with `printerAssoc` next door: that is what an
+ * admin ASSIGNED. This is what the machine says it actually HAS. FOG has
+ * had the first since 1.x and has never had the second, so an install that
+ * failed has always failed silently and the client has always retried the
+ * same thing on the next poll, forever.
+ *
+ * What it does NOT do is act on the difference. Deciding that an assigned
+ * printer is missing is the report's job (design 0010 section 6), and
+ * installing one is the agent's. This class only records.
+ *
+ * @category Printers
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class PrinterFacts extends FOGBase
+{
+ /**
+ * Most queues accepted from one host.
+ *
+ * A print server can legitimately carry hundreds, so this is generous
+ * rather than tight. It is here because the list is attacker-controlled
+ * input from a host that has enrolled: a machine claiming a million
+ * queues must fail this check rather than the database.
+ */
+ const MAX_PRINTERS = 512;
+
+ /**
+ * Column widths, so an overlong value is truncated here rather than
+ * failing the insert under strict mode and costing the host its poll.
+ *
+ * The URI is the long one. A CUPS device URI can carry a full IPP path
+ * plus query parameters, and an smb:// one carries a UNC path an admin
+ * chose the length of.
+ */
+ const WIDTHS = [
+ 'name' => 255,
+ 'uri' => 1024,
+ 'driver' => 255
+ ];
+
+ /**
+ * The subsystems a host may report.
+ *
+ * An unrecognized value is stored as the empty string rather than passed
+ * through, for DirectoryFacts::KINDS' reason: the report groups on it,
+ * and a host inventing a value would put an uncontrolled string into a
+ * page an admin reads.
+ *
+ * @var string[]
+ */
+ const SUBSYSTEMS = ['cups', 'winspool'];
+
+ /**
+ * Records the host's current printer set.
+ *
+ * The list is complete by contract: any queue currently recorded for
+ * this host and absent from it is gone. That is why the agent sends no
+ * block at all when its collector could not run -- an empty list here
+ * means "this machine has no printers", and would clear every row it
+ * has (design 0006 section 6).
+ *
+ * @param Host $Host the host the certificate bound
+ * @param array $block the reported printer block
+ *
+ * @throws \RuntimeException with an HTTP code when refused
+ *
+ * @return void
+ */
+ public static function report(Host $Host, array $block)
+ {
+ $list = $block['installed'] ?? [];
+ if (!is_array($list)) {
+ $list = [];
+ }
+ if (count($list) > self::MAX_PRINTERS) {
+ throw new \RuntimeException('printer list too large', 413);
+ }
+
+ $hostID = (int)$Host->get('id');
+ $incoming = self::_clean($list, (string)($block['default'] ?? ''));
+ $now = self::niceDate()->setTimezone(self::storageTimeZone())
+ ->format('Y-m-d H:i:s');
+
+ // Replace the set, in one transaction so nothing observes the
+ // intermediate empty state. Unlike hostSoftware, rows are deleted
+ // rather than closed: a printer that is gone is gone, and "which
+ // hosts had this queue in March" is not a question anyone asks.
+ // The removal itself is in the audit line below.
+ self::$DB->query('START TRANSACTION');
+ try {
+ $before = self::_currentNames($hostID);
+ self::$DB->query(
+ 'DELETE FROM `hostPrinter` WHERE `hpHostID`=:host',
+ [],
+ [':host' => $hostID]
+ );
+ self::_insert($hostID, $incoming, $now);
+ self::_spooler($hostID, (string)($block['subsystem'] ?? ''), $now);
+ self::$DB->query('COMMIT');
+ } catch (\Exception $e) {
+ self::$DB->query('ROLLBACK');
+ throw $e;
+ }
+
+ $added = array_diff(array_keys($incoming), $before);
+ $removed = array_diff($before, array_keys($incoming));
+ if (empty($added) && empty($removed)) {
+ // A queue whose driver or default flag moved is a change worth
+ // storing and not worth a line in the audit log; the set is what
+ // an admin reads a history for.
+ return;
+ }
+ Audit::record(
+ [
+ 'type' => 'agent.printers',
+ 'subjectType' => 'host',
+ 'subjectID' => $hostID,
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'affectedCount' => count($added) + count($removed),
+ // Named, not counted. A host has single digits of printers,
+ // so the names fit -- and "Accounts-HP4550 gone" is the line
+ // an admin is looking for, where "1 removed" sends them
+ // hunting for which one.
+ 'text' => substr(
+ 'agent reported printers: '
+ . self::describe($added, $removed),
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+
+ /**
+ * Normalizes the reported list, keyed by queue name.
+ *
+ * Keying deduplicates: a host reporting the same queue twice would
+ * otherwise hit the unique index mid-insert and roll back the whole
+ * poll. A queue with no name is dropped rather than stored as a row
+ * nothing can act on -- not the report, not a removal, not the admin.
+ *
+ * @param array $list the reported queues
+ * @param string $defaultName the block's default queue name
+ *
+ * @return array name => normalized row
+ */
+ private static function _clean(array $list, $defaultName)
+ {
+ $defaultName = trim($defaultName);
+ $out = [];
+ foreach ($list as $entry) {
+ if (!is_array($entry)) {
+ continue;
+ }
+ $row = [];
+ foreach (self::WIDTHS as $field => $width) {
+ $row[$field] = substr(
+ trim((string)($entry[$field] ?? '')),
+ 0,
+ $width
+ );
+ }
+ if ('' === $row['name']) {
+ continue;
+ }
+ // The agent reports the default by NAME at the block level,
+ // not as a flag on each queue. Resolving it here is what keeps
+ // the stored flag and the reported name from ever disagreeing,
+ // and it drops a default naming a queue that is not in the list
+ // for free -- which happens after a removal that did not clear
+ // the setting, and which no action could resolve.
+ $row['isDefault'] = ($row['name'] === $defaultName) ? 1 : 0;
+ $row['shared'] = !empty($entry['shared']) ? 1 : 0;
+ $out[$row['name']] = $row;
+ }
+
+ return $out;
+ }
+
+ /**
+ * The queue names currently recorded for a host, for the audit line.
+ *
+ * @param int $hostID the host
+ *
+ * @return string[]
+ */
+ private static function _currentNames($hostID)
+ {
+ $rows = self::$DB->query(
+ 'SELECT `hpName` FROM `hostPrinter` WHERE `hpHostID`=:host',
+ [],
+ [':host' => (int)$hostID]
+ )->fetch(\PDO::FETCH_ASSOC, 'fetch_all')->get();
+ $out = [];
+ foreach ((array)$rows as $row) {
+ $out[] = (string)($row['hpName'] ?? '');
+ }
+
+ return $out;
+ }
+
+ /**
+ * Inserts the reported queues.
+ *
+ * One statement rather than a row at a time: a print server with two
+ * hundred queues would otherwise cost two hundred round trips on every
+ * poll where anything moved. No chunking, unlike SoftwareFacts --
+ * MAX_PRINTERS caps the list at 512, which is well inside what a single
+ * statement and its placeholder count accept.
+ *
+ * @param int $hostID the host
+ * @param array $incoming name => normalized row
+ * @param string $now the timestamp for this reconcile
+ *
+ * @return void
+ */
+ private static function _insert($hostID, array $incoming, $now)
+ {
+ if (empty($incoming)) {
+ return;
+ }
+ $values = [];
+ $binds = [];
+ $i = 0;
+ foreach ($incoming as $row) {
+ // A distinct placeholder name per value rather than reusing one
+ // for the host id and the timestamp: a real prepared statement
+ // binds each name once, and a driver that is not emulating them
+ // rejects the repeat with a bound-parameter count error.
+ $p = ':r' . $i++ . '_';
+ $values[] = '(' . $p . 'h,' . $p . 'n,' . $p . 'u,' . $p . 'v,'
+ . $p . 'd,' . $p . 's,' . $p . 'o)';
+ $binds[$p . 'h'] = (int)$hostID;
+ $binds[$p . 'n'] = $row['name'];
+ $binds[$p . 'u'] = $row['uri'];
+ $binds[$p . 'v'] = $row['driver'];
+ $binds[$p . 'd'] = $row['isDefault'];
+ $binds[$p . 's'] = $row['shared'];
+ $binds[$p . 'o'] = $now;
+ }
+ self::$DB->query(
+ 'INSERT INTO `hostPrinter` '
+ . '(`hpHostID`,`hpName`,`hpURI`,`hpDriver`,`hpDefault`,'
+ . '`hpShared`,`hpObservedAt`) VALUES '
+ . implode(',', $values),
+ [],
+ $binds
+ );
+ }
+
+ /**
+ * Upserts the host's spooler row.
+ *
+ * Written even when the host reported no queues, and that is the point:
+ * a machine with CUPS and nothing installed has ANSWERED, and without
+ * this row the report could not tell it from a machine that has never
+ * checked in (design 0010 section 6).
+ *
+ * @param int $hostID the host
+ * @param string $subsystem the reported subsystem
+ * @param string $now the timestamp for this reconcile
+ *
+ * @return void
+ */
+ private static function _spooler($hostID, $subsystem, $now)
+ {
+ $subsystem = strtolower(trim($subsystem));
+ if (!in_array($subsystem, self::SUBSYSTEMS, true)) {
+ // A host that invents a subsystem gets none, not its own string.
+ $subsystem = '';
+ }
+ self::$DB->query(
+ 'INSERT INTO `hostSpooler` '
+ . '(`hspHostID`,`hspSubsystem`,`hspObservedAt`) '
+ . 'VALUES (:host,:sub,:now) '
+ . 'ON DUPLICATE KEY UPDATE '
+ . '`hspSubsystem`=VALUES(`hspSubsystem`),'
+ . '`hspObservedAt`=VALUES(`hspObservedAt`)',
+ [],
+ [':host' => (int)$hostID, ':sub' => $subsystem, ':now' => $now]
+ );
+ }
+
+ /**
+ * One line naming what changed, for the audit entry.
+ *
+ * @param string[] $added queues that appeared
+ * @param string[] $removed queues that went away
+ *
+ * @return string
+ */
+ private static function describe(array $added, array $removed)
+ {
+ $parts = [];
+ if (!empty($added)) {
+ $parts[] = 'added ' . implode(', ', $added);
+ }
+ if (!empty($removed)) {
+ $parts[] = 'removed ' . implode(', ', $removed);
+ }
+
+ return implode('; ', $parts);
+ }
+}
diff --git a/packages/web/src/Agent/PrinterSet.php b/packages/web/src/Agent/PrinterSet.php
new file mode 100644
index 0000000000..9aa05a4d53
--- /dev/null
+++ b/packages/web/src/Agent/PrinterSet.php
@@ -0,0 +1,280 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Assign\Resolver;
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+use FOG\Items\Printer;
+use FOG\Items\PrinterAssociation;
+use FOG\Router\Route;
+
+/**
+ * The printers capability (design 0010 section 5): a desired set of queues
+ * the host is held to, described as a device URI and a driver, with an
+ * outcome recorded per assignment.
+ *
+ * Like SoftwareSet and unlike a snapin, nothing here is a task: the set is
+ * read fresh on every state fetch, the agent converges it, and a report
+ * refreshes one row per host and printer.
+ *
+ * The contrast to draw is with PrinterFacts next door: that records what the
+ * machine SAYS IT HAS. This sends what it SHOULD have, and keeps what
+ * happened when it tried. FOG has had neither half until now -- an install
+ * that failed produced nothing an admin could see, and the client retried
+ * the same thing on the next poll, forever.
+ *
+ * @category PrinterSet
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class PrinterSet extends FOGBase
+{
+ /**
+ * The three modes, in words.
+ *
+ * `hostPrinterLevel` stores 0, 1 or 2, and the legacy wire has always
+ * sent 0, `a` or `ar` -- two vocabularies for one setting, neither of
+ * them written down anywhere an admin can see (design 0010 section 1.3).
+ * The agent gets a third that says what it means, and the legacy
+ * endpoint keeps sending what it always sent.
+ */
+ const MODE_OFF = 'off';
+ const MODE_ASSIGNED = 'assigned';
+ const MODE_EXCLUSIVE = 'exclusive';
+ const MODES = [0 => self::MODE_OFF, 1 => self::MODE_ASSIGNED,
+ 2 => self::MODE_EXCLUSIVE];
+
+ /**
+ * What the agent may report for one printer.
+ *
+ * `converged` means nothing needed doing, which is the resting state and
+ * the overwhelmingly common report. The rest are one action each, plus
+ * the two ways a provider can decline to act at all.
+ */
+ const STATUS_CONVERGED = 'converged';
+ const STATUSES = [
+ 'converged', 'installed', 'updated', 'removed', 'failed',
+ 'unsupported'
+ ];
+
+ /**
+ * The statuses that mean the printer is now as it should be, so any
+ * error recorded against it is stale.
+ */
+ const SETTLED_STATUSES = ['converged', 'installed', 'updated', 'removed'];
+
+ /**
+ * Longest error message kept. A provider's stderr can run to pages; the
+ * column is a varchar(255) because this is a line an admin reads in a
+ * report, not a log.
+ */
+ const MAX_ERROR = 255;
+
+ /**
+ * The desired set for a host, with the mode.
+ *
+ * Resolved through Resolver::resolvePrinters -- the same call
+ * PrinterClient makes for the legacy client -- so the two clients cannot
+ * be told different things about the same host.
+ *
+ * @param Host $Host the principal
+ *
+ * @return array
+ */
+ public static function desired(Host $Host)
+ {
+ $hostID = (int)$Host->get('id');
+ $level = (int)$Host->get('printerLevel');
+ $resolved = Resolver::resolvePrinters([$hostID])[$hostID]
+ ?? ['printers' => [], 'default' => null];
+
+ $printers = [];
+ $default = '';
+ foreach ((array)($resolved['printers'] ?? []) as $id) {
+ $Printer = new Printer((int)$id);
+ if (!$Printer->isValid()) {
+ continue;
+ }
+ $name = (string)$Printer->get('name');
+ $printers[] = [
+ 'id' => (int)$Printer->get('id'),
+ 'name' => $name,
+ // Derived on read when nothing was set explicitly, so a
+ // printer created years ago against pConfig/pIP/pPort works
+ // without anybody editing it (Items\Printer::uri()).
+ 'uri' => $Printer->uri(),
+ // Empty means driverless (IPP Everywhere), which is a value
+ // and not a missing field.
+ 'driver' => $Printer->driver()
+ ];
+ if (null !== ($resolved['default'] ?? null)
+ && (int)$resolved['default'] === (int)$id
+ ) {
+ $default = $name;
+ }
+ }
+
+ return [
+ 'manage' => self::MODES[$level] ?? self::MODE_OFF,
+ 'default' => $default,
+ 'printers' => $printers
+ ];
+ }
+
+ /**
+ * Records what the agent did about one assigned printer.
+ *
+ * Written onto the ASSOCIATION rather than a status table of its own,
+ * because the outcome belongs to "this host was told to have this
+ * printer" and dies with it: unassigning the printer should take the
+ * failure with it, and a CASCADE on printerAssoc does that for free.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param int $printerID the printer reported on
+ * @param array $body the reported result
+ *
+ * @throws \RuntimeException with an HTTP code when refused
+ *
+ * @return string the status recorded
+ */
+ public static function report(Host $Host, $printerID, array $body)
+ {
+ $hostID = (int)$Host->get('id');
+ $printerID = (int)$printerID;
+
+ // The host may only report on printers it was actually told to
+ // have. Checked against the resolver rather than against
+ // printerAssoc directly, so a printer reaching the host through a
+ // GROUP grant is accepted -- and one reaching it through neither is
+ // a host reporting on somebody else's row.
+ $resolved = Resolver::resolvePrinters([$hostID])[$hostID]
+ ?? ['printers' => []];
+ $set = array_map('intval', (array)($resolved['printers'] ?? []));
+ if (!in_array($printerID, $set, true)) {
+ throw new \RuntimeException('not in this host\'s printer set', 404);
+ }
+
+ $status = (string)($body['status'] ?? '');
+ if (!in_array($status, self::STATUSES, true)) {
+ throw new \RuntimeException('unknown status', 400);
+ }
+ // `details` and not `error`: every item report on this route carries
+ // the provider's output in `details` (a snapin's tail, a package
+ // manager's log), and a printer's failure message is the same thing
+ // -- lpadmin's own words. One field name for one meaning across the
+ // protocol beats a per-capability spelling.
+ $error = self::errorFor($status, (string)($body['details'] ?? ''));
+
+ $ids = Route::getIds(
+ 'printerassociation',
+ ['hostID' => $hostID, 'printerID' => $printerID],
+ 'id'
+ );
+ $id = (int)(array_shift($ids) ?: 0);
+ if ($id < 1) {
+ // Resolved through a group, so there is no host-direct row to
+ // stamp. The result is still real and still worth an audit line;
+ // it simply has nowhere on the association to live.
+ self::_audit($Host, $printerID, $status, $error);
+ return $status;
+ }
+ $Assoc = new PrinterAssociation($id);
+ if (!$Assoc->isValid()) {
+ self::_audit($Host, $printerID, $status, $error);
+ return $status;
+ }
+ $Assoc
+ // Named for the ATTEMPT, not the success: this is stamped
+ // whenever the agent acted, so a name like paInstalledAt would
+ // claim an install happened on every occasion one did not.
+ ->set(
+ 'appliedAt',
+ self::niceDate()->setTimezone(self::storageTimeZone())
+ ->format('Y-m-d H:i:s')
+ )
+ ->set('error', $error)
+ ->save();
+
+ // A converged heartbeat is not news. Auditing every poll that
+ // reported the same nothing would bury the results that matter.
+ if (self::STATUS_CONVERGED !== $status) {
+ self::_audit($Host, $printerID, $status, $error);
+ }
+
+ return $status;
+ }
+
+ /**
+ * The error to record for a reported status.
+ *
+ * A settled status CLEARS whatever was there. Leaving it would make the
+ * report show an error against a printer that is now installed, which
+ * is worse than showing nothing at all -- an admin chasing a stale
+ * message is worse off than one chasing none.
+ *
+ * A failure keeps its message, truncated: a provider's stderr runs to
+ * pages and this is a line somebody reads in a report, not a log.
+ *
+ * @param string $status the reported status
+ * @param string $error the reported message
+ *
+ * @return string
+ */
+ protected static function errorFor($status, $error)
+ {
+ if (in_array($status, self::SETTLED_STATUSES, true)) {
+ return '';
+ }
+
+ return substr(trim($error), 0, self::MAX_ERROR);
+ }
+ /**
+ * One audit line for a printer result.
+ *
+ * @param Host $Host the host
+ * @param int $printerID the printer
+ * @param string $status what the agent said it did
+ * @param string $error the message, if any
+ *
+ * @return void
+ */
+ private static function _audit(Host $Host, $printerID, $status, $error)
+ {
+ $Printer = new Printer((int)$printerID);
+ Audit::record(
+ [
+ 'type' => 'agent.result',
+ 'subjectType' => 'host',
+ 'subjectID' => (int)$Host->get('id'),
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'text' => substr(
+ sprintf(
+ 'printer "%s" %s%s',
+ (string)$Printer->get('name'),
+ $status,
+ '' === $error ? '' : ': ' . $error
+ ),
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+}
diff --git a/packages/web/src/Agent/SecureBootFacts.php b/packages/web/src/Agent/SecureBootFacts.php
new file mode 100644
index 0000000000..4c055f23ca
--- /dev/null
+++ b/packages/web/src/Agent/SecureBootFacts.php
@@ -0,0 +1,158 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Boot\SecureBootState;
+use FOG\Items\Host;
+use FOG\Managers\HostManager;
+
+/**
+ * Writes a reported Secure Boot posture onto hosts.hostSbState (design
+ * 0012).
+ *
+ * A fact report like InventoryFacts, and registered the same way: an entry
+ * in State::FACT_REPORTS and a block in the poll, never a route of its own
+ * (the route rule, protocol-v1.md).
+ *
+ * WHY A SECOND REPORTER AT ALL. hostSbState is written by iPXE on every PXE
+ * boot, which is the right place for it: iPXE runs whenever the machine
+ * netboots, where FOS runs only when someone schedules a task. But a machine
+ * that boots from its own disk never netboots, so for that machine the value
+ * is frozen at whatever it said the last time anybody imaged it -- and the
+ * staleness runs in the dangerous direction. `disabled` is the value that
+ * makes a host look like a valid enrollment target, and it is exactly what a
+ * machine leaves behind on the last netboot before it starts enforcing.
+ *
+ * OBSERVATIONS, NOT A VERDICT. The agent sends the same three raw values
+ * iPXE sends -- platform, the SecureBoot byte, the SetupMode byte -- and
+ * this class maps them with SecureBootState::fromBootRequest(), the very
+ * call the boot path uses. The six state names were copied verbatim from
+ * FOS's own sbState() so the reporters could not drift into two
+ * vocabularies for one fact; letting the agent send a computed name would
+ * reintroduce that drift with a third implementation, in Go.
+ *
+ * STILL ADVISORY (ADR 0029). An agent report arrives over an enrolled mTLS
+ * channel, so unlike an anonymous boot request the server knows whose
+ * certificate asserted it. That is attribution, not trust: a compromised
+ * operating system can lie about its own firmware. Nothing may read this
+ * column as a security control -- it is for targeting, filtering and
+ * display, exactly as before.
+ *
+ * @category SecureBoot
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class SecureBootFacts extends FOGBase
+{
+ /**
+ * Records a reported Secure Boot posture on the host row.
+ *
+ * Reached only when the server's hash for the block moved, so every
+ * call here is a real change in what the machine says about itself.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param array $block the reported observations
+ *
+ * @return void
+ */
+ public static function report(Host $Host, array $block)
+ {
+ // null and '' are DIFFERENT inputs to fromBootRequest(): '' means
+ // the machine looked and found nothing readable, null means it did
+ // not answer at all. Casting a missing key to '' would turn a
+ // malformed block into "UEFI, state unreadable", which asserts an
+ // observation about a machine that made none.
+ $state = SecureBootState::fromBootRequest(
+ (string)($block['platform'] ?? ''),
+ array_key_exists('secure_boot', $block)
+ ? (string)$block['secure_boot'] : null,
+ array_key_exists('setup_mode', $block)
+ ? (string)$block['setup_mode'] : null
+ );
+ if (!SecureBootState::isKnown($state)
+ || SecureBootState::UNKNOWN === $state
+ ) {
+ // fromBootRequest() answers UNKNOWN when it was given nothing
+ // at all. Writing that would erase a real observation and
+ // replace it with "nobody has ever said", which is worse than
+ // the stale value it overwrote -- and the agent does not send
+ // the block at all when it has nothing to say, so arriving
+ // here means a malformed report rather than an honest silence.
+ return;
+ }
+
+ $hostID = (int)$Host->get('id');
+ $previous = (string)$Host->get('sbstate');
+
+ // The manager rather than Host::save(), as agentPoll and
+ // Enrollment::renew do: a save rewrites the MAC association, and a
+ // fact report is a routine call on every poll where the posture
+ // moved.
+ //
+ // The time is the SERVER's, on storageTimeZone() like every other
+ // datetime FOG writes. A client-supplied timestamp on a
+ // client-supplied observation is two lies for the price of one, and
+ // the question the column answers -- how stale is this -- is only
+ // meaningful in the server's own time base.
+ (new HostManager())->update(
+ ['id' => $hostID],
+ '',
+ [
+ // PROPERTY names, not column names: update() looks each one
+ // up in Host::$databaseFields, so 'hostSbState' resolves to
+ // nothing and builds an UPDATE with an empty column.
+ 'sbstate' => $state,
+ 'sbstatetime' => self::niceDate()
+ ->setTimezone(self::storageTimeZone())
+ ->format('Y-m-d H:i:s')
+ ]
+ );
+
+ // Renderable, and naming both ends of the move: "enforcing" alone
+ // does not tell an admin that this host just stopped being a valid
+ // enrollment target, which is the thing worth seeing in a list.
+ Audit::record(
+ [
+ 'type' => 'agent.secureboot',
+ 'subjectType' => 'host',
+ 'subjectID' => $hostID,
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'affectedCount' => 1,
+ 'text' => substr(
+ // No "Secure Boot" prefix: label() already spells it
+ // where it belongs ("Secure Boot ON"), and prepending
+ // produced "agent reported Secure Boot Secure Boot ON"
+ // on the first real report. It reads correctly for the
+ // labels that do NOT carry the words, too -- "agent
+ // reported UEFI, state unreadable".
+ sprintf(
+ 'agent reported %s%s',
+ SecureBootState::label($state),
+ '' === $previous || $previous === $state
+ ? ''
+ : ' (was ' . SecureBootState::label($previous) . ')'
+ ),
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+}
diff --git a/packages/web/src/Agent/Snapins.php b/packages/web/src/Agent/Snapins.php
new file mode 100644
index 0000000000..dc63373af8
--- /dev/null
+++ b/packages/web/src/Agent/Snapins.php
@@ -0,0 +1,551 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+use FOG\Items\Snapin;
+use FOG\Items\SnapinTask;
+use FOG\Items\StorageGroup;
+use FOG\Items\StorageNode;
+use FOG\Managers\SnapinTaskManager;
+use FOG\Router\Route;
+
+/**
+ * The snapin capability (design 0001 section 7: snapins as payload-only
+ * software, the detection rule comes later).
+ *
+ * The queue is the host's snapin job as the server already builds it --
+ * snapinTasks in `sequence` order, which _createSnapinTasking wrote from
+ * Resolver::resolveSnapins: the host's own associations first, then its
+ * groups' grants, deduplicated. The agent honors that order and never
+ * re-sorts. Listing is read-only so the desired state stays idempotent;
+ * a task moves to in-progress when its payload is fetched and to
+ * complete when its result lands, exactly as the legacy client's
+ * SnapinClient does -- stream() and close() ARE that code, shared, so
+ * both clients mark tasks and end jobs identically.
+ *
+ * @category Snapins
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class Snapins extends FOGBase
+{
+ /**
+ * stReturnDetails is TEXT; the agent sends the last 4 KB of output and
+ * this is the server's own bound on what it keeps.
+ */
+ const MAX_DETAILS = 4096;
+
+ /**
+ * What a reported run says about itself: the payload ran and the exit
+ * code is its own, or it never ran and this names why.
+ */
+ const STATUS_RAN = 'ran';
+ const STATUSES = ['ran', 'hash_mismatch', 'timeout', 'cannot_run'];
+
+ /**
+ * What the server decides from the exit code and the snapin's
+ * return-code table, the way Intune and SCCM read installer codes.
+ */
+ const OUTCOME_SUCCESS = 'success';
+ const OUTCOME_REBOOT = 'reboot';
+ const OUTCOME_RETRY = 'retry';
+ const OUTCOME_FAILED = 'failed';
+ const OUTCOMES = ['success', 'reboot', 'retry', 'failed'];
+
+ /**
+ * The return-code table a snapin gets when its own is empty: Intune's
+ * defaults for installer exit codes. 3010 and 1641 are the two MSI
+ * "installed, reboot to finish" answers, 1618 is "another install is
+ * running". Anything not listed is failed.
+ */
+ const DEFAULT_RETURN_CODES = [
+ 0 => 'success',
+ 1707 => 'success',
+ 3010 => 'reboot',
+ 1641 => 'reboot',
+ 1618 => 'retry'
+ ];
+
+ /**
+ * The tasks still to run for this host, in run order. Empty when the
+ * host has no live snapin job.
+ *
+ * @param Host $Host the principal
+ *
+ * @return array
+ */
+ public static function queue(Host $Host)
+ {
+ $SnapinJob = $Host->get('snapinjob');
+ if (!$SnapinJob->isValid()) {
+ return [];
+ }
+ $rows = Route::getList(
+ 'snapintask',
+ [
+ 'jobID' => (int)$SnapinJob->get('id'),
+ 'stateID' => self::fastmerge(
+ self::getQueuedStates(),
+ (array)self::getProgressState()
+ )
+ ],
+ 'AND',
+ 'sequence'
+ );
+ $out = [];
+ foreach ($rows as $row) {
+ $SnapinTask = new SnapinTask((int)$row->id);
+ if (!$SnapinTask->isValid()) {
+ continue;
+ }
+ $Snapin = $SnapinTask->getSnapin();
+ if (!$Snapin->isValid()) {
+ continue;
+ }
+ $action = '';
+ if ($Snapin->get('shutdown')) {
+ $action = 'shutdown';
+ } elseif ($Snapin->get('reboot')) {
+ $action = 'reboot';
+ }
+ $out[] = [
+ 'task' => (int)$SnapinTask->get('id'),
+ 'snapin' => (int)$Snapin->get('id'),
+ 'name' => (string)$Snapin->get('name'),
+ 'file' => (string)$Snapin->get('file'),
+ 'size' => (int)$Snapin->get('size'),
+ // The hash the SnapinHash scanner maintains; the agent
+ // refuses a payload that does not match it.
+ 'sha512' => strtolower((string)$Snapin->get('hash')),
+ 'args' => (string)$Snapin->get('args'),
+ 'run_with' => (string)$Snapin->get('runWith'),
+ 'run_with_args' => (string)$Snapin->get('runWithArgs'),
+ 'timeout' => (int)$Snapin->get('timeout'),
+ 'action' => $action,
+ 'abort_on_fail' => (bool)$SnapinJob->get('abortOnFail')
+ ];
+ }
+ return $out;
+ }
+
+ /**
+ * The task, checked to belong to this host's own job.
+ *
+ * @param Host $Host the principal
+ * @param int $taskID the caller-supplied snapin task id
+ *
+ * @throws \RuntimeException 404 when it is not this host's live task
+ *
+ * @return SnapinTask
+ */
+ public static function ownTask(Host $Host, $taskID)
+ {
+ $SnapinJob = $Host->get('snapinjob');
+ $SnapinTask = new SnapinTask((int)$taskID);
+ // Same message for "no such task" and "someone else's task", so
+ // the id space is not an oracle (the legacy client's Aisle 009
+ // guard, kept here for the same reason).
+ if (!$SnapinJob->isValid()
+ || !$SnapinTask->isValid()
+ || (int)$SnapinTask->get('jobID') !== (int)$SnapinJob->get('id')
+ ) {
+ throw new \RuntimeException('no such snapin task', 404);
+ }
+ return $SnapinTask;
+ }
+
+ /**
+ * The payload of one task, for GET /agent/v1/payload/snapin/{id}: the
+ * task must be the host's own, and fetching is what marks it in
+ * progress. Streams and exits.
+ *
+ * @param Host $Host the agent's host
+ * @param int $taskID the snapin task
+ *
+ * @throws \RuntimeException 404, 503 (see ownTask, stream)
+ *
+ * @return void
+ */
+ public static function payload(Host $Host, $taskID)
+ {
+ self::stream($Host, self::ownTask($Host, (int)$taskID));
+ }
+
+ /**
+ * Streams the task's payload to the caller and marks the task, job and
+ * host task in progress. Does not return.
+ *
+ * The bytes come over the web tier's own FTP session to the storage
+ * node, as they always have: the agent trusts one certificate, the
+ * server's, and never a node's.
+ *
+ * @param Host $Host the principal
+ * @param SnapinTask $SnapinTask a task ownTask() returned
+ *
+ * @throws \RuntimeException 503 when no node can serve the file
+ *
+ * @return void
+ */
+ public static function stream(Host $Host, SnapinTask $SnapinTask)
+ {
+ $Snapin = $SnapinTask->getSnapin();
+ if (!$Snapin->isValid()) {
+ throw new \RuntimeException('no such snapin', 404);
+ }
+ $StorageNode = self::_node($Host, $Snapin);
+ $path = sprintf('/%s', trim((string)$StorageNode->get('snapinpath'), '/'));
+ $file = (string)$Snapin->get('file');
+ $filepath = sprintf('%s/%s', $path, $file);
+ $host = (string)$StorageNode->get('ip');
+ $user = (string)$StorageNode->get('user');
+ $pass = (string)$StorageNode->get('pass');
+ self::$FOGFTP->username = $user;
+ self::$FOGFTP->password = $pass;
+ self::$FOGFTP->host = $host;
+ if (!self::$FOGFTP->connect()) {
+ throw new \RuntimeException('cannot connect to the storage node', 503);
+ }
+ $SnapinFile = sprintf('ftp://%s:%s@%s%s', $user, urlencode($pass), $host, $filepath);
+ $fh = fopen($SnapinFile, 'rb');
+ if (false === $fh) {
+ throw new \RuntimeException('cannot read the snapin file', 503);
+ }
+ $date = self::niceDate()->format('Y-m-d H:i:s');
+ $Task = $Host->get('task');
+ if ($Task->isValid()) {
+ $Task
+ ->set('stateID', self::getProgressState())
+ ->set('checkInTime', $date)
+ ->save();
+ }
+ $Host->get('snapinjob')->set('stateID', self::getProgressState())->save();
+ $SnapinTask
+ ->set('checkin', $date)
+ ->set('stateID', self::getProgressState())
+ ->set('return', -1)
+ ->set('details', _('Pending...'))
+ ->save();
+ while (ob_get_level()) {
+ ob_end_clean();
+ }
+ header("X-Sendfile: $filepath");
+ header('Content-Description: File Transfer');
+ header('Content-Type: application/octet-stream');
+ header("Content-Disposition: attachment; filename=$file");
+ header('Expires: 0');
+ header('Cache-Control: must-revalidate');
+ header('Pragma: public');
+ while (feof($fh) === false) {
+ if (($line = fread($fh, 4096)) === false) {
+ break;
+ }
+ echo $line;
+ flush();
+ }
+ fclose($fh);
+ exit;
+ }
+
+ /**
+ * A snapin's return-code table: its own, one `code=class` per line,
+ * or the defaults when it has none. Lines that are not a code and a
+ * known class are ignored rather than failing the run.
+ *
+ * @param Snapin $Snapin the snapin
+ *
+ * @return array code => outcome
+ */
+ public static function returnCodes(Snapin $Snapin)
+ {
+ return self::parseReturnCodes(
+ (string)$Snapin->get('returnCodes'),
+ self::DEFAULT_RETURN_CODES
+ );
+ }
+
+ /**
+ * Parses a `code=class` table, one per line (commas and semicolons
+ * separate too). Unknown classes are skipped; an empty table is the
+ * defaults given.
+ *
+ * @param string $text the table as typed
+ * @param array $defaults code => class when the text has none
+ *
+ * @return array code => class
+ */
+ public static function parseReturnCodes($text, array $defaults)
+ {
+ $table = [];
+ foreach (preg_split('/[\r\n,;]+/', (string)$text) as $line) {
+ if (!preg_match('/^\s*(-?\d+)\s*=\s*([a-z_]+)\s*$/i', (string)$line, $m)) {
+ continue;
+ }
+ $class = strtolower($m[2]);
+ if (in_array($class, self::OUTCOMES, true)) {
+ $table[(int)$m[1]] = $class;
+ }
+ }
+ return count($table) > 0 ? $table : $defaults;
+ }
+
+ /**
+ * What one run came to. A payload that never ran failed, whatever
+ * the number beside it; one that ran is read against the table, and
+ * a code the table does not name is failed unless it is 0.
+ *
+ * @param Snapin $Snapin the snapin
+ * @param string $status one of STATUSES
+ * @param int $exitcode the program's exit code
+ *
+ * @return string one of OUTCOMES
+ */
+ public static function outcome(Snapin $Snapin, $status, $exitcode)
+ {
+ if (self::STATUS_RAN !== $status) {
+ return self::OUTCOME_FAILED;
+ }
+ $table = self::returnCodes($Snapin);
+ $exitcode = (int)$exitcode;
+ if (isset($table[$exitcode])) {
+ return $table[$exitcode];
+ }
+ return 0 === $exitcode ? self::OUTCOME_SUCCESS : self::OUTCOME_FAILED;
+ }
+
+ /**
+ * Records the result of one task and, when it was the last, ends the
+ * job -- canceling the rest first when the job aborts on failure.
+ *
+ * The outcome comes from the snapin's return-code table. A retry puts
+ * the task back in the queue with its details kept; everything else
+ * completes it. The task row keeps the raw code, the status (the
+ * outcome, or why the payload never ran) and the output.
+ *
+ * @param Host $Host the principal
+ * @param SnapinTask $SnapinTask a task ownTask() returned
+ * @param int $exitcode the payload's exit code
+ * @param string $details the output tail, or the agent's reason
+ * @param string $status one of STATUSES; the legacy client
+ * only ever reports a run
+ *
+ * @throws \RuntimeException 409 when the task is already closed
+ *
+ * @return string the outcome, one of OUTCOMES
+ */
+ public static function close(Host $Host, SnapinTask $SnapinTask, $exitcode, $details, $status = self::STATUS_RAN)
+ {
+ if (in_array(
+ (int)$SnapinTask->get('stateID'),
+ [self::getCompleteState(), self::getCancelledState()],
+ true
+ )) {
+ throw new \RuntimeException('snapin task already closed', 409);
+ }
+ $Snapin = $SnapinTask->getSnapin();
+ if (!$Snapin->isValid()) {
+ throw new \RuntimeException('no such snapin', 404);
+ }
+ $exitcode = (int)$exitcode;
+ $details = substr(trim((string)$details), 0, self::MAX_DETAILS);
+ $outcome = self::outcome($Snapin, $status, $exitcode);
+ $date = self::niceDate()->format('Y-m-d H:i:s');
+ $HostName = (string)$Host->get('name');
+ $SnapinJob = $Host->get('snapinjob');
+ $SnapinTask
+ ->set('return', $exitcode)
+ ->set('details', $details)
+ ->set('status', self::STATUS_RAN === $status ? $outcome : $status);
+ if (self::OUTCOME_RETRY === $outcome) {
+ // Back to the queue, not complete: the next check-in runs it
+ // again. The job stays open around it.
+ $SnapinTask->set('stateID', self::getQueuedState())->save();
+ return $outcome;
+ }
+ $SnapinTask
+ ->set('stateID', self::getCompleteState())
+ ->set('complete', $date)
+ ->save();
+ self::$EventManager->notify(
+ 'HOST_SNAPINTASK_COMPLETE',
+ [
+ 'Snapin' => &$Snapin,
+ 'SnapinTask' => &$SnapinTask,
+ 'Host' => &$Host,
+ 'HostName' => &$HostName
+ ]
+ );
+ $live = [
+ 'jobID' => (int)$SnapinJob->get('id'),
+ 'stateID' => self::fastmerge(
+ self::getQueuedStates(),
+ (array)self::getProgressState()
+ )
+ ];
+ $abortedOnFailure = false;
+ if ($SnapinJob->get('abortOnFail') && self::OUTCOME_FAILED === $outcome) {
+ $abortedOnFailure = true;
+ (new SnapinTaskManager())->update(
+ $live,
+ '',
+ [
+ 'stateID' => self::getCancelledState(),
+ 'return' => $exitcode,
+ 'details' => sprintf(
+ _('Aborted due to failure of "%s" with exit code %s'),
+ $Snapin->get('name'),
+ $exitcode
+ ),
+ 'complete' => $date
+ ]
+ );
+ }
+ if (Route::getCount('snapintask', $live) < 1) {
+ $stateID = $abortedOnFailure ? self::getCancelledState() : self::getCompleteState();
+ $Task = $Host->get('task');
+ if ($Task->isValid()) {
+ $Task->set('stateID', $stateID)->save();
+ }
+ $SnapinJob->set('stateID', $stateID)->save();
+ self::$EventManager->notify(
+ 'HOST_SNAPIN_COMPLETE',
+ [
+ 'HostName' => &$HostName,
+ 'Host' => &$Host
+ ]
+ );
+ }
+ return $outcome;
+ }
+
+ /**
+ * The agent's report for one task: close it and leave the audit row
+ * the host page shows.
+ *
+ * @param Host $Host the principal
+ * @param int $taskID the snapin task
+ * @param array $body status, exit_code, details
+ *
+ * @throws \RuntimeException 400 on a status that is not one
+ *
+ * @return string the outcome, for the agent to act on
+ */
+ public static function report(Host $Host, $taskID, array $body)
+ {
+ $SnapinTask = self::ownTask($Host, $taskID);
+ $name = (string)$SnapinTask->getSnapin()->get('name');
+ $status = (string)($body['status'] ?? self::STATUS_RAN);
+ if (!in_array($status, self::STATUSES, true)) {
+ throw new \RuntimeException('unknown status', 400);
+ }
+ $exitcode = (int)($body['exit_code'] ?? 0);
+ $details = (string)($body['details'] ?? '');
+ $outcome = self::close($Host, $SnapinTask, $exitcode, $details, $status);
+ $summary = self::STATUS_RAN === $status
+ ? sprintf('exit %d, %s', $exitcode, $outcome)
+ : $status;
+ Audit::record(
+ [
+ 'type' => 'agent.result',
+ 'subjectType' => 'host',
+ 'subjectID' => (int)$Host->get('id'),
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'text' => substr(
+ sprintf(
+ 'snapin "%s" (task %d) %s%s',
+ $name,
+ (int)$SnapinTask->get('id'),
+ $summary,
+ '' === trim($details) ? '' : ': ' . trim($details)
+ ),
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ return $outcome;
+ }
+
+ /**
+ * The node that serves this snapin to this host: a hook's choice, else
+ * the master of the snapin's storage group.
+ *
+ * @param Host $Host the principal
+ * @param Snapin $Snapin the snapin
+ *
+ * @throws \RuntimeException 503 when there is none
+ *
+ * @return StorageNode
+ */
+ private static function _node(Host $Host, Snapin $Snapin)
+ {
+ $HostName = (string)$Host->get('name');
+ $StorageGroup = self::_hooked(
+ 'SNAPIN_GROUP',
+ [
+ 'Host' => &$Host,
+ 'Snapin' => &$Snapin,
+ 'StorageGroup' => null,
+ 'HostName' => &$HostName
+ ],
+ 'StorageGroup'
+ );
+ $StorageNode = self::_hooked(
+ 'SNAPIN_NODE',
+ [
+ 'Host' => &$Host,
+ 'Snapin' => &$Snapin,
+ 'StorageNode' => null
+ ],
+ 'StorageNode'
+ );
+ if (!($StorageGroup instanceof StorageGroup && $StorageGroup->isValid())) {
+ $StorageGroup = $Snapin->getStorageGroup();
+ if (!$StorageGroup->isValid()) {
+ throw new \RuntimeException('no storage group for this snapin', 503);
+ }
+ }
+ if (!($StorageNode instanceof StorageNode && $StorageNode->isValid())) {
+ $StorageNode = $StorageGroup->getMasterStorageNode();
+ if (!($StorageNode instanceof StorageNode && $StorageNode->isValid())) {
+ throw new \RuntimeException('no storage node for this snapin', 503);
+ }
+ }
+ return $StorageNode;
+ }
+
+ /**
+ * Fires a hook event whose listeners answer by filling one slot of the
+ * payload, and returns what they left there.
+ *
+ * @param string $event the event
+ * @param array $args the payload; $args[$key] is the answer slot
+ * @param string $key the slot
+ *
+ * @return mixed null when no listener answered
+ */
+ private static function _hooked($event, array $args, $key)
+ {
+ $answer = $args[$key];
+ $args[$key] = &$answer;
+ self::$HookManager->processEvent($event, $args);
+ return $answer;
+ }
+}
diff --git a/packages/web/src/Agent/SoftwareFacts.php b/packages/web/src/Agent/SoftwareFacts.php
new file mode 100644
index 0000000000..20e3332a21
--- /dev/null
+++ b/packages/web/src/Agent/SoftwareFacts.php
@@ -0,0 +1,324 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+
+/**
+ * Reconciles a reported program list into `hostSoftware` (design 0006
+ * section 4).
+ *
+ * The contrast to draw is with SoftwareSet, next door: that one is desired
+ * state, what an admin wants installed. This one is a fact, what the host
+ * says is there. FOG 1.6 had nowhere to keep the second, which is why the
+ * table is new rather than a reuse of `software`.
+ *
+ * Rows are closed, never deleted. A program that stops being reported gets
+ * an `hsRemovedAt`, so "which hosts had log4j in March" is answerable after
+ * the estate has been cleaned up -- the reportability the table exists for.
+ * The current truth is the `hsRemovedAt IS NULL` slice.
+ *
+ * @category Software
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class SoftwareFacts extends FOGBase
+{
+ /**
+ * Most programs accepted from one host.
+ *
+ * A package-managed Linux host reports around 2800 (measured), so this
+ * is generous rather than tight. It is here because the list is the
+ * one unbounded thing in the protocol and the reconcile builds a
+ * statement per chunk: a host claiming a million programs must fail
+ * this check rather than the database.
+ */
+ const MAX_PROGRAMS = 20000;
+
+ /**
+ * Rows per INSERT. The reconcile is one transaction either way; the
+ * chunking keeps a single statement, and its placeholder count, within
+ * what MySQL's max_allowed_packet and prepared-statement limits accept.
+ */
+ const CHUNK = 250;
+
+ /**
+ * Column widths, so an overlong value is truncated here rather than
+ * failing the insert under strict mode and costing the host its poll.
+ */
+ const WIDTHS = [
+ 'name' => 255,
+ 'version' => 128,
+ 'publisher' => 255,
+ 'source' => 16,
+ 'arch' => 16
+ ];
+
+ /**
+ * Records the host's current program list.
+ *
+ * The list is complete by contract: anything currently installed for
+ * this host and absent from it is marked removed. That is why the
+ * agent sends no block at all when its collector could not run -- an
+ * empty list here means "this host has no software", and would close
+ * out every row it has.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param array $list the reported programs
+ *
+ * @throws \RuntimeException with an HTTP code when refused
+ *
+ * @return void
+ */
+ public static function report(Host $Host, array $list)
+ {
+ if (count($list) > self::MAX_PROGRAMS) {
+ throw new \RuntimeException('software list too large', 413);
+ }
+ $hostID = (int)$Host->get('id');
+ $incoming = self::_clean($list);
+ $now = self::niceDate()->format('Y-m-d H:i:s');
+
+ // Close every open row, then let the insert reopen the ones still
+ // reported. Doing it in that order is what keeps the statement
+ // size constant: the alternative, an UPDATE excluding the reported
+ // identities, needs a NOT IN carrying all 2800 of them. Nothing
+ // observes the intermediate "everything removed" state because
+ // both halves are one transaction.
+ self::$DB->query('START TRANSACTION');
+ try {
+ $before = self::_currentKeys($hostID);
+ self::_closeAll($hostID, $now);
+ self::_upsert($hostID, $incoming, $now);
+ self::$DB->query('COMMIT');
+ } catch (\Exception $e) {
+ self::$DB->query('ROLLBACK');
+ throw $e;
+ }
+
+ $added = count(array_diff_key($incoming, $before));
+ $removed = count(array_diff_key($before, $incoming));
+ if (0 === $added && 0 === $removed) {
+ // A refreshed hsLastSeen is not news. Auditing every poll that
+ // reported the same list would bury the changes that matter.
+ return;
+ }
+ Audit::record(
+ [
+ 'type' => 'agent.software',
+ 'subjectType' => 'host',
+ 'subjectID' => $hostID,
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'affectedCount' => $added + $removed,
+ 'text' => sprintf(
+ 'agent reported %d installed programs: %d added, %d removed',
+ count($incoming),
+ $added,
+ $removed
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+
+ /**
+ * Normalizes the reported list, keyed by the row's identity.
+ *
+ * Keying here deduplicates: a host that reports the same program twice
+ * would otherwise hit the unique index mid-insert and roll back the
+ * whole poll. A program with no name is dropped rather than stored as
+ * an empty row nobody can read.
+ *
+ * @param array $list the reported programs
+ *
+ * @return array identity => normalized row
+ */
+ private static function _clean(array $list)
+ {
+ $out = [];
+ foreach ($list as $entry) {
+ if (!is_array($entry)) {
+ continue;
+ }
+ $row = [];
+ foreach (self::WIDTHS as $field => $width) {
+ $row[$field] = substr(
+ trim((string)($entry[$field] ?? '')),
+ 0,
+ $width
+ );
+ }
+ if ('' === $row['name']) {
+ continue;
+ }
+ $row['install_date'] = self::_date($entry['install_date'] ?? '');
+ $out[self::_key($row['name'], $row['source'], $row['version'])] = $row;
+ }
+
+ return $out;
+ }
+
+ /**
+ * The identity of one row, matching the table's unique index.
+ *
+ * The version is part of it on purpose: an OS package list enumerates
+ * each installed version separately, two can coexist, and an upgrade
+ * then reads as one version closed and another opened -- which is the
+ * history a report wants (design 0006 section 4.1).
+ *
+ * @param string $name the program name
+ * @param string $source the package manager it came from
+ * @param string $version the version string
+ *
+ * @return string
+ */
+ private static function _key($name, $source, $version)
+ {
+ return $name . "\0" . $source . "\0" . $version;
+ }
+
+ /**
+ * A reported install date as a storable DATE, or null.
+ *
+ * @param mixed $value the reported value
+ *
+ * @return string|null
+ */
+ private static function _date($value)
+ {
+ $value = trim((string)$value);
+ if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
+ return null;
+ }
+
+ return $value;
+ }
+
+ /**
+ * The identities currently installed for a host, for the audit count.
+ *
+ * @param int $hostID the host
+ *
+ * @return array identity => true
+ */
+ private static function _currentKeys($hostID)
+ {
+ $rows = self::$DB->query(
+ 'SELECT `hsName`,`hsSource`,`hsVersion` FROM `hostSoftware`'
+ . ' WHERE `hsHostID`=:host AND `hsRemovedAt` IS NULL',
+ [],
+ [':host' => (int)$hostID]
+ )->fetch(\PDO::FETCH_ASSOC, 'fetch_all')->get();
+ $out = [];
+ foreach ((array)$rows as $row) {
+ $out[self::_key(
+ $row['hsName'] ?? '',
+ $row['hsSource'] ?? '',
+ $row['hsVersion'] ?? ''
+ )] = true;
+ }
+
+ return $out;
+ }
+
+ /**
+ * Marks every currently-installed row for a host as removed.
+ *
+ * Half of the reconcile: the insert that follows reopens whatever is
+ * still reported. A row already closed keeps the date it was closed on,
+ * because the WHERE only touches open ones.
+ *
+ * @param int $hostID the host
+ * @param string $now the timestamp for this reconcile
+ *
+ * @return void
+ */
+ private static function _closeAll($hostID, $now)
+ {
+ self::$DB->query(
+ 'UPDATE `hostSoftware` SET `hsRemovedAt`=:now'
+ . ' WHERE `hsHostID`=:host AND `hsRemovedAt` IS NULL',
+ [],
+ [':now' => $now, ':host' => (int)$hostID]
+ );
+ }
+
+ /**
+ * Inserts the reported rows, refreshing the ones already known.
+ *
+ * ON DUPLICATE KEY is what makes this one statement per chunk instead
+ * of a select and a branch per program: at 2800 programs a round trip
+ * each would make the poll cost seconds. hsFirstSeen is left alone on
+ * update -- it is when the version was first seen, not last -- and
+ * hsRemovedAt is cleared, which is how a reinstalled program reopens
+ * its own row rather than starting a second one.
+ *
+ * @param int $hostID the host
+ * @param array $incoming identity => normalized row
+ * @param string $now the timestamp for this reconcile
+ *
+ * @return void
+ */
+ private static function _upsert($hostID, array $incoming, $now)
+ {
+ if (empty($incoming)) {
+ return;
+ }
+ foreach (array_chunk($incoming, self::CHUNK) as $chunk) {
+ $values = [];
+ $binds = [];
+ foreach ($chunk as $i => $row) {
+ // A distinct placeholder name per value rather than reusing
+ // one for the host id and the timestamp: a real prepared
+ // statement binds each name once, and a driver that is not
+ // emulating them rejects the repeat with a bound-parameter
+ // count error (the same trap ActivityWindow documents).
+ $p = ':r' . $i . '_';
+ $values[] = '(' . $p . 'h,' . $p . 'n,' . $p . 'v,' . $p . 'p,'
+ . $p . 's,' . $p . 'a,' . $p . 'd,' . $p . 'f,' . $p . 'l)';
+ $binds[$p . 'h'] = (int)$hostID;
+ $binds[$p . 'n'] = $row['name'];
+ $binds[$p . 'v'] = $row['version'];
+ $binds[$p . 'p'] = $row['publisher'];
+ $binds[$p . 's'] = $row['source'];
+ $binds[$p . 'a'] = $row['arch'];
+ $binds[$p . 'd'] = $row['install_date'];
+ $binds[$p . 'f'] = $now;
+ $binds[$p . 'l'] = $now;
+ }
+ self::$DB->query(
+ 'INSERT INTO `hostSoftware` '
+ . '(`hsHostID`,`hsName`,`hsVersion`,`hsPublisher`,`hsSource`,'
+ . '`hsArch`,`hsInstallDate`,`hsFirstSeen`,`hsLastSeen`) VALUES '
+ . implode(',', $values)
+ . ' ON DUPLICATE KEY UPDATE '
+ . '`hsPublisher`=VALUES(`hsPublisher`),'
+ . '`hsArch`=VALUES(`hsArch`),'
+ . '`hsInstallDate`=VALUES(`hsInstallDate`),'
+ . '`hsLastSeen`=VALUES(`hsLastSeen`),'
+ // Reopens a row that _closeAll just closed, and a program
+ // reinstalled after months away. hsFirstSeen is deliberately
+ // absent: it is when this version was first seen, not last.
+ . '`hsRemovedAt`=NULL',
+ [],
+ $binds
+ );
+ }
+ }
+}
diff --git a/packages/web/src/Agent/SoftwareSet.php b/packages/web/src/Agent/SoftwareSet.php
new file mode 100644
index 0000000000..8c06485002
--- /dev/null
+++ b/packages/web/src/Agent/SoftwareSet.php
@@ -0,0 +1,221 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Assign\Resolver;
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+use FOG\Items\Software;
+use FOG\Items\SoftwareStatus;
+use FOG\Router\Route;
+
+/**
+ * The software capability (design 0003): a desired set of packages the
+ * host is held to by a package manager, reported back with the version
+ * the host actually has. Unlike a snapin nothing here is a task: the set
+ * is read fresh on every state fetch, the agent converges it, and a
+ * report refreshes one status row per host and entry.
+ *
+ * @category SoftwareSet
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class SoftwareSet extends FOGBase
+{
+ /**
+ * The agent's statuses. The four action statuses carry an exit code
+ * the server reads against the entry's return-code table; converged
+ * means nothing needed doing; the last two mean the backend never
+ * ran the action.
+ */
+ const STATUS_CONVERGED = 'converged';
+ const ACTION_STATUSES = ['installed', 'upgraded', 'removed'];
+ const STATUSES = [
+ 'converged', 'installed', 'upgraded', 'removed', 'timeout', 'cannot_run'
+ ];
+
+ /**
+ * The snapin defaults plus Chocolatey's own "pending reboot detected"
+ * code, which it answers before touching anything.
+ */
+ const DEFAULT_RETURN_CODES = [
+ 0 => 'success',
+ 1707 => 'success',
+ 3010 => 'reboot',
+ 1641 => 'reboot',
+ 350 => 'reboot',
+ 1618 => 'retry'
+ ];
+
+ /**
+ * The desired set for a host, in run order, with the drift interval.
+ * Disabled entries are left out rather than sent as absent: turning
+ * an entry off stops managing the package, it does not remove it.
+ *
+ * @param Host $Host the principal
+ *
+ * @return array
+ */
+ public static function desired(Host $Host)
+ {
+ $hostID = (int)$Host->get('id');
+ $ids = Resolver::resolveSoftware([$hostID])[$hostID] ?? [];
+ $entries = [];
+ foreach ($ids as $id) {
+ $Software = new Software((int)$id);
+ if (!$Software->isValid() || !$Software->get('isEnabled')) {
+ continue;
+ }
+ $entries[] = [
+ 'id' => (int)$Software->get('id'),
+ 'backend' => (string)$Software->get('backend'),
+ 'package' => (string)$Software->get('package'),
+ 'version' => (string)$Software->get('version'),
+ 'state' => (string)$Software->get('state'),
+ 'source' => (string)$Software->get('source'),
+ 'args' => (string)$Software->get('args'),
+ 'timeout' => (int)$Software->get('timeout')
+ ];
+ }
+ return [
+ 'drift_interval' => (int)self::getSetting('FOG_SOFTWARE_DRIFT_INTERVAL'),
+ // Empty url = no bootstrap; the agent then reports cannot_run
+ // for a host without Chocolatey (design 0003 section 8).
+ 'bootstrap' => [
+ 'url' => trim((string)self::getSetting('FOG_SOFTWARE_CHOCO_BOOTSTRAP_URL')),
+ 'nupkg_url' => trim((string)self::getSetting('FOG_SOFTWARE_CHOCO_NUPKG_URL'))
+ ],
+ 'entries' => $entries
+ ];
+ }
+
+ /**
+ * The entry's outcome for a report: the same reading as a snapin's,
+ * with converged always a success and a backend that never ran the
+ * action always a failure.
+ *
+ * @param Software $Software the entry
+ * @param string $status the agent's status
+ * @param int $exitcode the backend's exit code
+ *
+ * @return string one of Snapins::OUTCOMES
+ */
+ public static function outcome(Software $Software, $status, $exitcode)
+ {
+ if (self::STATUS_CONVERGED === $status) {
+ return Snapins::OUTCOME_SUCCESS;
+ }
+ if (!in_array($status, self::ACTION_STATUSES, true)) {
+ return Snapins::OUTCOME_FAILED;
+ }
+ $table = Snapins::parseReturnCodes(
+ (string)$Software->get('returnCodes'),
+ self::DEFAULT_RETURN_CODES
+ );
+ $exitcode = (int)$exitcode;
+ if (isset($table[$exitcode])) {
+ return $table[$exitcode];
+ }
+ return 0 === $exitcode ? Snapins::OUTCOME_SUCCESS : Snapins::OUTCOME_FAILED;
+ }
+
+ /**
+ * Records one entry's report on the host and answers the outcome.
+ *
+ * @param Host $Host the principal
+ * @param int $softwareID the entry
+ * @param array $body status, installed_version, exit_code, details
+ *
+ * @throws \RuntimeException 404 for an entry not in the host's set,
+ * 400 for an unknown status
+ *
+ * @return string the outcome
+ */
+ public static function report(Host $Host, $softwareID, array $body)
+ {
+ $hostID = (int)$Host->get('id');
+ $softwareID = (int)$softwareID;
+ $set = Resolver::resolveSoftware([$hostID])[$hostID] ?? [];
+ if (!in_array($softwareID, $set, true)) {
+ throw new \RuntimeException('not in this host\'s software set', 404);
+ }
+ $Software = new Software($softwareID);
+ if (!$Software->isValid()) {
+ throw new \RuntimeException('no such software', 404);
+ }
+ $status = (string)($body['status'] ?? '');
+ if (!in_array($status, self::STATUSES, true)) {
+ throw new \RuntimeException('unknown status', 400);
+ }
+ $exitcode = (int)($body['exit_code'] ?? 0);
+ $version = substr(trim((string)($body['installed_version'] ?? '')), 0, 64);
+ $details = substr(trim((string)($body['details'] ?? '')), 0, Snapins::MAX_DETAILS);
+ $outcome = self::outcome($Software, $status, $exitcode);
+ // What the row keeps: the action word when it succeeded, else the
+ // outcome, else the never-ran status verbatim. Same rule as
+ // snapinTasks.stStatus so the two histories read alike.
+ $recorded = $status;
+ if (in_array($status, self::ACTION_STATUSES, true)
+ && Snapins::OUTCOME_SUCCESS !== $outcome
+ ) {
+ $recorded = $outcome;
+ }
+ $ids = Route::getIds(
+ 'softwarestatus',
+ ['hostID' => $hostID, 'softwareID' => $softwareID]
+ );
+ $Status = new SoftwareStatus((int)($ids[0] ?? 0));
+ $Status
+ ->set('hostID', $hostID)
+ ->set('softwareID', $softwareID)
+ ->set('installedVersion', $version)
+ ->set('status', $recorded)
+ ->set('return', $exitcode)
+ ->set('details', $details)
+ ->set('checked', self::niceDate()->format('Y-m-d H:i:s'))
+ ->save();
+ // A converged heartbeat is not worth an audit row; an action or a
+ // failure is.
+ if (self::STATUS_CONVERGED !== $status) {
+ Audit::record(
+ [
+ 'type' => 'agent.result',
+ 'subjectType' => 'host',
+ 'subjectID' => $hostID,
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'text' => substr(
+ sprintf(
+ 'software "%s" (%s) %s, exit %d, %s%s%s',
+ (string)$Software->get('name'),
+ (string)$Software->get('package'),
+ $status,
+ $exitcode,
+ $outcome,
+ '' === $version ? '' : ', installed ' . $version,
+ '' === $details ? '' : ': ' . $details
+ ),
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+ return $outcome;
+ }
+}
diff --git a/packages/web/src/Agent/State.php b/packages/web/src/Agent/State.php
new file mode 100644
index 0000000000..43541c8a77
--- /dev/null
+++ b/packages/web/src/Agent/State.php
@@ -0,0 +1,652 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Assign\Resolver;
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+use FOG\Items\HostFactState;
+use FOG\Items\PowerManagement;
+use FOG\Router\Route;
+
+/**
+ * The convergence half of the protocol (design 0001 section 2): the server
+ * holds a desired state per host, the agent fetches it when the revision
+ * moves, reconciles, and reports.
+ *
+ * A capability is listed for a host when its legacy module is on for that
+ * host -- the global FOG_CLIENT_*_ENABLED setting and the host's resolved
+ * module set, exactly the two checks FOGClient makes for the old client --
+ * so an admin's existing per-host and per-group module choices carry over
+ * unchanged. Desired state is built only for the capabilities listed, and
+ * the revision is a digest of that state, so "anything changed?" costs the
+ * poll one string compare.
+ *
+ * Results are audit rows for now (renderable, on the host): the place FOG
+ * already shows what happened to a host, and no schema until inventory
+ * needs one.
+ *
+ * @category State
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class State extends FOGBase
+{
+ /**
+ * Capability name => the legacy module short name that switches it.
+ */
+ const CAPABILITIES = [
+ 'hostname' => 'hostnamechanger',
+ 'taskreboot' => 'taskreboot',
+ 'snapin' => 'snapinclient',
+ 'software' => 'software',
+ 'power' => 'powermanagement',
+ // The one legacy client module the rebuild keeps rather than
+ // drops (design 0014). Same switch, same per-host time, same
+ // five-minute floor an admin already knows.
+ 'autologout' => 'autologout',
+ // Both halves of the hostnamechanger module, kept apart on the wire
+ // because they are different acts with different blast radii: a
+ // rename touches this machine, a domain join touches somebody's
+ // directory and carries a credential. An admin who has turned the
+ // module off has turned off both, which is what they meant.
+ 'directory' => 'hostnamechanger',
+ // Gated on the EXISTING printermanager module, not a new switch:
+ // admins have been turning that one off for a decade and know
+ // where it is, so a host's current choice carries over untouched
+ // (design 0010 section 5).
+ 'printers' => 'printermanager',
+ // Gated on the EXISTING powermanagement module, for the printers
+ // reason: that is the switch an admin already turns off to stop
+ // FOG touching a machine's power, and relaying a wake is FOG using
+ // this machine to touch another one's (design 0011 section 4).
+ 'wake' => 'powermanagement'
+ ];
+
+ /**
+ * Results the agent reports that are not a capability of their own:
+ * the reboot coordinator's decisions (design 0001 section 6).
+ */
+ const RESULT_SOURCES = ['reboot'];
+
+ /**
+ * Capabilities whose reports can address one server-owned row: the
+ * class's report(Host, id, body) keeps the row, reads the exit code
+ * against its return-code table and answers the outcome the agent
+ * acts on.
+ *
+ * @var array
+ */
+ const ITEM_REPORTS = [
+ 'snapin' => Snapins::class,
+ 'software' => SoftwareSet::class,
+ 'printers' => PrinterSet::class,
+ // The row here is the host's own membership, and the agent
+ // addresses it by the only id it knows: its host id. Deliberately
+ // an ITEM report and not a shape of its own -- the outer `status`
+ // is the capability's applied/failed, and a join has its own
+ // vocabulary (joined, refused, unsupported) that needs somewhere to
+ // live that is not that field.
+ 'directory' => DirectoryJoin::class,
+ // The row here is another host's pending wake, which is the only
+ // item report whose id is NOT the reporting host's own. What makes
+ // that safe is the pending row itself: a host may only report on a
+ // wake it was actually asked to send, so there is no id it can
+ // name that it was not already handed.
+ 'wake' => WakeRelay::class,
+ ];
+
+ /**
+ * Capabilities with bytes to fetch for one row: the class's
+ * payload(Host, id) checks the row is the host's own and streams it.
+ *
+ * @var array
+ */
+ const PAYLOADS = [
+ 'snapin' => Snapins::class,
+ ];
+
+ /**
+ * What the agent may report for one capability.
+ */
+ const RESULT_STATUSES = ['applied', 'unchanged', 'pending_reboot', 'failed'];
+
+ /**
+ * Fact kinds an agent reports about its own host => the class that
+ * stores one (design 0006). Facts ride the poll request, not `result`:
+ * they are what the host observed, not what it did with a task.
+ *
+ * A third kind is an entry here and a block in the poll, never a new
+ * route -- the route rule (protocol-v1.md).
+ *
+ * @var array
+ */
+ const FACT_REPORTS = [
+ 'inventory' => InventoryFacts::class,
+ 'software' => SoftwareFacts::class,
+ 'directory' => DirectoryFacts::class,
+ 'printers' => PrinterFacts::class,
+ 'network' => NetworkFacts::class,
+ // The second reporter for hosts.hostSbState (design 0012). iPXE
+ // writes the same column on every netboot; this one speaks on
+ // every poll, which is what a machine that boots its own disk
+ // actually does. Both go through
+ // SecureBootState::fromBootRequest() so there is one mapping.
+ 'secureboot' => SecureBootFacts::class,
+ ];
+
+ /**
+ * The setting that gates fact collection for the whole install.
+ */
+ const FACTS_SETTING = 'FOG_AGENT_INVENTORY_ENABLED';
+
+ /**
+ * FOG's existing module for user tracking (design 0008). Admins have
+ * been switching this off for a decade, so sessions honor it rather
+ * than inventing a second switch nobody knows to look at.
+ */
+ const SESSIONS_MODULE = 'usertracker';
+
+ /**
+ * The capabilities this server offers this host.
+ *
+ * @param Host $Host the principal
+ *
+ * @return array capability names, in CAPABILITIES order
+ */
+ public static function capabilities(Host $Host)
+ {
+ $global = self::getGlobalModuleStatus();
+ $on = (array)Route::getIds(
+ 'module',
+ ['id' => $Host->resolvedModules()],
+ 'shortName'
+ );
+ $out = [];
+ foreach (self::CAPABILITIES as $capability => $shortName) {
+ if (!empty($global[$shortName]) && in_array($shortName, $on, true)) {
+ $out[] = $capability;
+ }
+ }
+ return $out;
+ }
+
+ /**
+ * The desired state, with its revision.
+ *
+ * @param Host $Host the principal
+ *
+ * @return array
+ */
+ public static function desired(Host $Host)
+ {
+ $capabilities = self::capabilities($Host);
+ $state = ['capabilities' => $capabilities];
+ if (in_array('hostname', $capabilities, true)) {
+ $state['hostname'] = [
+ 'name' => (string)$Host->get('name'),
+ // The host's "Enforce Hostname | AD Join Reboots" flag: may
+ // the agent reboot to finish a rename. The agent's reboot
+ // coordinator owns the when; this is only the permission.
+ 'enforce' => (bool)$Host->get('enforce')
+ ];
+ }
+ if (in_array('taskreboot', $capabilities, true)) {
+ // What Client\Jobs answers the old client: a task in a state
+ // that needs the machine to boot into FOS. Present only while
+ // one waits, so queueing or canceling a task moves the
+ // revision and the agent fetches the change on its next poll.
+ $Task = $Host->get('task');
+ $state['task'] = null;
+ if ($Task->isValid() && $Task->isInitNeededTasking()) {
+ $state['task'] = [
+ 'id' => (int)$Task->get('id'),
+ 'type' => (string)$Task->getTaskTypeText(),
+ // FOG_TASK_FORCE_REBOOT: reboot for the task even
+ // with users logged in.
+ 'force' => (bool)self::getSetting('FOG_TASK_FORCE_REBOOT')
+ ];
+ }
+ }
+ if (in_array('snapin', $capabilities, true)) {
+ // The host's snapin queue in run order (Agent\Snapins). Tasks
+ // leave it as they complete, so the revision moves with the
+ // queue and an empty list is the resting state.
+ $state['snapins'] = Snapins::queue($Host);
+ }
+ if (in_array('software', $capabilities, true)) {
+ // The desired package set in run order with the drift
+ // interval (Agent\SoftwareSet). Status reports do not touch
+ // it, so a reporting host does not move its own revision.
+ $state['software'] = SoftwareSet::desired($Host);
+ }
+ if (in_array('printers', $capabilities, true)) {
+ // The resolved printer set and the mode, in words (design 0010
+ // section 5). Resolved through the same call PrinterClient
+ // makes, so the agent and the legacy client cannot be told
+ // different things about one host. Results do not touch it, so
+ // a reporting host does not move its own revision.
+ $state['printers'] = PrinterSet::desired($Host);
+ }
+ if (in_array('directory', $capabilities, true)) {
+ // Design 0009 section 6, and the only block that ever carries a
+ // credential. Null for nearly every host, and every reason for
+ // null is a reason not to put a join account on a machine --
+ // see DirectoryJoin::desired(). Omitted entirely when null so
+ // the wire says nothing rather than saying "no credential".
+ $directory = DirectoryJoin::desired($Host);
+ if (null !== $directory) {
+ $state['directory'] = $directory;
+ }
+ }
+ if (in_array('wake', $capabilities, true)) {
+ // Design 0011: FOG hosts on this machine's own links that are
+ // waiting to be woken. Null for essentially every host on
+ // essentially every poll -- a wake is rare and pending for
+ // minutes -- so the block is omitted entirely rather than
+ // sent empty. There is no destination in it: the agent
+ // broadcasts on its own interfaces, so it cannot be aimed.
+ $wake = WakeRelay::desired($Host);
+ if (null !== $wake) {
+ $state['wake'] = $wake;
+ }
+ }
+ if (in_array('power', $capabilities, true)) {
+ // Design 0004. Schedules are what Client\PM hands the legacy
+ // client: the host's own rows and its groups' grants through
+ // the resolver, minus `wol`, which the server sends itself
+ // (TaskScheduler) since a sleeping machine cannot ask. The
+ // agent fires them with its own cron matcher. On-demand rows
+ // are the task half: present until the agent reports it
+ // accepted them (result(), below), so an admin's click moves
+ // the revision and the agent fetches it on its next poll.
+ $hostID = (int)$Host->get('id');
+ $resolved = Resolver::resolvePowerManagement([$hostID]);
+ $schedules = [];
+ foreach ($resolved[$hostID] ?? [] as $schedule) {
+ if ('wol' === $schedule['action']) {
+ continue;
+ }
+ $schedules[] = [
+ 'cron' => (string)$schedule['cron'],
+ 'action' => (string)$schedule['action']
+ ];
+ }
+ $ondemand = [];
+ foreach (self::_ondemand($hostID) as $row) {
+ $ondemand[] = [
+ 'id' => (int)$row['pmID'],
+ 'action' => (string)$row['pmAction']
+ ];
+ }
+ $state['power'] = [
+ 'schedules' => $schedules,
+ 'ondemand' => $ondemand
+ ];
+ }
+ if (in_array('autologout', $capabilities, true)) {
+ // Design 0014. getAlo() is the legacy accessor unchanged: the
+ // host's own hostAutoLogOut row falling back to the global
+ // FOG_CLIENT_AUTOLOGOFF_MIN, where 0 disables.
+ //
+ // The five-minute floor is applied here AND on the agent. That
+ // is not belt and braces for its own sake: a two-minute idle
+ // timer logs people off while they are reading the screen, and
+ // the client that used to enforce this refused it in
+ // FOG\Client\Autologout::json(). Sending nothing at all below
+ // the floor is what makes the agent forget a policy it had.
+ $minutes = (int)$Host->getAlo();
+ if ($minutes >= 5) {
+ $state['autologout'] = [
+ 'minutes' => $minutes,
+ 'warn_seconds' => (int)self::getSetting(
+ 'FOG_CLIENT_AUTOLOGOFF_WARN'
+ )
+ ];
+ }
+ // No 'message': the agent carries a sensible default, and a
+ // string set here would be one the server cannot translate into
+ // the language of whoever is sitting at the machine.
+ }
+ if (count($capabilities) > 0) {
+ // The policy every reboot obeys, whatever asked for it:
+ // FOG_GRACE_TIMEOUT is the warning logged-in users get.
+ $state['reboot'] = [
+ 'grace' => (int)self::getSetting('FOG_GRACE_TIMEOUT')
+ ];
+ }
+ $state['revision'] = self::revision($state);
+ return $state;
+ }
+
+ /**
+ * The revision of a desired state: a digest of everything but itself.
+ *
+ * @param array $state the desired state, revision ignored
+ *
+ * @return string 16 hex characters
+ */
+ public static function revision(array $state)
+ {
+ unset($state['revision']);
+ ksort($state);
+ return substr(hash('sha256', (string)json_encode($state)), 0, 16);
+ }
+
+ /**
+ * Records what the agent did with one capability.
+ *
+ * @param Host $Host the principal
+ * @param array $body revision, capability, status, detail, and
+ * optionally item (id plus what the capability's
+ * report class reads)
+ *
+ * @throws \RuntimeException 400 on a body that is not a result; an
+ * item report's own codes (404, 409, 503)
+ *
+ * @return string|null the outcome of an item report, else null
+ */
+ public static function result(Host $Host, array $body)
+ {
+ $capability = (string)($body['capability'] ?? '');
+ if (!isset(self::CAPABILITIES[$capability])
+ && !in_array($capability, self::RESULT_SOURCES, true)
+ ) {
+ throw new \RuntimeException('unknown capability', 400);
+ }
+ $status = (string)($body['status'] ?? '');
+ if (!in_array($status, self::RESULT_STATUSES, true)) {
+ throw new \RuntimeException('unknown status', 400);
+ }
+ // A report about one thing under the capability goes to that
+ // capability's report class, which keeps the row and answers the
+ // outcome. One route for every kind of report: a new artifact
+ // type is a new entry here, never a new path (protocol-v1.md).
+ $item = $body['item'] ?? null;
+ if (is_array($item)) {
+ $class = self::ITEM_REPORTS[$capability] ?? null;
+ if (null === $class) {
+ throw new \RuntimeException('capability has no item reports', 400);
+ }
+ return (string)$class::report($Host, (int)($item['id'] ?? 0), $item);
+ }
+ $revision = substr(preg_replace('/[^a-f0-9]/', '', (string)($body['revision'] ?? '')), 0, 16);
+ $detail = substr(trim((string)($body['detail'] ?? '')), 0, Audit::MAX_DETAIL);
+ if ('power' === $capability && 'applied' === $status) {
+ // The agent accepted the host's on-demand actions: they are
+ // consumed, the way Client\PM consumes them on read for the
+ // legacy client, except here only once the agent has them.
+ self::_consumeOndemand((int)$Host->get('id'));
+ }
+ Audit::record(
+ [
+ 'type' => 'agent.result',
+ 'subjectType' => 'host',
+ 'subjectID' => (int)$Host->get('id'),
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'text' => sprintf(
+ '%s %s at revision %s%s',
+ $capability,
+ $status,
+ $revision,
+ '' === $detail ? '' : ': ' . $detail
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ return null;
+ }
+
+ /**
+ * Stores the fact blocks a poll carried, and answers what is still
+ * wanted from this host.
+ *
+ * The mirror image of desired(): there the server holds a revision and
+ * sends state when the agent's is stale; here the server holds a hash
+ * per fact kind and asks for a block when it has none. Either way the
+ * expensive thing crosses the wire only when it has moved.
+ *
+ * The hash is computed here rather than taken from the agent. Two
+ * reasons: the server must not trust a caller's claim that its content
+ * is unchanged, and a hash the server computes is one it can compare
+ * against a block it actually received -- which is what lets an
+ * identical resend skip the whole reconcile.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param array $body the poll request
+ *
+ * @return array want_ => bool, for the poll answer
+ */
+ public static function facts(Host $Host, array $body)
+ {
+ // Always stated, never omitted: an agent cannot tell an absent
+ // JSON boolean from a false one, and "this server does not want
+ // facts" has to reach a host whose admin just turned the setting
+ // off. An agent too old to read it keeps sending, which the
+ // ignore below handles.
+ $answer = ['collect_facts' => self::factsEnabled()];
+ if (!$answer['collect_facts']) {
+ // Gate off: never ask, and ignore a block that arrives anyway
+ // (an agent that was collecting before the setting changed, or
+ // one still on its way to hearing about it).
+ return $answer;
+ }
+ $hostID = (int)$Host->get('id');
+ foreach (self::FACT_REPORTS as $kind => $class) {
+ $stored = self::_factHash($hostID, $kind);
+ $block = $body[$kind] ?? null;
+ if (is_array($block)) {
+ $hash = substr(
+ hash('sha256', (string)json_encode($block)),
+ 0,
+ 16
+ );
+ if ($hash !== $stored) {
+ $class::report($Host, $block);
+ self::_setFactHash($hostID, $kind, $hash);
+ $stored = $hash;
+ } else {
+ // Same content, so nothing to write but something to
+ // record: this is the host's last known good report.
+ self::_setFactHash($hostID, $kind, $hash);
+ }
+ }
+ $answer['want_' . $kind] = '' === $stored;
+ }
+
+ // The acting half of directory membership (design 0009 section 5),
+ // and the one place in facts() that does something rather than
+ // record something. It runs on every poll rather than off the
+ // report above, because a report only happens when the MACHINE's
+ // membership moved, and the other source of drift is an admin
+ // editing the host's OU -- which no machine will ever report.
+ //
+ // Under the facts gate on purpose: placement decides what to do from
+ // what the host observed, so an install that collects nothing has
+ // nothing to decide from.
+ DirectoryFacts::place($Host);
+
+ return $answer;
+ }
+
+ /**
+ * Records the host's reported user sessions.
+ *
+ * Deliberately not a FACT_REPORTS entry. Facts are hash-gated by the
+ * server, and a session set must not be: the open set is also the
+ * evidence a session is still alive, so the agent decides when to send
+ * and there is no want_sessions. See design 0008 section 4.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param array $body the poll request
+ *
+ * @return array collect_sessions => bool, for the poll answer
+ */
+ public static function sessions(Host $Host, array $body)
+ {
+ // Always stated, never omitted, for the same reason collect_facts
+ // is: an agent cannot tell an absent JSON boolean from a false one.
+ $answer = ['collect_sessions' => self::sessionsEnabled($Host)];
+ if (!$answer['collect_sessions']) {
+ // Gate off: ignore a block that arrives anyway, from an agent
+ // that was collecting before the module was switched off.
+ return $answer;
+ }
+ $block = $body['sessions'] ?? null;
+ if (is_array($block)) {
+ UserSessions::report($Host, $block);
+ }
+ return $answer;
+ }
+
+ /**
+ * Whether this host reports user sessions.
+ *
+ * Both halves of FOG's module gate, the same way capabilities() reads
+ * it: the global switch and the host's resolved module list.
+ *
+ * @param Host $Host the principal
+ *
+ * @return bool
+ */
+ public static function sessionsEnabled(Host $Host)
+ {
+ $global = self::getGlobalModuleStatus();
+ if (empty($global[self::SESSIONS_MODULE])) {
+ return false;
+ }
+ $on = (array)Route::getIds(
+ 'module',
+ ['id' => $Host->resolvedModules()],
+ 'shortName'
+ );
+ return in_array(self::SESSIONS_MODULE, $on, true);
+ }
+
+ /**
+ * Whether this install collects facts at all.
+ *
+ * @return bool
+ */
+ public static function factsEnabled()
+ {
+ return (bool)self::getSetting(self::FACTS_SETTING);
+ }
+
+ /**
+ * The hash the server holds for one host and fact kind.
+ *
+ * @param int $hostID the host
+ * @param string $kind the fact kind
+ *
+ * @return string the stored hash, '' when there is no row
+ */
+ private static function _factHash($hostID, $kind)
+ {
+ $id = self::_factStateID($hostID, $kind);
+ if (0 === $id) {
+ return '';
+ }
+
+ return (string)(new HostFactState($id))->get('hash');
+ }
+
+ /**
+ * The hostFactState row id for one host and fact kind, 0 for none.
+ *
+ * @param int $hostID the host
+ * @param string $kind the fact kind
+ *
+ * @return int
+ */
+ private static function _factStateID($hostID, $kind)
+ {
+ $ids = Route::getIds(
+ 'hostfactstate',
+ ['hostID' => (int)$hostID, 'kind' => $kind],
+ 'id'
+ );
+
+ return (int)(array_shift($ids) ?: 0);
+ }
+
+ /**
+ * Records the hash and the time for one host and fact kind.
+ *
+ * @param int $hostID the host
+ * @param string $kind the fact kind
+ * @param string $hash the hash of the block just stored
+ *
+ * @return void
+ */
+ private static function _setFactHash($hostID, $kind, $hash)
+ {
+ (new HostFactState(self::_factStateID($hostID, $kind)))
+ ->set('hostID', (int)$hostID)
+ ->set('kind', $kind)
+ ->set('hash', $hash)
+ ->set('updated', self::niceDate()->format('Y-m-d H:i:s'))
+ ->save();
+ }
+
+ /**
+ * The host's pending on-demand power rows: an admin's "shutdown now"
+ * or "reboot now" from the host list, stored as powerManagement rows
+ * with pmOndemand = 1 and no cron fields.
+ *
+ * @param int $hostID the host
+ *
+ * @return array rows with pmID and pmAction
+ */
+ private static function _ondemand($hostID)
+ {
+ $out = [];
+ $find = [
+ 'hostID' => (int)$hostID,
+ 'onDemand' => 1,
+ 'action' => ['shutdown', 'reboot']
+ ];
+ foreach (Route::getIds('powermanagement', $find, 'id') as $id) {
+ $PM = new PowerManagement((int)$id);
+ $out[] = [
+ 'pmID' => (int)$PM->get('id'),
+ 'pmAction' => (string)$PM->get('action')
+ ];
+ }
+ return $out;
+ }
+
+ /**
+ * Deletes the host's on-demand power rows once the agent has them.
+ *
+ * @param int $hostID the host
+ *
+ * @return void
+ */
+ private static function _consumeOndemand($hostID)
+ {
+ Route::deletemass(
+ 'powermanagement',
+ [
+ 'onDemand' => [1],
+ 'hostID' => (int)$hostID,
+ 'action' => ['shutdown', 'reboot']
+ ]
+ );
+ }
+}
diff --git a/packages/web/src/Agent/Token.php b/packages/web/src/Agent/Token.php
new file mode 100644
index 0000000000..357e11d5fe
--- /dev/null
+++ b/packages/web/src/Agent/Token.php
@@ -0,0 +1,160 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\AgentEnrollToken;
+use FOG\Router\Route;
+
+/**
+ * Mints, lists and revokes enrollment tokens.
+ *
+ * Only the sha256 of a token is stored, so the token itself is shown
+ * exactly once, in the answer to the mint. An expiry is required: a token
+ * that never lapses is a standing credential sitting in an image or a
+ * runbook, and the design's own golden-image case (0001 section 4.2) is
+ * served by a token that outlives the rollout and not the year. Uses
+ * count down to zero; -1 is unlimited until the expiry.
+ *
+ * Consumption lives in Enrollment::_consumeToken(), which is the only
+ * reader of the hash; this class is the admin's side.
+ *
+ * @category Token
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class Token extends FOGBase
+{
+ const UNLIMITED = -1;
+
+ /**
+ * Mints a token and returns it, once.
+ *
+ * @param string $name what the admin calls it (a rollout, a site)
+ * @param int $uses how many enrollments it approves; -1 unlimited
+ * @param string $expires 'Y-m-d H:i:s', must be in the future
+ * @param string $by the minting user's name
+ *
+ * @throws \RuntimeException 400 on a bad field
+ *
+ * @return array ['token' => the secret, 'row' => AgentEnrollToken]
+ */
+ public static function mint($name, $uses, $expires, $by)
+ {
+ $name = trim((string)$name);
+ if ('' === $name || strlen($name) > 191) {
+ throw new \RuntimeException('name is required, at most 191 characters', 400);
+ }
+ $uses = (int)$uses;
+ if ($uses < 1 && self::UNLIMITED !== $uses) {
+ throw new \RuntimeException('uses must be at least 1, or -1 for unlimited', 400);
+ }
+ $expires = trim((string)$expires);
+ if (!self::validDate($expires) || strtotime($expires) <= time()) {
+ throw new \RuntimeException('expires must be a date and time in the future', 400);
+ }
+ $expires = date('Y-m-d H:i:s', strtotime($expires));
+ // 24 random bytes as hex: 48 characters that survive every shell,
+ // every clipboard and every unattended-install file unquoted.
+ $secret = bin2hex(random_bytes(24));
+ $Row = new AgentEnrollToken();
+ $Row->set('name', $name)
+ ->set('hash', hash('sha256', $secret))
+ ->set('uses', $uses)
+ ->set('expires', $expires)
+ ->set('createdBy', (string)$by)
+ ->set('created', self::niceDate()->format('Y-m-d H:i:s'));
+ if (!$Row->save()) {
+ throw new \RuntimeException('could not store the token', 500);
+ }
+ Audit::record(
+ [
+ 'type' => 'agent.token',
+ 'subjectType' => 'agentenrolltoken',
+ 'subjectID' => (int)$Row->get('id'),
+ 'subjectLabel' => $name,
+ 'renderable' => 1,
+ 'text' => sprintf(
+ 'minted, %s, expires %s',
+ self::UNLIMITED === $uses ? 'unlimited uses' : $uses . ' use(s)',
+ $expires
+ )
+ ]
+ );
+ return ['token' => $secret, 'row' => $Row];
+ }
+
+ /**
+ * Revokes a token: the row goes, so the hash can never match again.
+ *
+ * @param int $id the token row
+ * @param string $by the revoking user's name
+ *
+ * @throws \RuntimeException 404 when there is no such token
+ *
+ * @return void
+ */
+ public static function revoke($id, $by)
+ {
+ $Row = new AgentEnrollToken((int)$id);
+ if (!$Row->isValid()) {
+ throw new \RuntimeException('no such token', 404);
+ }
+ $name = (string)$Row->get('name');
+ $Row->destroy();
+ Audit::record(
+ [
+ 'type' => 'agent.token',
+ 'subjectType' => 'agentenrolltoken',
+ 'subjectID' => (int)$id,
+ 'subjectLabel' => $name,
+ 'renderable' => 1,
+ 'text' => 'revoked by ' . $by
+ ]
+ );
+ }
+
+ /**
+ * Every token, for the admin's list. Never the hash.
+ *
+ * @return array
+ */
+ public static function rows()
+ {
+ $now = time();
+ $rows = [];
+ foreach ((array)Route::getList('agentenrolltoken', [], 'AND', 'id') as $row) {
+ $row = (array)$row;
+ $uses = (int)($row['uses'] ?? 0);
+ $expires = (string)($row['expires'] ?? '');
+ $rows[] = [
+ 'id' => (int)($row['id'] ?? 0),
+ 'name' => (string)($row['name'] ?? ''),
+ 'uses' => $uses,
+ 'expires' => $expires,
+ 'createdBy' => (string)($row['createdBy'] ?? ''),
+ 'created' => (string)($row['created'] ?? ''),
+ // What the list shows at a glance: a token that can no
+ // longer approve anything, and why.
+ 'state' => 0 === $uses ? 'spent'
+ : (self::validDate($expires) && strtotime($expires) < $now ? 'expired' : 'active')
+ ];
+ }
+ return $rows;
+ }
+}
diff --git a/packages/web/src/Agent/UserSessions.php b/packages/web/src/Agent/UserSessions.php
new file mode 100644
index 0000000000..cae84964b1
--- /dev/null
+++ b/packages/web/src/Agent/UserSessions.php
@@ -0,0 +1,493 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+
+/**
+ * Reconciles a reported session set into `hostUserSession` (design 0008).
+ *
+ * The contrast to draw is with `userTracking` next door, which this does not
+ * replace: that table is an append-only log of login and logout EVENTS, and
+ * it cannot answer who is logged in now. A logout event needs a network round
+ * trip at the one moment a machine is least able to make one, so events go
+ * missing -- six of eleven sessions on the lab server have no logout at all.
+ *
+ * A session here is one row with two ends. The open set is re-reported, so a
+ * machine that lost power closes its stale rows on the next contact instead
+ * of leaving them open forever. A close the agent did not witness is marked
+ * `inferred` and dated to the last time the session was seen, because
+ * "we never found out" and "logged out at 11:54" are different facts and the
+ * legacy table could not tell them apart.
+ *
+ * @category UserTracking
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class UserSessions extends FOGBase
+{
+ /**
+ * Most sessions accepted from one host in a single report.
+ *
+ * A busy terminal server genuinely carries dozens; this is generous
+ * rather than tight. It is here because the set is attacker-controlled
+ * input and the reconcile builds a statement from it, so a host claiming
+ * a million sessions must fail this check rather than the database.
+ */
+ const MAX_SESSIONS = 512;
+
+ /**
+ * Column widths, so an overlong value is truncated here rather than
+ * failing the insert under strict mode and costing the host its poll.
+ */
+ const WIDTHS = [
+ 'key' => 191,
+ 'user' => 255,
+ 'domain' => 255,
+ 'sid' => 191,
+ 'type' => 32,
+ 'state' => 32,
+ 'remote_host' => 255,
+ 'end_reason' => 32
+ ];
+
+ /**
+ * End reasons an agent may claim. `inferred` is deliberately absent: only
+ * this class sets that, and an agent that sent it would be asserting it
+ * watched something it did not.
+ */
+ const AGENT_END_REASONS = ['logout', 'disconnect', 'service_stop'];
+
+ /**
+ * The reason recorded for a session the agent never saw end.
+ */
+ const END_INFERRED = 'inferred';
+
+ /**
+ * Whether to mirror sessions into the legacy `userTracking` table.
+ */
+ const COMPAT_SETTING = 'FOG_USERTRACKING_COMPAT_WRITE';
+
+ /**
+ * Records the host's current sessions.
+ *
+ * The open set is complete by contract: any session open for this host
+ * and absent from it is closed. That is why the agent sends no block at
+ * all when its collector could not run -- an empty open set here means
+ * "nobody is logged on", and closes every session the host has.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param array $block the reported sessions: open[] and closed[]
+ *
+ * @throws \RuntimeException with an HTTP code when refused
+ *
+ * @return void
+ */
+ public static function report(Host $Host, array $block)
+ {
+ $open = self::_clean($block['open'] ?? [], false);
+ $closed = self::_clean($block['closed'] ?? [], true);
+ if (count($open) + count($closed) > self::MAX_SESSIONS) {
+ throw new \RuntimeException('session set too large', 413);
+ }
+ $hostID = (int)$Host->get('id');
+ $now = self::niceDate()->format('Y-m-d H:i:s');
+
+ self::$DB->query('START TRANSACTION');
+ try {
+ // Order matters. Closures land first so a session that opened
+ // and ended between two polls is closed rather than reopened by
+ // its own stale presence in a previous open set. Then the open
+ // set refreshes what is live, and only what is left over -- open
+ // on the server, unreported by the host -- is inferred closed.
+ foreach ($closed as $s) {
+ self::_closeReported($hostID, $s);
+ }
+ $opened = self::_upsertOpen($hostID, $open, $now);
+ $inferred = self::_closeUnreported($hostID, $open);
+ self::$DB->query('COMMIT');
+ } catch (\Exception $e) {
+ self::$DB->query('ROLLBACK');
+ throw $e;
+ }
+
+ if (self::compatWrites()) {
+ foreach ($opened as $s) {
+ self::_legacyRow($Host, $s, 1, $s['started_at']);
+ }
+ foreach ($closed as $s) {
+ self::_legacyRow($Host, $s, 0, $s['ended_at']);
+ }
+ // An inferred close writes NO legacy logout row. The legacy
+ // table cannot express "we inferred this", so a row there would
+ // read as a witnessed logout at a time nobody observed -- the
+ // exact defect design 0008 exists to stop reproducing.
+ }
+
+ if (empty($opened) && empty($closed) && 0 === $inferred) {
+ // A refreshed husLastSeen is not news. Auditing every poll that
+ // reported the same sessions would bury the changes that matter.
+ return;
+ }
+ Audit::record(
+ [
+ 'type' => 'agent.usersession',
+ 'subjectType' => 'host',
+ 'subjectID' => $hostID,
+ 'subjectLabel' => (string)$Host->get('name'),
+ 'renderable' => 1,
+ 'affectedCount' => count($opened) + count($closed) + $inferred,
+ 'text' => sprintf(
+ 'agent reported %d open session(s): %d opened, %d ended, '
+ . '%d closed without a reported end',
+ count($open),
+ count($opened),
+ count($closed),
+ $inferred
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+ }
+
+ /**
+ * Whether the legacy mirror is on.
+ *
+ * Defaults to ON: an estate migrating to fog-agent keeps the Activity
+ * page it already uses, and one running both client generations gets a
+ * single merged view. It is a setting so a fully migrated estate can
+ * stop paying for the duplicate rows.
+ *
+ * @return bool
+ */
+ public static function compatWrites()
+ {
+ $set = self::getSetting(self::COMPAT_SETTING);
+ return null === $set || '' === $set ? true : (bool)$set;
+ }
+
+ /**
+ * Validates and normalizes reported sessions.
+ *
+ * Anything unusable is dropped rather than stored wrong: a session with
+ * no key cannot be reconciled against later, and one with no start has
+ * no duration. Truncation is to the column width so strict mode cannot
+ * reject the insert and cost the host its whole poll.
+ *
+ * @param array $list the reported entries
+ * @param bool $wantClosed whether ended_at is required
+ *
+ * @return array normalized entries, keyed by session key + start
+ */
+ private static function _clean(array $list, $wantClosed)
+ {
+ $out = [];
+ foreach ($list as $s) {
+ if (!is_array($s)) {
+ continue;
+ }
+ $key = self::_trim($s['key'] ?? '', 'key');
+ $user = self::_trim($s['user'] ?? '', 'user');
+ $start = self::_stamp($s['started_at'] ?? '');
+ if ('' === $key || '' === $user || null === $start) {
+ continue;
+ }
+ $row = [
+ 'key' => $key,
+ 'user' => $user,
+ 'domain' => self::_trim($s['domain'] ?? '', 'domain'),
+ 'sid' => self::_trim($s['sid'] ?? '', 'sid'),
+ 'type' => self::_trim($s['type'] ?? '', 'type'),
+ 'state' => self::_trim($s['state'] ?? '', 'state'),
+ 'remote_host' => self::_trim($s['remote_host'] ?? '', 'remote_host'),
+ 'started_at' => $start,
+ 'ended_at' => null,
+ 'end_reason' => ''
+ ];
+ if ($wantClosed) {
+ $end = self::_stamp($s['ended_at'] ?? '');
+ if (null === $end) {
+ continue;
+ }
+ $reason = self::_trim($s['end_reason'] ?? '', 'end_reason');
+ if (!in_array($reason, self::AGENT_END_REASONS, true)) {
+ // An agent claiming `inferred`, or anything unknown, is
+ // not taken at its word: it witnessed the end, so the
+ // honest generic label is a logout.
+ $reason = 'logout';
+ }
+ $row['ended_at'] = $end;
+ $row['end_reason'] = $reason;
+ }
+ $out[$key . "\0" . $start] = $row;
+ }
+ return $out;
+ }
+
+ /**
+ * Truncates one value to its column width.
+ *
+ * @param mixed $val the reported value
+ * @param string $column the WIDTHS key
+ *
+ * @return string
+ */
+ private static function _trim($val, $column)
+ {
+ return substr(trim((string)$val), 0, self::WIDTHS[$column]);
+ }
+
+ /**
+ * Parses a reported RFC3339 timestamp into a DATETIME string.
+ *
+ * Returns null rather than "now" on anything unparsable. A fabricated
+ * timestamp silently becomes a session duration in a report, which is
+ * worse than a session that was dropped and can be re-reported.
+ *
+ * @param mixed $raw the reported value
+ *
+ * @return string|null
+ */
+ private static function _stamp($raw)
+ {
+ $raw = trim((string)$raw);
+ if ('' === $raw) {
+ return null;
+ }
+ try {
+ $d = new \DateTime($raw);
+ } catch (\Exception $e) {
+ return null;
+ }
+ // storageTimeZone(), NOT the PHP default: it is the clock niceDate()
+ // writes husLastSeen and every other date column on, and an inferred
+ // close copies husLastSeen into husEndedAt. Converting to the PHP
+ // default here put two clocks in one table -- on the lab server a
+ // one-second session read as five hours, a start in local time and an
+ // end in UTC. A duration that wrong is the exact failure this whole
+ // design exists to stop, so the conversion is pinned by
+ // tests/agent-user-sessions.test.php.
+ $d->setTimezone(self::storageTimeZone());
+ return $d->format('Y-m-d H:i:s');
+ }
+
+ /**
+ * Closes a session the agent watched end.
+ *
+ * A close with no matching open row is inserted already closed: the
+ * agent restarted, or the row was cleaned up, and a complete session is
+ * worth more than a tidy state machine.
+ *
+ * @param int $hostID the host
+ * @param array $s the normalized closed entry
+ *
+ * @return void
+ */
+ private static function _closeReported($hostID, array $s)
+ {
+ self::$DB->query(
+ 'UPDATE `hostUserSession` SET `husEndedAt`=:ended,'
+ . '`husEndReason`=:reason,`husState`=:state,`husLastSeen`=:ended '
+ . 'WHERE `husHostID`=:host AND `husSessionKey`=:key '
+ . 'AND `husStartedAt`=:started AND `husEndedAt` IS NULL',
+ [],
+ [
+ ':ended' => $s['ended_at'],
+ ':reason' => $s['end_reason'],
+ ':state' => $s['state'],
+ ':host' => $hostID,
+ ':key' => $s['key'],
+ ':started' => $s['started_at']
+ ]
+ );
+ if (self::$DB->affectedRows() > 0) {
+ return;
+ }
+ self::$DB->query(
+ 'INSERT INTO `hostUserSession` '
+ . '(`husHostID`,`husSessionKey`,`husUserName`,`husDomain`,'
+ . '`husUserSID`,`husType`,`husState`,`husRemoteHost`,'
+ . '`husStartedAt`,`husEndedAt`,`husEndReason`,`husLastSeen`) '
+ . 'VALUES (:host,:key,:user,:domain,:sid,:type,:state,:remote,'
+ . ':started,:ended,:reason,:ended) '
+ . 'ON DUPLICATE KEY UPDATE `husEndedAt`=VALUES(`husEndedAt`),'
+ . '`husEndReason`=VALUES(`husEndReason`)',
+ [],
+ [
+ ':host' => $hostID,
+ ':key' => $s['key'],
+ ':user' => $s['user'],
+ ':domain' => $s['domain'],
+ ':sid' => $s['sid'],
+ ':type' => $s['type'],
+ ':state' => $s['state'],
+ ':remote' => $s['remote_host'],
+ ':started' => $s['started_at'],
+ ':ended' => $s['ended_at'],
+ ':reason' => $s['end_reason']
+ ]
+ );
+ }
+
+ /**
+ * Opens or refreshes the reported live sessions.
+ *
+ * @param int $hostID the host
+ * @param array $open the normalized open entries
+ * @param string $now the reconcile timestamp
+ *
+ * @return array the entries that were not already open
+ */
+ private static function _upsertOpen($hostID, array $open, $now)
+ {
+ $existing = self::_openKeys($hostID);
+ $new = [];
+ foreach ($open as $ident => $s) {
+ if (!isset($existing[$ident])) {
+ $new[] = $s;
+ }
+ self::$DB->query(
+ 'INSERT INTO `hostUserSession` '
+ . '(`husHostID`,`husSessionKey`,`husUserName`,`husDomain`,'
+ . '`husUserSID`,`husType`,`husState`,`husRemoteHost`,'
+ . '`husStartedAt`,`husEndedAt`,`husEndReason`,`husLastSeen`) '
+ . 'VALUES (:host,:key,:user,:domain,:sid,:type,:state,'
+ . ':remote,:started,NULL,\'\',:now) '
+ . 'ON DUPLICATE KEY UPDATE `husState`=VALUES(`husState`),'
+ . '`husRemoteHost`=VALUES(`husRemoteHost`),'
+ . '`husUserSID`=VALUES(`husUserSID`),'
+ . '`husLastSeen`=VALUES(`husLastSeen`)',
+ [],
+ [
+ ':host' => $hostID,
+ ':key' => $s['key'],
+ ':user' => $s['user'],
+ ':domain' => $s['domain'],
+ ':sid' => $s['sid'],
+ ':type' => $s['type'],
+ ':state' => $s['state'],
+ ':remote' => $s['remote_host'],
+ ':started' => $s['started_at'],
+ ':now' => $now
+ ]
+ );
+ }
+ return $new;
+ }
+
+ /**
+ * Closes rows still open on the server that the host did not report.
+ *
+ * Dated to `husLastSeen`, not to now: the session ended at some point
+ * between the last time it was seen and this report, and the last sighting
+ * is the only defensible end. `inferred` says exactly that, so a report
+ * can label the duration a lower bound instead of presenting a guess as a
+ * measurement.
+ *
+ * @param int $hostID the host
+ * @param array $open the normalized open entries
+ *
+ * @return int rows closed
+ */
+ private static function _closeUnreported($hostID, array $open)
+ {
+ $sql = 'UPDATE `hostUserSession` SET `husEndedAt`=`husLastSeen`,'
+ . '`husEndReason`=:reason WHERE `husHostID`=:host '
+ . 'AND `husEndedAt` IS NULL';
+ $params = [':reason' => self::END_INFERRED, ':host' => $hostID];
+ if (!empty($open)) {
+ $keep = [];
+ $i = 0;
+ foreach ($open as $s) {
+ $k = ':k' . $i;
+ $t = ':t' . $i;
+ $keep[] = '(`husSessionKey`<>' . $k
+ . ' OR `husStartedAt`<>' . $t . ')';
+ $params[$k] = $s['key'];
+ $params[$t] = $s['started_at'];
+ ++$i;
+ }
+ $sql .= ' AND ' . implode(' AND ', $keep);
+ }
+ self::$DB->query($sql, [], $params);
+ return (int)self::$DB->affectedRows();
+ }
+
+ /**
+ * The identities of this host's currently open sessions.
+ *
+ * @param int $hostID the host
+ *
+ * @return array identity => true
+ */
+ private static function _openKeys($hostID)
+ {
+ $rows = (array)self::$DB->query(
+ 'SELECT `husSessionKey`,`husStartedAt` FROM `hostUserSession` '
+ . 'WHERE `husHostID`=:host AND `husEndedAt` IS NULL',
+ [],
+ [':host' => $hostID]
+ )->fetch(\PDO::FETCH_ASSOC, 'fetch_all')->get();
+ $out = [];
+ foreach ($rows as $r) {
+ $out[$r['husSessionKey'] . "\0" . $r['husStartedAt']] = true;
+ }
+ return $out;
+ }
+
+ /**
+ * Mirrors one session edge into the legacy `userTracking` table.
+ *
+ * COMPATIBILITY SHIM. It exists so an estate migrating to fog-agent does
+ * not lose the Activity page it already reads, and so an estate running
+ * both client generations sees one merged view. Nothing new should be
+ * built on `userTracking`; build on `hostUserSession`.
+ *
+ * The legacy columns are narrower and lossier than the session row --
+ * the username is stored without its domain there, as the legacy client
+ * always sent it -- which is the point: this writes what that table can
+ * hold and nothing more.
+ *
+ * @param Host $Host the host
+ * @param array $s the normalized session entry
+ * @param int $action 1 login, 0 logout
+ * @param string $when the event time
+ *
+ * @return void
+ */
+ private static function _legacyRow(Host $Host, array $s, $action, $when)
+ {
+ self::$DB->query(
+ 'INSERT INTO `userTracking` '
+ . '(`utHostID`,`utUserName`,`utAction`,`utDateTime`,`utDate`,'
+ . '`utIP`,`utHostName`,`utCreatedBy`) '
+ . 'VALUES (:host,:user,:action,:when,:date,:ip,:name,:by)',
+ [],
+ [
+ ':host' => (int)$Host->get('id'),
+ ':user' => substr(strtolower($s['user']), 0, 50),
+ ':action' => (string)$action,
+ ':when' => $when,
+ ':date' => substr($when, 0, 10),
+ ':ip' => substr($s['remote_host'], 0, 50),
+ ':name' => substr((string)$Host->get('name'), 0, 16),
+ ':by' => 'fog-agent'
+ ]
+ );
+ }
+}
diff --git a/packages/web/src/Agent/WakeRelay.php b/packages/web/src/Agent/WakeRelay.php
new file mode 100644
index 0000000000..aa650d390f
--- /dev/null
+++ b/packages/web/src/Agent/WakeRelay.php
@@ -0,0 +1,433 @@
+
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+
+namespace FOG\Agent;
+
+use FOG\Audit\Audit;
+use FOG\Base\FOGBase;
+use FOG\Items\Host;
+use FOG\Router\Route;
+
+/**
+ * Asks an already-awake agent to broadcast a magic packet for a sleeping
+ * neighbor (design 0011).
+ *
+ * A magic packet is a link-layer broadcast, so FOG can only send one from a
+ * machine it owns. `FOGBase::wakeUp()` already fans out to every enabled,
+ * online storage node, which covers every link FOG has a machine on -- and
+ * in a routed estate a subnet routinely has FOG hosts on it and no FOG
+ * server or storage node at all. The documented answer, a directed
+ * broadcast, has been off by default on enterprise routers since the smurf
+ * attack, and asking a security team to re-enable it is asking them to undo
+ * a decision that was right.
+ *
+ * The sender that was always there is a machine already ON that link,
+ * already awake, already authenticated to FOG. That is what this class
+ * finds and asks.
+ *
+ * The security shape is the whole design, so both halves are stated here
+ * rather than only in the document:
+ *
+ * - THE SERVER PICKS BOTH ENDS. An agent never chooses a target, and the
+ * target is always a row in `hosts` whose MACs are that host's own
+ * `hostMAC` rows. There is no path from an arbitrary MAC to the wire.
+ * - THE AGENT IS NEVER TOLD WHERE TO SEND. The block carries host ids and
+ * MACs and no destination at all; the agent broadcasts on its own
+ * interfaces. An agent that accepted a destination would be a UDP
+ * reflector for whoever could feed it one.
+ *
+ * This is ADDITIONAL. The node fan-out still runs first and unchanged, and
+ * an estate with a storage node on the link never needs any of this.
+ *
+ * @category WakeRelay
+ * @package FOGProject
+ * @author Tom Elliott
+ * @license http://opensource.org/licenses/gpl-3.0 GPLv3
+ * @link https://fogproject.org
+ */
+class WakeRelay extends FOGBase
+{
+ /**
+ * The setting that turns the relay on for the whole install.
+ *
+ * Off by default. This asks one customer machine to put traffic on the
+ * network on behalf of another, which is a thing an estate owner opts
+ * into rather than discovers after an upgrade.
+ */
+ const RELAY_SETTING = 'FOG_AGENT_WAKE_RELAY_ENABLED';
+
+ /**
+ * How many neighbors are asked for one wake.
+ *
+ * More than one on purpose. A magic packet is a single UDP datagram, so
+ * asking three costs nothing measurable, and the alternative is a wake
+ * that silently does nothing because the one chosen sender went to
+ * sleep between the poll that told it and the moment it would have
+ * sent.
+ */
+ const MAX_SENDERS = 3;
+
+ /**
+ * Seconds a request stays askable.
+ *
+ * This is what keeps a wake from becoming a standing instruction. A
+ * laptop that comes back next Tuesday must not be handed a wake
+ * somebody ordered last week, by which time the machine is either
+ * already awake or deliberately off.
+ */
+ const TTL = 600;
+
+ /**
+ * Seconds since a host's last check-in for it to count as awake.
+ *
+ * A sender that last polled an hour ago is a sender that is asleep, and
+ * asking it is how a wake gets recorded as pending forever. Three poll
+ * intervals at the default five minutes: long enough to survive one
+ * missed poll, short enough to mean something.
+ */
+ const AWAKE_WITHIN = 900;
+
+ /**
+ * Most targets in one poll answer, mirroring the agent's own constant.
+ *
+ * The agent enforces its own ceiling regardless of what arrives, which
+ * is the half that matters; this one keeps the server from composing a
+ * block it knows will be truncated.
+ */
+ const MAX_TARGETS = 32;
+
+ /**
+ * What an agent may report for one relay.
+ */
+ const STATUS_SENT = 'sent';
+ const STATUSES = ['sent', 'failed'];
+
+ /**
+ * The state of a request nobody got to in time.
+ */
+ const STATUS_PENDING = 'pending';
+ const STATUS_EXPIRED = 'expired';
+
+ /**
+ * Longest detail kept: the column is a varchar(255) because this is a
+ * line an admin reads in a report, not a log.
+ */
+ const MAX_DETAIL = 255;
+
+ /**
+ * Asks this host's awake neighbors to wake it.
+ *
+ * Called alongside the existing node fan-out, never instead of it. A
+ * return of zero is the normal answer in an estate that does not need
+ * this: the relay is off, or FOG already owns a machine on the link.
+ *
+ * @param Host $Target the host to wake
+ * @param string $by who asked, for the record
+ *
+ * @return int how many neighbors were asked
+ */
+ public static function request(Host $Target, $by = '')
+ {
+ if (!self::enabled() || !$Target->isValid()) {
+ return 0;
+ }
+ $targetID = (int)$Target->get('id');
+ $senders = self::senders($targetID);
+ if (empty($senders)) {
+ return 0;
+ }
+
+ $now = self::niceDate();
+ $requestedAt = self::stamp($now);
+ $expiresAt = self::stamp(
+ (clone $now)->modify('+' . self::TTL . ' seconds')
+ );
+ foreach ($senders as $senderID) {
+ $Wake = new \FOG\Items\AgentWake();
+ $Wake
+ ->set('targetID', $targetID)
+ ->set('senderID', (int)$senderID)
+ ->set('requestedAt', $requestedAt)
+ ->set('expiresAt', $expiresAt)
+ ->set('status', self::STATUS_PENDING)
+ ->set('requestedBy', substr(trim((string)$by), 0, 255))
+ ->save();
+ }
+
+ Audit::record(
+ [
+ 'type' => 'agent.wake',
+ 'subjectType' => 'host',
+ 'subjectID' => $targetID,
+ 'subjectLabel' => (string)$Target->get('name'),
+ 'renderable' => 1,
+ 'affectedCount' => count($senders),
+ 'text' => substr(
+ sprintf(
+ 'asked %d neighboring agent(s) to broadcast a wake',
+ count($senders)
+ ),
+ 0,
+ Audit::MAX_DETAIL
+ ),
+ 'authSource' => Principal::AUTH_SOURCE
+ ]
+ );
+
+ return count($senders);
+ }
+
+ /**
+ * The wake block for a host, or null when it has nothing to relay.
+ *
+ * Null is the answer essentially always: a wake is a rare event and it
+ * is pending for only a few minutes.
+ *
+ * @param Host $Host the principal
+ *
+ * @return array|null
+ */
+ public static function desired(Host $Host)
+ {
+ if (!self::enabled()) {
+ return null;
+ }
+ self::expire();
+
+ $rows = self::$DB->query(
+ 'SELECT `awTargetID` FROM `agentWake` '
+ . 'WHERE `awSenderID`=:sender AND `awStatus`=:pending '
+ . 'ORDER BY `awRequestedAt` ASC LIMIT ' . (int)self::MAX_TARGETS,
+ [],
+ [
+ ':sender' => (int)$Host->get('id'),
+ ':pending' => self::STATUS_PENDING
+ ]
+ )->fetch(\PDO::FETCH_ASSOC, 'fetch_all')->get();
+
+ $targets = [];
+ foreach ((array)$rows as $row) {
+ $targetID = (int)($row['awTargetID'] ?? 0);
+ $macs = self::macsFor($targetID);
+ if (empty($macs)) {
+ // Nothing to send. Left pending so it expires on its own
+ // rather than being reported as a failure by a machine
+ // that never had anything to fail at.
+ continue;
+ }
+ $targets[] = ['id' => $targetID, 'macs' => $macs];
+ }
+ if (empty($targets)) {
+ return null;
+ }
+
+ return ['targets' => $targets];
+ }
+
+ /**
+ * Records what an agent did about one relay.
+ *
+ * The authorization is the pending row itself. A host may only report
+ * on a wake it was actually ASKED to send, which is the check that
+ * makes the item id safe to be another host's: without it any enrolled
+ * agent could write a result against any host in the estate.
+ *
+ * @param Host $Host the host the certificate bound
+ * @param int $targetID the host it says it woke
+ * @param array $body the reported result
+ *
+ * @throws \RuntimeException with an HTTP code when refused
+ *
+ * @return string the status recorded
+ */
+ public static function report(Host $Host, $targetID, array $body)
+ {
+ $status = (string)($body['status'] ?? '');
+ if (!in_array($status, self::STATUSES, true)) {
+ throw new \RuntimeException('unknown status', 400);
+ }
+
+ $ids = Route::getIds(
+ 'agentwake',
+ [
+ 'senderID' => (int)$Host->get('id'),
+ 'targetID' => (int)$targetID,
+ 'status' => self::STATUS_PENDING
+ ],
+ 'id'
+ );
+ $id = (int)(array_shift($ids) ?: 0);
+ if ($id < 1) {
+ throw new \RuntimeException('no wake was requested of this host', 404);
+ }
+
+ $Wake = new \FOG\Items\AgentWake($id);
+ $Wake
+ ->set('status', $status)
+ // The packet count, because "sent" with a count of zero would
+ // be a lie -- and FOG's existing wake path cannot tell the
+ // difference at all.
+ ->set('packets', max(0, (int)($body['packets'] ?? 0)))
+ ->set('detail', substr(
+ trim((string)($body['details'] ?? '')),
+ 0,
+ self::MAX_DETAIL
+ ))
+ ->set('reportedAt', self::stamp(self::niceDate()))
+ ->save();
+
+ return $status;
+ }
+
+ /**
+ * The hosts that could broadcast for this one.
+ *
+ * The query is the design in one place. A candidate has to be:
+ *
+ * 1. on the same LINK -- the same network address AND the same prefix,
+ * which is what makes two addresses neighbors rather than merely
+ * similar,
+ * 2. able to broadcast there: the interface up, the link carrying a
+ * broadcast address at all, and not wireless (an access point will
+ * not bridge a broadcast to a station that is asleep and therefore
+ * not associated, so a wireless relay sends into a link the target
+ * has already left),
+ * 3. awake, judged by its own agent check-in, and
+ * 4. not the target, which is asleep and is the reason we are here.
+ *
+ * Ordered by the most recent check-in, because the machine that spoke
+ * most recently is the one most likely to still be listening.
+ *
+ * @param int $targetID the host to wake
+ *
+ * @return int[] host ids
+ */
+ protected static function senders($targetID)
+ {
+ $rows = self::$DB->query(
+ 'SELECT DISTINCT `mine`.`hnHostID` AS `hostID` '
+ . 'FROM `hostNetwork` AS `theirs` '
+ . 'INNER JOIN `hostNetwork` AS `mine` '
+ . 'ON `mine`.`hnNetwork` = `theirs`.`hnNetwork` '
+ . 'AND `mine`.`hnPrefix` = `theirs`.`hnPrefix` '
+ . 'INNER JOIN `hosts` ON `hostID` = `mine`.`hnHostID` '
+ . 'WHERE `theirs`.`hnHostID` = :target '
+ . 'AND `mine`.`hnHostID` <> :target2 '
+ . 'AND `mine`.`hnUp` = 1 '
+ . 'AND `mine`.`hnWireless` = 0 '
+ . "AND `mine`.`hnBroadcast` <> '' "
+ . 'AND `hostAgentCheckin` >= :fresh '
+ . 'ORDER BY `hostAgentCheckin` DESC '
+ . 'LIMIT ' . (int)self::MAX_SENDERS,
+ [],
+ [
+ ':target' => (int)$targetID,
+ ':target2' => (int)$targetID,
+ ':fresh' => self::stamp(
+ self::niceDate()
+ ->modify('-' . self::AWAKE_WITHIN . ' seconds')
+ )
+ ]
+ )->fetch(\PDO::FETCH_ASSOC, 'fetch_all')->get();
+
+ $out = [];
+ foreach ((array)$rows as $row) {
+ $out[] = (int)$row['hostID'];
+ }
+
+ return $out;
+ }
+
+ /**
+ * The target's MAC addresses.
+ *
+ * PENDING MACs are excluded, the way `Group::wakeOnLAN()` already does
+ * and `Host::wakeOnLAN()` does not. A pending MAC is one FOG has seen
+ * and nobody has accepted, and asking the fleet to broadcast at it is
+ * exactly the wrong default. This is a deliberate behavior difference
+ * from the existing path, and it is confined to the new one --
+ * narrowing `Host::wakeOnLAN()` is a separate change with its own blast
+ * radius.
+ *
+ * @param int $targetID the host to wake
+ *
+ * @return string[]
+ */
+ protected static function macsFor($targetID)
+ {
+ $macs = Route::getIds(
+ 'macaddressassociation',
+ ['hostID' => (int)$targetID, 'pending' => [0, '']],
+ 'mac'
+ );
+ $out = [];
+ foreach ((array)$macs as $mac) {
+ $mac = trim((string)$mac);
+ if ('' !== $mac) {
+ $out[] = $mac;
+ }
+ }
+
+ return array_values(array_unique($out));
+ }
+
+ /**
+ * Ages out requests nobody got to.
+ *
+ * Run on the read rather than on a cron: the rows only matter when a
+ * poll is composing a block, and a request that expired unnoticed is
+ * one nobody was going to act on anyway.
+ *
+ * @return void
+ */
+ protected static function expire()
+ {
+ self::$DB->query(
+ 'UPDATE `agentWake` SET `awStatus`=:expired '
+ . 'WHERE `awStatus`=:pending AND `awExpiresAt` < :now',
+ [],
+ [
+ ':expired' => self::STATUS_EXPIRED,
+ ':pending' => self::STATUS_PENDING,
+ ':now' => self::stamp(self::niceDate())
+ ]
+ );
+ }
+
+ /**
+ * Whether the relay is on for this install.
+ *
+ * @return bool
+ */
+ protected static function enabled()
+ {
+ return (bool)self::getSetting(self::RELAY_SETTING);
+ }
+
+ /**
+ * A moment in storage time.
+ *
+ * @param \DateTime $at the moment
+ *
+ * @return string
+ */
+ protected static function stamp($at)
+ {
+ // Cloned, because setTimezone() and modify() both mutate in place:
+ // stamping a moment must not move the caller's copy of it.
+ $when = clone $at;
+
+ return $when->setTimezone(self::storageTimeZone())
+ ->format('Y-m-d H:i:s');
+ }
+}
diff --git a/packages/web/src/Assign/Resolver.php b/packages/web/src/Assign/Resolver.php
index c60067b393..a88e11dbca 100644
--- a/packages/web/src/Assign/Resolver.php
+++ b/packages/web/src/Assign/Resolver.php
@@ -157,6 +157,68 @@ public static function resolveSnapins(array $hostIDs)
return $resolved;
}
+ /**
+ * Resolves the ordered software set for each host: the same shape and
+ * rule as resolveSnapins (direct first, then groups in group order,
+ * deduplicated), over the software tables (design 0003).
+ *
+ * @param array $hostIDs the hosts to resolve for
+ *
+ * @return array hostID => [softwareID, ...]; every host id is a key
+ * @throws \RuntimeException on any query failure
+ */
+ public static function resolveSoftware(array $hostIDs)
+ {
+ $hostIDs = self::_ids($hostIDs);
+ if (count($hostIDs) < 1) {
+ return [];
+ }
+ $resolved = [];
+ $direct = [];
+ $rows = self::_rows(
+ 'SELECT `swaHostID`, `swaSoftwareID` FROM `softwareAssoc` '
+ . 'WHERE `swaHostID` IN (' . implode(',', $hostIDs) . ') '
+ . 'ORDER BY `swaHostID`, `swaSequence`, `swaID`'
+ );
+ foreach ($rows as $row) {
+ $direct[(int)$row['swaHostID']][] = (int)$row['swaSoftwareID'];
+ }
+
+ list($groupsByHost, $groupIDs) = self::_membership($hostIDs);
+ $byGroup = [];
+ if (count($groupIDs) > 0) {
+ $rows = self::_rows(
+ 'SELECT `gswaGroupID`, `gswaSoftwareID` FROM `groupSoftwareAssoc` '
+ . 'WHERE `gswaGroupID` IN (' . implode(',', $groupIDs) . ') '
+ . 'ORDER BY `gswaSequence`, `gswaID`'
+ );
+ foreach ($rows as $row) {
+ $byGroup[(int)$row['gswaGroupID']][] = (int)$row['gswaSoftwareID'];
+ }
+ }
+ $ordered = self::_orderedGroupIDs($groupIDs);
+
+ foreach ($hostIDs as $hostID) {
+ $out = $direct[$hostID] ?? [];
+ $seen = array_flip($out);
+ foreach ($ordered as $groupID) {
+ if (!isset($groupsByHost[$hostID][$groupID])) {
+ continue;
+ }
+ foreach ($byGroup[$groupID] ?? [] as $softwareID) {
+ if (isset($seen[$softwareID])) {
+ continue;
+ }
+ $seen[$softwareID] = true;
+ $out[] = $softwareID;
+ }
+ }
+ $resolved[$hostID] = $out;
+ }
+
+ return $resolved;
+ }
+
/**
* Resolves the printer list and default printer for each host.
*
@@ -186,12 +248,12 @@ public static function resolvePrinters(array $hostIDs)
$hostID = (int)$row['paHostID'];
$printerID = (int)$row['paPrinterID'];
$direct[$hostID][] = $printerID;
- // paIsDefault is varchar(2) on a 1.5-origin database and carries
- // '1', '0' and '' -- it predates booleans-are-tinyint. Compare it
- // as the string the writers actually store rather than casting,
- // which would make the empty string a 0 and read the same either
- // way, but only by luck.
- if ('1' === (string)$row['paIsDefault']
+ // Schema 426 made paIsDefault a tinyint(1), so it now carries
+ // 0 or 1 like gpaIsDefault below and is read the same way. It
+ // was a varchar(2) carrying '1', '0' and '' -- a 1.5-origin
+ // column that predated booleans-are-tinyint -- and the upgrade
+ // normalizes the empty string to 0 before retyping.
+ if ((int)$row['paIsDefault'] > 0
&& !isset($directDefault[$hostID])
) {
$directDefault[$hostID] = $printerID;
diff --git a/packages/web/src/Audit/Retention.php b/packages/web/src/Audit/Retention.php
index f030190cdb..20169b910d 100644
--- a/packages/web/src/Audit/Retention.php
+++ b/packages/web/src/Audit/Retention.php
@@ -133,6 +133,11 @@ public static function coreRegistry()
'date' => 'utDateTime',
'id' => 'utID',
],
+ 'hostUserSession' => [
+ 'setting' => 'FOG_HOSTUSERSESSION_RETENTION_DAYS',
+ 'date' => 'husStartedAt',
+ 'id' => 'husID',
+ ],
];
}
/**
diff --git a/packages/web/src/Audit/SnapinStats.php b/packages/web/src/Audit/SnapinStats.php
index 7b01d1ee47..7dd8a2a6f6 100644
--- a/packages/web/src/Audit/SnapinStats.php
+++ b/packages/web/src/Audit/SnapinStats.php
@@ -143,6 +143,7 @@ private static function _runsSql()
`snapinJobs`.`sjHostID` AS `hostID`,
`st`.`stCompleteDate` AS `completed`,
`st`.`stReturnCode` AS `code`,
+ `st`.`stStatus` AS `status`,
`st`.`stReturnDetails` AS `details`,
`st`.`stState` AS `stateID`
FROM `snapinTasks` AS `st`
diff --git a/packages/web/src/Auth/Authorization.php b/packages/web/src/Auth/Authorization.php
index 8ae972f5d0..a77ff780e7 100644
--- a/packages/web/src/Auth/Authorization.php
+++ b/packages/web/src/Auth/Authorization.php
@@ -119,6 +119,9 @@ class Authorization extends FOGBase
// on snapin.view. Same reasoning as the two above (ADR 0030
// decision 4).
'snapin_report' => 'snapin',
+ // Software Report reads `softwareStatus`, which Software Management
+ // gates on software.view. Same reasoning.
+ 'software_report' => 'software',
// Fleet Report reads `hosts` and `inventory`, both gated on
// host.view everywhere else. Same reasoning (ADR 0030 decision 4).
'fleet_report' => 'host',
@@ -126,6 +129,13 @@ class Authorization extends FOGBase
// the `inventory` node onto `host`. Same reasoning (ADR 0030
// decision 4).
'hardware_report' => 'host',
+ // Installed Software reads `hostSoftware` (design 0006), which is
+ // host data -- the same table the host's own Installed Software tab
+ // reads, gated on host.view. Same reasoning.
+ 'installed_software' => 'host',
+ 'directory_membership' => 'host',
+ 'printer_deployment' => 'host',
+ 'user_sessions' => 'host',
// Storage Report reads `images`, `imageGroupAssoc`, `nfsGroups` and
// `nfsGroupMembers`. Group and node names are the part not already
// reachable from a narrower screen, so it lands on storagenode.
@@ -334,6 +344,22 @@ class Authorization extends FOGBase
// than left to the unknown-route fallback so the intent is recorded.
'openapi' => null,
'openapiSwaggerAlias' => null,
+ // fog-agent enrollment: public by construction (the caller is asking
+ // for its credential), and it decides nothing an admin did not
+ // approve -- see FOG\Agent\Enrollment. The admin side reads and
+ // edits hosts, so it carries the host permissions.
+ 'agentenroll' => null,
+ 'agentpoll' => null, // fog-agent: gated by the client certificate in Route, not by a token
+ 'agentrenew' => null, // fog-agent: same gate
+ 'agentresult' => null, // fog-agent: same gate
+ 'agentpayload' => null, // fog-agent: same gate
+ 'agentenrollments' => 'host.view',
+ 'agentenrollmentdecide' => 'host.edit',
+ // Tokens approve machines the admin has not seen, which creates
+ // hosts; minting one is host.create and pulling one is host.delete.
+ 'agenttokens' => 'host.view',
+ 'agenttokenmint' => 'host.create',
+ 'agenttokenrevoke' => 'host.delete',
'export' => 'system.export',
'kernelUpdate' => 'settings.view',
'initrdUpdate' => 'settings.view',
@@ -374,7 +400,6 @@ class Authorization extends FOGBase
'hookevent' => 'settings',
'host' => 'host',
'hostautologout' => 'host',
- 'hostscreensetting' => 'host',
'image' => 'image',
'imageassociation' => 'image',
'imagepartitiontype' => 'image',
@@ -407,6 +432,25 @@ class Authorization extends FOGBase
'snapingroupassociation' => 'snapin',
'snapinjob' => 'task',
'snapintask' => 'task',
+ // The agent's reported facts about one host, gated by the host node
+ // they belong to -- the same call as 'inventory' above, and for the
+ // same reason: they are host detail, not a feature of their own.
+ 'hostsoftware' => 'host',
+ 'hostdirectory' => 'host',
+ 'hostprinter' => 'host',
+ 'hostspooler' => 'host',
+ 'hostnetwork' => 'host',
+ 'hostusersession' => 'host',
+ // A wake relay names two hosts and belongs to neither more than
+ // the other. Gated on the host node all the same: seeing that a
+ // machine was asked to wake another is seeing host detail, and
+ // ordering the wake goes through the host's own page.
+ 'agentwake' => 'host',
+ 'hostfactstate' => 'host',
+ 'software' => 'software',
+ 'softwareassociation' => 'software',
+ 'groupsoftwareassociation' => 'software',
+ 'softwarestatus' => 'software',
'storagegroup' => 'storagegroup',
'storagenode' => 'storagenode',
'task' => 'task',
@@ -530,6 +574,7 @@ public static function coreRegistry()
'group' => ['view', 'create', 'edit', 'delete', 'task'],
'image' => ['view', 'create', 'edit', 'delete', 'task'],
'snapin' => ['view', 'create', 'edit', 'delete'],
+ 'software' => ['view', 'create', 'edit', 'delete'],
'printer' => ['view', 'create', 'edit', 'delete'],
'module' => ['view', 'create', 'edit', 'delete'],
'user' => ['view', 'create', 'edit', 'delete'],
@@ -619,6 +664,17 @@ public static function coreRegistry()
// narrowly: an audit row necessarily discloses attempted
// usernames.
'audit' => ['view', 'manage'],
+ // The agent's half of that trail, read by host. Its OWN node
+ // rather than an alias onto `audit`: ADR 0021 made audit.view
+ // narrow because the audit log discloses attempted usernames and
+ // refusals, and agent rows are enrollments, inventories and task
+ // results a machine reported -- a different disclosure with a
+ // different audience. Aliasing would force anyone who may see
+ // what an agent did to also see every failed sign-in.
+ //
+ // `view` only. Nothing here writes: auditlog has no create,
+ // update or delete route anywhere in FOG (ADR 0021 Decision 8).
+ 'agentactivity' => ['view'],
// The log viewer. Third sibling under Logging, and the one that
// shipped without an entry here when it moved to its own node
// (#1507) -- so it fell into "a node absent from the registry is
diff --git a/packages/web/src/Auth/Redaction.php b/packages/web/src/Auth/Redaction.php
index bede22b2d1..9349e15aac 100644
--- a/packages/web/src/Auth/Redaction.php
+++ b/packages/web/src/Auth/Redaction.php
@@ -116,6 +116,15 @@ class Redaction extends FOGBase
'host' => [
'tokenlock',
],
+ // A session "key" is the operating system's own session identifier --
+ // a WTS session number like "2", or a logind id like "110" (design
+ // 0008). It is an opaque local handle that the machine hands out and
+ // that means nothing off the host: it authenticates nobody, and it is
+ // the column the reconcile matches on, so redacting it would make the
+ // session list unreadable while protecting nothing.
+ 'hostusersession' => [
+ 'sessionkey',
+ ],
// A menu hotkey is a keyboard key, and keysequence is the Konami-code
// style unlock sequence for a menu entry -- neither is a secret, and
// the sequence is already rendered into the iPXE menu in clear.
diff --git a/packages/web/src/Base/FOGBase.php b/packages/web/src/Base/FOGBase.php
index 8d079f774b..5bf2eb69b5 100644
--- a/packages/web/src/Base/FOGBase.php
+++ b/packages/web/src/Base/FOGBase.php
@@ -382,6 +382,7 @@ abstract class FOGBase
// here. No error, just the wrong half of an if.
'site',
'snapin',
+ 'software',
'storagegroup',
'storagenode',
'task',
@@ -1774,12 +1775,30 @@ protected function setRequest()
*
* @param int|float $size the size to convert
*
- * @return float
+ * @return string
*/
protected static function formatByteSize($size)
{
$units = ['iB', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
- $factor = floor((strlen($size) - 1) / 3);
+ $size = (float)$size;
+ if ($size <= 0) {
+ return sprintf('%3.2f %s', 0, $units[0]);
+ }
+ // log(1024), not the DECIMAL digit count. The original picked the
+ // unit with floor((strlen($size) - 1) / 3) -- three digits per
+ // step, which is a step of 1000 -- and then divided by a power of
+ // 1024. The two disagree for every value between 10^(3n) and
+ // 1024^n, which reads as a fraction of the unit above: an agent
+ // host with 968 MB of RAM (1,015,021,568 bytes, ten digits, so the
+ // old code chose GiB) rendered "0.95 GiB" instead of "968.00 MiB",
+ // and a 1 GB image showed "0.93 GiB". Found on the Inventory tab,
+ // 2026-09-04.
+ //
+ // Clamped because the array ends at YiB: beyond that, keep the
+ // largest unit and let the number grow rather than index past the
+ // end.
+ $factor = (int)floor(log($size, 1024));
+ $factor = max(0, min($factor, count($units) - 1));
return sprintf('%3.2f %s', $size / pow(1024, $factor), $units[$factor]);
}
@@ -1801,12 +1820,12 @@ protected static function getGlobalModuleStatus($names = false, $keys = false)
// FOG_CLIENT__ENABLED in lowercase.
$services = [
'autologout' => 'autologoff',
- 'displaymanager' => true,
'hostnamechanger' => true,
'hostregister' => true,
'powermanagement' => true,
'printermanager' => true,
'snapinclient' => 'snapin',
+ 'software' => true,
'taskreboot' => true,
'usertracker' => true
];
@@ -3646,7 +3665,9 @@ private static function _warmFromFileCache()
*
* @throws Exception
*
- * @return string|array
+ * @return string|array|null the value, null when the key has no row; the
+ * array form holds one entry per requested key,
+ * null in the slots that are missing
*/
public static function getSetting($key)
{
diff --git a/packages/web/src/Base/FOGPage.php b/packages/web/src/Base/FOGPage.php
index 39a3824946..55b54d62d2 100644
--- a/packages/web/src/Base/FOGPage.php
+++ b/packages/web/src/Base/FOGPage.php
@@ -68,6 +68,29 @@ abstract class FOGPage extends FOGBase
* @var string
*/
public $title;
+ /**
+ * Whether this page's grid lets you select and act on rows.
+ *
+ * The toolbar used to decide by NODE NAME -- a hardcoded list of
+ * ['plugin', 'task', 'activity', 'audit'] that a read-only page had to
+ * be added to, and which the next one silently was not: Agent Activity
+ * shipped drawing a red "Delete selected" over a grid whose own JS sets
+ * `select: false` and whose table has no delete route anywhere in FOG
+ * (ADR 0021 Decision 8).
+ *
+ * A page says what it is instead of the toolbar guessing from its URL.
+ * The pages that were in that list set this false, and so does any page
+ * added later -- forgetting it now means the buttons appear, which is
+ * visible, rather than a name missing from a list nobody reads.
+ *
+ * This is the PHP half. Select All / Deselect All are DataTables Buttons
+ * and are dropped by registerTable() when a table passes
+ * `select: false`, which is the same statement made in the layer that
+ * owns those buttons.
+ *
+ * @var bool
+ */
+ public $selectable = true;
/**
* The menu (always display)
*
@@ -99,6 +122,18 @@ abstract class FOGPage extends FOGBase
* @var array
*/
public $noteSources = [];
+ /**
+ * Pre-rendered action buttons for the info card, or ''.
+ *
+ * Sits to the right of the notes in the same card. Built by a page's
+ * edit() -- renderQuickTaskActions() is the only builder today -- and
+ * echoed by renderInfoCard(). A string rather than a spec array because
+ * the only thing the renderer does with it is echo it, and the pages
+ * that set it are already building markup with makeButton().
+ *
+ * @var string
+ */
+ public $noteActions = '';
/**
* Table header data
*
@@ -138,6 +173,7 @@ abstract class FOGPage extends FOGBase
'storagenode',
'storagegroup',
'snapin',
+ 'software',
'plugin',
'printer',
'task',
@@ -546,6 +582,10 @@ public static function buildMainMenuItems(&$main = '', &$hookMain = '')
self::$foglang['Snapins'],
'fas fa-cube'
],
+ 'software' => [
+ self::$foglang['Software'],
+ 'fas fa-box-open'
+ ],
'storagegroup' => [
self::$foglang['Storagegroups'],
'far fa-object-group'
@@ -642,6 +682,16 @@ public static function buildMainMenuItems(&$main = '', &$hookMain = '')
_('Log Viewer'),
'fas fa-file-lines'
],
+ // Fourth under Logging. The audit log above holds these rows
+ // too, but only as one flat install-wide grid -- this reads them
+ // by host, which is the question anyone actually has about an
+ // agent. Its own gate for the reason its coreRegistry() entry
+ // gives: what a machine reported and who failed to sign in are
+ // different disclosures.
+ 'agentactivity' => [
+ _('Agent Activity'),
+ 'fas fa-satellite-dish'
+ ],
'service' => [
self::$foglang['ClientSettings'],
'fas fa-gears'
@@ -846,7 +896,7 @@ private static function _menuGroups()
'logging' => [
'title' => _('Logging'),
'icon' => 'fas fa-scroll',
- 'children' => ['activity', 'audit', 'logviewer'],
+ 'children' => ['activity', 'audit', 'logviewer', 'agentactivity'],
],
];
}
@@ -1084,6 +1134,9 @@ private static function _nodeMenuStrings($node)
case 'snapin':
return ['list' => _('List All Snapins'),
'add' => _('Create New Snapin')];
+ case 'software':
+ return ['list' => _('List All Software'),
+ 'add' => _('Create New Software')];
case 'storagegroup':
return ['list' => _('List All Storage Groups'),
'add' => _('Create New Storage Group')];
@@ -1273,6 +1326,18 @@ private static function _buildSubMenuItems($refNode = '')
'pendingMacs',
_('Pending MACs')
);
+ self::arrayInsertBefore(
+ 'export',
+ $menu,
+ 'pendingAgents',
+ _('Pending Agents')
+ );
+ self::arrayInsertBefore(
+ 'export',
+ $menu,
+ 'agentTokens',
+ _('Agent Tokens')
+ );
break;
case 'report':
// Two kinds of screen under one menu, labeled as two.
@@ -1860,18 +1925,20 @@ public function process(
if ($sub == 'list') {
// Tasks are canceled per-pane, never deleted; the tabbed
// task page hits sub=list via the no-sub default, so keep
- // the delete actionbox off it. Activity and the audit log
- // are read-only views of the event logs -- ?node=X&sub=list
- // resolves to index() like any unknown sub does, and without
- // this they would draw a "Delete selected" neither page
- // implements. For the audit log there is nothing to
- // implement it WITH: auditlog and auditchange have no delete
- // route anywhere in FOG (ADR 0021 Decision 8).
- if (!in_array(
- $node,
- ['plugin', 'task', 'activity', 'audit'],
- true
- )) {
+ // the delete actionbox off it. Activity, the audit log and
+ // agent activity are read-only views of the event logs --
+ // ?node=X&sub=list resolves to index() like any unknown sub
+ // does, and without this they would draw a "Delete selected"
+ // none of them implements. For the audit trail there is
+ // nothing to implement it WITH: auditlog and auditchange
+ // have no delete route anywhere in FOG (ADR 0021
+ // Decision 8).
+ //
+ // Read from the page, not from its node name. The list this
+ // replaces had to be edited every time a read-only page was
+ // added and was not when Agent Activity arrived, so that
+ // page shipped a red Delete selected it could not honor.
+ if ($this->selectable) {
$actionbox .= self::makeButton(
'deleteSelected',
_('Delete selected'),
@@ -3646,20 +3713,17 @@ public function requestClientInfo()
(new RegisterClient())->json();
ob_end_clean();
try {
+ // The legacy client has no module for `software`: the agent
+ // takes it through /agent/v1 (Agent\State). Left in this list
+ // the default branch below resolves the key to Items\Software,
+ // which has no json(), and every legacy check-in fatals.
$igMods = [
- 'dircleanup',
- 'usercleanup',
- 'clientupdater',
'hostregister',
+ 'software',
];
$globalModules = array_diff(
self::getGlobalModuleStatus(false, true),
- [
- 'dircleanup',
- 'usercleanup',
- 'clientupdater',
- 'hostregister'
- ]
+ $igMods
);
$globalInfo = self::getGlobalModuleStatus();
$globalDisabled = [];
diff --git a/packages/web/src/Base/FOGPagePost.php b/packages/web/src/Base/FOGPagePost.php
index 65c80cab9e..10b77e9131 100644
--- a/packages/web/src/Base/FOGPagePost.php
+++ b/packages/web/src/Base/FOGPagePost.php
@@ -394,17 +394,25 @@ protected function assocPostInverse($ownerClass, $addMethod, $removeMethod)
/**
* Handles a standard association add/remove POST: reads the additems /
* remitems arrays and dispatches them to the object's add/remove methods.
- * When $orderMethod is supplied, also honors a snapinorder array (used by
- * the group/host snapin tabs to persist execution order).
+ * When $orderMethod is supplied, also honors an ordered-id-list POST
+ * array (used by the group/host snapin and software tabs to persist run
+ * order), under the wire name $orderField.
*
* @param string $addMethod obj method to add associations (e.g. 'addGroup')
* @param string $removeMethod obj method to remove associations (e.g. 'removeGroup')
- * @param string $orderMethod obj method to set ordering from the snapinorder
- * POST array, or null when the tab has no ordering
+ * @param string $orderMethod obj method to set ordering from the
+ * $orderField POST array, or null when the
+ * tab has no ordering
+ * @param string $orderField POST field name carrying the ordered id
+ * list. Defaults to 'snapinorder', the
+ * original (and still only pre-existing)
+ * caller; a second ordered association
+ * (software) needs its own name so the two
+ * do not share one wire field.
*
* @return void
*/
- protected function assocPost($addMethod, $removeMethod, $orderMethod = null)
+ protected function assocPost($addMethod, $removeMethod, $orderMethod = null, $orderField = 'snapinorder')
{
self::checkAuthAndCSRF();
if (isset($_POST['confirmadd'])) {
@@ -435,16 +443,16 @@ protected function assocPost($addMethod, $removeMethod, $orderMethod = null)
$this->obj->{$removeMethod}($items);
}
}
- if ($orderMethod !== null && isset($_POST['snapinorder'])) {
+ if ($orderMethod !== null && isset($_POST[$orderField])) {
$order = filter_input_array(
INPUT_POST,
[
- 'snapinorder' => [
+ $orderField => [
'flags' => FILTER_REQUIRE_ARRAY
]
]
);
- $order = $order['snapinorder'];
+ $order = $order[$orderField];
if (count($order ?: []) > 0) {
$this->obj->{$orderMethod}($order);
}
diff --git a/packages/web/src/Base/FOGPageRender.php b/packages/web/src/Base/FOGPageRender.php
index bde8ae1056..ac3bfc334f 100644
--- a/packages/web/src/Base/FOGPageRender.php
+++ b/packages/web/src/Base/FOGPageRender.php
@@ -546,23 +546,162 @@ protected static function noteSourceAttrs($source)
return $attrs;
}
+ /**
+ * The info card's one-click task buttons.
+ *
+ * The host and group LIST grids have carried these since
+ * HostManagement::_quickTaskItems(): the two or three task types that
+ * take no options, fired straight at the create endpoint instead of
+ * fetching an options form only to post it back untouched. This is the
+ * same affordance on the edit pages, so an admin already looking at a
+ * host or a group does not have to go back to the grid, find the row
+ * again and tick it to do the obvious thing to it.
+ *
+ * Deploy and Capture for a host, Deploy and Multi-Cast for a group --
+ * the same pairing _quickTaskItems() documents, and for the same
+ * reason: those are the types that need no options, which is the whole
+ * reason they can be one click.
+ *
+ * btn-secondary, and neither of them primary. Nothing here is the card's
+ * commit action -- the General tab's Update is -- so these are two
+ * shortcuts in a header strip, not a decision cluster in a form footer,
+ * and the weight a red button would carry is carried by the
+ * confirmation modal instead. It is also what the list grid's own quick
+ * buttons are, since DataTables draws its button bar that way.
+ *
+ * Filled, NOT btn-outline-secondary, and that is a contrast decision
+ * rather than a taste one. Outline keeps #6c757d as the TEXT color, and
+ * against the dark card (#212529) that is 3.29:1 -- under the 4.5:1 AA
+ * floor for body-sized text. Filled puts white on #6c757d instead and
+ * holds 4.69:1 in both themes. Measured against the shipped
+ * adminlte4.min.css + fog-default-ui.min.css, not assumed.
+ *
+ * @param string $node Page node, e.g. 'host' or 'group'. Also decides
+ * the permission: ?node=X&sub=deploy resolves to
+ * X.task via Authorization::_subToAction(), so
+ * the gate here and the gate the POST hits are
+ * the same string by construction.
+ * @param int $id The entity being edited.
+ * @param array $typeIds TaskType ids, in the order they should appear.
+ * @param string $target Already-translated description of what the task
+ * lands on, e.g. 'host "foo"'. Interpolated into
+ * the confirmation. Built by the caller because
+ * only the caller knows whether it is one machine
+ * or a group of them.
+ *
+ * @return string The button group markup, or '' if none may be shown.
+ */
+ public static function renderQuickTaskActions(
+ $node,
+ $id,
+ array $typeIds,
+ $target
+ ) {
+ // Same refusal _quickTaskItems() makes: a user without the
+ // permission would be shown buttons whose POST can only be denied.
+ if (!Authorization::can($node . '.task')) {
+ return '';
+ }
+
+ $buttons = '';
+ foreach ($typeIds as $typeId) {
+ $TaskType = new TaskType($typeId);
+ // A server whose taskTypes row was deleted simply loses that
+ // button, the same way the accordion and the grid lose theirs.
+ if (!$TaskType->isValid()) {
+ continue;
+ }
+ $name = (string)$TaskType->get('name');
+ // Built here, not in the script. gettext runs server side, so a
+ // sentence assembled in JS would never reach the .pot -- the
+ // same reason noteSourceAttrs() builds its on/off labels here.
+ $confirm = sprintf(
+ _('Create a %1$s task for %2$s?'),
+ $name,
+ $target
+ );
+ $buttons .= self::makeButton(
+ 'quicktask-' . \Initiator::e($node) . '-' . (int)$TaskType->get('id'),
+ ' ' . \Initiator::e($name),
+ 'btn btn-secondary fog-quicktask',
+ 'type="button"'
+ . ' data-node="' . \Initiator::e($node) . '"'
+ . ' data-id="' . (int)$id . '"'
+ . ' data-type="' . (int)$TaskType->get('id') . '"'
+ . ' data-confirm="' . \Initiator::e($confirm) . '"'
+ );
+ }
+ if ('' === $buttons) {
+ return '';
+ }
+
+ // The confirmation is a modal, not window.confirm(). The browser's
+ // own dialog cannot be styled, ignores the dark theme entirely, and
+ // announces itself with the page's URL -- next to AdminLTE it reads
+ // as something the site got wrong. Same shape as assocDelModal(),
+ // which is what every other "are you sure" in this app looks like.
+ //
+ // ONE modal for the whole card, filled in by the script from the
+ // clicked button's data-confirm, rather than one per button: two
+ // would eventually say the same thing in two different wordings.
+ //
+ // Emitted next to the buttons, the way assocDelModal() sits in its
+ // card-footer. A .modal is position:fixed and display:none until
+ // shown, so it adds nothing to the flex row it nominally lives in.
+ $modal = self::makeModal(
+ 'quicktask-confirm-modal',
+ '' . \Initiator::e(_('Create tasking'))
+ . '
',
+ '',
+ self::makeButton(
+ 'quicktask-confirm-cancel',
+ _('Cancel'),
+ 'btn btn-outline-secondary float-start',
+ 'type="button" data-bs-dismiss="modal"'
+ )
+ . self::makeButton(
+ 'quicktask-confirm-go',
+ _('Create'),
+ 'btn btn-outline-secondary float-end',
+ 'type="button"'
+ ),
+ '',
+ 'warning'
+ );
+
+ return '' . $buttons . '
' . $modal;
+ }
+
protected function renderInfoCard()
{
$notes = (array)$this->notes;
$sources = (array)$this->noteSources;
+ $actions = (string)$this->noteActions;
// Mirrors PLUGINS_INJECT_TABDATA in tabFields(): a plugin that adds
// a tab to a core page can add its line here too. 1.5's equivalent
// rode SUB_MENULINK_DATA, which 1.6 repurposed for the sidebar node
// menu, so there is no back-compat name to keep.
+ //
+ // 'actions' rides the same event rather than getting one of its own:
+ // a plugin adding a button to this card is doing the same thing as a
+ // plugin adding a line to it, and a second event would mean two
+ // registrations for one card.
self::$HookManager->processEvent(
'EDIT_INFO_DATA',
[
'notes' => &$notes,
'noteSources' => &$sources,
+ 'noteActions' => &$actions,
'obj' => &$this->obj
]
);
- if (!count($notes)) {
+ // Either half is enough to be worth drawing. A page with buttons and
+ // no notes is unusual but not wrong, and returning early on the note
+ // count alone would silently drop the buttons.
+ if (!count($notes) && '' === trim($actions)) {
return;
}
echo '';
@@ -593,6 +732,16 @@ protected function renderInfoCard()
echo '
';
echo ' ';
}
+ // Last in the row and pushed to the far edge with ms-auto, so the
+ // buttons sit clear of the notes however many notes there are. A
+ // flex auto margin, not a float: the row is display:flex and a float
+ // would do nothing here.
+ if ('' !== trim($actions)) {
+ echo '