From: Jeff Halter Date: Tue, 21 Jun 2022 05:21:28 +0000 (-0700) Subject: Convert hardcoded path separators to filepath.Join X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/commitdiff_plain/f22acf38da970aa0d865a9978c9499dad01d235f Convert hardcoded path separators to filepath.Join --- diff --git a/cmd/mobius-hotline-server/main.go b/cmd/mobius-hotline-server/main.go index bf41da1..63dc824 100644 --- a/cmd/mobius-hotline-server/main.go +++ b/cmd/mobius-hotline-server/main.go @@ -14,8 +14,8 @@ import ( "math/rand" "net/http" "os" + "path/filepath" "runtime" - "strings" "time" ) @@ -71,12 +71,8 @@ func main() { defer func() { _ = l.Sync() }() logger := l.Sugar() - if !(strings.HasSuffix(*configDir, "/") || strings.HasSuffix(*configDir, "\\")) { - *configDir = *configDir + "/" - } - if *init { - if _, err := os.Stat(*configDir + "/config.yaml"); os.IsNotExist(err) { + if _, err := os.Stat(filepath.Join(*configDir, "/config.yaml")); os.IsNotExist(err) { if err := os.MkdirAll(*configDir, 0750); err != nil { logger.Fatal(err) } @@ -92,7 +88,7 @@ func main() { } if _, err := os.Stat(*configDir); os.IsNotExist(err) { - logger.Fatalw("Configuration directory not found", "path", configDir) + logger.Fatalw("Configuration directory not found. Correct the path or re-run with -init to generate initial config.", "path", configDir) } srv, err := hotline.NewServer(*configDir, *basePort, logger, &hotline.OSFileStore{}) @@ -176,17 +172,17 @@ func copyDir(src, dst string) error { } for _, dirEntry := range entries { if dirEntry.IsDir() { - if err := os.MkdirAll(dst+"/"+dirEntry.Name(), 0777); err != nil { + if err := os.MkdirAll(filepath.Join(dst, dirEntry.Name()), 0777); err != nil { panic(err) } - subdirEntries, _ := cfgTemplate.ReadDir(src + "/" + dirEntry.Name()) + subdirEntries, _ := cfgTemplate.ReadDir(filepath.Join(src, dirEntry.Name())) for _, subDirEntry := range subdirEntries { - f, err := os.Create(dst + "/" + dirEntry.Name() + "/" + subDirEntry.Name()) + f, err := os.Create(filepath.Join(dst, dirEntry.Name(), subDirEntry.Name())) if err != nil { return err } - srcFile, err := cfgTemplate.Open(src + "/" + dirEntry.Name() + "/" + subDirEntry.Name()) + srcFile, err := cfgTemplate.Open(filepath.Join(src, dirEntry.Name(), subDirEntry.Name())) if err != nil { return err } @@ -197,12 +193,12 @@ func copyDir(src, dst string) error { f.Close() } } else { - f, err := os.Create(dst + "/" + dirEntry.Name()) + f, err := os.Create(filepath.Join(dst, dirEntry.Name())) if err != nil { return err } - srcFile, err := cfgTemplate.Open(src + "/" + dirEntry.Name()) + srcFile, err := cfgTemplate.Open(filepath.Join(src, dirEntry.Name())) if err != nil { return err } diff --git a/hotline/file_path.go b/hotline/file_path.go index cdd95b9..c8fe652 100644 --- a/hotline/file_path.go +++ b/hotline/file_path.go @@ -5,12 +5,10 @@ import ( "encoding/binary" "errors" "io" - "path" + "path/filepath" "strings" ) -const pathSeparator = "/" // File path separator TODO: make configurable to support Windows - // FilePathItem represents the file or directory portion of a delimited file path (e.g. foo and bar in "/foo/bar") // 00 00 // 09 @@ -84,7 +82,7 @@ func (fp *FilePath) String() string { out = append(out, string(i.Name)) } - return path.Join(out...) + return filepath.Join(out...) } func readPath(fileRoot string, filePath, fileName []byte) (fullPath string, err error) { @@ -95,11 +93,11 @@ func readPath(fileRoot string, filePath, fileName []byte) (fullPath string, err } } - fullPath = path.Join( + fullPath = filepath.Join( "/", fileRoot, fp.String(), - path.Join("/", string(fileName)), + filepath.Join("/", string(fileName)), ) return fullPath, nil diff --git a/hotline/file_transfer.go b/hotline/file_transfer.go index 4a93390..90dbbe6 100644 --- a/hotline/file_transfer.go +++ b/hotline/file_transfer.go @@ -3,7 +3,7 @@ package hotline import ( "encoding/binary" "fmt" - "strings" + "path/filepath" ) // File transfer types @@ -51,11 +51,12 @@ func (fu *folderUpload) FormattedPath() string { var pathSegments []string pathData := fu.FileNamePath + // TODO: implement scanner interface instead? for i := uint16(0); i < pathItemLen; i++ { segLen := pathData[2] pathSegments = append(pathSegments, string(pathData[3:3+segLen])) pathData = pathData[3+segLen:] } - return strings.Join(pathSegments, pathSeparator) + return filepath.Join(pathSegments...) } diff --git a/hotline/file_types.go b/hotline/file_types.go index 2162323..40b8374 100644 --- a/hotline/file_types.go +++ b/hotline/file_types.go @@ -11,51 +11,55 @@ var defaultFileType = fileType{ } var fileTypes = map[string]fileType{ - "sit": { + ".sit": { TypeCode: "SIT!", CreatorCode: "SIT!", }, - "pdf": { + ".pdf": { TypeCode: "PDF ", CreatorCode: "CARO", }, - "gif": { + ".gif": { TypeCode: "GIFf", CreatorCode: "ogle", }, - "txt": { + ".txt": { TypeCode: "TEXT", CreatorCode: "ttxt", }, - "zip": { + ".zip": { TypeCode: "ZIP ", CreatorCode: "SITx", }, - "tgz": { + ".tgz": { TypeCode: "Gzip", CreatorCode: "SITx", }, - "hqx": { + ".hqx": { TypeCode: "TEXT", CreatorCode: "SITx", }, - "jpg": { + ".jpg": { TypeCode: "JPEG", CreatorCode: "ogle", }, - "img": { + ".jpeg": { + TypeCode: "JPEG", + CreatorCode: "ogle", + }, + ".img": { TypeCode: "rohd", CreatorCode: "ddsk", }, - "sea": { + ".sea": { TypeCode: "APPL", CreatorCode: "aust", }, - "mov": { + ".mov": { TypeCode: "MooV", CreatorCode: "TVOD", }, - "incomplete": { // Partial file upload + ".incomplete": { // Partial file upload TypeCode: "HTft", CreatorCode: "HTLC", }, diff --git a/hotline/file_wrapper.go b/hotline/file_wrapper.go index 3773e79..2ad76f4 100644 --- a/hotline/file_wrapper.go +++ b/hotline/file_wrapper.go @@ -8,13 +8,13 @@ import ( "io/fs" "os" "path" - "strings" + "path/filepath" ) const ( incompleteFileSuffix = ".incomplete" - infoForkNameTemplate = "%s.info_%s" // template string for info fork filenames - rsrcForkNameTemplate = "%s.rsrc_%s" // template string for resource fork filenames + infoForkNameTemplate = ".info_%s" // template string for info fork filenames + rsrcForkNameTemplate = ".rsrc_%s" // template string for resource fork filenames ) // fileWrapper encapsulates the data, info, and resource forks of a Hotline file and provides methods to manage the files. @@ -33,18 +33,17 @@ type fileWrapper struct { } func newFileWrapper(fs FileStore, path string, dataOffset int64) (*fileWrapper, error) { - pathSegs := strings.Split(path, pathSeparator) - dir := strings.Join(pathSegs[:len(pathSegs)-1], pathSeparator) - fName := pathSegs[len(pathSegs)-1] + dir := filepath.Dir(path) + fName := filepath.Base(path) f := fileWrapper{ fs: fs, name: fName, path: dir, dataPath: path, dataOffset: dataOffset, - rsrcPath: fmt.Sprintf(rsrcForkNameTemplate, dir+"/", fName), - infoPath: fmt.Sprintf(infoForkNameTemplate, dir+"/", fName), - incompletePath: dir + "/" + fName + incompleteFileSuffix, + rsrcPath: filepath.Join(dir, fmt.Sprintf(rsrcForkNameTemplate, fName)), + infoPath: filepath.Join(dir, fmt.Sprintf(infoForkNameTemplate, fName)), + incompletePath: filepath.Join(dir, fName+incompleteFileSuffix), ffo: &flattenedFileObject{}, } @@ -100,11 +99,11 @@ func (f *fileWrapper) incompleteDataName() string { } func (f *fileWrapper) rsrcForkName() string { - return fmt.Sprintf(rsrcForkNameTemplate, "", f.name) + return fmt.Sprintf(rsrcForkNameTemplate, f.name) } func (f *fileWrapper) infoForkName() string { - return fmt.Sprintf(infoForkNameTemplate, "", f.name) + return fmt.Sprintf(infoForkNameTemplate, f.name) } func (f *fileWrapper) creatorCode() []byte { diff --git a/hotline/files.go b/hotline/files.go index b66580f..dc19653 100644 --- a/hotline/files.go +++ b/hotline/files.go @@ -10,17 +10,9 @@ import ( "strings" ) -func downcaseFileExtension(filename string) string { - splitStr := strings.Split(filename, ".") - ext := strings.ToLower( - splitStr[len(splitStr)-1], - ) - - return ext -} - -func fileTypeFromFilename(fn string) fileType { - ft, ok := fileTypes[downcaseFileExtension(fn)] +func fileTypeFromFilename(filename string) fileType { + fileExt := strings.ToLower(filepath.Ext(filename)) + ft, ok := fileTypes[fileExt] if ok { return ft } @@ -38,8 +30,8 @@ func fileTypeFromInfo(info fs.FileInfo) (ft fileType, err error) { return ft, nil } -func getFileNameList(filePath string) (fields []Field, err error) { - files, err := os.ReadDir(filePath) +func getFileNameList(path string) (fields []Field, err error) { + files, err := os.ReadDir(path) if err != nil { return fields, nil } @@ -59,12 +51,12 @@ func getFileNameList(filePath string) (fields []Field, err error) { } if fileInfo.Mode()&os.ModeSymlink != 0 { - resolvedPath, err := os.Readlink(filePath + "/" + file.Name()) + resolvedPath, err := os.Readlink(filepath.Join(path, file.Name())) if err != nil { return fields, err } - rFile, err := os.Stat(filePath + "/" + resolvedPath) + rFile, err := os.Stat(filepath.Join(path, resolvedPath)) if errors.Is(err, os.ErrNotExist) { continue } @@ -73,7 +65,7 @@ func getFileNameList(filePath string) (fields []Field, err error) { } if rFile.IsDir() { - dir, err := ioutil.ReadDir(filePath + "/" + file.Name()) + dir, err := ioutil.ReadDir(filepath.Join(path, file.Name())) if err != nil { return fields, err } @@ -95,7 +87,7 @@ func getFileNameList(filePath string) (fields []Field, err error) { } } else if file.IsDir() { - dir, err := ioutil.ReadDir(filePath + "/" + file.Name()) + dir, err := ioutil.ReadDir(filepath.Join(path, file.Name())) if err != nil { return fields, err } @@ -116,7 +108,7 @@ func getFileNameList(filePath string) (fields []Field, err error) { continue } - hlFile, err := newFileWrapper(&OSFileStore{}, filePath+"/"+file.Name(), 0) + hlFile, err := newFileWrapper(&OSFileStore{}, path+"/"+file.Name(), 0) if err != nil { return nil, err } diff --git a/hotline/server.go b/hotline/server.go index 9df89f2..9ffd272 100644 --- a/hotline/server.go +++ b/hotline/server.go @@ -17,7 +17,6 @@ import ( "math/rand" "net" "os" - "path" "path/filepath" "runtime/debug" "strings" @@ -227,28 +226,28 @@ func NewServer(configDir string, netPort int, logger *zap.SugaredLogger, FS File return nil, err } - server.Agreement, err = os.ReadFile(configDir + agreementFile) + server.Agreement, err = os.ReadFile(filepath.Join(configDir, agreementFile)) if err != nil { return nil, err } - if server.FlatNews, err = os.ReadFile(configDir + "MessageBoard.txt"); err != nil { + if server.FlatNews, err = os.ReadFile(filepath.Join(configDir, "MessageBoard.txt")); err != nil { return nil, err } - if err := server.loadThreadedNews(configDir + "ThreadedNews.yaml"); err != nil { + if err := server.loadThreadedNews(filepath.Join(configDir, "ThreadedNews.yaml")); err != nil { return nil, err } - if err := server.loadConfig(configDir + "config.yaml"); err != nil { + if err := server.loadConfig(filepath.Join(configDir, "config.yaml")); err != nil { return nil, err } - if err := server.loadAccounts(configDir + "Users/"); err != nil { + if err := server.loadAccounts(filepath.Join(configDir, "Users/")); err != nil { return nil, err } - server.Config.FileRoot = configDir + "Files/" + server.Config.FileRoot = filepath.Join(configDir, "Files") *server.NextGuestID = 1 @@ -329,7 +328,7 @@ func (s *Server) writeThreadedNews() error { return err } err = ioutil.WriteFile( - s.ConfigDir+"ThreadedNews.yaml", + filepath.Join(s.ConfigDir, "ThreadedNews.yaml"), out, 0666, ) @@ -379,7 +378,7 @@ func (s *Server) NewUser(login, name, password string, access []byte) error { } s.Accounts[login] = &account - return s.FS.WriteFile(s.ConfigDir+"Users/"+login+".yaml", out, 0666) + return s.FS.WriteFile(filepath.Join(s.ConfigDir, "Users", login+".yaml"), out, 0666) } func (s *Server) UpdateUser(login, newLogin, name, password string, access []byte) error { @@ -388,7 +387,7 @@ func (s *Server) UpdateUser(login, newLogin, name, password string, access []byt // update renames the user login if login != newLogin { - err := os.Rename(s.ConfigDir+"Users/"+login+".yaml", s.ConfigDir+"Users/"+newLogin+".yaml") + err := os.Rename(filepath.Join(s.ConfigDir, "Users", login+".yaml"), filepath.Join(s.ConfigDir, "Users", newLogin+".yaml")) if err != nil { return err } @@ -405,7 +404,8 @@ func (s *Server) UpdateUser(login, newLogin, name, password string, access []byt if err != nil { return err } - if err := os.WriteFile(s.ConfigDir+"Users/"+newLogin+".yaml", out, 0666); err != nil { + + if err := os.WriteFile(filepath.Join(s.ConfigDir, "Users", newLogin+".yaml"), out, 0666); err != nil { return err } @@ -419,7 +419,7 @@ func (s *Server) DeleteUser(login string) error { delete(s.Accounts, login) - return s.FS.Remove(s.ConfigDir + "Users/" + login + ".yaml") + return s.FS.Remove(filepath.Join(s.ConfigDir, "Users", login+".yaml")) } func (s *Server) connectedUsers() []Field { @@ -455,7 +455,7 @@ func (s *Server) loadThreadedNews(threadedNewsPath string) error { // loadAccounts loads account data from disk func (s *Server) loadAccounts(userDir string) error { - matches, err := filepath.Glob(path.Join(userDir, "*.yaml")) + matches, err := filepath.Glob(filepath.Join(userDir, "*.yaml")) if err != nil { return err } @@ -1059,8 +1059,8 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro ) if fu.IsFolder == [2]byte{0, 1} { - if _, err := os.Stat(dstPath + "/" + fu.FormattedPath()); os.IsNotExist(err) { - if err := os.Mkdir(dstPath+"/"+fu.FormattedPath(), 0777); err != nil { + if _, err := os.Stat(filepath.Join(dstPath, fu.FormattedPath())); os.IsNotExist(err) { + if err := os.Mkdir(filepath.Join(dstPath, fu.FormattedPath()), 0777); err != nil { return err } } @@ -1073,7 +1073,7 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro nextAction := dlFldrActionSendFile // Check if we have the full file already. If so, send dlFldrAction_NextFile to client to skip. - _, err = os.Stat(dstPath + "/" + fu.FormattedPath()) + _, err = os.Stat(filepath.Join(dstPath, fu.FormattedPath())) if err != nil && !errors.Is(err, fs.ErrNotExist) { return err } @@ -1082,7 +1082,7 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro } // Check if we have a partial file already. If so, send dlFldrAction_ResumeFile to client to resume upload. - incompleteFile, err := os.Stat(dstPath + "/" + fu.FormattedPath() + incompleteFileSuffix) + incompleteFile, err := os.Stat(filepath.Join(dstPath, fu.FormattedPath()+incompleteFileSuffix)) if err != nil && !errors.Is(err, fs.ErrNotExist) { return err } @@ -1135,7 +1135,7 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro return err } - filePath := dstPath + "/" + fu.FormattedPath() + filePath := filepath.Join(dstPath, fu.FormattedPath()) hlFile, err := newFileWrapper(s.FS, filePath, 0) if err != nil { diff --git a/hotline/transaction_handlers_test.go b/hotline/transaction_handlers_test.go index ebb4a95..0e2c949 100644 --- a/hotline/transaction_handlers_test.go +++ b/hotline/transaction_handlers_test.go @@ -7,6 +7,7 @@ import ( "io/fs" "math/rand" "os" + "path/filepath" "strings" "testing" "time" @@ -630,7 +631,7 @@ func TestHandleGetFileInfo(t *testing.T) { Config: &Config{ FileRoot: func() string { path, _ := os.Getwd() - return path + "/test/config/Files" + return filepath.Join(path, "/test/config/Files") }(), }, },