Ukázka pro předmět Překladače, příkaz CACLS

Následuje ukázka implementace příkazu CACLS s parametry ve zjednodušené formě podle příkazů na Příkazovém řádku Windows.

package wintrainer;

/**
 *
 * @author sarka
 */

// trida pro zpracovani prikazu CACLS

public class TCacls {
    TData data;
    public String out;

    public TCacls (TData d) {
        data = d;
    }

    public void getHelp() {
         out = "Zobrazí nebo změní seznamy řízení přístupu (ACL) k souborům\n\n"
         + "\tCACLS název_souboru [/T] [/M] [/E] [/G uživatel:oprávnění\n"
         + "\t\t[/R uživatel [...]] [/P uživatel:oprávnění [...]] [/D uživatel [\n"
         + "\t\t...]]\n"
         + "   název_souboru Zobrazí ACL.\n"
         + "    /E            Místo nahrazení ACL jej upraví.\n"
         + "    /G uživatel:oprávnění  Udělí určenému uživateli přístupová oprávnění.\n"
         + "                 Oprávnění může být: R  Číst\n"
         + "                               W  Zapisovat\n"
         + "                               C  Měnit (zapisovat)\n"
         + "                               F  Úplné řízení\n"
         + "    /R uživatel       Odvolá přístupová oprávnění určeného uživatele\n"
         + "                      (platný pouze s parametrem /E).\n"
         + "    /P uživatel:oprávnění  Nahradí přístupová oprávnění určeného uživatele.\n"
         + "                  Oprávnění může být: N  Žádné\n"
         + "                               R  Číst\n"
         + "                               W  Zapisovat (i mazat)\n"
         + "                               C  Měnit (zapisovat)\n"
         + "                               F  Úplné řízení\n"
         + "    /D uživatel   Odepře přístup určenému uživateli.\n"
          + "nPro určení více než jednoho souboru mohou být v příkazu použity\n"
          + "zástupné znaky. Tato aplikace podporuje pouze řetězec \"*\", a to\n"
          + "pouze pro výpis existujících oprávnění (ne při použití přepínačů).\n\n"

         + " Zkratky (není podporováno aplikací):\n"
         + "    CI - Dědit kontejner.\n"
         + "         ACE bude děděno adresáři.\n"
         + "    OI - Dědit objekt.\n"
         + "         ACE bude děděno soubory.\n"
         + "    IO - Pouze dědit.\n"
         + "        ACE se nepoužije na aktuální adresář či soubor.\n"
         + "    ID - Zděděno.\n"
         + "         ACE bylo zděděno z nadřízeného adresáře ACL.\n";
    }

    // vypise ACL daneho uzlu v adresarove strukture
    void vypisFUzel(TData.TFileNode node) {
        out += node.getFullName();
        TData.TFileDescriptor desc = node.descriptor;
        for (int i = 0; i < TData.MaxUsers; i++) {   // nejdriv uzivatele
            if (desc.acl[i] != null && desc.acl[i].defined) {
                out += "\n\t" + data.users.user[i].name;
                TData.TFileDescriptor.TAcl acl = desc.acl[i];
                if (acl.rights[0] && acl.rights[1] && acl.rights[2]) out += ":F";
                else if (!(acl.rights[0] || acl.rights[1] || acl.rights[2])) out += ":N";
                else {
                    out += ":";
                    if (acl.rights[0]) out += "R";
                    if (acl.rights[1]) out += "W";
                    if (acl.rights[2]) out += "C";
                }                    
            }                
        }
        for (int i = TData.MaxUsers; i < 2*TData.MaxUsers+1; i++) {   // pak skupiny
            if (desc.acl[i] != null && desc.acl[i].defined) {
                out += "\n\t" + data.users.group[i-TData.MaxUsers].name;
                TData.TFileDescriptor.TAcl acl = desc.acl[i];
                if (acl.rights[0] && acl.rights[1] && acl.rights[2]) out += ":F";
                else if (!(acl.rights[0] || acl.rights[1] || acl.rights[2])) out += ":N";
                else {
                    out += ":";
                    if (acl.rights[0]) out += "R";
                    if (acl.rights[1]) out += "W";
                    if (acl.rights[2]) out += "C";
                }                    
            }                
        }  
        out += "\n\n";
    } // void vypisFUzel
    
    // vola predchozi funkci (vypisFUzel) pro vsechny potomky zadaneho adresare
    void vypisPotomky(TData.TDirNode node) {
        if (node.childCount > 0) {
            for (int i = 0; i < node.childCount; i++)
                vypisFUzel(node.child[i]);
        }
        if (node.fileCount > 0) {
            for (int i = 0; i < node.fileCount; i++)
                vypisFUzel (node.file[i]);
        }
    }

