diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-02-04 21:37:02 +0100 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-02-04 21:37:02 +0100 |
| commit | 6d81feb101da689092d3370c1dc55be89e11fd35 (patch) | |
| tree | 3fe910711cc55f86e548193d02d4d133d5c12a29 /internal | |
| parent | ba201a220aa723f98c6a81d74dc4229bf89b282a (diff) | |
Share replacement code
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/mobius/friendship_quest_file_extensions.go | 217 |
1 files changed, 78 insertions, 139 deletions
diff --git a/internal/mobius/friendship_quest_file_extensions.go b/internal/mobius/friendship_quest_file_extensions.go index f04868c..98d82ff 100644 --- a/internal/mobius/friendship_quest_file_extensions.go +++ b/internal/mobius/friendship_quest_file_extensions.go @@ -12,111 +12,127 @@ import ( ) // ResolveUserPath processes paths for the special `~` directory. -// If the requested path starts with `~`, it returns the user's corresponding folder. func ResolveUserPath(cc *hotline.ClientConn, requestedPath string) (string, error) { - if strings.HasPrefix(requestedPath, "~") { - userFolder := filepath.Join("~", cc.Account.Login) - actualUserFolder := filepath.Join(cc.FileRoot(), userFolder) - if stat, err := os.Stat(actualUserFolder); err == nil && stat.IsDir() { - return strings.Replace(requestedPath, "~", userFolder, 1), nil - } else { - return "", fmt.Errorf("user folder does not exist") - } + if !strings.HasPrefix(requestedPath, "~") { + return requestedPath, nil + } + + userFolder := filepath.Join("~", cc.Account.Login) + actualUserFolder := filepath.Join(cc.FileRoot(), userFolder) + if stat, err := os.Stat(actualUserFolder); err == nil && stat.IsDir() { + return strings.Replace(requestedPath, "~", userFolder, 1), nil } - return requestedPath, nil + + return "", fmt.Errorf("user folder does not exist") } // updateTransactionPath updates the FieldFilePath in a transaction in-place. func updateTransactionPath(t *hotline.Transaction, newPath string) { - for i, field := range t.Fields { - if field.Type == hotline.FieldFilePath { + for i, field := range t.Fields { + if field.Type == hotline.FieldFilePath { + if encodedPath, err := txtEncoder.String(newPath); err == nil { + if fpBytes, err := encodeFilePath(encodedPath); err == nil { + t.Fields[i].Data = fpBytes + } + } + return + } + } +} - // Convert newPath to the correct binary format - encodedPath, err := txtEncoder.String(newPath) - if err != nil { - return // Encoding failure, don't update - } +// encodeFilePath encodes a string path into hotline.FilePath binary format. +func encodeFilePath(path string) ([]byte, error) { + components := strings.Split(path, string(filepath.Separator)) + var fp hotline.FilePath + binary.BigEndian.PutUint16(fp.ItemCount[:], uint16(len(components))) - // Convert the new path into the correct binary format for FilePath - fpBytes, err := encodeFilePath(encodedPath) - if err != nil { - return - } + var buffer bytes.Buffer + if err := binary.Write(&buffer, binary.BigEndian, fp.ItemCount); err != nil { + return nil, err + } - // Assign correctly formatted binary path - t.Fields[i].Data = fpBytes - return - } - } + for _, component := range components { + if component == "" || len(component) > 255 { + return nil, fmt.Errorf("invalid file path component") + } + encodedComponent, err := txtEncoder.String(component) + if err != nil { + return nil, err + } + buffer.Write([]byte{0x00, 0x00, byte(len(encodedComponent))}) + buffer.Write([]byte(encodedComponent)) + } + + return buffer.Bytes(), nil } -// Encode a string path into hotline.FilePath binary format -func encodeFilePath(path string) ([]byte, error) { - components := strings.Split(path, string(filepath.Separator)) - var fp hotline.FilePath +// handleFileTransaction handles various file operations that require resolving `~` +func handleFileTransaction(cc *hotline.ClientConn, t *hotline.Transaction, handler func(*hotline.ClientConn, *hotline.Transaction) []hotline.Transaction, errMsg string) []hotline.Transaction { + requestedPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFilePath).Data, nil) + if err != nil { + return nil + } - // Set the item count - binary.BigEndian.PutUint16(fp.ItemCount[:], uint16(len(components))) + resolvedPath, err := ResolveUserPath(cc, requestedPath[len(cc.FileRoot())+1:]) + if err != nil { + return cc.NewErrReply(t, errMsg) + } - var buffer bytes.Buffer - err := binary.Write(&buffer, binary.BigEndian, fp.ItemCount) - if err != nil { - return nil, err - } + updateTransactionPath(t, resolvedPath) + return handler(cc, t) +} - for _, component := range components { - if component == "" { - continue - } +// File operation handlers +func HandleUploadFileWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) []hotline.Transaction { + return handleFileTransaction(cc, t, HandleUploadFile, "Cannot upload to non-existent user folder.") +} - if len(component) > 255 { // Ensure component size is within range - return nil, fmt.Errorf("file path component too long") - } +func HandleUploadFolderWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) []hotline.Transaction { + return handleFileTransaction(cc, t, HandleUploadFolder, "Cannot upload to non-existent user folder.") +} - // Convert to MacRoman encoding - encodedComponent, err := txtEncoder.String(component) - if err != nil { - return nil, err - } +func HandleDeleteFileWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) []hotline.Transaction { + return handleFileTransaction(cc, t, HandleDeleteFile, "Cannot delete non-existent file.") +} - // Write length and name - buffer.Write([]byte{0x00, 0x00, byte(len(encodedComponent))}) // Leading bytes - buffer.Write([]byte(encodedComponent)) - } +func HandleDownloadFileWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) []hotline.Transaction { + return handleFileTransaction(cc, t, HandleDownloadFile, "Cannot download non-existent user file.") +} - return buffer.Bytes(), nil +func HandleDownloadFolderWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) []hotline.Transaction { + return handleFileTransaction(cc, t, HandleDownloadFolder, "Cannot download non-existent user folder.") } // HandleGetFileNameListWithUserFolders modifies the file listing behavior for `~` -func HandleGetFileNameListWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotline.Transaction) { +func HandleGetFileNameListWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) []hotline.Transaction { requestedPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFilePath).Data, nil) if err != nil { - return res + return nil } if requestedPath == cc.FileRoot() { fileNames, err := hotline.GetFileNameList(cc.FileRoot(), cc.Server.Config.IgnoreFiles) if err != nil { - return res + return nil } userFolder := filepath.Join(cc.FileRoot(), "~", cc.Account.Login) if stat, err := os.Stat(userFolder); err != nil || !stat.IsDir() { - filteredFiles := []hotline.Field{} + filteredFiles := make([]hotline.Field, 0, len(fileNames)) for _, file := range fileNames { if !strings.Contains(string(file.Data), "~") { filteredFiles = append(filteredFiles, file) } } - return append(res, cc.NewReply(t, filteredFiles...)) + return []hotline.Transaction{cc.NewReply(t, filteredFiles...)} } - return append(res, cc.NewReply(t, fileNames...)) + return []hotline.Transaction{cc.NewReply(t, fileNames...)} } if strings.HasPrefix(requestedPath, filepath.Join(cc.FileRoot(), "~")) { resolvedPath, err := ResolveUserPath(cc, requestedPath[len(cc.FileRoot())+1:]) if err != nil { - return res + return nil } updateTransactionPath(t, resolvedPath) return HandleGetFileNameList(cc, t) @@ -124,80 +140,3 @@ func HandleGetFileNameListWithUserFolders(cc *hotline.ClientConn, t *hotline.Tra return HandleGetFileNameList(cc, t) } - -// HandleUploadFileWithUserFolders ensures uploads go to the correct user folder when using `~`. -func HandleUploadFileWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotline.Transaction) { - requestedPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFilePath).Data, nil) - if err != nil { - return res - } - - resolvedPath, err := ResolveUserPath(cc, requestedPath[len(cc.FileRoot())+1:]) - if err != nil { - return cc.NewErrReply(t, "Cannot upload to non-existent user folder.") - } - - updateTransactionPath(t, resolvedPath) - return HandleUploadFile(cc, t) -} - -// HandleUploadFolderWithUserFolders ensures directory uploads go to the correct user folder when using `~`. -func HandleUploadFolderWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotline.Transaction) { - requestedPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFilePath).Data, nil) - if err != nil { - return res - } - - resolvedPath, err := ResolveUserPath(cc, requestedPath[len(cc.FileRoot())+1:]) - if err != nil { - return cc.NewErrReply(t, "Cannot upload to non-existent user folder.") - } - - updateTransactionPath(t, resolvedPath) - return HandleUploadFolder(cc, t) -} - -func HandleDeleteFileWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotline.Transaction) { - requestedPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFilePath).Data, nil) - if err != nil { - return res - } - - resolvedPath, err := ResolveUserPath(cc, requestedPath[len(cc.FileRoot())+1:]) - if err != nil { - return cc.NewErrReply(t, "Cannot delete non-existent file.") - } - - updateTransactionPath(t, resolvedPath) - return HandleDeleteFile(cc, t) -} - -func HandleDownloadFileWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotline.Transaction) { - requestedPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFilePath).Data, nil) - if err != nil { - return res - } - - resolvedPath, err := ResolveUserPath(cc, requestedPath[len(cc.FileRoot())+1:]) - if err != nil { - return cc.NewErrReply(t, "Cannot download non-existent user file.") - } - - updateTransactionPath(t, resolvedPath) - return HandleDownloadFile(cc, t) -} - -func HandleDownloadFolderWithUserFolders(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotline.Transaction) { - requestedPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFilePath).Data, nil) - if err != nil { - return res - } - - resolvedPath, err := ResolveUserPath(cc, requestedPath[len(cc.FileRoot())+1:]) - if err != nil { - return cc.NewErrReply(t, "Cannot download non-existent user folder.") - } - - updateTransactionPath(t, resolvedPath) - return HandleDownloadFolder(cc, t) -} |