#!/usr/bin/env qore
# -*- mode: qore; indent-tabs-mode: nil -*-

%enable-all-warnings
%new-style
%strict-args
%require-types

# uses the openldap module
%requires openldap

# ensure minimum version of qore
%requires qore >= 0.8.7

main();

const Defaults = (
    "uri": "ldap://localhost:389",
    );

const opts = (
    # common
    "uri": "H,uri=s",
    "binddn": "D,binddn=s",
    "password": "w,passwd=s",
    "promptbind": "W,prompt-bind",
    "info": "i,info",
    "verbose": "v,verbose",
    "timeout": "l,timeout=i",
    "protocol": "P,protocol=i",
    "no-referrals": "r,no-referrals",
    "starttls": "Z,starttls",
    "help": "h,help",
    );

const LdapOptions = ("binddn", "password", "timeout", "protocol", "no-referrals", "starttls");

sub main() {
    # process command-line options
    GetOpt g(opts);
    hash opts = g.parse3(\ARGV);
    if (opts.help)
	usage();

    if (opts.info) {
	printf("%N\n", LdapClient::getInfo());
	exit(0);
    }

    *string dn = shift ARGV;
    if (!dn)
        error("missing dn to delete");

    if (!opts.uri)
	opts.uri = Defaults.uri;

    if (opts.promptbind) {
        stdout.printf("Enter LDAP Bind Password: ");
        TerminalInputHelper t();
        opts.password = t.getLine();
    }

    hash lopt = opts{LdapOptions};

    if (opts.verbose)
        printf("uri: %y, lopt: %y, dn: %y\n", opts.uri, lopt, dn);

    LdapClient ldap(opts.uri, lopt);
    ldap.del(dn);
}

sub error(string fmt) {
    fmt = sprintf("%s: %s\n", get_script_name(), fmt);
    stderr.vprintf(fmt, argv);
    exit(1);
}

sub usage() {
    printf("usage: %s [options] <dn> <attr>=<value> [<attr>=<value> ...]
Common LDAP Options:
  -D,--binddn=ARG     bind DN
  -H,--uri=ARG        LDAP Uniform Resource Identifier(s)
  -l,--timeout=ARG    set timeout in milliseconds (default: %y)
  -P,--protocol=ARG   set protocol version (default: 3)
  -r,--no-referrals   do not chase referrals
  -v,--verbose        verbose mode; shows more information
  -w,--passwd=ARG     bind password (for simple authentication)
  -W,--prompt-bind    prompt for bind password
  -Z,--starttls       ensure a secure connection

Other Options:
  -i,--info           show ldap library info and exit
  -h,--help           this help text
", get_script_name(), OpenLdap::DefaultTimeout);
    exit(0);
}

class TerminalInputHelper {
    private {
        # saved original terminal attributes
        TermIOS orig = stdin.getTerminalAttributes();

        # input terminal attributes
        TermIOS input;

        # restore flag
        bool rest = False;
    }

    public {}

    constructor() {
        input = orig.copy();

        # get local flags
        int lflag = input.getLFlag();

        # turn on "raw" mode: disable canonical input mode
        lflag &= ~ICANON;

        # turn off echo mode
        lflag &= ~ECHO;

        # set the new local flags
        input.setLFlag(lflag);

        # turn off input buffering: set minimum characters to return on a read
        input.setCC(VMIN, 1);

        # disable input timer: set character input timer to 0.1 second increments
        input.setCC(VTIME, 0);
    }

    destructor() {
        if (rest)
            restore();
    }

    *string getLine() {
        # set input attributes
        stdin.setTerminalAttributes(TCSADRAIN, input);
        rest = True;

        # restore attributes on exit
        on_exit {
            stdin.setTerminalAttributes(TCSADRAIN, orig);
            rest = False;
            stdout.print("\n");
        }

        return stdin.readLine(False);
    }

    restore() {
        # restore terminal attributes
        stdin.setTerminalAttributes(TCSADRAIN, orig);
    }
}
