tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MethodProps.cpp (11712B)


      1 // MethodProps.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../Common/StringToInt.h"
      6 
      7 #include "MethodProps.h"
      8 
      9 using namespace NWindows;
     10 
     11 bool StringToBool(const wchar_t *s, bool &res)
     12 {
     13  if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON"))
     14  {
     15    res = true;
     16    return true;
     17  }
     18  if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF"))
     19  {
     20    res = false;
     21    return true;
     22  }
     23  return false;
     24 }
     25 
     26 HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest)
     27 {
     28  switch (prop.vt)
     29  {
     30    case VT_EMPTY: dest = true; return S_OK;
     31    case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK;
     32    case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG;
     33  }
     34  return E_INVALIDARG;
     35 }
     36 
     37 unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number)
     38 {
     39  const wchar_t *start = srcString;
     40  const wchar_t *end;
     41  number = ConvertStringToUInt32(start, &end);
     42  return (unsigned)(end - start);
     43 }
     44 
     45 static unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number)
     46 {
     47  const wchar_t *start = srcString;
     48  const wchar_t *end;
     49  number = ConvertStringToUInt64(start, &end);
     50  return (unsigned)(end - start);
     51 }
     52 
     53 HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
     54 {
     55  // =VT_UI4
     56  // =VT_EMPTY
     57  // {stringUInt32}=VT_EMPTY
     58 
     59  if (prop.vt == VT_UI4)
     60  {
     61    if (!name.IsEmpty())
     62      return E_INVALIDARG;
     63    resValue = prop.ulVal;
     64    return S_OK;
     65  }
     66  if (prop.vt != VT_EMPTY)
     67    return E_INVALIDARG;
     68  if (name.IsEmpty())
     69    return S_OK;
     70  UInt32 v;
     71  if (ParseStringToUInt32(name, v) != name.Len())
     72    return E_INVALIDARG;
     73  resValue = v;
     74  return S_OK;
     75 }
     76 
     77 HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
     78 {
     79  if (name.IsEmpty())
     80  {
     81    switch (prop.vt)
     82    {
     83      case VT_UI4:
     84        numThreads = prop.ulVal;
     85        break;
     86      default:
     87      {
     88        bool val;
     89        RINOK(PROPVARIANT_to_bool(prop, val));
     90        numThreads = (val ? defaultNumThreads : 1);
     91        break;
     92      }
     93    }
     94    return S_OK;
     95  }
     96  if (prop.vt != VT_EMPTY)
     97    return E_INVALIDARG;
     98  return ParsePropToUInt32(name, prop, numThreads);
     99 }
    100 
    101 
    102 static HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp)
    103 {
    104  const wchar_t *end;
    105  UInt32 number = ConvertStringToUInt32(s, &end);
    106  unsigned numDigits = (unsigned)(end - s.Ptr());
    107  if (numDigits == 0 || s.Len() > numDigits + 1)
    108    return E_INVALIDARG;
    109  
    110  if (s.Len() == numDigits)
    111  {
    112    if (number >= 64)
    113      return E_INVALIDARG;
    114    if (number < 32)
    115      destProp = (UInt32)((UInt32)1 << (unsigned)number);
    116    else
    117      destProp = (UInt64)((UInt64)1 << (unsigned)number);
    118    return S_OK;
    119  }
    120  
    121  unsigned numBits;
    122  
    123  switch (MyCharLower_Ascii(s[numDigits]))
    124  {
    125    case 'b': destProp = number; return S_OK;
    126    case 'k': numBits = 10; break;
    127    case 'm': numBits = 20; break;
    128    case 'g': numBits = 30; break;
    129    default: return E_INVALIDARG;
    130  }
    131  
    132  if (number < ((UInt32)1 << (32 - numBits)))
    133    destProp = (UInt32)(number << numBits);
    134  else
    135    destProp = (UInt64)((UInt64)number << numBits);
    136  
    137  return S_OK;
    138 }
    139 
    140 
    141 static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVariant &destProp)
    142 {
    143  if (prop.vt == VT_UI4)
    144  {
    145    UInt32 v = prop.ulVal;
    146    if (v >= 64)
    147      return E_INVALIDARG;
    148    if (v < 32)
    149      destProp = (UInt32)((UInt32)1 << (unsigned)v);
    150    else
    151      destProp = (UInt64)((UInt64)1 << (unsigned)v);
    152    return S_OK;
    153  }
    154  if (prop.vt == VT_BSTR)
    155  {
    156    UString s;
    157    s = prop.bstrVal;
    158    return StringToDictSize(s, destProp);
    159  }
    160  return E_INVALIDARG;
    161 }
    162 
    163 
    164 void CProps::AddProp32(PROPID propid, UInt32 val)
    165 {
    166  CProp &prop = Props.AddNew();
    167  prop.IsOptional = true;
    168  prop.Id = propid;
    169  prop.Value = (UInt32)val;
    170 }
    171 
    172 void CProps::AddPropBool(PROPID propid, bool val)
    173 {
    174  CProp &prop = Props.AddNew();
    175  prop.IsOptional = true;
    176  prop.Id = propid;
    177  prop.Value = val;
    178 }
    179 
    180 class CCoderProps
    181 {
    182  PROPID *_propIDs;
    183  NCOM::CPropVariant *_props;
    184  unsigned _numProps;
    185  unsigned _numPropsMax;
    186 public:
    187  CCoderProps(unsigned numPropsMax)
    188  {
    189    _numPropsMax = numPropsMax;
    190    _numProps = 0;
    191    _propIDs = new PROPID[numPropsMax];
    192    _props = new NCOM::CPropVariant[numPropsMax];
    193  }
    194  ~CCoderProps()
    195  {
    196    delete []_propIDs;
    197    delete []_props;
    198  }
    199  void AddProp(const CProp &prop);
    200  HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties)
    201  {
    202    return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps);
    203  }
    204 };
    205 
    206 void CCoderProps::AddProp(const CProp &prop)
    207 {
    208  if (_numProps >= _numPropsMax)
    209    throw 1;
    210  _propIDs[_numProps] = prop.Id;
    211  _props[_numProps] = prop.Value;
    212  _numProps++;
    213 }
    214 
    215 HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const
    216 {
    217  CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0));
    218  FOR_VECTOR (i, Props)
    219    coderProps.AddProp(Props[i]);
    220  if (dataSizeReduce)
    221  {
    222    CProp prop;
    223    prop.Id = NCoderPropID::kReduceSize;
    224    prop.Value = *dataSizeReduce;
    225    coderProps.AddProp(prop);
    226  }
    227  return coderProps.SetProps(scp);
    228 }
    229 
    230 
    231 int CMethodProps::FindProp(PROPID id) const
    232 {
    233  for (int i = Props.Size() - 1; i >= 0; i--)
    234    if (Props[i].Id == id)
    235      return i;
    236  return -1;
    237 }
    238 
    239 int CMethodProps::GetLevel() const
    240 {
    241  int i = FindProp(NCoderPropID::kLevel);
    242  if (i < 0)
    243    return 5;
    244  if (Props[i].Value.vt != VT_UI4)
    245    return 9;
    246  UInt32 level = Props[i].Value.ulVal;
    247  return level > 9 ? 9 : (int)level;
    248 }
    249 
    250 struct CNameToPropID
    251 {
    252  VARTYPE VarType;
    253  const char *Name;
    254 };
    255 
    256 
    257 // the following are related to NCoderPropID::EEnum values
    258 
    259 static const CNameToPropID g_NameToPropID[] =
    260 {
    261  { VT_UI4, "" },
    262  { VT_UI4, "d" },
    263  { VT_UI4, "mem" },
    264  { VT_UI4, "o" },
    265  { VT_UI4, "c" },
    266  { VT_UI4, "pb" },
    267  { VT_UI4, "lc" },
    268  { VT_UI4, "lp" },
    269  { VT_UI4, "fb" },
    270  { VT_BSTR, "mf" },
    271  { VT_UI4, "mc" },
    272  { VT_UI4, "pass" },
    273  { VT_UI4, "a" },
    274  { VT_UI4, "mt" },
    275  { VT_BOOL, "eos" },
    276  { VT_UI4, "x" },
    277  { VT_UI8, "reduce" },
    278  { VT_UI8, "expect" },
    279  { VT_UI4, "b" },
    280  { VT_UI4, "check" },
    281  { VT_BSTR, "filter" },
    282  { VT_UI8, "memuse" }
    283 };
    284 
    285 static int FindPropIdExact(const UString &name)
    286 {
    287  for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++)
    288    if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name))
    289      return i;
    290  return -1;
    291 }
    292 
    293 static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
    294 {
    295  if (varType == srcProp.vt)
    296  {
    297    destProp = srcProp;
    298    return true;
    299  }
    300 
    301  if (varType == VT_UI8 && srcProp.vt == VT_UI4)
    302  {
    303    destProp = (UInt64)srcProp.ulVal;
    304    return true;
    305  }
    306 
    307  if (varType == VT_BOOL)
    308  {
    309    bool res;
    310    if (PROPVARIANT_to_bool(srcProp, res) != S_OK)
    311      return false;
    312    destProp = res;
    313    return true;
    314  }
    315  if (srcProp.vt == VT_EMPTY)
    316  {
    317    destProp = srcProp;
    318    return true;
    319  }
    320  return false;
    321 }
    322    
    323 static void SplitParams(const UString &srcString, UStringVector &subStrings)
    324 {
    325  subStrings.Clear();
    326  UString s;
    327  unsigned len = srcString.Len();
    328  if (len == 0)
    329    return;
    330  for (unsigned i = 0; i < len; i++)
    331  {
    332    wchar_t c = srcString[i];
    333    if (c == L':')
    334    {
    335      subStrings.Add(s);
    336      s.Empty();
    337    }
    338    else
    339      s += c;
    340  }
    341  subStrings.Add(s);
    342 }
    343 
    344 static void SplitParam(const UString &param, UString &name, UString &value)
    345 {
    346  int eqPos = param.Find(L'=');
    347  if (eqPos >= 0)
    348  {
    349    name.SetFrom(param, eqPos);
    350    value = param.Ptr(eqPos + 1);
    351    return;
    352  }
    353  unsigned i;
    354  for (i = 0; i < param.Len(); i++)
    355  {
    356    wchar_t c = param[i];
    357    if (c >= L'0' && c <= L'9')
    358      break;
    359  }
    360  name.SetFrom(param, i);
    361  value = param.Ptr(i);
    362 }
    363 
    364 static bool IsLogSizeProp(PROPID propid)
    365 {
    366  switch (propid)
    367  {
    368    case NCoderPropID::kDictionarySize:
    369    case NCoderPropID::kUsedMemorySize:
    370    case NCoderPropID::kBlockSize:
    371    case NCoderPropID::kBlockSize2:
    372    // case NCoderPropID::kReduceSize:
    373      return true;
    374  }
    375  return false;
    376 }
    377 
    378 HRESULT CMethodProps::SetParam(const UString &name, const UString &value)
    379 {
    380  int index = FindPropIdExact(name);
    381  if (index < 0)
    382    return E_INVALIDARG;
    383  const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
    384  CProp prop;
    385  prop.Id = index;
    386 
    387  if (IsLogSizeProp(prop.Id))
    388  {
    389    RINOK(StringToDictSize(value, prop.Value));
    390  }
    391  else
    392  {
    393    NCOM::CPropVariant propValue;
    394    if (nameToPropID.VarType == VT_BSTR)
    395      propValue = value;
    396    else if (nameToPropID.VarType == VT_BOOL)
    397    {
    398      bool res;
    399      if (!StringToBool(value, res))
    400        return E_INVALIDARG;
    401      propValue = res;
    402    }
    403    else if (!value.IsEmpty())
    404    {
    405      if (nameToPropID.VarType == VT_UI4)
    406      {
    407        UInt32 number;
    408        if (ParseStringToUInt32(value, number) == value.Len())
    409          propValue = number;
    410        else
    411          propValue = value;
    412      }
    413      else if (nameToPropID.VarType == VT_UI8)
    414      {
    415        UInt64 number;
    416        if (ParseStringToUInt64(value, number) == value.Len())
    417          propValue = number;
    418        else
    419          propValue = value;
    420      }
    421      else
    422        propValue = value;
    423    }
    424    if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))
    425      return E_INVALIDARG;
    426  }
    427  Props.Add(prop);
    428  return S_OK;
    429 }
    430 
    431 HRESULT CMethodProps::ParseParamsFromString(const UString &srcString)
    432 {
    433  UStringVector params;
    434  SplitParams(srcString, params);
    435  FOR_VECTOR (i, params)
    436  {
    437    const UString &param = params[i];
    438    UString name, value;
    439    SplitParam(param, name, value);
    440    RINOK(SetParam(name, value));
    441  }
    442  return S_OK;
    443 }
    444 
    445 HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)
    446 {
    447  if (realName.Len() == 0)
    448  {
    449    // [empty]=method
    450    return E_INVALIDARG;
    451  }
    452  if (value.vt == VT_EMPTY)
    453  {
    454    // {realName}=[empty]
    455    UString name, valueStr;
    456    SplitParam(realName, name, valueStr);
    457    return SetParam(name, valueStr);
    458  }
    459  
    460  // {realName}=value
    461  int index = FindPropIdExact(realName);
    462  if (index < 0)
    463    return E_INVALIDARG;
    464  const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
    465  CProp prop;
    466  prop.Id = index;
    467  
    468  if (IsLogSizeProp(prop.Id))
    469  {
    470    RINOK(PROPVARIANT_to_DictSize(value, prop.Value));
    471  }
    472  else
    473  {
    474    if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))
    475      return E_INVALIDARG;
    476  }
    477  Props.Add(prop);
    478  return S_OK;
    479 }
    480 
    481 HRESULT COneMethodInfo::ParseMethodFromString(const UString &s)
    482 {
    483  MethodName.Empty();
    484  int splitPos = s.Find(L':');
    485  {
    486    UString temp = s;
    487    if (splitPos >= 0)
    488      temp.DeleteFrom(splitPos);
    489    if (!temp.IsAscii())
    490      return E_INVALIDARG;
    491    MethodName.SetFromWStr_if_Ascii(temp);
    492  }
    493  if (splitPos < 0)
    494    return S_OK;
    495  PropsString = s.Ptr(splitPos + 1);
    496  return ParseParamsFromString(PropsString);
    497 }
    498 
    499 HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)
    500 {
    501  if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, "m"))
    502    return ParseParamsFromPROPVARIANT(realName, value);
    503  // -m{N}=method
    504  if (value.vt != VT_BSTR)
    505    return E_INVALIDARG;
    506  UString s;
    507  s = value.bstrVal;
    508  return ParseMethodFromString(s);
    509 }