VirtualBox

Changeset 93918 in vbox


Ignore:
Timestamp:
Feb 24, 2022 1:58:10 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
150145
Message:

Main/Unattended: bugref:9781. Addressing a todo item in UnattendedScript.cpp

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/UnattendedScript.cpp

    r93839 r93918  
    5757
    5858
     59/*********************************************************************************************************************************
     60*   Static Functions                                                                                                             *
     61*********************************************************************************************************************************/
     62
     63/**
     64 * Searches comparison operators'<', '<=', '>', '>=', or '=' in string.
     65 *
     66 * @returns true if detected, false if not.
     67 * @param   pszComparisonOperator Comparison operators string array. Assumed to be of size 3,
     68 * @param   pachPlaceholder       The string array in which we search the comparison operators,
     69 * @param   startPos              The position with in the pachPlaceholder from where the seach starts. Required to be smaller then
     70 *                                sizeof(pachPlaceholder) - 3
     71 */
     72
     73static bool detectComparisonOperator(char *pszComparisonOperator, const char *pachPlaceholder, size_t &startPos)
     74{
     75    memset(pszComparisonOperator, '\0', 3);
     76    /* Search for '>', '<', '>=', '<=', '='. */
     77    if (pachPlaceholder[startPos] == '<')
     78    {
     79        pszComparisonOperator[0] = '<';
     80        ++startPos;
     81        if (pachPlaceholder[startPos] == '=')
     82        {
     83            pszComparisonOperator[1] = '=';
     84            ++startPos;
     85        }
     86        return true;
     87    }
     88    if (pachPlaceholder[startPos] == '>')
     89    {
     90        pszComparisonOperator[0] = '>';
     91        ++startPos;
     92        if (pachPlaceholder[startPos] == '=')
     93        {
     94            pszComparisonOperator[1] = '=';
     95            ++startPos;
     96        }
     97        return true;
     98    }
     99    else if (pachPlaceholder[startPos] == '=')
     100    {
     101        pszComparisonOperator[0] = '=';
     102        ++startPos;
     103        return true;
     104    }
     105    return false;
     106}
    59107/*********************************************************************************************************************************
    60108*   UnattendedScriptTemplate Implementation                                                                                      *
     
    795843    else if (IS_PLACEHOLDER_MATCH("HAS_PROXY"))
    796844        *pfOutputting = mpUnattended->i_getProxy().isNotEmpty();
    797     else if (IS_PLACEHOLDER_PARTIALLY_MATCH("GUEST_VERSION"))
    798     {
    799         //parse the placeholder and extract the OS version from there
    800         RTCString strPlaceHolder(pachPlaceholder); /** @todo r=bird: What's the meaning of duplicating the rest of the script here
    801                                                     * when you could just add cchPlaceholder to the parameter list and limit it to
    802                                                     * what is actually needed.  OTOH it's really not needed to make copies here,
    803                                                     * validating the "[" can be done in the partial match above and "]@@" by using
    804                                                     * cchPlaceholder, what you wnat to get at is inbetween and does not need
    805                                                     * two copies (only one for RTStrVersionCompare). */
    806         size_t startPos = sizeof("@@VBOX_COND_GUEST_VERSION") - 1;//-1 is for '\n'
    807         size_t endPos = strPlaceHolder.find("@@", startPos + 2);
    808         //next part should look like [>8.0.0] for example where:
    809         // - "[,]" is just the brackets to wrap up the condition;
    810         // - ">" is "greater". Also possible comparison is "<";
    811         // - 8.0.0 is required guest OS version.
    812         //The end of placeholder is "@@" like for others.
    813 
    814         /** @todo r=bird: What kind of syntax checking is this? Ignore any kind of
    815          *        mistyped stuff and let the user figure out what he did wrong
    816          *        without clues?  Lazy. */
    817         if ( strPlaceHolder[endPos] == '@'
    818              && strPlaceHolder[endPos+1] == '@' )
    819         {
    820             if ( strPlaceHolder[startPos++] == '[' && strPlaceHolder[--endPos] == ']' )
    821             {
    822                 char chComp = strPlaceHolder[startPos++];
    823                 RTCString strRequiredOSVersion = strPlaceHolder.substr(startPos, endPos - startPos);
    824                 RTCString strDetectedOSVersion = mpUnattended->i_getDetectedOSVersion();
    825                 int res = RTStrVersionCompare(strDetectedOSVersion.c_str(), strRequiredOSVersion.c_str());
    826                 if ( res >= 0 && chComp == '>' )
    827                         *pfOutputting = true;
    828                 else if ( res < 0 && chComp == '<' )
    829                         *pfOutputting = true;
    830                 else if ( res == 0 && chComp == '=' )
    831                         *pfOutputting = true;
    832                 else
    833                     *pfOutputting = false;
    834             }
    835         }
     845    else if (IS_PLACEHOLDER_PARTIALLY_MATCH("GUEST_VERSION["))
     846    {
     847        /* Check the passed string against format @@VBOX_COND_GUEST_VERSION[>8.04.0]@@. Allowed comparison operators are:
     848         *  '<', '<=', '>', '>=', or '=' in string. No spaces are allowed in anywhere of the expr. */
     849        static const char s_szTail[] = "]@@";
     850        size_t endLength = sizeof(s_szTail) - 1;
     851        if (memcmp(&pachPlaceholder[cchPlaceholder - endLength], RT_STR_TUPLE(s_szTail)) != 0)
     852        {
     853            *pfOutputting = false;
     854            return mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, tr("Malformed @@VBOX_COND_GUEST_VERSION[expr]@@: Missing ']' (%.*s)"),
     855                                            cchPlaceholder, pachPlaceholder);
     856        }
     857        size_t startPos = sizeof("@@VBOX_COND_GUEST_VERSION[") - 1;
     858        size_t  endPos = cchPlaceholder - endLength;
     859        if (startPos >= endPos)
     860        {
     861            *pfOutputting = false;
     862            return mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, tr("Malformed @@VBOX_COND_GUEST_VERSION[expr]@@: Missing expr (%.*s)"),
     863                                            cchPlaceholder, pachPlaceholder);
     864        }
     865        /* Parse for the comparison operator. Assuming the expression starts with one of the allowed operators. */
     866        char pszComparisonOperator[3];
     867        if (!detectComparisonOperator(pszComparisonOperator, pachPlaceholder, startPos))
     868        {
     869            *pfOutputting = false;
     870            return mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, tr("Malformed @@VBOX_COND_GUEST_VERSION[expr]@@: Only space, '>', '>=', '<', <=', and '=' are allowed at the start. (%.*s)"),
     871                                            cchPlaceholder, pachPlaceholder);
     872        }
     873        if (startPos >= endPos)
     874        {
     875            *pfOutputting = false;
     876            return mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, tr("Malformed @@VBOX_COND_GUEST_VERSION[expr]@@: No version string found. (%.*s)"),
     877                                            cchPlaceholder, pachPlaceholder);
     878        }
     879        /* Check if the version string includes any character other than '.' and digits. */
     880        for (size_t i = startPos; i < endPos; ++i)
     881        {
     882            if ( (pachPlaceholder[i] < '0' || pachPlaceholder[i] > '9') && pachPlaceholder[i] != '.')
     883            {
     884                *pfOutputting = false;
     885                return mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, tr("Malformed @@VBOX_COND_GUEST_VERSION[expr]@@: Version string must be consist of only digits and '.', and no spaces. (%.*s)"),
     886                                                cchPlaceholder, pachPlaceholder);
     887            }
     888        }
     889
     890        RTCString strRequiredOSVersion(pachPlaceholder, startPos, endPos - startPos);
     891        RTCString strDetectedOSVersion = mpUnattended->i_getDetectedOSVersion();
     892        int res = RTStrVersionCompare(strDetectedOSVersion.c_str(), strRequiredOSVersion.c_str());
     893
     894        if (   res == 0
     895            && (   pszComparisonOperator[0] == '='
     896                || memcmp(pszComparisonOperator, ">=", 2) == 0
     897                || memcmp(pszComparisonOperator, "<=", 2) == 0))
     898            *pfOutputting = true;
     899        else if (res < 0 && pszComparisonOperator[0] == '<')
     900            *pfOutputting = true;
     901        else if (res > 0 && pszComparisonOperator[0] == '>')
     902            *pfOutputting = true;
    836903        else
    837             *pfOutputting = false;//initially is set to "false"
     904            *pfOutputting = false;
    838905    }
    839906    else
     
    9881055}
    9891056#endif /* just for reference */
    990 
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette