<commit_before>/*
* Copyright (c) 2003-2012 <NAME> <<EMAIL>>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

// file CoreOtherDB.cpp
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------
// 'Other' Database function - PWScore member functions
//     Compare, Merge & Synchronize
//-----------------------------------------------------------------
#include "PWScore.h"
#include "core.h"
#include "Util.h"
#include "Report.h"
#include "StringXStream.h"
#include "DBCompareData.h"

#include "os/typedefs.h"

#include <string>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

using pws_os::CUUID;

// hide w_char/char differences where possible:
#ifdef UNICODE
typedef std::wifstream ifstreamT;
typedef std::wofstream ofstreamT;
#else
typedef std::ifstream ifstreamT;
typedef std::ofstream ofstreamT;
#endif
typedef std::vector<stringT>::iterator viter;

const StringX sx_StartChevron(_T("\xab"));
const StringX sx_MiddleChevron(_T("\xbb \xab"));
const StringX sx_EndChevron(_T("\xbb"));

inline bool FieldsNotEqual(StringX a, StringX b, const bool bTreatWhiteSpaceasEmpty)
{
  if (bTreatWhiteSpaceasEmpty) { // m_treatwhitespaceasempty
    EmptyIfOnlyWhiteSpace(a);
    EmptyIfOnlyWhiteSpace(b);
  }
  return a != b;
}

void PWScore::Compare(PWScore *pothercore,
                      const CItemData::FieldBits &bsFields, const bool &subgroup_bset,
                      const bool &bTreatWhiteSpaceasEmpty,  const stringT &subgroup_name,
                      const int &subgroup_object, const int &subgroup_function,
                      CompareData &list_OnlyInCurrent, CompareData &list_OnlyInComp,
                      CompareData &list_Conflicts, CompareData &list_Identical)
{
  /*
  Purpose:
    Compare entries from comparison database (compCore) with current database (m_core)

  Algorithm:
    Foreach entry in current database {
      Find in comparison database - subject to subgroup checking
      if found {
        Compare
        if match
          OK
       else
          There are conflicts; note them & increment numConflicts
      } else {
        save & increment numOnlyInCurrent
      }
    }

    Foreach entry in comparison database {
      Find in current database - subject to subgroup checking
      if not found
        save & increment numOnlyInComp
    }
  */

  CItemData::FieldBits bsConflicts(0);
  st_CompareData st_data;
  int numOnlyInCurrent(0), numOnlyInComp(0), numConflicts(0), numIdentical(0);

  ItemListIter currentPos;
  for (currentPos = GetEntryIter();
       currentPos != GetEntryEndIter();
       currentPos++) {
    st_data.Empty();
    CItemData currentItem = GetEntry(currentPos);

    if (!subgroup_bset ||
        currentItem.Matches(std::wstring(subgroup_name), subgroup_object,
                            subgroup_function)) {
      st_data.group = currentItem.GetGroup();
      st_data.title = currentItem.GetTitle();
      st_data.user = currentItem.GetUser();

      StringX sx_original = sx_StartChevron +
                             st_data.group + sx_MiddleChevron +
                             st_data.title + sx_MiddleChevron +
                             st_data.user  + sx_EndChevron;

      // Update the Wizard page
      UpdateWizard(sx_original.c_str());

      ItemListIter foundPos = pothercore->Find(st_data.group,
                                               st_data.title, st_data.user);
      if (foundPos != pothercore->GetEntryEndIter()) {
        // found a match, see if all other fields also match
        // Difference flags:
        /*
         First byte (values in square brackets taken from ItemData.h)
         1... ....  NAME       [0x00] - n/a - depreciated
         .1.. ....  UUID       [0x01] - n/a - unique
         ..1. ....  GROUP      [0x02] - not checked - must be identical
         ...1 ....  TITLE      [0x03] - not checked - must be identical
         .... 1...  USER       [0x04] - not checked - must be identical
         .... .1..  NOTES      [0x05]
         .... ..1.  PASSWORD   [<PASSWORD>]
         .... ...1  CTIME      [0x07] - not checked by default

         Second byte
         1... ....  PMTIME     [0x08] - not checked by default
         .1.. ....  ATIME      [0x09] - not checked by default
         ..1. ....  XTIME      [0x0a] - not checked by default
         ...1 ....  RESERVED   [0x0b] - not used
         .... 1...  RMTIME     [0x0c] - not checked by default
         .... .1..  URL        [0x0d]
         .... ..1.  AUTOTYPE   [0x0e]
         .... ...1  PWHIST     [0x0f]

         Third byte
         1... ....  POLICY     [0x10] - not checked by default
         .1.. ....  XTIME_INT  [0x11] - not checked by default
         ..1. ....  RUNCMD     [0x12]
         ...1 ....  DCA        [0x13]
         .... 1...  EMAIL      [0x14]
         .... .1..  PROTECTED  [0x15]
         .... ..1.  SYMBOLS    [0x16]
         .... ...1  SHIFTDCA   [0x17]

         Fourth byte
         1... ....  POLICYNAME [0x18] - not checked by default


        */
        bsConflicts.reset();
        StringX sxCurrentPassword, sxComparisonPassword;

        CItemData compItem = pothercore->GetEntry(foundPos);

        if (currentItem.GetEntryType() == CItemData::ET_ALIAS ||
            currentItem.GetEntryType() == CItemData::ET_SHORTCUT) {
          CItemData *pci_base = GetBaseEntry(&currentItem);
          sxCurrentPassword == pci_base->GetPassword();
        } else
          sxCurrentPassword == currentItem.GetPassword();

        if (compItem.GetEntryType() == CItemData::ET_ALIAS ||
            compItem.GetEntryType() == CItemData::ET_SHORTCUT) {
          CItemData *pci_base = pothercore->GetBaseEntry(&compItem);
          sxComparisonPassword == pci_base->GetPassword();
        } else
          sxComparisonPassword == compItem.GetPassword();

        if (bsFields.test(CItemData::PASSWORD) &&
            sxCurrentPassword != sxComparisonPassword)
          bsConflicts.flip(CItemData::PASSWORD);

        if (bsFields.test(CItemData::NOTES) &&
            FieldsNotEqual(currentItem.GetNotes(), compItem.GetNotes(), bTreatWhiteSpaceasEmpty))
          bsConflicts.flip(CItemData::NOTES);

        if (bsFields.test(CItemData::CTIME) &&
            currentItem.GetCTime() != compItem.GetCTime())
          bsConflicts.flip(CItemData::CTIME);

        if (bsFields.test(CItemData::PMTIME) &&
            currentItem.GetPMTime() != compItem.GetPMTime())
          bsConflicts.flip(CItemData::PMTIME);<commit_msg>Fix password compare code in DB Compare.<commit_after>/*
* Copyright (c) 2003-2012 <NAME> <<EMAIL>>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

// file CoreOtherDB.cpp
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------
// 'Other' Database function - PWScore member functions
//     Compare, Merge & Synchronize
//-----------------------------------------------------------------
#include "PWScore.h"
#include "core.h"
#include "Util.h"
#include "Report.h"
#include "StringXStream.h"
#include "DBCompareData.h"

#include "os/typedefs.h"

#include <string>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

using pws_os::CUUID;

// hide w_char/char differences where possible:
#ifdef UNICODE
typedef std::wifstream ifstreamT;
typedef std::wofstream ofstreamT;
#else
typedef std::ifstream ifstreamT;
typedef std::ofstream ofstreamT;
#endif
typedef std::vector<stringT>::iterator viter;

const StringX sx_StartChevron(_T("\xab"));
const StringX sx_MiddleChevron(_T("\xbb \xab"));
const StringX sx_EndChevron(_T("\xbb"));

inline bool FieldsNotEqual(StringX a, StringX b, const bool bTreatWhiteSpaceasEmpty)
{
  if (bTreatWhiteSpaceasEmpty) { // m_treatwhitespaceasempty
    EmptyIfOnlyWhiteSpace(a);
    EmptyIfOnlyWhiteSpace(b);
  }
  return a != b;
}

void PWScore::Compare(PWScore *pothercore,
                      const CItemData::FieldBits &bsFields, const bool &subgroup_bset,
                      const bool &bTreatWhiteSpaceasEmpty,  const stringT &subgroup_name,
                      const int &subgroup_object, const int &subgroup_function,
                      CompareData &list_OnlyInCurrent, CompareData &list_OnlyInComp,
                      CompareData &list_Conflicts, CompareData &list_Identical)
{
  /*
  Purpose:
    Compare entries from comparison database (compCore) with current database (m_core)

  Algorithm:
    Foreach entry in current database {
      Find in comparison database - subject to subgroup checking
      if found {
        Compare
        if match
          OK
       else
          There are conflicts; note them & increment numConflicts
      } else {
        save & increment numOnlyInCurrent
      }
    }

    Foreach entry in comparison database {
      Find in current database - subject to subgroup checking
      if not found
        save & increment numOnlyInComp
    }
  */

  CItemData::FieldBits bsConflicts(0);
  st_CompareData st_data;
  int numOnlyInCurrent(0), numOnlyInComp(0), numConflicts(0), numIdentical(0);

  ItemListIter currentPos;
  for (currentPos = GetEntryIter();
       currentPos != GetEntryEndIter();
       currentPos++) {
    st_data.Empty();
    CItemData currentItem = GetEntry(currentPos);

    if (!subgroup_bset ||
        currentItem.Matches(std::wstring(subgroup_name), subgroup_object,
                            subgroup_function)) {
      st_data.group = currentItem.GetGroup();
      st_data.title = currentItem.GetTitle();
      st_data.user = currentItem.GetUser();

      StringX sx_original = sx_StartChevron +
                             st_data.group + sx_MiddleChevron +
                             st_data.title + sx_MiddleChevron +
                             st_data.user  + sx_EndChevron;

      // Update the Wizard page
      UpdateWizard(sx_original.c_str());

      ItemListIter foundPos = pothercore->Find(st_data.group,
                                               st_data.title, st_data.user);
      if (foundPos != pothercore->GetEntryEndIter()) {
        // found a match, see if all other fields also match
        // Difference flags:
        /*
         First byte (values in square brackets taken from ItemData.h)
         1... ....  NAME       [0x00] - n/a - depreciated
         .1.. ....  UUID       [0x01] - n/a - unique
         ..1. ....  GROUP      [0x02] - not checked - must be identical
         ...1 ....  TITLE      [0x03] - not checked - must be identical
         .... 1...  USER       [0x04] - not checked - must be identical
         .... .1..  NOTES      [0x05]
         .... ..1.  PASSWORD   [0x06]
         .... ...1  CTIME      [0x07] - not checked by default

         Second byte
         1... ....  PMTIME     [0x08] - not checked by default
         .1.. ....  ATIME      [0x09] - not checked by default
         ..1. ....  XTIME      [0x0a] - not checked by default
         ...1 ....  RESERVED   [0x0b] - not used
         .... 1...  RMTIME     [0x0c] - not checked by default
         .... .1..  URL        [0x0d]
         .... ..1.  AUTOTYPE   [0x0e]
         .... ...1  PWHIST     [0x0f]

         Third byte
         1... ....  POLICY     [0x10] - not checked by default
         .1.. ....  XTIME_INT  [0x11] - not checked by default
         ..1. ....  RUNCMD     [0x12]
         ...1 ....  DCA        [0x13]
         .... 1...  EMAIL      [0x14]
         .... .1..  PROTECTED  [0x15]
         .... ..1.  SYMBOLS    [0x16]
         .... ...1  SHIFTDCA   [0x17]

         Fourth byte
         1... ....  POLICYNAME [0x18] - not checked by default


        */
        bsConflicts.reset();
        StringX sxCurrentPassword, sxComparisonPassword;

        CItemData compItem = pothercore->GetEntry(foundPos);

        if (currentItem.IsDependent()) {
          CItemData *pci_base = GetBaseEntry(&currentItem);
          sxCurrentPassword = pci_base->GetPassword();
        } else
          sxCurrentPassword = currentItem.GetPassword();

        if (compItem.IsDependent()) {
          CItemData *pci_base = pothercore->GetBaseEntry(&compItem);
          sxComparisonPassword = pci_base->GetPassword();
        } else
          sxComparisonPassword = compItem.GetPassword();

        if (bsFields.test(CItemData::PASSWORD) &&
            sxCurrentPassword != sxComparisonPassword)
          bsConflicts.flip(CItemData::PASSWORD);

        if (bsFields.test(CItemData::NOTES) &&
            FieldsNotEqual(currentItem.GetNotes(), compItem.GetNotes(), bTreatWhiteSpaceasEmpty))
          bsConflicts.flip(CItemData::NOTES);

        if (bsFields.test(CItemData::CTIME) &&
            currentItem.GetCTime() != compItem.GetCTime())
          bsConflicts.flip(CItemData::CTIME);

        if (bsFields.test(CItemData::PMTIME) &&
            currentItem.GetPMTime() != compItem.GetPMTime())
          bsConflicts.flip(CItemData::PMTIME);
{'fraction_non_alphanumeric': 0.14515646054798623, 'fraction_numerical': 0.016394669860757598, 'mean_word_length': 1.890307226308957, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6525423', 'n_tokens_mistral': 4198, 'n_tokens_neox': 3898, 'n_words': 955}