Index: trunk/src/VBox/Runtime/common/misc/expreval.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/misc/expreval.cpp	(revision 102286)
+++ trunk/src/VBox/Runtime/common/misc/expreval.cpp	(revision 102287)
@@ -46,6 +46,8 @@
 #include <iprt/ctype.h>
 #include <iprt/err.h>
+#include <iprt/md5.h>
 #include <iprt/mem.h>
 #include <iprt/path.h>
+#include <iprt/sha.h>
 #include <iprt/string.h>
 
@@ -525,23 +527,25 @@
 
 
-#if 0  /* unused */
 /**
  * Initializes a new variables with a string value.
  *
  * @returns kExprRet_Ok or kExprRet_Error.
+ * @param   pThis   The evaluator expression instance.
  * @param   pVar    The new variable.
  * @param   psz     The string value.
  * @param   enmType The string type.
  */
-static EXPRRET expr_var_init_string(PEXPRVAR pVar, const char *psz, EXPRVARTYPE enmType)
-{
-    return expr_var_init_substring(pVar, psz, strlen(psz), enmType);
-}
-
-
+static EXPRRET expr_var_init_string(PEXPR pThis, PEXPRVAR pVar, const char *psz, EXPRVARTYPE enmType)
+{
+    return expr_var_init_substring(pThis, pVar, psz, strlen(psz), enmType);
+}
+
+
+#if 0  /* unused */
 /**
  * Assigns a sub-string value to a variable.
  *
  * @returns kExprRet_Ok or kExprRet_Error.
+ * @param   pThis   The evaluator expression instance.
  * @param   pVar    The new variable.
  * @param   psz     The start of the string value.
@@ -549,9 +553,10 @@
  * @param   enmType The string type.
  */
-static void expr_var_assign_substring(PEXPRVAR pVar, const char *psz, size_t cch, EXPRVARTYPE enmType)
+static EXPRRET expr_var_assign_substring(PEXPR pThis, PEXPRVAR pVar, const char *psz, size_t cch, EXPRVARTYPE enmType)
 {
     expr_var_delete(pVar);
-    return expr_var_init_substring(pVar, psz, cch, enmType);
-}
+    return expr_var_init_substring(pThis, pVar, psz, cch, enmType);
+}
+#endif /* unused */
 
 
@@ -560,14 +565,14 @@
  *
  * @returns kExprRet_Ok or kExprRet_Error.
+ * @param   pThis       The evaluator expression instance.
  * @param   pVar    The variable.
  * @param   psz     The string value.
  * @param   enmType The string type.
  */
