Skip to content

Long names fail exporting when invalid windows characters are present. #7

@synrais

Description

@synrais

Changing these 3 def in mymc.py will allow long names to export saves, and cleans the invalid characters to nothing.



def sanitize_filename(name):
    # Windows does not allow these characters in file names: < > : " / \ | ? *
    return re.sub(r'[<>:"/\\|?*]', '', name)

def do_export(cmd, mc, opts, args, opterr):
    if len(args) < 1:
        opterr("Directory name required")
    if opts.overwrite_existing and opts.ignore_existing:
        opterr("The -i and -f options are mutually exclusive.")
        
    args = glob_args(args, mc.glob)
    if opts.output_file is not None:
        if len(args) > 1:
            opterr("Only one directory can be exported when the -o option is used.")
        if opts.longnames:
            opterr("The -o and -l options are mutually exclusive.")

    if opts.directory is not None:
        os.chdir(opts.directory)
        
    for dirname in args:
        sf = mc.export_save_file(dirname)
        filename = opts.output_file
        if opts.longnames:
            # Generate the long name and append the file type extension
            long_name = ps2save.make_longname(dirname, sf) + "." + opts.type
            # Sanitize the long name to remove any invalid characters
            filename = sanitize_filename(long_name)
        if filename is None:
            filename = dirname + "." + opts.type
                
        if not opts.overwrite_existing:
            exists = True
            try:
                open(filename, "rb").close()
            except EnvironmentError:
                exists = False
            if exists:
                if opts.ignore_existing:
                    continue
                raise io_error(EEXIST, "File exists", filename)
            
        f = open(filename, "wb")
        try:
            print("Exporing", dirname, "to", filename)
            
            if opts.type == "max":
                format_max_drive.save(sf, f)
            elif opts.type == "psv":
                format_psv.save(sf, f)
            else:
                format_ems.save(sf, f)
        finally:
            f.close()

def do_dir(cmd, mc, opts, args, opterr):
    # Allow a directory argument (default to root if none provided)
    if len(args) == 0:
        args = ["/"]
    args = glob_args(args, mc.glob)

    # Choose encoding: if --ascii was given, force ascii; otherwise use sys.stdout.encoding with a fallback.
    enc = "ascii" if opts.ascii else (getattr(sys.stdout, "encoding", "utf-8") or "utf-8")

    for root in args:
        try:
            d = mc.dir_open(root)
        except Exception as e:
            opterr("Cannot open directory: " + root)
        if len(args) > 1:
            print("\n" + root + ":\n")
        for ent in list(d)[2:]:
            dirmode = ent[0]
            if not mode_is_dir(dirmode):
                continue
            # Use the chosen encoding to decode the directory name,
            # replacing any characters that can’t be decoded.
            subdir = "/" + ent[8].decode(enc, errors="replace")
            full_path = root.rstrip("/") + subdir
            # Change into the subdirectory to obtain its details
            mc.chdir(full_path)
            length = mc.dir_size(".")
            if dirmode & DF_PSX:
                title = _get_psx_title(mc, ent[8], enc)
            else:
                title = _get_ps2_title(mc, enc)
            if title is None:
                title = ["Corrupt", ""]
            protection = dirmode & (DF_PROTECTED | DF_WRITE)
            if protection == 0:
                protection = "Delete Protected"
            elif protection == DF_WRITE:
                protection = "Not Protected"
            elif protection == DF_PROTECTED:
                protection = "Copy & Delete Protected"
            else:
                protection = "Copy Protected"
            type = None
            if dirmode & DF_PSX:
                type = "PlayStation"
                if dirmode & DF_POCKETSTN:
                    type = "PocketStation"
            if type is not None:
                protection = type

            # Use the chosen encoding when printing out the directory name.
            print("%-32s %s" % (ent[8].decode(enc, errors="replace"), title[0]))
            print("%4dKB %-25s %s" % (length // 1024, protection, title[1]))
            print()
        d.close()

    free = mc.get_free_space() // 1024
    if free > 999999:
        free = "%d,%03d,%03d" % (free // 1000000, free // 1000 % 1000, free % 1000)
    elif free > 999:
        free = "%d,%03d" % (free // 1000, free % 1000)
    else:
        free = "%d" % free

    print(free + " KB Free")


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions