Browse Source

try to automatically find shared data dirs in system-wide paths

Signed-off-by: Nicola Murino <[email protected]>
Nicola Murino 3 years ago
parent
commit
80da2dc722
16 changed files with 63 additions and 53 deletions
  1. 0 5
      Dockerfile
  2. 0 5
      Dockerfile.alpine
  3. 0 5
      Dockerfile.distroless
  4. 3 4
      docs/howto/lets-encrypt-certificate.md
  5. 0 3
      docs/service.md
  6. 1 1
      ftpd/ftpd_test.go
  7. 1 1
      ftpd/handler.go
  8. 4 4
      go.mod
  9. 6 14
      go.sum
  10. 3 3
      httpd/httpd.go
  11. 0 3
      pkgs/build.sh
  12. 2 5
      smtp/smtp.go
  13. 26 0
      util/util.go
  14. 6 0
      vfs/osfs.go
  15. 4 0
      vfs/sys_unix.go
  16. 7 0
      vfs/sys_windows.go

+ 0 - 5
Dockerfile

@@ -47,11 +47,6 @@ COPY --from=builder /workspace/sftpgo /usr/local/bin/
 
 # Log to the stdout so the logs will be available using docker logs
 ENV SFTPGO_LOG_FILE_PATH=""
-# templates and static paths are inside the container
-ENV SFTPGO_HTTPD__TEMPLATES_PATH=/usr/share/sftpgo/templates
-ENV SFTPGO_SMTP__TEMPLATES_PATH=/usr/share/sftpgo/templates
-ENV SFTPGO_HTTPD__STATIC_FILES_PATH=/usr/share/sftpgo/static
-ENV SFTPGO_HTTPD__OPENAPI_PATH=/usr/share/sftpgo/openapi
 
 # Modify the default configuration file
 RUN sed -i 's|"users_base_dir": "",|"users_base_dir": "/srv/sftpgo/data",|' /etc/sftpgo/sftpgo.json && \

+ 0 - 5
Dockerfile.alpine

@@ -52,11 +52,6 @@ COPY --from=builder /workspace/sftpgo /usr/local/bin/
 
 # Log to the stdout so the logs will be available using docker logs
 ENV SFTPGO_LOG_FILE_PATH=""
-# templates and static paths are inside the container
-ENV SFTPGO_HTTPD__TEMPLATES_PATH=/usr/share/sftpgo/templates
-ENV SFTPGO_SMTP__TEMPLATES_PATH=/usr/share/sftpgo/templates
-ENV SFTPGO_HTTPD__STATIC_FILES_PATH=/usr/share/sftpgo/static
-ENV SFTPGO_HTTPD__OPENAPI_PATH=/usr/share/sftpgo/openapi
 
 # Modify the default configuration file
 RUN sed -i 's|"users_base_dir": "",|"users_base_dir": "/srv/sftpgo/data",|' /etc/sftpgo/sftpgo.json && \

+ 0 - 5
Dockerfile.distroless

@@ -46,11 +46,6 @@ COPY --from=builder /etc/mime.types /etc/mime.types
 
 # Log to the stdout so the logs will be available using docker logs
 ENV SFTPGO_LOG_FILE_PATH=""
-# templates and static paths are inside the container
-ENV SFTPGO_HTTPD__TEMPLATES_PATH=/usr/share/sftpgo/templates
-ENV SFTPGO_SMTP__TEMPLATES_PATH=/usr/share/sftpgo/templates
-ENV SFTPGO_HTTPD__STATIC_FILES_PATH=/usr/share/sftpgo/static
-ENV SFTPGO_HTTPD__OPENAPI_PATH=/usr/share/sftpgo/openapi
 # These env vars are required to avoid the following error when calling user.Current():
 # unable to get the current user: user: Current requires cgo or $USER set in environment
 ENV USER=sftpgo

+ 3 - 4
docs/howto/lets-encrypt-certificate.md

@@ -74,10 +74,9 @@ Open the SFTPGo configuration file, search for the `httpd` section and change it
         "render_openapi": true
       }
     ],
-    "templates_path": "/usr/share/sftpgo/templates",
-    "static_files_path": "/usr/share/sftpgo/static",
-    "backups_path": "/srv/sftpgo/backups",
-    "openapi_path": "/srv/sftpgo/openapi",
+    "templates_path": "templates",
+    "static_files_path": "static",
+    "openapi_path": "openapi",
     "web_root": "",
     "certificate_file": "/etc/sftpgo/certs/sftpgo.com.crt",
     "certificate_key_file": "/etc/sftpgo/certs/sftpgo.com.key",