-static void expr_var_assign_string(PEXPRVAR pVar, const char *psz, EXPRVARTYPE enmType)
+static EXPRRET expr_var_assign_string(PEXPR pThis, PEXPRVAR pVar, const char *psz, EXPRVARTYPE enmType)
 {
     expr_var_delete(pVar);
-    return expr_var_init_string(pVar, psz, enmType);
-}
-#endif /* unused */
+    return expr_var_init_string(pThis, pVar, psz, enmType);
+}
 
 
@@ -1314,4 +1319,108 @@
 
 /**
+ * Returns the MD5 digest of the input as a string.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_md5(PEXPR pThis)
+{
+    PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
+    EXPRRET  rc   = expr_var_make_simple_string(pThis, pVar);
+    if (rc == kExprRet_Ok)
+    {
+        pVar->enmType = kExprVar_QuotedSimpleString;
+
+        uint8_t abDigest[RTMD5_HASH_SIZE];
+        RTMd5(pVar->uVal.psz, strlen(pVar->uVal.psz), abDigest);
+        char szHash[RTMD5_DIGEST_LEN + 1];
+        RTMd5ToString(abDigest, szHash, sizeof(szHash));
+
+        rc = expr_var_assign_string(pThis, pVar, szHash, kExprVar_QuotedSimpleString);
+    }
+
+    return rc;
+}
+
+
+/**
+ * Returns the SHA1 digest of the input as a string.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_sha1(PEXPR pThis)
+{
+    PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
+    EXPRRET  rc   = expr_var_make_simple_string(pThis, pVar);
+    if (rc == kExprRet_Ok)
+    {
+        pVar->enmType = kExprVar_QuotedSimpleString;
+
+        uint8_t abDigest[RTSHA1_HASH_SIZE];
+        RTSha1(pVar->uVal.psz, strlen(pVar->uVal.psz), abDigest);
+        char szHash[RTSHA1_DIGEST_LEN + 1];
+        RTSha1ToString(abDigest, szHash, sizeof(szHash));
+
+        rc = expr_var_assign_string(pThis, pVar, szHash, kExprVar_QuotedSimpleString);
+    }
+
+    return rc;
+}
+
+
+/**
+ * Returns the SHA256 digest of the input as a string.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_sha256(PEXPR pThis)
+{
+    PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
+    EXPRRET  rc   = expr_var_make_simple_string(pThis, pVar);
+    if (rc == kExprRet_Ok)
+    {
+        pVar->enmType = kExprVar_QuotedSimpleString;
+
+        uint8_t abDigest[RTSHA256_HASH_SIZE];
+        RTSha256(pVar->uVal.psz, strlen(pVar->uVal.psz), abDigest);
+        char szHash[RTSHA256_DIGEST_LEN + 1];
+        RTSha256ToString(abDigest, szHash, sizeof(szHash));
+
+        rc = expr_var_assign_string(pThis, pVar, szHash, kExprVar_QuotedSimpleString);
+    }
+
+    return rc;
+}
+
+
+/**
+ * Returns the SHA-512 digest of the input as a string.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_sha512(PEXPR pThis)
+{
+    PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
+    EXPRRET  rc   = expr_var_make_simple_string(pThis, pVar);
+    if (rc == kExprRet_Ok)
+    {
+        pVar->enmType = kExprVar_QuotedSimpleString;
+
+        uint8_t abDigest[RTSHA512_HASH_SIZE];
+        RTSha512(pVar->uVal.psz, strlen(pVar->uVal.psz), abDigest);
+        char szHash[RTSHA512_DIGEST_LEN + 1];
+        RTSha512ToString(abDigest, szHash, sizeof(szHash));
+
+        rc = expr_var_assign_string(pThis, pVar, szHash, kExprVar_QuotedSimpleString);
+    }
+
+    return rc;
+}
+
+
+/**
  * Pluss (dummy / make_integer)
  *
@@ -1443,4 +1552,55 @@
     return rc;
 }
+
+
+#if 0 /** @todo not happy with 'strcat' as an operator. Dot doesn't work, so, figure something else out... */
+/**
+ * Concatnation (string).
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_concat(PEXPR pThis)
+{
+    PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
+    EXPRRET  rc    = kExprRet_Ok;
+    if (!expr_var_is_string(pVar1))
+        rc = expr_var_make_simple_string(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        if (!expr_var_is_string(pVar2))
+            rc = expr_var_make_simple_string(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+        {
+            /** @todo this may be problematic if we combine simple with quoted strings
+             *        if the simple string contains $. */
+            if (rc >= kExprRet_Ok)
+            {
+                size_t cchVar1 = strlen(pVar1->uVal.psz);
+                size_t cchVar2 = strlen(pVar2->uVal.psz);
+                size_t cchNew  = cchVar1 + cchVar2;
+                char  *pszNew  = (char *)RTMemTmpAlloc(cchNew + 1);
+                if (pszNew)
+                {
+                    memcpy(pszNew, pVar1->uVal.psz, cchVar1);
+                    memcpy(&pszNew[cchVar1], pVar2->uVal.psz, cchVar2);
+                    pszNew[cchNew] = '\0';
+                    RTMemTmpFree(pVar1->uVal.psz);
+                    pVar1->uVal.psz = pszNew;
+                }
+                else
+                {
+                    RTErrInfoSetF(pThis->pErrInfo, VERR_NO_TMP_MEMORY, "Failed to allocate %zu bytes", cchNew + 1);
+                    rc = kExprRet_Error;
+                }
+            }
+        }
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+#endif
 
 
@@ -2062,5 +2222,9 @@
     EXPR_OP("exists",      90,      1,    expr_op_exists),
     EXPR_OP("bool",        90,      1,    expr_op_bool),
+    EXPR_OP("md5",         90,      1,    expr_op_md5),
     EXPR_OP("num",         90,      1,    expr_op_num),
+    EXPR_OP("sha1",        90,      1,    expr_op_sha1),
+    EXPR_OP("sha256",      90,      1,    expr_op_sha256),
+    EXPR_OP("sha512",      90,      1,    expr_op_sha512),
     EXPR_OP("strlen",      90,      1,    expr_op_strlen),
     EXPR_OP("str",         90,      1,    expr_op_str),