    // hlavni funkce tridy, vyhodnocuje parametry prikazu CACLS a vola predchozi funkce
    public int run(String params) {
        if (params == null || params.length() == 0) { getHelp(); return 0; }
        params = params.trim() + ' ';
        int delka = params.length();
        out = "";

        char [] rad = params.toCharArray();
        int pos = 0;

        // vyhodnoceni prepinacu prikazu
        boolean switchE = false, switchG = false, switchT = false, switchR = false, switchD = false;
        boolean switchesAre = false;
        String soub = "", uziv = "";            // nejdriv musi byt nazev
        char zn = ' ';
        if (rad[0] == '/' && rad[1] == '?') {
            getHelp();
            return 0;
        }
        if (rad[0] == '\"') {                   // nazev uzavren v uvozovkach
            switchesAre = true;
            pos++;
            while (pos < delka && rad[pos] != '\"') {
                soub += rad[pos];
                pos++;
            }
            if (rad[pos] != '\"') { out = "Chybí párová uvozovka."; return 0; }
            pos++;
        } else {                                // neni v uvozovkach
            while (pos < delka && rad[pos] != ' ') {
                soub += rad[pos];
                pos++;
            }
        }
        while (pos < delka) {
            while (pos < delka && rad[pos] == ' ') pos++;
            if (pos >= delka) break;
            if (rad[pos] == '/') {
                pos++;
                switch (rad[pos]) {
                    case '?': getHelp(); return 0;
                    case 'e': case 'E': pos++; switchE = true; switchesAre = true; break;
                    case 'g': case 'G': pos++; switchG = true; switchesAre = true; break;
                    case 't': case 'T': pos++; switchT = true; switchesAre = true; break;
                    case 'r': case 'R': pos++; switchR = true; switchesAre = true; break;
                    case 'd': case 'D': pos++; switchD = true; switchesAre = true; break;
                    default: pos++;   // nerozpoznany prepinac
                }
            } else if (Character.isLetter(rad[pos]) || Character.isDigit(rad[pos])) {                
                while (pos < delka && rad[pos] !=' ' && rad[pos] != ':' ) {
                    uziv += rad[pos];
                    pos++;
                }
                while (pos < delka && rad[pos] == ' ') pos++;
                if (pos < delka && rad[pos] == ':') {
                    pos++;
                    while (pos < delka && rad[pos] == ' ') pos++;
                    if (pos >= delka) {getHelp(); return 0; }
                    switch (rad[pos]) {
                        case 'r': case 'R': zn = 'r'; pos++; break;
                        case 'w': case 'W': zn = 'w'; pos++; break;
                        case 'c': case 'C': zn = 'c'; pos++; break;
                        case 'n': case 'N': zn = 'n'; pos++; break;
                        case 'f': case 'F': zn = 'f'; pos++; break;
                        default: out = "Oprávnění jsou R, W, C, N, F."; return 0;   // neexistujici opravneni
                    }
                }
            }
        }  
        // nacteny vsechny vstupy, dal bude analyza vstupu a vypisovani
        
        
        if (!switchesAre) {  // bez prepinacu, pouze se vypise
            if (soub.charAt(0) == '*') {  // vypsat vse v tomto uzlu
                vypisPotomky(data.active);
                return 1;
            } else {
                TData.TFileNode node = data.getFileNode(soub);
                if (node != null) {
                    vypisFUzel(node);
                    return 1;
                } else { out = "Soubor nenalezen."; return 0; }
            }
        }
        if (soub.charAt(0) == '*') { 
            out = "V této verzi lze používat hvězdičku pouze pro výpis oprávnění."; return 0;
        }

        int uzivatel = data.users.findUser(uziv);
        if (uzivatel < 0) { out = "Uživatel " + uziv + " nenalezen."; return 0; }
        TData.TFileNode node = data.getFileNode(soub);
        TData.TFileDescriptor desc = node.descriptor;
        if (!desc.acl[data.loggedUser].rights[1]) { out = "Máte nedostatečná oprávnění."; return 0; }   // nemuze upravovat
        if (switchG) {
            if (switchE) { //  /e /g
                switch (zn) {
                    case 'r': desc.setRead(uzivatel, true); out = "Zpracovávaný soubor: "+ node.getFullName(); return 0;
                    case 'w': desc.setWrite(uzivatel, true); out = "Zpracovávaný soubor: "+ node.getFullName(); return 0;
                    case 'c': desc.setChange(uzivatel, true); out = "Zpracovávaný soubor: "+ node.getFullName(); return 0;
                    case 'f': desc.setFull(uzivatel); out = "Zpracovávaný soubor: "+ node.getFullName(); return 0;
                    case 'n': desc.setNone(uzivatel); out = "Zpracovávaný soubor: "+ node.getFullName(); return 0;
                }
                getHelp();
                return 0;
            } else {   // jen /g
               switch (zn) {
                   case 'r':    desc.setRead(uzivatel, true);
                                desc.setWrite(uzivatel, false);  // vcetne "change"
                                out = "Zpracovávaný soubor: "+ node.getFullName();
                                return 0;
                   case 'w':    desc.setRead(uzivatel,false);
                                desc.setWrite(uzivatel, true);
                                out = "Zpracovávaný soubor: "+ node.getFullName();
                                return 0;
                   case 'c':    desc.setRead(uzivatel, false);
                                desc.setWrite(uzivatel, false);
                                desc.setChange(uzivatel, true);
                                out = "Zpracovávaný soubor: "+ node.getFullName();
                                return 0;
                   case 'f': desc.setFull(uzivatel); out = "Zpracovávaný soubor: "+ node.getFullName(); return 0;
                   case 'n': desc.setNone(uzivatel); out = "Zpracovávaný soubor: "+ node.getFullName(); return 0;
               }
               getHelp();
               return 0;
            }
        }
        if (switchR) {
            desc.acl[uzivatel].defined = false;
            out = "Zpracovávaný soubor: "+ node.getFullName();
            return 0;
        }
        if (switchD) {
            desc.setNone(uzivatel);
            out = "Zpracovávaný soubor: "+ node.getFullName();
            return 0;
        }
        getHelp();
        return -1;
    }
}