// Return whether first '«g» «t» «u»' is greater than the second '«g» «t» «u»'
// used in std::sort below.
// Need this as '»' is not in the correct lexical order for blank fields in entry
bool MergeSyncGTUCompare(const StringX &elem1, const StringX &elem2)
{
  StringX g1, t1, u1, g2, t2, u2, tmp1, tmp2;

  StringX::size_type i1 = elem1.find(L'\xbb');
  g1 = (i1 == StringX::npos) ? elem1 : elem1.substr(0, i1 - 1);
  StringX::size_type i2 = elem2.find(L'\xbb');
  g2 = (i2 == StringX::npos) ? elem2 : elem2.substr(0, i2 - 1);
  if (g1 != g2)
    return g1.compare(g2) < 0;

  tmp1 = elem1.substr(g1.length() + 3);
  tmp2 = elem2.substr(g2.length() + 3);
  i1 = tmp1.find(L'\xbb');
  t1 = (i1 == StringX::npos) ? tmp1 : tmp1.substr(0, i1 - 1);
  i2 = tmp2.find(L'\xbb');
  t2 = (i2 == StringX::npos) ? tmp2 : tmp2.substr(0, i2 - 1);
  if (t1 != t2)
    return t1.compare(t2) < 0;

  tmp1 = tmp1.substr(t1.length() + 3);
  tmp2 = tmp2.substr(t2.length() + 3);
  i1 = tmp1.find(L'\xbb');
  u1 = (i1 == StringX::npos) ? tmp1 : tmp1.substr(0, i1 - 1);
  i2 = tmp2.find(L'\xbb');
  u2 = (i2 == StringX::npos) ? tmp2 : tmp2.substr(0, i2 - 1);
  return u1.compare(u2) < 0;
}
Пример #2
0
static void ParseNotes(StringX &sxNotes,
                       std::vector<StringX> &vsxnotes_lines)
{
  if (!sxNotes.empty()) {
    // Use \n and \r to tokenise this line
    StringX::size_type st_start(0), st_end(0);
    const StringX sxdelim = _T("\r\n");
    StringX sxline;
    StringX::size_type st_index;
    while (st_end != StringX::npos) {
      st_end = sxNotes.find(sxdelim, st_start);
      sxline = (sxNotes.substr(st_start, 
                   (st_end == StringX::npos) ? StringX::npos : st_end - st_start));
      st_index = 0;
      // Remove all tabs - \t
      for (;;) {
        st_index = sxline.find(_T("\\t"), st_index);
        if (st_index == StringX::npos)
          break;
        sxline.replace(st_index, 2, _T(""));
        st_index += 1;
      }
      vsxnotes_lines.push_back(sxline);
      st_start = ((st_end > (StringX::npos - sxdelim.size()))
                          ? StringX::npos : st_end + sxdelim.size());
    }
  }
}
Пример #3
0
bool FindNoCase( const StringX& src, const StringX& dest)
{
    StringX srcLower = src;
    ToLower(srcLower);

    StringX destLower = dest;
    ToLower(destLower);

    return destLower.find(srcLower) != StringX::npos;
}
Пример #4
0
void PasswordSafeSearch::FindMatches(const StringX& searchText, bool fCaseSensitive, SearchPointer& searchPtr,
                                       const CItemData::FieldBits& bsFields, bool fUseSubgroups, const wxString& subgroupText,
                                       CItemData::FieldType subgroupObject, PWSMatch::MatchRule subgroupFunction,
                                       bool subgroupFunctionCaseSensitive, Iter begin, Iter end, Accessor afn)
{
  if (searchText.empty())
      return;

  searchPtr.Clear();

  typedef StringX (CItemData::*ItemDataFuncT)() const;

  struct {
      CItemData::FieldType type;
      ItemDataFuncT        func;
  } ItemDataFields[] = {  {CItemData::GROUP,     &CItemData::GetGroup},
                          {CItemData::TITLE,     &CItemData::GetTitle},
                          {CItemData::USER,      &CItemData::GetUser},
                          {CItemData::PASSWORD,  &CItemData::GetPassword},
//                        {CItemData::NOTES,     &CItemData::GetNotes},
                          {CItemData::URL,       &CItemData::GetURL},
                          {CItemData::EMAIL,     &CItemData::GetEmail},
                          {CItemData::RUNCMD,    &CItemData::GetRunCommand},
                          {CItemData::AUTOTYPE,  &CItemData::GetAutoType},
                          {CItemData::XTIME_INT, &CItemData::GetXTimeInt},

                      };

  for ( Iter itr = begin; itr != end; ++itr) {

    const int fn = (subgroupFunctionCaseSensitive? -subgroupFunction: subgroupFunction);
    if (fUseSubgroups && !afn(itr).Matches(stringT(subgroupText.c_str()), subgroupObject, fn))
        continue;

    bool found = false;
    for (size_t idx = 0; idx < NumberOf(ItemDataFields) && !found; ++idx) {
      if (bsFields.test(ItemDataFields[idx].type)) {
          const StringX str = (afn(itr).*ItemDataFields[idx].func)();
          found = fCaseSensitive? str.find(searchText) != StringX::npos: FindNoCase(searchText, str);
      }
    }

    if (!found && bsFields.test(CItemData::NOTES)) {
        StringX str = afn(itr).GetNotes();
        found = fCaseSensitive? str.find(searchText) != StringX::npos: FindNoCase(searchText, str);
    }

    if (!found && bsFields.test(CItemData::PWHIST)) {
        size_t pwh_max, err_num;
        PWHistList pwhistlist;
        CreatePWHistoryList(afn(itr).GetPWHistory(), pwh_max, err_num,
                            pwhistlist, PWSUtil::TMC_XML);
        for (PWHistList::iterator iter = pwhistlist.begin(); iter != pwhistlist.end(); iter++) {
          PWHistEntry pwshe = *iter;
          found = fCaseSensitive? pwshe.password.find(searchText) != StringX::npos: FindNoCase(searchText, pwshe.password );
          if (found)
            break;  // break out of for loop
        }
        pwhistlist.clear();
    }

    if (found) {
        uuid_array_t uuid;
        afn(itr).GetUUID(uuid);
        searchPtr.Add(pws_os::CUUID(uuid));
    }
  }
}
Пример #5
0
//-----------------------------------------------------------------
// Internal functions
//-----------------------------------------------------------------
static UINT ParseRunCommand(const StringX &sxInputString,
                            std::vector<st_RunCommandTokens> &v_rctokens,
                            bool &bDoAutoType, StringX &sxAutoType,
                            stringT &serrmsg, StringX::size_type &st_column)
{
  // tokenize into separate elements
  std::vector<st_RunCommandTokens>::iterator rc_iter;
  std::vector<size_t> v_pos;
  StringX::iterator str_Iter;
  st_RunCommandTokens st_rctoken;
  size_t st_num_quotes(0);

  UINT uierr(0);
  int var_index(0);

  const stringT alphanum =
    _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");

  if (sxInputString.empty()) {
  // String is empty!
    uierr = IDSC_EXS_INPUTEMPTY;
    goto exit;
  }

  for (StringX::size_type l = 0; l < sxInputString.length(); l++) {
    if (sxInputString[l] == _T('"'))
      st_num_quotes++;
  }

  if (st_num_quotes % 2 != 0) {
    st_column = sxInputString.find(_T('"'));
    // Unmatched quotes
    uierr = IDSC_EXS_UNMATCHEDQUOTES;
    goto exit;
  }

  // tokenize into separate elements using $ as the field separator
  for (StringX::size_type st_startpos = 0;
       st_startpos < sxInputString.size();
       /* st_startpos advanced in body */) {
    StringX::size_type st_next = sxInputString.find(_T('$'), st_startpos);
    if (st_next == StringX::npos)
      st_next = sxInputString.size();
    if (st_next > 0) {
      st_rctoken.sxname = sxInputString.substr(st_startpos, st_next - st_startpos);
      st_rctoken.sxindex = _T("");
      st_rctoken.index = 0;
      st_rctoken.is_variable  = st_startpos == 0 ? false : true;
      st_rctoken.has_brackets = false;
      v_rctokens.push_back(st_rctoken);
      v_pos.push_back(st_startpos);
    }
    st_startpos = st_next + 1; // too complex for for statement
  } // tokenization for loop

  // Check if escaped - ending character of previous token == '\'
  // Make sure this '\' is not escaped itself!
  for (size_t st_idx = v_rctokens.size() - 1; st_idx > 0 ; st_idx--) {
    st_RunCommandTokens &st_rctokens = v_rctokens[st_idx - 1];
    StringX::size_type name_len = st_rctokens.sxname.length();
    if (name_len == 0 || (name_len >= 2 &&
            st_rctokens.sxname.substr(name_len - 2, 2).compare(_T("\\\\")) == 0))
      continue;

    if (st_rctokens.sxname.substr(name_len - 1, 1).compare(_T("\\")) == 0) {
      st_rctokens.sxname = st_rctokens.sxname.substr(0, name_len - 1) + 
                         _T("$") + v_rctokens[st_idx].sxname;
      v_rctokens.erase(v_rctokens.begin() + st_idx);
    }
  }

  // Check if variable enclosed in curly brackets
  for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) {
    if (v_rctokens[st_idx].sxname.length() == 0)
      continue;

    str_Iter = v_rctokens[st_idx].sxname.begin();
    // Does it start with a curly bracket?
    if (*str_Iter == _T('{')) {
      v_rctokens[st_idx].has_brackets = true;
      StringX sxvar, sxnonvar, sxindex(_T(""));
      // Yes - Find end curly bracket
      StringX::size_type st_end_cb = v_rctokens[st_idx].sxname.find(_T('}'));
      if (st_end_cb == StringX::npos) {
        st_column = v_pos[st_idx] + v_rctokens[st_idx].sxname.length();
        // Missing end curly bracket
        uierr = IDSC_EXS_MISSINGCURLYBKT;
        goto exit;
      }
      // Now see if there is an Index here
      StringX::size_type st_start_sb = v_rctokens[st_idx].sxname.find(_T('['));
      if (st_start_sb != StringX::npos) {
        // Yes  - find end square bracket
        if (st_start_sb > st_end_cb) {
          // Square backet after end of variable
          sxvar = v_rctokens[st_idx].sxname.substr(1, st_end_cb - 1);
          sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1);
          v_rctokens[st_idx].sxname = sxvar;
          if (sxnonvar.length() > 0) {
            st_rctoken.sxname = sxnonvar;
            st_rctoken.sxindex = _T("");
            st_rctoken.index = 0;
            st_rctoken.is_variable = false;
            st_rctoken.has_brackets = false;
            v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken);
            v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_end_cb);
          }
          continue;
        }
        StringX::size_type st_end_sb = v_rctokens[st_idx].sxname.find(_T(']'), st_start_sb);
        if (st_end_sb == StringX::npos) {
          st_column = v_pos[st_idx] + 1;
          // Missing end square bracket
          uierr = IDSC_EXS_MISSINGSQUAREBKT;
          goto exit;
        }
        // The end-curly backet must immediately follow the end-square bracket
        if (st_end_cb != st_end_sb + 1) {
          st_column = v_pos[st_idx] + st_end_sb + 1;
          // Characters between ']' and ')'
          uierr = IDSC_EXS_INVALIDBRACKETS;
          goto exit;
        }
        sxindex = v_rctokens[st_idx].sxname.substr(st_start_sb + 1, st_end_sb - st_start_sb - 1);
        v_rctokens[st_idx].sxindex = sxindex;
        // Now check index
        uierr = ProcessIndex(sxindex, var_index, st_column);
        if (uierr > 0) {
          st_column += v_pos[st_idx];
          goto exit;
        }

        v_rctokens[st_idx].index = var_index;
        sxvar = v_rctokens[st_idx].sxname.substr(1, st_start_sb - 1);
        sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1);
      } else {
        // No square bracket
        // Split current token into 'variable' and 'non-variable' parts
        sxvar = v_rctokens[st_idx].sxname.substr(1, st_end_cb - 1);
        sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1);
      }
      v_rctokens[st_idx].sxname = sxvar;
      if (sxnonvar.length() > 0) {
        st_rctoken.sxname = sxnonvar;
        st_rctoken.sxindex = _T("");
        st_rctoken.index = 0;
        st_rctoken.is_variable = false;
        st_rctoken.has_brackets = false;
        v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken);
        v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_end_cb);
      }
    }
  }

  // Now use rules of variables to get the real variable
  for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) {
    if (!v_rctokens[st_idx].is_variable)
      continue;

    if (v_rctokens[st_idx].sxname.length() == 0) {
      st_column = v_pos[st_idx];
      // Variable name is empty
      uierr = IDSC_EXS_VARNAMEEMPTY;
      goto exit;
    }

    str_Iter = v_rctokens[st_idx].sxname.begin();
    if (!isalpha(*str_Iter)) {
      st_column = v_pos[st_idx];
      // First character of variable is not alphabetic
      uierr = IDSC_EXS_FIRSTNOTALPHA;
      goto exit;
    }
    StringX::size_type st_next = v_rctokens[st_idx].sxname.find_first_not_of(alphanum.c_str());
    if (st_next != StringX::npos) {
      // Split current token into 'variable' and 'non-variable' parts
      StringX sxvar = v_rctokens[st_idx].sxname.substr(0, st_next);
      StringX sxnonvar = v_rctokens[st_idx].sxname.substr(st_next);
      v_rctokens[st_idx].sxname = sxvar;
      // Before saving non-variable part - check if it is an Index e.g. var[i]
      if (sxnonvar.c_str()[0] == _T('[')) {
        // Find ending square bracket
        StringX::size_type st_end_sb = sxnonvar.find(_T(']'));
        if (st_end_sb == StringX::npos) {
          st_column = v_pos[st_idx] + sxvar.length() + 2;
          // Missing end square bracket
          uierr = IDSC_EXS_MISSINGSQUAREBKT;
          goto exit;
        }
        StringX sxindex = sxnonvar.substr(1, st_end_sb - 1);
        v_rctokens[st_idx].sxindex = sxindex;
        // Now check index
        uierr = ProcessIndex(sxindex, var_index, st_column);
        if (uierr > 0) {
          st_column += v_pos[st_idx] + sxvar.length();
          goto exit;
        }

        v_rctokens[st_idx].index = var_index;
        sxnonvar = sxnonvar.substr(st_end_sb + 1);
      } else {
        // Not a square bracket
        if (v_rctokens[st_idx].has_brackets) {
          st_column = v_pos[st_idx] + st_next + 1;
          // Variable must be alphanumeric
          uierr = IDSC_EXS_VARNAMEINVALID;
          goto exit;
        }
      }
      if (!sxnonvar.empty()) {
        st_rctoken.sxname = sxnonvar;
        st_rctoken.sxindex = _T("");
        st_rctoken.index = 0;
        st_rctoken.is_variable = false;
        st_rctoken.has_brackets = false;
        v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken);
        v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_next);
      }
    }
  }

  // Special Autotype processing
  bDoAutoType = false;
  sxAutoType = _T("");
  for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) {
    if (!v_rctokens[st_idx].is_variable)
      continue;

    // Is it a autotype variable?
    if (v_rctokens[st_idx].sxname == _T("a") ||
        v_rctokens[st_idx].sxname == _T("autotype")) {
      bDoAutoType = true;
      // Is the next token text and starts with '('?
      if (st_idx + 1 < v_rctokens.size() &&
          !v_rctokens[st_idx + 1].is_variable &&
          v_rctokens[st_idx + 1].sxname.c_str()[0] == _T('(')) {
        // Find ending round bracket
        StringX sx_autotype = v_rctokens[st_idx + 1].sxname;
        StringX::size_type st_end_rb = sx_autotype.find(_T(')'));
        if (st_end_rb == StringX::npos) {
          st_column = v_pos[st_idx + 1] + sx_autotype.length() + 2;
          // Missing end round bracket
          uierr = IDSC_EXS_MISSINGROUNDBKT;
          goto exit;
        }
        sxAutoType = sx_autotype.substr(1, st_end_rb - 1);
        v_rctokens[st_idx + 1].sxname = sx_autotype.substr(st_end_rb + 1);
        // Check if anything left in this text - none -> delete
        if (v_rctokens[st_idx + 1].sxname.length() == 0)
          v_rctokens.erase(v_rctokens.begin() + st_idx + 1);
        // Now delete Autotype variable
        v_rctokens.erase(v_rctokens.begin() + st_idx);
        break;
      }
    }
  }

