<commit_before># -*- coding: utf-8 -*-
"""Parser for .customDestinations-ms files."""

from __future__ import unicode_literals

import os

from dfvfs.lib import definitions
from dfvfs.lib import errors as dfvfs_errors
from dfvfs.path import factory as path_spec_factory
from dfvfs.resolver import resolver

from plaso.lib import errors
from plaso.parsers import dtfabric_parser
from plaso.parsers import manager
from plaso.parsers import winlnk


class CustomDestinationsParser(dtfabric_parser.DtFabricBaseParser):
  """Parses .customDestinations-ms files."""

  NAME = 'custom_destinations'
  DESCRIPTION = 'Parser for *.customDestinations-ms files.'

  _INITIAL_FILE_OFFSET = None

  _DEFINITION_FILE = 'custom_destinations.yaml'

  # We cannot use the parser registry here since winlnk could be disabled.
  # TODO: see if there is a more elegant solution for this.
  _WINLNK_PARSER = winlnk.WinLnkParser()

  _LNK_GUID = (
      b'\x01\x14\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46')

  _FILE_FOOTER_SIGNATURE = 0xbabffbab

  def _ParseLNKFile(
      self, parser_mediator, file_entry, file_offset, remaining_file_size):
    """Parses a LNK file stored within the .customDestinations-ms file.

    Args:
      parser_mediator (ParserMediator): mediates interactions between parsers
          and other components, such as storage and dfvfs.
      file_entry (dfvfs.FileEntry): a file entry.
      file_offset (int): offset to the LNK file, relative to the start of the
          .customDestinations-ms file.
      remaining_file_size (int): size of the data remaining in the
          .customDestinations-ms file.

    Returns:
      int: size of the LNK file data or 0 if the LNK file could not be read.
    """
    path_spec = path_spec_factory.Factory.NewPathSpec(
        definitions.TYPE_INDICATOR_DATA_RANGE, range_offset=file_offset,
        range_size=remaining_file_size, parent=file_entry.path_spec)

    display_name = '{0:s} # 0x{1:08x}'.format(file_entry.name, file_offset)

    try:
      lnk_file_object = resolver.Resolver.OpenFileObject(path_spec)
    except (dfvfs_errors.BackEndError, RuntimeError) as exception:
      message = (
          'unable to open LNK file: {0:s} with error: {1!s}').format(
              display_name, exception)
      parser_mediator.ProduceExtractionWarning(message)
      return 0

    parser_mediator.AppendToParserChain(self._WINLNK_PARSER)
    try:
      lnk_file_object.seek(0, os.SEEK_SET)
      self._WINLNK_PARSER.ParseFileLNKFile(
          parser_mediator, lnk_file_object, display_name)
    finally:
      parser_mediator.PopFromParserChain()

    # We cannot trust the file size in the LNK data so we get the last offset
    # that was read instead.
    lnk_file_size = lnk_file_object.get_offset()

    lnk_file_object.close()

    return lnk_file_size

  def ParseFileObject(self, parser_mediator, file_object):
    """Parses a .customDestinations-ms file-like object.<commit_msg>Changes to custom destinations parser (#2505)<commit_after># -*- coding: utf-8 -*-
"""Parser for .customDestinations-ms files."""

from __future__ import unicode_literals

import os

from dfvfs.lib import definitions
from dfvfs.lib import errors as dfvfs_errors
from dfvfs.path import factory as path_spec_factory
from dfvfs.resolver import resolver

from plaso.lib import errors
from plaso.lib import specification
from plaso.parsers import dtfabric_parser
from plaso.parsers import manager
from plaso.parsers import winlnk


class CustomDestinationsParser(dtfabric_parser.DtFabricBaseParser):
  """Parses .customDestinations-ms files."""

  NAME = 'custom_destinations'
  DESCRIPTION = 'Parser for *.customDestinations-ms files.'

  _INITIAL_FILE_OFFSET = None

  _DEFINITION_FILE = 'custom_destinations.yaml'

  # We cannot use the parser registry here since winlnk could be disabled.
  # TODO: see if there is a more elegant solution for this.
  _WINLNK_PARSER = winlnk.WinLnkParser()

  _LNK_GUID = (
      b'\x01\x14\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46')

  _FILE_FOOTER_SIGNATURE = 0xbabffbab

  def _ParseLNKFile(
      self, parser_mediator, file_entry, file_offset, remaining_file_size):
    """Parses a LNK file stored within the .customDestinations-ms file.

    Args:
      parser_mediator (ParserMediator): mediates interactions between parsers
          and other components, such as storage and dfvfs.
      file_entry (dfvfs.FileEntry): a file entry.
      file_offset (int): offset to the LNK file, relative to the start of the
          .customDestinations-ms file.
      remaining_file_size (int): size of the data remaining in the
          .customDestinations-ms file.

    Returns:
      int: size of the LNK file data or 0 if the LNK file could not be read.
    """
    path_spec = path_spec_factory.Factory.NewPathSpec(
        definitions.TYPE_INDICATOR_DATA_RANGE, range_offset=file_offset,
        range_size=remaining_file_size, parent=file_entry.path_spec)

    display_name = '{0:s} # 0x{1:08x}'.format(file_entry.name, file_offset)

    try:
      lnk_file_object = resolver.Resolver.OpenFileObject(
          path_spec, resolver_context=parser_mediator.resolver_context)
    except (dfvfs_errors.BackEndError, RuntimeError) as exception:
      message = (
          'unable to open LNK file: {0:s} with error: {1!s}').format(
              display_name, exception)
      parser_mediator.ProduceExtractionWarning(message)
      return 0

    parser_mediator.AppendToParserChain(self._WINLNK_PARSER)
    try:
      lnk_file_object.seek(0, os.SEEK_SET)
      self._WINLNK_PARSER.ParseFileLNKFile(
          parser_mediator, lnk_file_object, display_name)
    finally:
      parser_mediator.PopFromParserChain()

    # We cannot trust the file size in the LNK data so we get the last offset
    # that was read instead.
    lnk_file_size = lnk_file_object.get_offset()

    lnk_file_object.close()

    return lnk_file_size

  @classmethod
  def GetFormatSpecification(cls):
    """Retrieves the format specification.

    Returns:
      FormatSpecification: format specification.
    """
    format_specification = specification.FormatSpecification(cls.NAME)
    format_specification.AddNewSignature(b'\xab\xfb\xbf\xba', offset=-4)
    return format_specification

  def ParseFileObject(self, parser_mediator, file_object):
    """Parses a .customDestinations-ms file-like object.
{'fraction_non_alphanumeric': 0.07857254656440757, 'fraction_numerical': 0.01424323055251213, 'mean_word_length': 3.7298297557364917, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4537191', 'n_tokens_mistral': 2176, 'n_tokens_neox': 2035, 'n_words': 533}