Example #1
0
        ///////////////////////////////////////////////////////////////////////

        #region IExecute Members
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return(ReturnCode.Error);
            }

            if (arguments == null)
            {
                result = "invalid argument list";
                return(ReturnCode.Error);
            }

            if (arguments.Count < 2)
            {
                result = "wrong # args: should be \"hash option ?arg ...?\"";
                return(ReturnCode.Error);
            }

            ReturnCode code;
            string     subCommand = arguments[1];
            bool       tried      = false;

            code = ScriptOps.TryExecuteSubCommandFromEnsemble(
                interpreter, this, clientData, arguments, true,
                false, ref subCommand, ref tried, ref result);

            if ((code != ReturnCode.Ok) || tried)
            {
                return(code);
            }

            //
            // NOTE: These algorithms are known to be supported by the
            //       framework.
            //
            //       Normal: MD5, RIPEMD160, SHA, SHA1, SHA256, SHA384, SHA512
            //
            //        Keyed: MACTripleDES
            //
            //         HMAC: HMACMD5, HMACRIPEMD160, HMACSHA1, HMACSHA256,
            //               HMACSHA384, HMACSHA512
            //
            switch (subCommand)
            {
            case "keyed":
            {
                if (arguments.Count >= 4)
                {
                    OptionDictionary options = new OptionDictionary(
                        new IOption[] {
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-raw",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-filename",
                                       null), /* COMPAT: Tcllib. */
                            new Option(null, OptionFlags.MustHaveEncodingValue,
                                       Index.Invalid, Index.Invalid, "-encoding",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid,
                                       Option.EndOfOptions, null)
                        });

                    int argumentIndex = Index.Invalid;

                    code = interpreter.GetOptions(
                        options, arguments, 0, 2, Index.Invalid, false,
                        ref argumentIndex, ref result);

                    if (code == ReturnCode.Ok)
                    {
                        if ((argumentIndex != Index.Invalid) &&
                            ((argumentIndex + 2) <= arguments.Count) &&
                            ((argumentIndex + 3) >= arguments.Count))
                        {
                            Variant value = null;
                            bool    raw   = false;

                            if (options.IsPresent("-raw"))
                            {
                                raw = true;
                            }

                            bool isFileName = false;

                            if (options.IsPresent("-filename", ref value))
                            {
                                isFileName = true;
                            }

                            Encoding encoding = null;

                            if (options.IsPresent("-encoding", ref value))
                            {
                                encoding = (Encoding)value.Value;
                            }

                            if (code == ReturnCode.Ok)
                            {
                                try
                                {
                                    using (KeyedHashAlgorithm algorithm =
                                               KeyedHashAlgorithm.Create(
                                                   arguments[argumentIndex]))
                                    {
                                        if (algorithm != null)
                                        {
                                            algorithm.Initialize();

                                            if ((argumentIndex + 3) == arguments.Count)
                                            {
                                                byte[] bytes = null;

                                                code = StringOps.GetBytes(
                                                    encoding, arguments[argumentIndex + 2],
                                                    EncodingType.Binary, ref bytes, ref result);

                                                if (code == ReturnCode.Ok)
                                                {
                                                    algorithm.Key = bytes;
                                                }
                                            }

                                            if (code == ReturnCode.Ok)
                                            {
                                                if (isFileName)
                                                {
                                                    Stream stream = null;

                                                    try
                                                    {
                                                        code = RuntimeOps.NewStream(
                                                            interpreter,
                                                            arguments[argumentIndex + 1],
                                                            FileMode.Open, FileAccess.Read,
                                                            ref stream, ref result);

                                                        if (code == ReturnCode.Ok)
                                                        {
                                                            if (raw)
                                                            {
                                                                result = new ByteList(
                                                                    algorithm.ComputeHash(stream));
                                                            }
                                                            else
                                                            {
                                                                result = FormatOps.Hash(
                                                                    algorithm.ComputeHash(stream));
                                                            }
                                                        }
                                                    }
                                                    finally
                                                    {
                                                        if (stream != null)
                                                        {
                                                            stream.Close();
                                                            stream = null;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    byte[] bytes = null;

                                                    code = StringOps.GetBytes(
                                                        encoding, arguments[argumentIndex + 1],
                                                        EncodingType.Binary, ref bytes, ref result);

                                                    if (raw)
                                                    {
                                                        result = new ByteList(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                    else
                                                    {
                                                        result = FormatOps.Hash(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            result = String.Format(
                                                "unsupported keyed hash algorithm \"{0}\"",
                                                arguments[argumentIndex]);

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Engine.SetExceptionErrorCode(interpreter, e);

                                    result = e;
                                    code   = ReturnCode.Error;
                                }
                            }
                        }
                        else
                        {
                            if ((argumentIndex != Index.Invalid) &&
                                Option.LooksLikeOption(arguments[argumentIndex]))
                            {
                                result = OptionDictionary.BadOption(
                                    options, arguments[argumentIndex]);
                            }
                            else
                            {
                                result = String.Format(
                                    "wrong # args: should be \"{0} {1} ?options? algorithm string ?key?\"",
                                    this.Name, subCommand);
                            }

                            code = ReturnCode.Error;
                        }
                    }
                }
                else
                {
                    result = String.Format(
                        "wrong # args: should be \"{0} {1} ?options? algorithm string ?key?\"",
                        this.Name, subCommand);

                    code = ReturnCode.Error;
                }
                break;
            }

            case "list":
            {
                if ((arguments.Count == 2) || (arguments.Count == 3))
                {
                    string type = null;

                    if (arguments.Count == 3)
                    {
                        type = arguments[2];
                    }

                    switch (type)
                    {
                    case null:
                    case "all":
                    {
                        StringList list = new StringList();

                        lock (syncRoot)
                        {
                            if (defaultAlgorithms != null)
                            {
                                list.AddRange(defaultAlgorithms);
                            }
                        }

                        if (keyedHashAlgorithmNames != null)
                        {
                            foreach (string hashAlgorithmName in keyedHashAlgorithmNames)
                            {
                                list.Add(StringList.MakeList("keyed", hashAlgorithmName));
                            }
                        }

                        if (macHashAlgorithmNames != null)
                        {
                            foreach (string hashAlgorithmName in macHashAlgorithmNames)
                            {
                                list.Add(StringList.MakeList("mac", hashAlgorithmName));
                            }
                        }

                        if (normalHashAlgorithmNames != null)
                        {
                            foreach (string hashAlgorithmName in normalHashAlgorithmNames)
                            {
                                list.Add(StringList.MakeList("normal", hashAlgorithmName));
                            }
                        }

                        result = list;
                        break;
                    }

                    case "default":
                    {
                        lock (syncRoot)
                        {
                            result = (defaultAlgorithms != null) ?
                                     new StringList(defaultAlgorithms) : null;
                        }
                        break;
                    }

                    case "keyed":
                    {
                        result = (keyedHashAlgorithmNames != null) ?
                                 new StringList(keyedHashAlgorithmNames) : null;

                        break;
                    }

                    case "mac":
                    {
                        result = (macHashAlgorithmNames != null) ?
                                 new StringList(macHashAlgorithmNames) : null;

                        break;
                    }

                    case "normal":
                    {
                        result = (normalHashAlgorithmNames != null) ?
                                 new StringList(normalHashAlgorithmNames) : null;

                        break;
                    }

                    default:
                    {
                        result = "unknown algorithm list, must be: all, default, keyed, mac, or normal";
                        code   = ReturnCode.Error;
                        break;
                    }
                    }
                }
                else
                {
                    result = String.Format(
                        "wrong # args: should be \"{0} {1} ?type?\"",
                        this.Name, subCommand);

                    code = ReturnCode.Error;
                }
                break;
            }

            case "mac":
            {
                if (arguments.Count >= 4)
                {
                    OptionDictionary options = new OptionDictionary(
                        new IOption[] {
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-raw",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-filename",
                                       null), /* COMPAT: Tcllib. */
                            new Option(null, OptionFlags.MustHaveEncodingValue,
                                       Index.Invalid, Index.Invalid, "-encoding",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid,
                                       Option.EndOfOptions, null)
                        });

                    int argumentIndex = Index.Invalid;

                    code = interpreter.GetOptions(
                        options, arguments, 0, 2, Index.Invalid, false,
                        ref argumentIndex, ref result);

                    if (code == ReturnCode.Ok)
                    {
                        if ((argumentIndex != Index.Invalid) &&
                            ((argumentIndex + 2) <= arguments.Count) &&
                            ((argumentIndex + 3) >= arguments.Count))
                        {
                            Variant value = null;
                            bool    raw   = false;

                            if (options.IsPresent("-raw"))
                            {
                                raw = true;
                            }

                            bool isFileName = false;

                            if (options.IsPresent("-filename", ref value))
                            {
                                isFileName = true;
                            }

                            Encoding encoding = null;

                            if (options.IsPresent("-encoding", ref value))
                            {
                                encoding = (Encoding)value.Value;
                            }

                            if (code == ReturnCode.Ok)
                            {
                                try
                                {
                                    using (HMAC algorithm = HMAC.Create(
                                               arguments[argumentIndex]))
                                    {
                                        if (algorithm != null)
                                        {
                                            algorithm.Initialize();

                                            if ((argumentIndex + 3) == arguments.Count)
                                            {
                                                byte[] bytes = null;

                                                code = StringOps.GetBytes(
                                                    encoding, arguments[argumentIndex + 2],
                                                    EncodingType.Binary, ref bytes, ref result);

                                                if (code == ReturnCode.Ok)
                                                {
                                                    algorithm.Key = bytes;
                                                }
                                            }

                                            if (code == ReturnCode.Ok)
                                            {
                                                if (isFileName)
                                                {
                                                    Stream stream = null;

                                                    try
                                                    {
                                                        code = RuntimeOps.NewStream(
                                                            interpreter,
                                                            arguments[argumentIndex + 1],
                                                            FileMode.Open, FileAccess.Read,
                                                            ref stream, ref result);

                                                        if (code == ReturnCode.Ok)
                                                        {
                                                            if (raw)
                                                            {
                                                                result = new ByteList(
                                                                    algorithm.ComputeHash(stream));
                                                            }
                                                            else
                                                            {
                                                                result = FormatOps.Hash(
                                                                    algorithm.ComputeHash(stream));
                                                            }
                                                        }
                                                    }
                                                    finally
                                                    {
                                                        if (stream != null)
                                                        {
                                                            stream.Close();
                                                            stream = null;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    byte[] bytes = null;

                                                    code = StringOps.GetBytes(
                                                        encoding, arguments[argumentIndex + 1],
                                                        EncodingType.Binary, ref bytes, ref result);

                                                    if (raw)
                                                    {
                                                        result = new ByteList(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                    else
                                                    {
                                                        result = FormatOps.Hash(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            result = String.Format(
                                                "unsupported hmac algorithm \"{0}\"",
                                                arguments[argumentIndex]);

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Engine.SetExceptionErrorCode(interpreter, e);

                                    result = e;
                                    code   = ReturnCode.Error;
                                }
                            }
                        }
                        else
                        {
                            if ((argumentIndex != Index.Invalid) &&
                                Option.LooksLikeOption(arguments[argumentIndex]))
                            {
                                result = OptionDictionary.BadOption(
                                    options, arguments[argumentIndex]);
                            }
                            else
                            {
                                result = String.Format(
                                    "wrong # args: should be \"{0} {1} ?options? algorithm string ?key?\"",
                                    this.Name, subCommand);
                            }

                            code = ReturnCode.Error;
                        }
                    }
                }
                else
                {
                    result = String.Format(
                        "wrong # args: should be \"{0} {1} ?options? algorithm string ?key?\"",
                        this.Name, subCommand);

                    code = ReturnCode.Error;
                }
                break;
            }

            case "normal":
            {
                if (arguments.Count >= 4)
                {
                    OptionDictionary options = new OptionDictionary(
                        new IOption[] {
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-raw",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-filename",
                                       null), /* COMPAT: Tcllib. */
                            new Option(null, OptionFlags.MustHaveEncodingValue,
                                       Index.Invalid, Index.Invalid, "-encoding",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid,
                                       Option.EndOfOptions, null)
                        });

                    int argumentIndex = Index.Invalid;

                    code = interpreter.GetOptions(
                        options, arguments, 0, 2, Index.Invalid, false,
                        ref argumentIndex, ref result);

                    if (code == ReturnCode.Ok)
                    {
                        if ((argumentIndex != Index.Invalid) &&
                            ((argumentIndex + 2) == arguments.Count))
                        {
                            Variant value = null;
                            bool    raw   = false;

                            if (options.IsPresent("-raw"))
                            {
                                raw = true;
                            }

                            bool isFileName = false;

                            if (options.IsPresent("-filename", ref value))
                            {
                                isFileName = true;
                            }

                            Encoding encoding = null;

                            if (options.IsPresent("-encoding", ref value))
                            {
                                encoding = (Encoding)value.Value;
                            }

                            if (code == ReturnCode.Ok)
                            {
                                try
                                {
                                    using (HashAlgorithm algorithm =
                                               HashAlgorithm.Create(
                                                   arguments[argumentIndex]))
                                    {
                                        if (algorithm != null)
                                        {
                                            algorithm.Initialize();

                                            if (isFileName)
                                            {
                                                Stream stream = null;

                                                try
                                                {
                                                    code = RuntimeOps.NewStream(
                                                        interpreter,
                                                        arguments[argumentIndex + 1],
                                                        FileMode.Open, FileAccess.Read,
                                                        ref stream, ref result);

                                                    if (code == ReturnCode.Ok)
                                                    {
                                                        if (raw)
                                                        {
                                                            result = new ByteList(
                                                                algorithm.ComputeHash(stream));
                                                        }
                                                        else
                                                        {
                                                            result = FormatOps.Hash(
                                                                algorithm.ComputeHash(stream));
                                                        }
                                                    }
                                                }
                                                finally
                                                {
                                                    if (stream != null)
                                                    {
                                                        stream.Close();
                                                        stream = null;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                byte[] bytes = null;

                                                code = StringOps.GetBytes(
                                                    encoding, arguments[argumentIndex + 1],
                                                    EncodingType.Binary, ref bytes, ref result);

                                                if (code == ReturnCode.Ok)
                                                {
                                                    if (raw)
                                                    {
                                                        result = new ByteList(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                    else
                                                    {
                                                        result = FormatOps.Hash(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            result = String.Format(
                                                "unsupported hash algorithm \"{0}\"",
                                                arguments[argumentIndex]);

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Engine.SetExceptionErrorCode(interpreter, e);

                                    result = e;
                                    code   = ReturnCode.Error;
                                }
                            }
                        }
                        else
                        {
                            if ((argumentIndex != Index.Invalid) &&
                                Option.LooksLikeOption(arguments[argumentIndex]))
                            {
                                result = OptionDictionary.BadOption(
                                    options, arguments[argumentIndex]);
                            }
                            else
                            {
                                result = String.Format(
                                    "wrong # args: should be \"{0} {1} ?options? algorithm string\"",
                                    this.Name, subCommand);
                            }

                            code = ReturnCode.Error;
                        }
                    }
                }
                else
                {
                    result = String.Format(
                        "wrong # args: should be \"{0} {1} ?options? algorithm string\"",
                        this.Name, subCommand);

                    code = ReturnCode.Error;
                }
                break;
            }

            default:
            {
                result = ScriptOps.BadSubCommand(
                    interpreter, null, null, subCommand, this, null, null);

                code = ReturnCode.Error;
                break;
            }
            }

            return(code);
        }