exit:
  if (uierr != 0)
    LoadAString(serrmsg, uierr);
  else
    serrmsg = _T("");

  if (uierr > 0) {
    v_rctokens.clear();
  }
  v_pos.clear();
  return uierr;
}
Пример #6
0
StringX PWSAuxParse::GetAutoTypeString(const StringX &sx_in_autotype,
                                       const StringX &sx_group,
                                       const StringX &sx_title,
                                       const StringX &sx_user,
                                       const StringX &sx_pwd,
                                       const StringX &sx_notes,
                                       const StringX &sx_url,
                                       const StringX &sx_email,
                                       std::vector<size_t> &vactionverboffsets)
{
  StringX sxtmp(_T(""));
  StringX sxNotes(sx_notes);
  TCHAR curChar;
  StringX sx_autotype(sx_in_autotype);
  StringX::size_type st_index;
  std::vector<StringX> vsxnotes_lines;

  vactionverboffsets.clear();

  // If empty, try the database default
  if (sx_autotype.empty()) {
    sx_autotype = PWSprefs::GetInstance()->
              GetPref(PWSprefs::DefaultAutotypeString);

    // If still empty, take this default
    if (sx_autotype.empty()) {
      // checking for user and password for default settings
      if (!sx_pwd.empty()){
        if (!sx_user.empty())
          sx_autotype = DEFAULT_AUTOTYPE;
        else
          sx_autotype = _T("\\p\\n");
      }
    }
  }

  // No recursive substitution (e.g. \p or \u), although '\t' will be replaced by a tab
  if (!sx_notes.empty()) {
    // Use \n and \r to tokenise this line
    StringX::size_type st_start(0), st_end(0);
    const StringX sxdelim = _T("\r\n");
    StringX sxline;
    while (st_end != StringX::npos) {
      st_end = sxNotes.find_first_of(sxdelim, st_start);
      sxline = (sxNotes.substr(st_start, (st_end == StringX::npos) ? 
                              StringX::npos : st_end - st_start));
      st_index = 0;
      for (;;) {
        st_index = sxline.find(_T("\\t"), st_index);
        if (st_index == StringX::npos)
          break;
        sxline.replace(st_index, 2, _T("\t"));
        st_index += 1;
      }
      vsxnotes_lines.push_back(sxline);
      // If we just hit a "\r\n", move past it.  Or else, it is a "\r" without
      // a following "\n" or a "\n", so just move past one single char
      if (st_end != StringX::npos) {
        st_start = st_end + (sxNotes.compare(st_end, 2, sxdelim) == 0 ? 2 : 1);
        if (st_start >= sxNotes.length())
          break;
      }
    }
    // Now change '\n' to '\r' in the complete notes field
    st_index = 0;
    for (;;) {
      st_index = sxNotes.find(sxdelim, st_index);
      if (st_index == StringX::npos)
        break;
      sxNotes.replace(st_index, 2, _T("\r"));
      st_index += 1;
    }
    st_index = 0;
    for (;;) {
      st_index = sxNotes.find(_T("\\t"), st_index);
      if (st_index == StringX::npos)
        break;
      sxNotes.replace(st_index, 2, _T("\t"));
      st_index += 1;
    }
  }

  const size_t N = sx_autotype.length();
  const StringX sxZeroes = _T("000");
  int gNumIts;

  for (size_t n = 0; n < N; n++){
    curChar = sx_autotype[n];
    if (curChar == TCHAR('\\')) {
      n++;
      if (n < N)
        curChar = sx_autotype[n];

      switch (curChar){
        case TCHAR('\\'):
          sxtmp += TCHAR('\\');
          break;
        case TCHAR('n'):
        case TCHAR('r'):
          sxtmp += TCHAR('\r');
          break;
        case TCHAR('t'):
          sxtmp += TCHAR('\t');
          break;
        case TCHAR('s'):
          sxtmp += TCHAR('\v');
          break;
        case TCHAR('g'):
          sxtmp += sx_group;
          break;
        case TCHAR('i'):
          sxtmp += sx_title;
          break;
        case TCHAR('u'):
          sxtmp += sx_user;
          break;
        case TCHAR('p'):
          sxtmp += sx_pwd;
          break;
        case TCHAR('l'):
          sxtmp += sx_url;
          break;
        case TCHAR('m'):
          sxtmp += sx_email;
          break;

        case TCHAR('o'):
        {
          if (n == (N - 1)) {
            // This was the last character - send the lot!
            sxtmp += sxNotes;
            break;
          }
          size_t line_number(0);
          gNumIts = 0;
          for (n++; n < N && (gNumIts < 3); ++gNumIts, n++) {
            if (_istdigit(sx_autotype[n])) {
              line_number *= 10;
              line_number += (sx_autotype[n] - TCHAR('0'));
            } else
              break; // for loop
          }
          if (line_number == 0) {
            // Send the lot
            sxtmp += sx_notes;
          } else
          if (line_number <= vsxnotes_lines.size()) {
            // User specifies a too big a line number - ignore the lot
            sxtmp += vsxnotes_lines[line_number - 1];
          }

          // Backup the extra character that delimited the \oNNN string
          n--;
          break; // case 'o'
        }

        // Action Verbs:
        // These are the only ones processed specially by the UI as they involve
        // actions it performs whilst doing the key sending.
        // Copy them to output string unchanged.
        case TCHAR('b'):  // backspace!
        case TCHAR('z'):  // Use older method
          vactionverboffsets.push_back(sxtmp.length());
          sxtmp += _T("\\");
          sxtmp += curChar;
          break; // case 'b' & 'z'

        case TCHAR('d'):  // Delay
        case TCHAR('w'):  // Wait milli-seconds
        case TCHAR('W'):  // Wait seconds
        {
          // Need to ensure that the field length is 3, even if it wasn't
          vactionverboffsets.push_back(sxtmp.length());
          sxtmp += _T("\\");
          sxtmp += curChar;

          gNumIts = 0;
          size_t i = n;
          for (i++; i < N && (gNumIts < 3); ++gNumIts, i++) {
            if (!_istdigit(sx_autotype[i]))
              break;
          }
          // Insert sufficient zeroes to ensure field is 3 characters long
          sxtmp += sxZeroes.substr(0, 3 - gNumIts);
          break; // case 'd', 'w' & 'W'
        }

        // Also copy explicit control characters to output string unchanged.
        case TCHAR('a'): // bell (can't hear it during testing!)
        case TCHAR('v'): // vertical tab
        case TCHAR('f'): // form feed
        case TCHAR('e'): // escape
        case TCHAR('x'): // hex digits (\xNN)
        // and any others we have forgotten!
        // '\cC', '\uXXXX', '\OOO', '\<any other charatcer not recognised above>'
        default:
          sxtmp += L'\\';
          sxtmp += curChar;
          break;
      }
    } else
      sxtmp += curChar;
  }

  vsxnotes_lines.clear();
  return sxtmp;
}