<commit_before>/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2013 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

define([
    "jquery",
    "base1/cockpit",
    "shell/controls",
    "shell/shell",
    "shell/cockpit-main"
], function($, cockpit, controls, shell) {
"use strict";

var _ = cockpit.gettext;
var C_ = cockpit.gettext;

function update_accounts_privileged() {
    controls.update_privileged_ui(
        shell.default_permission, ".accounts-privileged",
        cockpit.format(
            _("The user <b>$0</b> is not permitted to modify accounts"),
            cockpit.user.name)
    );
    $(".accounts-privileged").children("input")
        .attr('disabled', shell.default_permission.allowed === false);
}

function passwd_self(old_pass, new_pass) {
    var old_exps = [
        /.*\(current\) UNIX password: $/,
    ];
    var new_exps = [
        /.*New password: $/,
        /.*Retype new password: $/
    ];
    var bad_exps = [
        /.*BAD PASSWORD:.*/
    ];

    var dfd = $.Deferred();
    var buffer = "";
    var sent_new = false;
    var failure = _("Old password not accepted");
    var i;

    var timeout = window.setTimeout(function() {
        failure = _("Prompting via passwd timed out");
        proc.close("terminated");
    }, 10 * 1000);

    var proc = cockpit.spawn(["/usr/bin/passwd"], { pty: true, environ: [ "LC_ALL=C" ], err: "out" })
        .always(function() {
            window.clearInterval(timeout);
        })
        .done(function() {
            dfd.resolve();
        })
        .fail(function(ex) {
            if (ex.constructor.name == "ProcessError")
                ex = new Error(failure);
            dfd.reject(ex);
        })
        .stream(function(data) {
            buffer += data;
            for (i = 0; i < old_exps.length; i++) {
                if (old_exps[i].test(buffer)) {
                    buffer = "";
                    proc.input(old_pass + "\n", true);
                    return;
                }
            }

            for (i = 0; i < new_exps.length; i++) {
                if (new_exps[i].test(buffer)) {
                    buffer = "";
                    proc.input(new_pass + "\n", true);
                    failure = _("Failed to change password");
                    sent_new = true;
                    return;
                }
            }

            for (i = 0; sent_new && i < bad_exps.length; i++) {
                if (bad_exps[i].test(buffer)) {
                    failure = _("New password was not accepted");
                    return;
                }
            }
        });

    return dfd.promise();
}

function passwd_change(user, new_pass) {
    var dfd = $.Deferred();

    var buffer = "";
    cockpit.spawn(["/usr/bin/passwd", "--stdin", user ], {superuser: true, err: "out" })
        .input(new_pass)
        .stream(function(data) {
            buffer += data;
        })
        .done(function() {
            dfd.resolve();
        })
        .fail(function(ex) {
            if (ex.constructor.name == "ProcessError") {
                console.log(ex);
                if (buffer)
                    ex = new Error(buffer);
                else
                    ex = new Error(_("Failed to change password"));
            }
            dfd.reject(ex);
        });

    return dfd.promise();
}

$(shell.default_permission).on("changed", update_accounts_privileged);

function parse_passwd_content(content, tag, error) {
    if (content === null) {
        console.warn("Couldn't read /etc/passwd", error);
        return [ ];
    }

    var ret = [ ];
    var lines = content.split('\n');
    var column;

    for (var i = 0; i < lines.length; i++) {
        if (! lines[i])
            continue;
        column = lines[i].split(':');
        ret[i] = [];
        ret[i]["name"] = column[0];
        ret[i]["password"] = column[1];
        ret[i]["uid"] = column[2];
        ret[i]["gid"] = column[3];
        ret[i]["gecos"] = column[4];
        ret[i]["home"] = column[5];
        ret[i]["shell"] = column[6];
    }

    return ret;
}

function parse_group_content(content, tag, error) {
    if (content === null) {
        console.warn("Couldn't read /etc/group", error);
        return [ ];
    }

    var ret = [ ];
    var lines = content.split('\n');
    var column;

    for (var i = 0; i < lines.length; i++) {
        if (! lines[i])
            continue;
        column = lines[i].split(':');
        ret[i] = [];
        ret[i]["name"] = column[0];
        ret[i]["password"] = column[1];
        ret[i]["gid"] = column[2];
        ret[i]["userlist"] = column[3].split(',');
    }

    return ret;
}

function is_user_in_group(user, group) {
    for (var i = 0; group["userlist"] && i < group["userlist"].length; i++) {
        if (group["userlist"][i] === user)<commit_msg>shell: use integer for UID and GID<commit_after>/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2013 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

define([
    "jquery",
    "base1/cockpit",
    "shell/controls",
    "shell/shell",
    "shell/cockpit-main"
], function($, cockpit, controls, shell) {
"use strict";

var _ = cockpit.gettext;
var C_ = cockpit.gettext;

function update_accounts_privileged() {
    controls.update_privileged_ui(
        shell.default_permission, ".accounts-privileged",
        cockpit.format(
            _("The user <b>$0</b> is not permitted to modify accounts"),
            cockpit.user.name)
    );
    $(".accounts-privileged").children("input")
        .attr('disabled', shell.default_permission.allowed === false);
}

function passwd_self(old_pass, new_pass) {
    var old_exps = [
        /.*\(current\) UNIX password: $/,
    ];
    var new_exps = [
        /.*New password: $/,
        /.*Retype new password: $/
    ];
    var bad_exps = [
        /.*BAD PASSWORD:.*/
    ];

    var dfd = $.Deferred();
    var buffer = "";
    var sent_new = false;
    var failure = _("Old password not accepted");
    var i;

    var timeout = window.setTimeout(function() {
        failure = _("Prompting via passwd timed out");
        proc.close("terminated");
    }, 10 * 1000);

    var proc = cockpit.spawn(["/usr/bin/passwd"], { pty: true, environ: [ "LC_ALL=C" ], err: "out" })
        .always(function() {
            window.clearInterval(timeout);
        })
        .done(function() {
            dfd.resolve();
        })
        .fail(function(ex) {
            if (ex.constructor.name == "ProcessError")
                ex = new Error(failure);
            dfd.reject(ex);
        })
        .stream(function(data) {
            buffer += data;
            for (i = 0; i < old_exps.length; i++) {
                if (old_exps[i].test(buffer)) {
                    buffer = "";
                    proc.input(old_pass + "\n", true);
                    return;
                }
            }

            for (i = 0; i < new_exps.length; i++) {
                if (new_exps[i].test(buffer)) {
                    buffer = "";
                    proc.input(new_pass + "\n", true);
                    failure = _("Failed to change password");
                    sent_new = true;
                    return;
                }
            }

            for (i = 0; sent_new && i < bad_exps.length; i++) {
                if (bad_exps[i].test(buffer)) {
                    failure = _("New password was not accepted");
                    return;
                }
            }
        });

    return dfd.promise();
}

function passwd_change(user, new_pass) {
    var dfd = $.Deferred();

    var buffer = "";
    cockpit.spawn(["/usr/bin/passwd", "--stdin", user ], {superuser: true, err: "out" })
        .input(new_pass)
        .stream(function(data) {
            buffer += data;
        })
        .done(function() {
            dfd.resolve();
        })
        .fail(function(ex) {
            if (ex.constructor.name == "ProcessError") {
                console.log(ex);
                if (buffer)
                    ex = new Error(buffer);
                else
                    ex = new Error(_("Failed to change password"));
            }
            dfd.reject(ex);
        });

    return dfd.promise();
}

$(shell.default_permission).on("changed", update_accounts_privileged);

function parse_passwd_content(content, tag, error) {
    if (content === null) {
        console.warn("Couldn't read /etc/passwd", error);
        return [ ];
    }

    var ret = [ ];
    var lines = content.split('\n');
    var column;

    for (var i = 0; i < lines.length; i++) {
        if (! lines[i])
            continue;
        column = lines[i].split(':');
        ret[i] = [];
        ret[i]["name"] = column[0];
        ret[i]["password"] = column[1];
        ret[i]["uid"] = parseInt(column[2], 10);
        ret[i]["gid"] = parseInt(column[3], 10);
        ret[i]["gecos"] = column[4];
        ret[i]["home"] = column[5];
        ret[i]["shell"] = column[6];
    }

    return ret;
}

function parse_group_content(content, tag, error) {
    if (content === null) {
        console.warn("Couldn't read /etc/group", error);
        return [ ];
    }

    var ret = [ ];
    var lines = content.split('\n');
    var column;

    for (var i = 0; i < lines.length; i++) {
        if (! lines[i])
            continue;
        column = lines[i].split(':');
        ret[i] = [];
        ret[i]["name"] = column[0];
        ret[i]["password"] = column[1];
        ret[i]["gid"] = parseInt(column[2], 10);
        ret[i]["userlist"] = column[3].split(',');
    }

    return ret;
}

function is_user_in_group(user, group) {
    for (var i = 0; group["userlist"] && i < group["userlist"].length; i++) {
        if (group["userlist"][i] === user)
{'fraction_non_alphanumeric': 0.1540700318326512, 'fraction_numerical': 0.006184629376989541, 'mean_word_length': 1.8516597510373445, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4713199', 'n_tokens_mistral': 3454, 'n_tokens_neox': 3311, 'n_words': 844}