package main import ( "canguidev/shelfy/internal/db" "canguidev/shelfy/internal/routes" "canguidev/shelfy/internal/utils" "crypto/tls" "errors" "log" "os" "path/filepath" "strings" "time" ftpserverlib "github.com/fclairamb/ftpserverlib" "github.com/gin-gonic/gin" "github.com/spf13/afero" ) // ------------ FTP DRIVER ------------ type ftpMainDriver struct{} type ftpClientDriver struct { fs afero.Fs } func (d *ftpMainDriver) GetSettings() (*ftpserverlib.Settings, error) { return &ftpserverlib.Settings{ ListenAddr: ":2121", IdleTimeout: 300, ConnectionTimeout: 60, Banner: "Bienvenue sur le FTP Go!", }, nil } func (d *ftpMainDriver) ClientConnected(cc ftpserverlib.ClientContext) (string, error) { return "Bienvenue ! utilisateur FTP : cangui / GHT30k7", nil } func (d *ftpMainDriver) ClientDisconnected(cc ftpserverlib.ClientContext) {} func (d *ftpMainDriver) GetTLSConfig() (*tls.Config, error) { return nil, nil } func (d *ftpMainDriver) AuthUser(cc ftpserverlib.ClientContext, user, pass string) (ftpserverlib.ClientDriver, error) { if user == "cangui" && pass == "GHT30k7!" { os.MkdirAll("upload", 0755) base := filepath.Clean("upload") fs := afero.NewBasePathFs(afero.NewOsFs(), base) return &ftpClientDriver{fs: fs}, nil } return nil, errors.New("invalid login")} func (c *ftpClientDriver) Name() string { return "aferofs" } func (c *ftpClientDriver) Create(name string) (afero.File, error) { return c.fs.Create(name) } func (c *ftpClientDriver) Mkdir(name string, perm os.FileMode) error { return c.fs.Mkdir(name, perm) } func (c *ftpClientDriver) MkdirAll(path string, perm os.FileMode) error { return c.fs.MkdirAll(path, perm) } func (c *ftpClientDriver) Open(name string) (afero.File, error) { return c.fs.Open(name) } func (c *ftpClientDriver) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) { return c.fs.OpenFile(name, flag, perm) } func (c *ftpClientDriver) Remove(name string) error { return c.fs.Remove(name) } func (c *ftpClientDriver) RemoveAll(path string) error { return c.fs.RemoveAll(path) } func (c *ftpClientDriver) Rename(old, new string) error { return c.fs.Rename(old, new) } func (c *ftpClientDriver) Stat(name string) (os.FileInfo, error) { return c.fs.Stat(name) } func (c *ftpClientDriver) LstatIfPossible(name string) (os.FileInfo, bool, error) { fi, err := c.fs.Stat(name) return fi, false, err } // Implémentation Chmod pour FTP (utilise l'OS direct, ou ignore si non supporté) func (c *ftpClientDriver) Chmod(name string, mode os.FileMode) error { // Essayons d'utiliser OsFs (car BasePathFs ne l'exporte pas) fullPath := filepath.Join("upload", name) return os.Chmod(fullPath, mode) } // Implémentation Chown pour FTP (non supportée en général) func (c *ftpClientDriver) Chown(name string, uid, gid int) error { // Optionnel, non supporté par OsFs sur Windows/Mac return nil } // Implémentation Chtimes pour FTP (utilise l'OS direct) func (c *ftpClientDriver) Chtimes(name string, atime, mtime time.Time) error { fullPath := filepath.Join("upload", name) return os.Chtimes(fullPath, atime, mtime) } // ------------ MAIN ------------ func main() { go func() { ftpSrv := ftpserverlib.NewFtpServer(&ftpMainDriver{}) log.Println("[FTP] Serveur FTP sur ftp://test:test@localhost:2121 (upload/)") if err := ftpSrv.ListenAndServe(); err != nil { log.Fatal("[FTP] Erreur FTP :", err) } }() // Serveur HTTP Gin bd := db.InitDB() app := gin.Default() api := app.Group("/api/v1") routes.AddRoutes(api, bd) utils.CreateDefaultFolder(bd) app.Static("/static", "./web") app.NoRoute(func(c *gin.Context) { if strings.HasPrefix(c.Request.URL.Path, "/api/") { c.JSON(404, gin.H{"error": "Not found"}) return } c.File("./web/index.html") }) log.Println("[HTTP] Serveur Gin sur http://localhost:8080") app.Run(":8080") }