Opened 15 years ago

Closed 15 years ago

Last modified 12 years ago

#9610 closed (fixed)

File upload duplicate filename check mechanism fail

Reported by: fadlytabrani Owned by: fadlytabrani
Component: File uploads/storage Version: 1.0
Severity: Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The file upload duplicate filename check mechanism will fail if the upload directory contains a dot and when the filename does not.

django.core.files.storage:Storage

def get_available_name(self, name):
        """
        Returns a filename that's free on the target storage system, and
        available for new content to be written to.
        """
        # If the filename already exists, keep adding an underscore to the name
        # of the file until the filename doesn't exist.
        while self.exists(name):
            try:
                dot_index = name.rindex('.')
            except ValueError: # filename has no dot
                name += '_'
            else:
                name = name[:dot_index] + '_' + name[dot_index:]
        return name

# Failure example, uploading duplicate file "testlog" will create new directory upload_.10122008
# Correct result would be "testlog" would be uploaded with the filename testlog_
get_available_name("c:\\django\\media\\upload.10122008\\testlog")

Using os.path would solve the problem

def get_available_name(self, name):
        while self.exists(name):
            dname, fname = os.path.split(name)
            try:
                dot_index = fname.rindex('.')
            except ValueError:
                fname += '_'
            else:
                fname = fname[:dot_index] + '_' + fname[dot_index:]
                
            return os.path.join(dname, fname)

Attachments (3)

storage.py.patch (478 bytes ) - added by fadlytabrani 15 years ago.
storage.py.2.patch (477 bytes ) - added by fadlytabrani 15 years ago.
9610.diff (2.2 KB ) - added by Andy Durdin 15 years ago.
Added tests, and updated the patch to unified diff format.

Download all attachments as: .zip

Change History (18)

comment:1 by fadlytabrani, 15 years ago

Initial submitted fix doesn't work, this does

def get_available_namex(self, name):
        while self.exists(name):
            dname, fname = os.path.split(name)
            try:
                dot_index = fname.rindex('.')
            except ValueError:
                fname += '_'
            else:
                fname = fname[:dot_index] + '_' + fname[dot_index:]
            name = os.path.join(dname, fname)
        return name

comment:2 by dc, 15 years ago

Little improvement:

def get_available_namex(self, name):
    dir_name, file_name = os.path.split(name) 
    while self.exists(name):
        try:
            dot_index = file_name.rindex('.')
        except ValueError:
            file_name += '_'
        else:
            file_name = file_name[:dot_index] + '_' + file_name[dot_index:]
        name = os.path.join(dir_name, file_name)
    return name

by fadlytabrani, 15 years ago

Attachment: storage.py.patch added

comment:3 by fadlytabrani, 15 years ago

Owner: changed from nobody to fadlytabrani
Status: newassigned

Patch attached

The line :

dir_name, file_name = os.path.split(name)

should be within the while loop to acommodate checking more than once

def get_available_name(self, name): 
    while self.exists(name):
		dir_name, file_name = os.path.split(name)
        try:
            dot_index = file_name.rindex('.')
        except ValueError:
            file_name += '_'
        else:
            file_name = file_name[:dot_index] + '_' + file_name[dot_index:]
        name = os.path.join(dir_name, file_name)
    return name

comment:4 by fadlytabrani, 15 years ago

Triage Stage: UnreviewedReady for checkin

comment:5 by fadlytabrani, 15 years ago

Triage Stage: Ready for checkinDesign decision needed

comment:6 by fadlytabrani, 15 years ago

Resolution: worksforme
Status: assignedclosed
Triage Stage: Design decision neededUnreviewed

in reply to:  4 ; comment:7 by dc, 15 years ago

Patch needs improvement: set

Replying to fadlytabrani:

The line should be within the while loop to acommodate checking more than once

Nope. dir_name never changes and it should be calculated once. But your version calls unneeded split every iteration. Just check in debugger (or something like that) if you unsure.

by fadlytabrani, 15 years ago

Attachment: storage.py.2.patch added

in reply to:  7 comment:8 by fadlytabrani, 15 years ago

Replying to dc:

Replying to fadlytabrani:

The line should be within the while loop to acommodate checking more than once

Nope. dir_name never changes and it should be calculated once. But your version calls unneeded split every iteration. Just check in debugger (or something like that) if you unsure.

Thanks dc, you're correct :) I missed that one

Have uploaded correct path

comment:9 by fadlytabrani, 15 years ago

Needs tests: set
Patch needs improvement: unset

comment:10 by dc, 15 years ago

Resolution: worksforme
Status: closedreopened

Still a bug which must be fixed.

comment:11 by (none), 15 years ago

milestone: post-1.0

Milestone post-1.0 deleted

comment:12 by Jacob, 15 years ago

milestone: 1.1
Triage Stage: UnreviewedAccepted

by Andy Durdin, 15 years ago

Attachment: 9610.diff added

Added tests, and updated the patch to unified diff format.

comment:13 by Andy Durdin, 15 years ago

Needs tests: unset
Triage Stage: AcceptedReady for checkin

comment:14 by Gary Wilson, 15 years ago

Resolution: fixed
Status: reopenedclosed

(In [10702]) [1.0.X]: Fixed #9610 -- Fixed duplicate uploaded file name mangling when directory contained a dot and file didn't. Based on patches from fadlytabrani and adurdin.

Backport of r10701 from trunk.

comment:15 by Jacob, 12 years ago

milestone: 1.1

Milestone 1.1 deleted

Note: See TracTickets for help on using tickets.
Back to Top