brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.3 KiB · 6d5b862 Raw
83 lines · python
1# -*- coding: utf-8 -*-2# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3# See https://llvm.org/LICENSE.txt for license information.4# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5""" This module implements basic shell escaping/unescaping methods. """6 7import re8import shlex9 10__all__ = ["encode", "decode"]11 12 13def encode(command):14    """Takes a command as list and returns a string."""15 16    def needs_quote(word):17        """Returns true if arguments needs to be protected by quotes.18 19        Previous implementation was shlex.split method, but that's not good20        for this job. Currently is running through the string with a basic21        state checking."""22 23        reserved = {24            " ",25            "$",26            "%",27            "&",28            "(",29            ")",30            "[",31            "]",32            "{",33            "}",34            "*",35            "|",36            "<",37            ">",38            "@",39            "?",40            "!",41        }42        state = 043        for current in word:44            if state == 0 and current in reserved:45                return True46            elif state == 0 and current == "\\":47                state = 148            elif state == 1 and current in reserved | {"\\"}:49                state = 050            elif state == 0 and current == '"':51                state = 252            elif state == 2 and current == '"':53                state = 054            elif state == 0 and current == "'":55                state = 356            elif state == 3 and current == "'":57                state = 058        return state != 059 60    def escape(word):61        """Do protect argument if that's needed."""62 63        table = {"\\": "\\\\", '"': '\\"'}64        escaped = "".join([table.get(c, c) for c in word])65 66        return '"' + escaped + '"' if needs_quote(word) else escaped67 68    return " ".join([escape(arg) for arg in command])69 70 71def decode(string):72    """Takes a command string and returns as a list."""73 74    def unescape(arg):75        """Gets rid of the escaping characters."""76 77        if len(arg) >= 2 and arg[0] == arg[-1] and arg[0] == '"':78            arg = arg[1:-1]79            return re.sub(r'\\(["\\])', r"\1", arg)80        return re.sub(r"\\([\\ $%&\(\)\[\]\{\}\*|<>@?!])", r"\1", arg)81 82    return [unescape(arg) for arg in shlex.split(string)]83