parameters: (self, path_def, installed, extensions=None)
return_statement: return addon, [
              path
              for path in paths
              if not extensions or path.split('.')[-1] in extensions
          ]
docstring: Returns a list of file paths matching a given glob (path_def) as well as
          the addon targeted by the path definition. If no file matches that glob,
          the path definition is returned as is. This is either because the path is
          not correctly written or because it points to a URL.
  
          :param path_def: the definition (glob) of file paths to match
          :param installed: the list of installed addons
          :param extensions: a list of extensions that found files must match
          :returns: a tuple: the addon targeted by the path definition [0] and the
              list of file paths matching the definition [1] (or the glob itself if
              none). Note that these paths are filtered on the given `extensions`.
docstring_summary: Returns a list of file paths matching a given glob (path_def) as well as
          the addon targeted by the path definition. If no file matches that glob,
          the path definition is returned as is. This is either because the path is
          not correctly written or because it points to a URL.
docstring_tokens: Returns a list of file paths matching a given glob ( path_def ) as well as the addon targeted by the path definition . If no file matches that glob the path definition is returned as is . This is either because the path is not correctly written or because it points to a URL .
function: def _get_paths(self, path_def, installed, extensions=None):
          """
          Returns a list of file paths matching a given glob (path_def) as well as
          the addon targeted by the path definition. If no file matches that glob,
          the path definition is returned as is. This is either because the path is
          not correctly written or because it points to a URL.
  
          :param path_def: the definition (glob) of file paths to match
          :param installed: the list of installed addons
          :param extensions: a list of extensions that found files must match
          :returns: a tuple: the addon targeted by the path definition [0] and the
              list of file paths matching the definition [1] (or the glob itself if
              none). Note that these paths are filtered on the given `extensions`.
          """
          paths = []
          path_url = fs2web(path_def)
          path_parts = [part for part in path_url.split('/') if part]
          addon = path_parts[0]
          addon_manifest = http.addons_manifest.get(addon)
  
          safe_path = True
          if addon_manifest:
              if addon not in installed:
                  # Assert that the path is in the installed addons
                  raise Exception("Unallowed to fetch files from addon %s" % addon)
              addons_path = os.path.join(addon_manifest['addons_path'], '')[:-1]
              full_path = os.path.normpath(os.path.join(addons_path, *path_parts))
  
              # first security layer: forbid escape from the current addon
              # "/mymodule/../myothermodule" is forbidden
              # the condition after the or is to further guarantee that we won't access
              # a directory that happens to be named like an addon (web....)
              if addon not in full_path or addons_path not in full_path:
                  addon = None
                  safe_path = False
              else:
                  paths = [
                      path for path in sorted(glob(full_path, recursive=True))
                  ]
  
              # second security layer: do we have the right to access the files
              # that are grabbed by the glob ?
              # In particular we don't want to expose data in xmls of the module
              def is_safe_path(path):
                  try:
                      misc.file_path(path, SCRIPT_EXTENSIONS + STYLE_EXTENSIONS + TEMPLATE_EXTENSIONS)
                  except (ValueError, FileNotFoundError):
                      return False
                  if path.rpartition('.')[2] in TEMPLATE_EXTENSIONS:
                      # normpath will strip the trailing /, which is why it has to be added afterwards
                      static_path = os.path.normpath("%s/static" % addon) + os.path.sep
                      # Forbid xml to leak
                      return static_path in path
                  return True
  
              len_paths = len(paths)
              paths = list(filter(is_safe_path, paths))
              safe_path = safe_path and len_paths == len(paths)
  
              # When fetching template file paths, we need the full paths since xml
              # files are read from the file system. But web assets (scripts and
              # stylesheets) must be loaded using relative paths, hence the trimming
              # for non-xml file paths.
              paths = [path if path.split('.')[-1] in TEMPLATE_EXTENSIONS else fs2web(path[len(addons_path):]) for path in paths]
  
          else:
              addon = None
  
          if not paths and (not can_aggregate(path_url) or (safe_path and not is_wildcard_glob(path_url))):
              # No file matching the path; the path_def could be a url.
              paths = [path_url]
  
          if not paths:
              msg = f'IrAsset: the path "{path_def}" did not resolve to anything.'
              if not safe_path:
                  msg += " It may be due to security reasons."
              _logger.warning(msg)
          # Paths are filtered on the extensions (if any).
          return addon, [
              path
              for path in paths
              if not extensions or path.split('.')[-1] in extensions
          ]
function_tokens: def _get_paths ( self , path_def , installed , extensions = None ) : paths = [ ] path_url = fs2web ( path_def ) path_parts = [ part for part in path_url . split ( '/' ) if part ] addon = path_parts [ 0 ] addon_manifest = http . addons_manifest . get ( addon ) safe_path = True if addon_manifest : if addon not in installed : # Assert that the path is in the installed addons raise Exception ( "Unallowed to fetch files from addon %s" % addon ) addons_path = os . path . join ( addon_manifest [ 'addons_path' ] , '' ) [ : - 1 ] full_path = os . path . normpath ( os . path . join ( addons_path , * path_parts ) ) # first security layer: forbid escape from the current addon # "/mymodule/../myothermodule" is forbidden # the condition after the or is to further guarantee that we won't access # a directory that happens to be named like an addon (web....) if addon not in full_path or addons_path not in full_path : addon = None safe_path = False else : paths = [ path for path in sorted ( glob ( full_path , recursive = True ) ) ] # second security layer: do we have the right to access the files # that are grabbed by the glob ? # In particular we don't want to expose data in xmls of the module def is_safe_path ( path ) : try : misc . file_path ( path , SCRIPT_EXTENSIONS + STYLE_EXTENSIONS + TEMPLATE_EXTENSIONS ) except ( ValueError , FileNotFoundError ) : return False if path . rpartition ( '.' ) [ 2 ] in TEMPLATE_EXTENSIONS : # normpath will strip the trailing /, which is why it has to be added afterwards static_path = os . path . normpath ( "%s/static" % addon ) + os . path . sep # Forbid xml to leak return static_path in path return True len_paths = len ( paths ) paths = list ( filter ( is_safe_path , paths ) ) safe_path = safe_path and len_paths == len ( paths ) # When fetching template file paths, we need the full paths since xml # files are read from the file system. But web assets (scripts and # stylesheets) must be loaded using relative paths, hence the trimming # for non-xml file paths. paths = [ path if path . split ( '.' ) [ - 1 ] in TEMPLATE_EXTENSIONS else fs2web ( path [ len ( addons_path ) : ] ) for path in paths ] else : addon = None if not paths and ( not can_aggregate ( path_url ) or ( safe_path and not is_wildcard_glob ( path_url ) ) ) : # No file matching the path; the path_def could be a url. paths = [ path_url ] if not paths : msg = f'IrAsset: the path "{path_def}" did not resolve to anything.' if not safe_path : msg += " It may be due to security reasons." _logger . warning ( msg ) # Paths are filtered on the extensions (if any). return addon , [ path for path in paths if not extensions or path . split ( '.' ) [ - 1 ] in extensions ]