+ 0 - 3
docs/service.md

@@ -36,9 +36,6 @@ sudo install -Dm755 sftpgo /usr/bin/sftpgo
 # install the default configuration file, edit it if required
 sudo install -Dm644 sftpgo.json /etc/sftpgo/
 # override some configuration keys using environment variables
-sudo sh -c 'echo "SFTPGO_HTTPD__TEMPLATES_PATH=/usr/share/sftpgo/templates" > /etc/sftpgo/sftpgo.env'
-sudo sh -c 'echo "SFTPGO_HTTPD__STATIC_FILES_PATH=/usr/share/sftpgo/static" >> /etc/sftpgo/sftpgo.env'
-sudo sh -c 'echo "SFTPGO_HTTPD__OPENAPI_PATH=/usr/share/sftpgo/openapi" >> /etc/sftpgo/sftpgo.env'
 sudo sh -c 'echo "SFTPGO_HTTPD__BACKUPS_PATH=/var/lib/sftpgo/backups" >> /etc/sftpgo/sftpgo.env'
 sudo sh -c 'echo "SFTPGO_DATA_PROVIDER__CREDENTIALS_PATH=/var/lib/sftpgo/credentials" >> /etc/sftpgo/sftpgo.env'
 # if you use a file based data provider such as sqlite or bolt consider to set the database path too, for example:

+ 1 - 1
ftpd/ftpd_test.go

