2025-07-27 14:26:30 +00:00
|
|
|
|
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!",
|
2025-07-27 15:57:23 +00:00
|
|
|
|
PublicHost: "media.canguidev.fr",
|
2025-07-27 14:26:30 +00:00
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
func (d *ftpMainDriver) ClientConnected(cc ftpserverlib.ClientContext) (string, error) {
|
2025-07-27 15:32:50 +00:00
|
|
|
|
return "Bienvenue ! utilisateur FTP : cangui / GHT30k7!", nil
|
2025-07-27 14:26:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2025-07-27 15:32:50 +00:00
|
|
|
|
log.Printf("[FTP] Tentative login user='%s' pass='%s'", user, pass)
|
|
|
|
|
|
|
2025-07-27 15:42:13 +00:00
|
|
|
|
if user == "cangui2089" {
|
2025-07-27 14:26:30 +00:00
|
|
|
|
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")
|
2025-07-27 14:33:19 +00:00
|
|
|
|
app.Run(":8080")
|
2025-07-27 14:26:30 +00:00
|
|
|
|
}
|