Changeset 13551
- Timestamp:
- 10/24/08 14:10:08 (3 months ago)
- Files:
-
- trunk/include/VBox/HostServices/GuestPropertySvc.h (modified) (1 diff)
- trunk/src/VBox/HostServices/GuestProperties/service.cpp (modified) (4 diffs)
- trunk/src/VBox/Main/ConsoleImpl.cpp (modified) (1 diff)
- trunk/src/VBox/Main/MachineImpl.cpp (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/include/VBox/HostServices/GuestPropertySvc.h
r13376 r13551 57 57 /** Maximum number of properties per guest */ 58 58 enum { MAX_PROPS = 256 }; 59 /** Maximum size for enumeration patterns */ 60 enum { MAX_PATTERN_LEN = 1024 }; 59 61 60 62 /** trunk/src/VBox/HostServices/GuestProperties/service.cpp
r13376 r13551 203 203 AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER); 204 204 SELF *pSelf = reinterpret_cast<SELF *>(pvService); 205 //pSelf->mpfnHostCallback = pfnExtension;205 pSelf->mpfnHostCallback = pfnExtension; 206 206 pSelf->mpvHostData = pvExtension; 207 207 return VINF_SUCCESS; … … 614 614 615 615 /** 616 * Matches a sample name against a pattern.617 *618 * @returns True if matches, false if not.619 * @param pszPat Pattern.620 * @param pszName Name to match against the pattern.621 * @todo move this into IPRT622 */623 static bool matchesSinglePattern(const char *pszPat, const char *pszName)624 {625 /* ASSUMES ASCII */626 for (;;)627 {628 char chPat = *pszPat;629 switch (chPat)630 {631 default:632 if (*pszName != chPat)633 return false;634 break;635 636 case '*':637 {638 while ((chPat = *++pszPat) == '*' || chPat == '?')639 /* nothing */;640 641 for (;;)642 {643 char ch = *pszName++;644 if ( ch == chPat645 && ( !chPat646 || matchesSinglePattern(pszPat + 1, pszName)))647 return true;648 if (!ch)649 return false;650 }651 /* won't ever get here */652 break;653 }654 655 case '?':656 if (!*pszName)657 return false;658 break;659 660 case '\0':661 return !*pszName;662 }663 pszName++;664 pszPat++;665 }666 return true;667 }668 669 670 /* Checks to see if the given string matches against one of the patterns in671 * the list. */672 static bool matchesPattern(const char *paszPatterns, size_t cchPatterns,673 const char *pszString)674 {675 size_t iOffs = 0;676 /* If the first pattern in the list is empty, treat it as "match all". */677 bool matched = (cchPatterns > 0) && (0 == *paszPatterns) ? true : false;678 while ((iOffs < cchPatterns) && !matched)679 {680 size_t cchCurrent;681 if ( RT_SUCCESS(RTStrNLenEx(paszPatterns + iOffs,682 cchPatterns - iOffs, &cchCurrent))683 && (cchCurrent > 0)684 )685 {686 matched = matchesSinglePattern(paszPatterns + iOffs, pszString);687 iOffs += cchCurrent + 1;688 }689 else690 iOffs = cchPatterns;691 }692 return matched;693 }694 695 696 /**697 616 * Enumerate guest properties by mask, checking the validity 698 617 * of the arguments passed. … … 730 649 if (RT_SUCCESS(rc)) 731 650 rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &paszPatterns, &cchPatterns); 651 if (RT_SUCCESS(rc) && cchPatterns > MAX_PATTERN_LEN + 1) 652 rc = VERR_TOO_MUCH_DATA; 732 653 if (RT_SUCCESS(rc)) 733 654 rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pchBuf, &cchBuf); 734 655 735 656 /* 736 * Start by enumerating all values in the current node into a temporary buffer. 657 * First repack the patterns into the format expected by RTStrSimplePatternMatch() 658 */ 659 bool matchAll = false; 660 char pszPatterns[MAX_PATTERN_LEN + 1]; 661 if ( (NULL == paszPatterns) 662 || (cchPatterns < 2) /* An empty pattern string means match all */ 663 ) 664 matchAll = true; 665 else 666 { 667 for (unsigned i = 0; i < cchPatterns - 1; ++i) 668 if (paszPatterns[i] != '\0') 669 pszPatterns[i] = paszPatterns[i]; 670 else 671 pszPatterns[i] = '|'; 672 pszPatterns[cchPatterns - 1] = '\0'; 673 } 674 675 /* 676 * Next enumerate all values in the current node into a temporary buffer. 737 677 */ 738 678 RTMemAutoPtr<char> TmpBuf; … … 756 696 * overwrite it next iteration. */ 757 697 if ( RT_SUCCESS(rc) 758 && matchesPattern(paszPatterns, cchPatterns, &TmpBuf[iTmpBuf]) 698 && ( matchAll 699 || RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX, 700 &TmpBuf[iTmpBuf], RTSTR_MAX, 701 NULL) 702 ) 759 703 ) 760 704 { trunk/src/VBox/Main/ConsoleImpl.cpp
r13417 r13551 3659 3659 VBOXHGCMSVCPARM parm[3]; 3660 3660 3661 /* 3662 * Set up the pattern parameter, translating the comma-separated list to a 3663 * double-terminated zero-separated one. 3664 */ 3665 Utf8Str utf8In(aPatterns); 3666 Utf8Str utf8Out(utf8In.length() + 2); /* Double terminator */ 3667 if ( ((aPatterns != NULL) && (utf8In.isNull())) 3668 || utf8Out.isNull()) 3669 return E_OUTOFMEMORY; 3670 const char *pcszIn = utf8In.raw(); 3671 char *pszzOut = utf8Out.mutableRaw(); 3672 size_t iIn = 0, iOut = 0; 3673 if (aPatterns != NULL) 3674 while (pcszIn[iIn] != '\0') 3675 { 3676 if (pcszIn[iIn] != ',') 3677 { 3678 pszzOut[iOut] = pcszIn[iIn]; 3679 ++iIn; 3680 } 3681 else 3682 { 3683 pszzOut[iOut] = '\0'; 3684 while ((',' == pcszIn[iIn]) || (' ' == pcszIn[iIn])) 3685 ++iIn; 3686 } 3687 ++iOut; 3688 } 3689 pszzOut[iOut] = '\0'; 3690 3661 Utf8Str utf8Patterns(aPatterns); 3691 3662 parm[0].type = VBOX_HGCM_SVC_PARM_PTR; 3692 parm[0].u.pointer.addr = pszzOut;3693 parm[0].u.pointer.size = iOut+ 1;3663 parm[0].u.pointer.addr = utf8Patterns.mutableRaw(); 3664 parm[0].u.pointer.size = utf8Patterns.length() + 1; 3694 3665 3695 3666 /* trunk/src/VBox/Main/MachineImpl.cpp
r13461 r13551 71 71 #include <iprt/cpputils.h> 72 72 #include <iprt/env.h> 73 #include <iprt/string.h> 73 74 74 75 #include <VBox/err.h> … … 2830 2831 } 2831 2832 2832 /**2833 * Matches a sample name against a pattern.2834 *2835 * @returns True if matches, false if not.2836 * @param pszPat Pattern.2837 * @param cchPat Number of characters in pszPat2838 * @param pszName Name to match against the pattern.2839 * @todo move this into IPRT2840 */2841 static bool matchesSinglePatternEx(const char *pszPat, size_t cchPat, const char *pszName)2842 {2843 /* ASSUMES ASCII */2844 for (;;)2845 {2846 char chPat = *pszPat;2847 switch (chPat)2848 {2849 default:2850 if (*pszName != chPat)2851 return false;2852 break;2853 2854 case '*':2855 {2856 while ( (--cchPat > 0)2857 && ((chPat = *++pszPat) == '*' || chPat == '?')2858 )2859 /* nothing */;2860 2861 for (;;)2862 {2863 char ch = *pszName++;2864 if ( cchPat == 02865 || (cchPat == 1 && ch == chPat)2866 || matchesSinglePatternEx(pszPat, cchPat, pszName)2867 )2868 return true;2869 if (!ch)2870 return false;2871 }2872 /* won't ever get here */2873 break;2874 }2875 2876 case '?':2877 if (!*pszName)2878 return false;2879 break;2880 2881 case '\0':2882 return !*pszName;2883 }2884 pszName++;2885 pszPat++;2886 if (--cchPat == 0)2887 return !*pszName;2888 Assert(cchPat > 0);2889 }2890 return true;2891 }2892 2893 /* Checks to see if a pattern matches a name. */2894 static bool matchesSinglePattern(const char *pszPat, const char *pszName)2895 {2896 return matchesSinglePatternEx(pszPat, strlen(pszPat), pszName);2897 }2898 2899 /* Checks to see if the given string matches against one of the patterns in2900 * the list. */2901 static bool matchesPattern(const char *paszPatterns, size_t cchPatterns,2902 const char *pszString)2903 {2904 size_t iOffs = 0;2905 /* If the first pattern in the list is empty, treat it as "match all". */2906 bool matched = (cchPatterns > 0) && (0 == *paszPatterns);2907 while ((iOffs < cchPatterns) && !matched)2908 {2909 size_t cchCurrent;2910 if ( RT_SUCCESS(RTStrNLenEx(paszPatterns + iOffs,2911 cchPatterns - iOffs, &cchCurrent))2912 && (cchCurrent > 0)2913 )2914 {2915 matched = matchesSinglePattern(paszPatterns + iOffs, pszString);2916 iOffs += cchCurrent + 1;2917 }2918 else2919 iOffs = cchPatterns;2920 }2921 return matched;2922 }2923 2924 /* Checks to see if the given string matches against one of the patterns in2925 * the comma-separated list. Note that spaces at the beginning of patterns2926 * are ignored - '?' should be used here if that is really needed. */2927 static bool matchesPatternComma(const char *pcszPatterns, const char *pcszString)2928 {2929 AssertPtr(pcszPatterns);2930 const char *pcszCur = pcszPatterns;2931 /* If list is empty, treat it as "match all". */2932 bool matched = (0 == *pcszPatterns);2933 bool done = false;2934 while (!done && !matched)2935 {2936 const char *pcszNext = strchr(pcszCur, ',');2937 if (pcszNext != NULL)2938 {2939 matched = matchesSinglePatternEx(pcszCur, pcszNext - pcszCur, pcszString);2940 pcszCur = pcszNext;2941 while ((',' == *pcszCur) || (' ' == *pcszCur))2942 ++pcszCur;2943 }2944 else2945 {2946 matched = matchesSinglePattern(pcszCur, pcszString);2947 done = true;2948 }2949 }2950 return matched;2951 }2952 2953 2833 STDMETHODIMP Machine::SetGuestProperty (INPTR BSTR aName, INPTR BSTR aValue, INPTR BSTR aFlags) 2954 2834 { … … 2973 2853 ) 2974 2854 return E_OUTOFMEMORY; 2855 bool matchAll = false; 2856 if (0 == utf8Patterns.length()) 2857 matchAll = true; 2975 2858 2976 2859 uint32_t fFlags = NILFLAG; … … 3056 2939 &dummy, &dummy64, &dummy); 3057 2940 } 3058 if (SUCCEEDED (rc) && matchesPatternComma (utf8Patterns.raw(), utf8Name.raw())) 2941 if ( SUCCEEDED (rc) 2942 && ( matchAll 2943 || RTStrSimplePatternMultiMatch (utf8Patterns.raw(), RTSTR_MAX, 2944 utf8Name.raw(), RTSTR_MAX, NULL) 2945 ) 2946 ) 3059 2947 mParent->onGuestPropertyChange (mData->mUuid, aName, aValue, aFlags); 3060 2948 return rc; … … 3091 2979 HRESULT rc = E_FAIL; 3092 2980 2981 bool matchAll = false; 2982 if ((NULL == aPatterns) || (0 == aPatterns[0])) 2983 matchAll = true; 3093 2984 if (!mHWData->mPropertyServiceActive) 3094 2985 { … … 3100 2991 for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin(); 3101 2992 it != mHWData->mGuestProperties.end(); ++it) 3102 if (matchesPatternComma(Utf8Str(aPatterns).raw(), Utf8Str(it->mName).raw())) 2993 if ( matchAll 2994 || RTStrSimplePatternMultiMatch (Utf8Str(aPatterns).raw(), 2995 RTSTR_MAX, 2996 Utf8Str(it->mName).raw(), 2997 RTSTR_MAX, NULL) 2998 ) 3103 2999 propList.push_back(*it); 3104 3000 … … 9347 9243 return E_POINTER; /* aValue can be NULL to indicate deletion */ 9348 9244 9245 Utf8Str utf8Name(aName); 9246 Utf8Str utf8Flags(aFlags); 9247 Utf8Str utf8Patterns(mHWData->mGuestPropertyNotificationPatterns); 9248 if ( utf8Name.isNull() 9249 || ((aFlags != NULL) && utf8Flags.isNull()) 9250 || utf8Patterns.isNull() 9251 ) 9252 return E_OUTOFMEMORY; 9253 9349 9254 uint32_t fFlags = NILFLAG; 9350 if ((aFlags != NULL) && RT_FAILURE (validateFlags ( Utf8Str(aFlags).raw(), &fFlags)))9255 if ((aFlags != NULL) && RT_FAILURE (validateFlags (utf8Flags.raw(), &fFlags))) 9351 9256 return E_INVALIDARG; 9257 9258 bool matchAll = false; 9259 if (0 == utf8Patterns.length()) 9260 matchAll = true; 9352 9261 9353 9262 AutoCaller autoCaller (this); … … 9375 9284 /* send a callback notification if appropriate */ 9376 9285 alock.leave(); 9377 if (matchesPatternComma (Utf8Str(mHWData->mGuestPropertyNotificationPatterns).raw(), 9378 Utf8Str(aName).raw())) 9286 if ( matchAll 9287 || RTStrSimplePatternMultiMatch (utf8Patterns.raw(), RTSTR_MAX, 9288 utf8Name.raw(), RTSTR_MAX, NULL) 9289 ) 9379 9290 mParent->onGuestPropertyChange (mData->mUuid, aName, aValue, aFlags); 9380 9291

