Exemplo n.º 1
0
 def get_available_name(self, name, max_length=None):
     """
     Return a filename that's free on the target storage system and
     available for new content to be written to.
     """
     dir_name, file_name = os.path.split(name)
     if '..' in pathlib.PurePath(dir_name).parts:
         raise SuspiciousFileOperation(
             "Detected path traversal attempt in '%s'" % dir_name)
     validate_file_name(file_name)
     file_root, file_ext = os.path.splitext(file_name)
     # If the filename already exists, generate an alternative filename
     # until it doesn't exist.
     # Truncate original name if required, so the new filename does not
     # exceed the max_length.
     while self.exists(name) or (max_length and len(name) > max_length):
         # file_ext includes the dot.
         name = os.path.join(dir_name,
                             self.get_alternative_name(file_root, file_ext))
         if max_length is None:
             continue
         # Truncate file_root if max_length exceeded.
         truncation = len(name) - max_length
         if truncation > 0:
             file_root = file_root[:-truncation]
             # Entire file_root was truncated in attempt to find an available filename.
             if not file_root:
                 raise SuspiciousFileOperation(
                     'Storage can not find an available filename for "%s". '
                     'Please make sure that the corresponding file field '
                     'allows sufficient "max_length".' % name)
             name = os.path.join(
                 dir_name, self.get_alternative_name(file_root, file_ext))
     return name
Exemplo n.º 2
0
    def save(self, name, content, max_length=None):
        """
        Save new content to the file specified by name. The content should be
        a proper File object or any Python file-like object, ready to be read
        from the beginning.
        """
        # Get the proper name for the file, as it will actually be saved.
        if name is None:
            name = content.name

        if not hasattr(content, "chunks"):
            content = File(content, name)

        name = self.get_available_name(name, max_length=max_length)
        name = self._save(name, content)
        # Ensure that the name returned from the storage system is still valid.
        validate_file_name(name, allow_relative_path=True)
        return name
Exemplo n.º 3
0
 def generate_filename(self, instance, filename):
     """
     Apply (if callable) or prepend (if a string) upload_to to the filename,
     then delegate further processing of the name to the storage backend.
     Until the storage layer, all file paths are expected to be Unix style
     (with forward slashes).
     """
     filename = validate_file_name(filename)
     if callable(self.upload_to):
         filename = self.upload_to(instance, filename)
     else:
         dirname = datetime.datetime.now().strftime(str(self.upload_to))
         filename = posixpath.join(dirname, filename)
     return self.storage.generate_filename(filename)
Exemplo n.º 4
0
    def _set_name(self, name):
        # Sanitize the file name so that it can't be dangerous.
        if name is not None:
            # Just use the basename of the file -- anything else is dangerous.
            name = os.path.basename(name)

            # File names longer than 255 characters can cause problems on older OSes.
            if len(name) > 255:
                name, ext = os.path.splitext(name)
                ext = ext[:255]
                name = name[:255 - len(ext)] + ext

            name = validate_file_name(name)

        self._name = name