@@ -2073,4 +2237,7 @@
     EXPR_OP("+",           70,      2,    expr_op_add),
     EXPR_OP("-",           70,      2,    expr_op_sub),
+#if 0  /** @todo not happy with 'strcat' as an operator. Dot doesn't work, so, figure something else out... */
+    EXPR_OP("strcat",      70,      2,    expr_op_concat),
+#endif
     EXPR_OP("<<",          65,      2,    expr_op_shift_left),
     EXPR_OP(">>",          65,      2,    expr_op_shift_right),
Index: trunk/src/VBox/Runtime/testcase/tstRTExprEval.cpp
===================================================================
--- trunk/src/VBox/Runtime/testcase/tstRTExprEval.cpp	(revision 102286)
+++ trunk/src/VBox/Runtime/testcase/tstRTExprEval.cpp	(revision 102287)
@@ -69,4 +69,6 @@
     else if (MATCH_VAR("MYNESTED1"))
         pszValue = "MYVAR1";
+    else if (MATCH_VAR("FOX_AND_DOG"))
+        pszValue = "The quick brown fox jumps over the lazy dog";
     else
         return VERR_NOT_FOUND;
@@ -171,4 +173,42 @@
     CHECK_FREE_pszResult("3");
 
+    /* hash functions: */
+    g_fQueryVariableExpected = true;
+    RTTESTI_CHECK_RC(RTExprEvalToString(hExprEval, RT_STR_TUPLE("sha1 \"${FOX_AND_DOG}\""), &pszResult, NULL), VINF_SUCCESS);
+    g_fQueryVariableExpected = false;
+    CHECK_FREE_pszResult("2fd4e1c67a2d28fced849ee1bb76e7391b93eb12");
+
+    g_fQueryVariableExpected = true;
+    RTTESTI_CHECK_RC(RTExprEvalToString(hExprEval, RT_STR_TUPLE("sha1(\"${FOX_AND_DOG}\")"), &pszResult, NULL), VINF_SUCCESS);
+    g_fQueryVariableExpected = false;
+    CHECK_FREE_pszResult("2fd4e1c67a2d28fced849ee1bb76e7391b93eb12");
+
+    g_fQueryVariableExpected = true;
+    RTTESTI_CHECK_RC(RTExprEvalToString(hExprEval, RT_STR_TUPLE("sha1(${FOX_AND_DOG})"), &pszResult, NULL), VINF_SUCCESS);
+    g_fQueryVariableExpected = false;
+    CHECK_FREE_pszResult("2fd4e1c67a2d28fced849ee1bb76e7391b93eb12");
+
+#if 0 /** @todo not happy with 'strcat' as an operator. Dot doesn't work, so, figure something else out... */
+    g_fQueryVariableExpected = true;
+    RTTESTI_CHECK_RC(RTExprEvalToString(hExprEval, RT_STR_TUPLE("sha1(${FOX_AND_DOG}) strcat sha1('')"), &pszResult, NULL), VINF_SUCCESS);
+    g_fQueryVariableExpected = false;
+    CHECK_FREE_pszResult("2fd4e1c67a2d28fced849ee1bb76e7391b93eb12da39a3ee5e6b4b0d3255bfef95601890afd80709");
+#endif
+
+    g_fQueryVariableExpected = true;
+    RTTESTI_CHECK_RC(RTExprEvalToString(hExprEval, RT_STR_TUPLE("sha256('')"), &pszResult, NULL), VINF_SUCCESS);
+    g_fQueryVariableExpected = false;
+    CHECK_FREE_pszResult("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+
+    g_fQueryVariableExpected = true;
+    RTTESTI_CHECK_RC(RTExprEvalToString(hExprEval, RT_STR_TUPLE("sha512('')"), &pszResult, NULL), VINF_SUCCESS);
+    g_fQueryVariableExpected = false;
+    CHECK_FREE_pszResult("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
+
+    g_fQueryVariableExpected = true;
+    RTTESTI_CHECK_RC(RTExprEvalToString(hExprEval, RT_STR_TUPLE("md5(${FOX_AND_DOG})"), &pszResult, NULL), VINF_SUCCESS);
+    g_fQueryVariableExpected = false;
+    CHECK_FREE_pszResult("9e107d9d372bb6826bd81d3542a419d6");
+
     RTTESTI_CHECK_RETV(RTExprEvalRelease(hExprEval) == 0);
 }