@@ -611,7 +611,7 @@ func TestListDirWithWildcards(t *testing.T) {
 			testFileSize := int64(65535)
 			err = createTestFile(testFilePath, testFileSize)
 			assert.NoError(t, err)
-			fileName := "fil*e.dat"
+			fileName := "file[a-z]e.dat"
 			err = ftpUploadFile(testFilePath, fileName, testFileSize, client, 0)
 			assert.NoError(t, err)
 			localDownloadPath := filepath.Join(homeBasePath, testDLFileName)

+ 1 - 1
ftpd/handler.go

@@ -147,7 +147,7 @@ func (c *Connection) Stat(name string) (os.FileInfo, error) {
 
 	fi, err := c.DoStat(name, 0, true)
 	if err != nil {
-		if c.isListDirWithWildcards(path.Base(name), err) {
+		if c.isListDirWithWildcards(path.Base(name), os.ErrNotExist) {
 			return vfs.NewFileInfo(name, true, 0, time.Now(), false), nil
 		}
 		return nil, err

+ 4 - 4
go.mod

@@ -31,11 +31,11 @@ require (
 	github.com/google/uuid v1.3.0
 	github.com/grandcat/zeroconf v1.0.0
 	github.com/hashicorp/go-hclog v1.2.0
-	github.com/hashicorp/go-plugin v1.4.3
+	github.com/hashicorp/go-plugin v1.4.4
 	github.com/hashicorp/go-retryablehttp v0.7.1
 	github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
 	github.com/klauspost/compress v1.15.2
-	github.com/lestrrat-go/jwx v1.2.23
+	github.com/lestrrat-go/jwx v1.2.24
 	github.com/lib/pq v1.10.5
 	github.com/lithammer/shortuuid/v3 v3.0.7
 	github.com/mattn/go-sqlite3 v1.14.12
@@ -64,7 +64,7 @@ require (
 	go.etcd.io/bbolt v1.3.6
 	go.uber.org/automaxprocs v1.5.1
 	gocloud.dev v0.25.0
-	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
+	golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f
 	golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
 	golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
 	golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6
@@ -163,6 +163,6 @@ require (
 
 replace (
 	github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9
-	golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20220412172350-e76a61f8e7d2
+	golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20220505051548-eb52ab1741ed
 	golang.org/x/net => github.com/drakkan/net v0.0.0-20220504073018-5d1702f4106f
 )

+ 6 - 14
go.sum

@@ -251,8 +251,8 @@ github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/
 github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
 github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
 github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
-github.com/drakkan/crypto v0.0.0-20220412172350-e76a61f8e7d2 h1:5XmEywX1u5gPgOC+MJuTwLtjMd6gC6t40W+dBgbriSE=
-github.com/drakkan/crypto v0.0.0-20220412172350-e76a61f8e7d2/go.mod h1:SiM6ypd8Xu1xldObYtbDztuUU7xUzMnUULfphXFZmro=
+github.com/drakkan/crypto v0.0.0-20220505051548-eb52ab1741ed h1:08cqWe9aKRNPpH5nfTyAVoitSif6pvXbGa9v3+PDAzI=
+github.com/drakkan/crypto v0.0.0-20220505051548-eb52ab1741ed/go.mod h1:SiM6ypd8Xu1xldObYtbDztuUU7xUzMnUULfphXFZmro=
 github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9 h1:LPH1dEblAOO/LoG7yHPMtBLXhQmjaga91/DDjWk9jWA=
 github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9/go.mod h1:2lmrmq866uF2tnje75wQHzmPXhmSWUt7Gyx2vgK1RCU=
 github.com/drakkan/net v0.0.0-20220504073018-5d1702f4106f h1:BUIQ/l47ZPdruH1S17AdCCq6YNR/DyLpvysRXikD/Xg=
@@ -323,7 +323,6 @@ github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22
 github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
 github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
 github.com/goccy/go-json v0.7.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM=
 github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -446,18 +445,16 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
 github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
-github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
 github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
 github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-plugin v1.4.3 h1:DXmvivbWD5qdiBts9TpBC7BYL1Aia5sxbRgQB+v6UZM=
-github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
+github.com/hashicorp/go-plugin v1.4.4 h1:NVdrSdFRt3SkZtNckJ6tog7gbpRrcbOjQi/rgF7JYWQ=
+github.com/hashicorp/go-plugin v1.4.4/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
 github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ=
 github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
 github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I=
 github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -518,7 +515,6 @@ github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dv
 github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
-github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -575,8 +571,8 @@ github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbq
 github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
 github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
 github.com/lestrrat-go/jwx v1.2.6/go.mod h1:tJuGuAI3LC71IicTx82Mz1n3w9woAs2bYJZpkjJQ5aU=
-github.com/lestrrat-go/jwx v1.2.23 h1:8oP5fY1yzCRraUNNyfAVdOkLCqY7xMZz11lVcvHqC1Y=
-github.com/lestrrat-go/jwx v1.2.23/go.mod h1:sAXjRwzSvCN6soO4RLoWWm1bVPpb8iOuv0IYfH8OWd8=
+github.com/lestrrat-go/jwx v1.2.24 h1:N6Qsn6TUsDzz+qgS/1xcfBtkQfnbwW01fLFJpuYgKsg=
+github.com/lestrrat-go/jwx v1.2.24/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY=
 github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
 github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@@ -627,7 +623,6 @@ github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy
 github.com/minio/sio v0.3.0 h1:syEFBewzOMOYVzSTFpp1MqpSZk8rUNbz8VIIc+PNzus=
 github.com/minio/sio v0.3.0/go.mod h1:8b0yPp2avGThviy/+OCJBI6OMpvxoUuiLvE6F1lebhw=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
 github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
 github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@@ -642,7 +637,6 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
 github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
 github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
 github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
 github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=
@@ -1114,7 +1108,6 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
 google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
 google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1209,7 +1202,6 @@ google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX
 google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/genproto v0.0.0-20220504150022-98cd25cafc72 h1:iif0mpUetMBqcQPUoq+JnCcmzvfpp8wRx515va8wP1c=
 google.golang.org/genproto v0.0.0-20220504150022-98cd25cafc72/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=

+ 3 - 3
httpd/httpd.go

@@ -593,9 +593,9 @@ func (c *Conf) getRedacted() Conf {
 // Initialize configures and starts the HTTP server
 func (c *Conf) Initialize(configDir string) error {
 	logger.Info(logSender, "", "initializing HTTP server with config %+v", c.getRedacted())
-	staticFilesPath := getConfigPath(c.StaticFilesPath, configDir)
-	templatesPath := getConfigPath(c.TemplatesPath, configDir)
-	openAPIPath := getConfigPath(c.OpenAPIPath, configDir)
+	staticFilesPath := util.FindSharedDataPath(c.StaticFilesPath, configDir)
+	templatesPath := util.FindSharedDataPath(c.TemplatesPath, configDir)
+	openAPIPath := util.FindSharedDataPath(c.OpenAPIPath, configDir)
 	if err := c.checkRequiredDirs(staticFilesPath, templatesPath); err != nil {
 		return err
 	}

+ 0 - 3
pkgs/build.sh

@@ -39,10 +39,7 @@ fi
 cp ${BASE_DIR}/sftpgo.json .
 sed -i "s|sftpgo.db|/var/lib/sftpgo/sftpgo.db|" sftpgo.json
 sed -i "s|\"users_base_dir\": \"\",|\"users_base_dir\": \"/srv/sftpgo/data\",|" sftpgo.json
-sed -i "s|\"templates\"|\"/usr/share/sftpgo/templates\"|" sftpgo.json
-sed -i "s|\"static\"|\"/usr/share/sftpgo/static\"|" sftpgo.json
 sed -i "s|\"backups\"|\"/srv/sftpgo/backups\"|" sftpgo.json
-sed -i "s|\"openapi\"|\"/usr/share/sftpgo/openapi\"|" sftpgo.json
 sed -i "s|\"credentials\"|\"/var/lib/sftpgo/credentials\"|" sftpgo.json
 
 cat >nfpm.yaml <<EOF

+ 2 - 5
smtp/smtp.go

@@ -91,13 +91,10 @@ func (c *Config) Initialize(configDir string) error {
 	if c.Encryption < 0 || c.Encryption > 2 {
 		return fmt.Errorf("smtp: invalid encryption %v", c.Encryption)
 	}
-	templatesPath := c.TemplatesPath
-	if templatesPath == "" || !util.IsFileInputValid(templatesPath) {
+	templatesPath := util.FindSharedDataPath(c.TemplatesPath, configDir)
+	if templatesPath == "" {
 		return fmt.Errorf("smtp: invalid templates path %#v", templatesPath)
 	}
-	if !filepath.IsAbs(templatesPath) {
-		templatesPath = filepath.Join(configDir, templatesPath)
-	}
 	loadTemplates(filepath.Join(templatesPath, templateEmailDir))
 	from = c.From
 	smtpServer = mail.NewSMTPClient()

+ 26 - 0
util/util.go

@@ -346,6 +346,32 @@ func IsFileInputValid(fileInput string) bool {
 	return true
 }
 
+// FindSharedDataPath searches for the specified directory name in searchDir
+// and in system-wide shared data directories.
+// If name is an absolute path it is returned unmodified.
+func FindSharedDataPath(name, searchDir string) string {
+	if !IsFileInputValid(name) {
+		return ""
+	}
+	if name != "" && !filepath.IsAbs(name) {
+		searchList := []string{searchDir}
+		if runtime.GOOS != osWindows {
+			searchList = append(searchList, "/usr/share/sftpgo")
+			searchList = append(searchList, "/usr/local/share/sftpgo")
+		}
+		for _, basePath := range searchList {
+			res := filepath.Join(basePath, name)
+			_, err := os.Stat(res)
+			if err == nil {
+				logger.Debug(logSender, "", "found share data path for name %#v: %#v", name, res)
+				return res
+			}
+		}
+		return filepath.Join(searchDir, name)
+	}
+	return name
+}
+
 // CleanDirInput sanitizes user input for directories.
 // On Windows it removes any trailing `"`.
 // We try to help windows users that set an invalid path such as "C:\ProgramData\SFTPGO\".

+ 6 - 0
vfs/osfs.go

@@ -174,6 +174,9 @@ func (*OsFs) Truncate(name string, size int64) error {
 func (*OsFs) ReadDir(dirname string) ([]os.FileInfo, error) {
 	f, err := os.Open(dirname)
 	if err != nil {
+		if isInvalidNameError(err) {
+			err = os.ErrNotExist
+		}
 		return nil, err
 	}
 	list, err := f.Readdir(-1)
@@ -291,6 +294,9 @@ func (fs *OsFs) ResolvePath(virtualPath string) (string, error) {
 	}
 	r := filepath.Clean(filepath.Join(fs.rootDir, virtualPath))
 	p, err := filepath.EvalSymlinks(r)
+	if isInvalidNameError(err) {
+		err = os.ErrNotExist
+	}
 	if err != nil && !os.IsNotExist(err) {
 		return "", err
 	} else if os.IsNotExist(err) {

+ 4 - 0
vfs/sys_unix.go

@@ -12,3 +12,7 @@ import (
 func isCrossDeviceError(err error) bool {
 	return errors.Is(err, unix.EXDEV)
 }
+
+func isInvalidNameError(err error) bool {
+	return false
+}

+ 7 - 0
vfs/sys_windows.go

@@ -9,3 +9,10 @@ import (
 func isCrossDeviceError(err error) bool {
 	return errors.Is(err, windows.ERROR_NOT_SAME_DEVICE)
 }
+
+func isInvalidNameError(err error) bool {
+	if err == nil {
+		return false
+	}
+	return errors.Is(err, windows.ERROR_INVALID_NAME)
+}