WebClient: make folder deletion recursive
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
222f0c735b
commit
6f422c3d8b
10 changed files with 453 additions and 364 deletions
67
go.mod
67
go.mod
|
@ -8,15 +8,15 @@ require (
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1
|
||||||
github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962
|
github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962
|
||||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
||||||
github.com/aws/aws-sdk-go-v2 v1.17.0
|
github.com/aws/aws-sdk-go-v2 v1.17.1
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.17.9
|
github.com/aws/aws-sdk-go-v2/config v1.17.10
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.22
|
github.com/aws/aws-sdk-go-v2/credentials v1.12.23
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.18
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19
|
||||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.36
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.37
|
||||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.20
|
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.21
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.0
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.1
|
||||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.3
|
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.4
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.0
|
github.com/aws/aws-sdk-go-v2/service/sts v1.17.1
|
||||||
github.com/cockroachdb/cockroach-go/v2 v2.2.16
|
github.com/cockroachdb/cockroach-go/v2 v2.2.16
|
||||||
github.com/coreos/go-oidc/v3 v3.4.0
|
github.com/coreos/go-oidc/v3 v3.4.0
|
||||||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
|
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
|
||||||
|
@ -34,12 +34,12 @@ require (
|
||||||
github.com/hashicorp/go-hclog v1.3.1
|
github.com/hashicorp/go-hclog v1.3.1
|
||||||
github.com/hashicorp/go-plugin v1.4.5
|
github.com/hashicorp/go-plugin v1.4.5
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.1
|
github.com/hashicorp/go-retryablehttp v0.7.1
|
||||||
github.com/jackc/pgx/v5 v5.0.4-0.20221022150232-3e825ec8982f
|
github.com/jackc/pgx/v5 v5.0.4
|
||||||
github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
|
github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
|
||||||
github.com/klauspost/compress v1.15.11
|
github.com/klauspost/compress v1.15.12
|
||||||
github.com/lestrrat-go/jwx v1.2.25
|
github.com/lestrrat-go/jwx v1.2.25
|
||||||
github.com/lithammer/shortuuid/v3 v3.0.7
|
github.com/lithammer/shortuuid/v3 v3.0.7
|
||||||
github.com/mattn/go-sqlite3 v1.14.15
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
github.com/mhale/smtpd v0.8.0
|
github.com/mhale/smtpd v0.8.0
|
||||||
github.com/minio/sio v0.3.0
|
github.com/minio/sio v0.3.0
|
||||||
github.com/otiai10/copy v1.7.0
|
github.com/otiai10/copy v1.7.0
|
||||||
|
@ -54,9 +54,9 @@ require (
|
||||||
github.com/sftpgo/sdk v0.1.2
|
github.com/sftpgo/sdk v0.1.2
|
||||||
github.com/shirou/gopsutil/v3 v3.22.9
|
github.com/shirou/gopsutil/v3 v3.22.9
|
||||||
github.com/spf13/afero v1.9.2
|
github.com/spf13/afero v1.9.2
|
||||||
github.com/spf13/cobra v1.6.0
|
github.com/spf13/cobra v1.6.1
|
||||||
github.com/spf13/viper v1.13.0
|
github.com/spf13/viper v1.13.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.1
|
||||||
github.com/studio-b12/gowebdav v0.0.0-20221015232716-17255f2e7423
|
github.com/studio-b12/gowebdav v0.0.0-20221015232716-17255f2e7423
|
||||||
github.com/subosito/gotenv v1.4.1
|
github.com/subosito/gotenv v1.4.1
|
||||||
github.com/unrolled/secure v1.13.0
|
github.com/unrolled/secure v1.13.0
|
||||||
|
@ -71,28 +71,29 @@ require (
|
||||||
golang.org/x/oauth2 v0.1.0
|
golang.org/x/oauth2 v0.1.0
|
||||||
golang.org/x/sys v0.1.0
|
golang.org/x/sys v0.1.0
|
||||||
golang.org/x/time v0.1.0
|
golang.org/x/time v0.1.0
|
||||||
google.golang.org/api v0.100.0
|
google.golang.org/api v0.101.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.104.0 // indirect
|
cloud.google.com/go v0.105.0 // indirect
|
||||||
cloud.google.com/go/compute v1.10.0 // indirect
|
cloud.google.com/go/compute v1.12.1 // indirect
|
||||||
cloud.google.com/go/iam v0.5.0 // indirect
|
cloud.google.com/go/compute/metadata v0.1.1 // indirect
|
||||||
|
cloud.google.com/go/iam v0.6.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 // indirect
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.24 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.18 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.25 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.15 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.16 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.10 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.19 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.20 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.18 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.18 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.24 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.7 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 // indirect
|
||||||
github.com/aws/smithy-go v1.13.3 // indirect
|
github.com/aws/smithy-go v1.13.4 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1 // indirect
|
github.com/boombuler/barcode v1.0.1 // indirect
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||||
|
@ -131,7 +132,7 @@ require (
|
||||||
github.com/magiconair/properties v1.8.6 // indirect
|
github.com/magiconair/properties v1.8.6 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/miekg/dns v1.1.50 // indirect
|
github.com/miekg/dns v1.1.50 // indirect
|
||||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||||
|
@ -159,7 +160,7 @@ require (
|
||||||
golang.org/x/tools v0.2.0 // indirect
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 // indirect
|
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 // indirect
|
||||||
google.golang.org/grpc v1.50.1 // indirect
|
google.golang.org/grpc v1.50.1 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
@ -171,5 +172,5 @@ require (
|
||||||
replace (
|
replace (
|
||||||
github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9
|
github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9
|
||||||
golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20221020054403-a265c1cba3cb
|
golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20221020054403-a265c1cba3cb
|
||||||
golang.org/x/net => github.com/drakkan/net v0.0.0-20221020052826-79457e688bf9
|
golang.org/x/net => github.com/drakkan/net v0.0.0-20221026175805-eaebd725b308
|
||||||
)
|
)
|
||||||
|
|
136
go.sum
136
go.sum
|
@ -36,8 +36,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9
|
||||||
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
|
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
|
||||||
cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
|
cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
|
||||||
cloud.google.com/go v0.103.0/go.mod h1:vwLx1nqLrzLX/fpwSMOXmFIqBOyHsvHbnAdbGSJ+mKk=
|
cloud.google.com/go v0.103.0/go.mod h1:vwLx1nqLrzLX/fpwSMOXmFIqBOyHsvHbnAdbGSJ+mKk=
|
||||||
cloud.google.com/go v0.104.0 h1:gSmWO7DY1vOm0MVU6DNXM11BWHHsTUmsC5cv1fuW5X8=
|
cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
|
||||||
cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
|
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
@ -50,16 +50,18 @@ cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6m
|
||||||
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
|
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
|
||||||
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
||||||
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
||||||
cloud.google.com/go/compute v1.10.0 h1:aoLIYaA1fX3ywihqpBk2APQKOo20nXsp1GEZQbx5Jk4=
|
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
|
||||||
cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU=
|
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
|
||||||
|
cloud.google.com/go/compute/metadata v0.1.1 h1:/sxEbyrm6cw+XOUw1YxBHlatV71z4vpnmO7z2IZ0h3I=
|
||||||
|
cloud.google.com/go/compute/metadata v0.1.1/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
|
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
|
||||||
cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c=
|
cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c=
|
||||||
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
||||||
cloud.google.com/go/iam v0.5.0 h1:fz9X5zyTWBmamZsqvqZqD7khbifcZF/q+Z1J8pfhIUg=
|
cloud.google.com/go/iam v0.6.0 h1:nsqQC88kT5Iwlm4MeNGTpfMWddp6NB/UOLFTH6m1QfQ=
|
||||||
cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
|
cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc=
|
||||||
cloud.google.com/go/kms v1.4.0 h1:iElbfoE61VeLhnZcGOltqL8HIly8Nhbe5t6JlH9GXjo=
|
cloud.google.com/go/kms v1.4.0 h1:iElbfoE61VeLhnZcGOltqL8HIly8Nhbe5t6JlH9GXjo=
|
||||||
cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA=
|
cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA=
|
||||||
cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4=
|
cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4=
|
||||||
|
@ -224,70 +226,70 @@ github.com/aws/aws-sdk-go v1.44.45/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4
|
||||||
github.com/aws/aws-sdk-go v1.44.68/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
github.com/aws/aws-sdk-go v1.44.68/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.16.8/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw=
|
github.com/aws/aws-sdk-go-v2 v1.16.8/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.17.0 h1:kWm8OZGx0Zvd6PsOfjFtwbw7+uWYp65DK8suo7WVznw=
|
github.com/aws/aws-sdk-go-v2 v1.17.1 h1:02c72fDJr87N8RAC2s3Qu0YuvMRZKNZJ9F+lAehCazk=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.17.0/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k=
|
github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw=
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.3/go.mod h1:gNsR5CaXKmQSSzrmGxmwmct/r+ZBfbxorAuXYsj/M5Y=
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.3/go.mod h1:gNsR5CaXKmQSSzrmGxmwmct/r+ZBfbxorAuXYsj/M5Y=
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 h1:tcFliCWne+zOuUfKNRn8JdFBuWPDuISDH08wD2ULkhk=
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 h1:RKci2D7tMwpvGpDNZnGQw9wk6v7o/xSwFcUAuNPoB8k=
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8/go.mod h1:JTnlBSot91steJeti4ryyu/tLd4Sk84O5W22L7O2EQU=
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9/go.mod h1:vCmV1q1VK8eoQJ5+aYE7PkK1K6v41qJ5pJdK3ggCDvg=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.15.15/go.mod h1:A1Lzyy/o21I5/s2FbyX5AevQfSVXpvvIDCoVFD0BC4E=
|
github.com/aws/aws-sdk-go-v2/config v1.15.15/go.mod h1:A1Lzyy/o21I5/s2FbyX5AevQfSVXpvvIDCoVFD0BC4E=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.17.9 h1:PyqFD7DTmOx5gdvjFwZH2Tx0vivy+cJdM3SE3NVoWZc=
|
github.com/aws/aws-sdk-go-v2/config v1.17.10 h1:zBy5QQ/mkvHElM1rygHPAzuH+sl8nsdSaxSWj0+rpdE=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.17.9/go.mod h1:NGC2Ut1x1Gl+qBdh4uGdqRTDtk6f3qS8VQ45kEoyAvM=
|
github.com/aws/aws-sdk-go-v2/config v1.17.10/go.mod h1:/4np+UiJJKpWHN7Q+LZvqXYgyjgeXm5+lLfDI6TPZao=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.10/go.mod h1:g5eIM5XRs/OzIIK81QMBl+dAuDyoLN0VYaLP+tBqEOk=
|
github.com/aws/aws-sdk-go-v2/credentials v1.12.10/go.mod h1:g5eIM5XRs/OzIIK81QMBl+dAuDyoLN0VYaLP+tBqEOk=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.22 h1:HPig9ugqH7Eyf2aqNVAPOCp3L/N2vlQ/IiaTxwcrH8U=
|
github.com/aws/aws-sdk-go-v2/credentials v1.12.23 h1:LctvcJMIb8pxvk5hQhChpCu0WlU6oKQmcYb1HA4IZSA=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.22/go.mod h1:XfHZqa+J1j2Am2GHrsWtg24tnkFkKxmWbWWel+W1zp0=
|
github.com/aws/aws-sdk-go-v2/credentials v1.12.23/go.mod h1:0awX9iRr/+UO7OwRQFpV1hNtXxOVuehpjVEzrIAYNcA=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.9/go.mod h1:KDCCm4ONIdHtUloDcFvK2+vshZvx4Zmj7UMDfusuz5s=
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.9/go.mod h1:KDCCm4ONIdHtUloDcFvK2+vshZvx4Zmj7UMDfusuz5s=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.18 h1:63dqlW4EI4nfhmXJOUqP0zIaGEHoRPn1ahLz8hUOWrQ=
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 h1:E3PXZSI3F2bzyj6XxUXdTIfvp425HHhwKsFvmzBwHgs=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.18/go.mod h1:O3tSoDcot3jy62HNmq7ms16dPHQMR6nqQxooj8T53tI=
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19/go.mod h1:VihW95zQpeKQWVPGkwT+2+WJNQV8UXFfMTWdU6VErL8=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.21/go.mod h1:iIYPrQ2rYfZiB/iADYlhj9HHZ9TTi6PqKQPAqygohbE=
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.21/go.mod h1:iIYPrQ2rYfZiB/iADYlhj9HHZ9TTi6PqKQPAqygohbE=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.36 h1:DYIvpSIM9YTdid6yRZk/w2kJhJJIbFnL/76NfzmfaTs=
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.37 h1:e1VtTBo+cLNjres0wTlMkmwCGGRjDEkkrz3frxxcaCs=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.36/go.mod h1:1vzWYwKGRitVzk7xD3y8Ko7lg26qX+Pxwb5uRaOPSlM=
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.37/go.mod h1:kdAV1UMnCkyG6tZJUC4mHbPoRjPA3dIK0L8mnsHERiM=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.15/go.mod h1:pWrr2OoHlT7M/Pd2y4HV3gJyPb3qj5qMmnPkKSNPYK4=
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.15/go.mod h1:pWrr2OoHlT7M/Pd2y4HV3gJyPb3qj5qMmnPkKSNPYK4=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.24 h1:WFIoN2kiF95/4z4HNcJ9F9B0xFV0vrPlUOf3+uNIujM=
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 h1:nBO/RFxeq/IS5G9Of+ZrgucRciie2qpLy++3UGZ+q2E=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.24/go.mod h1:ghMzB/j2wRbPx5/4jPYxJdOtCG2ggrtY01j8K7FMBDA=
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25/go.mod h1:Zb29PYkf42vVYQY6pvSyJCJcFHlPIiY+YKdPtwnvMkY=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.9/go.mod h1:08tUpeSGN33QKSO7fwxXczNfiwCpbj+GxK6XKwqWVv0=
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.9/go.mod h1:08tUpeSGN33QKSO7fwxXczNfiwCpbj+GxK6XKwqWVv0=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.18 h1:c2RKF0UvfdVI6epHtFjDujlbiK+VeY85dP1i4gmYc5w=
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 h1:oRHDrwCTVT8ZXi4sr9Ld+EXk7N/KGssOr2ygNeojEhw=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.18/go.mod h1:fkQKYK/jUhCL/wNS1tOPrlYhr9vqutjCz4zZC1wBE1s=
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19/go.mod h1:6Q0546uHDp421okhmmGfbxzq2hBqbXFNpi4k+Q1JnQA=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.16/go.mod h1:CYmI+7x03jjJih8kBEEFKRQc40UjUokT0k7GbvrhhTc=
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.16/go.mod h1:CYmI+7x03jjJih8kBEEFKRQc40UjUokT0k7GbvrhhTc=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.25 h1:q4TXoep+lPTJneYxlIdcBrlGmTrhfNwrfkdBt1+HqzA=
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26 h1:Mza+vlnZr+fPKFKRq/lKGVvM6B/8ZZmNdEopOwSQLms=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.25/go.mod h1:9uX0Ksj6Zmsd3iQIyVkwkPWUqhPF6TxT/t8zYwUiQEU=
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26/go.mod h1:Y2OJ+P+MC1u1VKnavT+PshiEuGPyh/7DqxoDNij4/bg=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.6/go.mod h1:O7Oc4peGZDEKlddivslfYFvAbgzvl/GH3J8j3JIGBXc=
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.6/go.mod h1:O7Oc4peGZDEKlddivslfYFvAbgzvl/GH3J8j3JIGBXc=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.15 h1:15q0OjFjny5qjCC8nI+4DH+MZFDC2/BtXxONBNnVZR8=
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.16 h1:2EXB7dtGwRYIN3XQ9qwIW504DVbKIw3r89xQnonGdsQ=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.15/go.mod h1:t7/Pw0mlxveHXyfzEkGjzQ59Xu9xUmzOfxe1S52TJ8Q=
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.16/go.mod h1:XH+3h395e3WVdd6T2Z3mPxuI+x/HVtdqVOREkTiyubs=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.3/go.mod h1:gkb2qADY+OHaGLKNTYxMaQNacfeyQpZ4csDTQMeFmcw=
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.3/go.mod h1:gkb2qADY+OHaGLKNTYxMaQNacfeyQpZ4csDTQMeFmcw=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9 h1:Lh1AShsuIJTwMkoxVCAYPJgNG5H+eN6SmoUn8nOZ5wE=
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.10 h1:dpiPHgmFstgkLG07KaYAewvuptq5kvo52xn7tVSrtrQ=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9/go.mod h1:a9j48l6yL5XINLHLcOKInjdvknN+vWqPBxqeIDw7ktw=
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.10/go.mod h1:9cBNUHI2aW4ho0A5T87O294iPDuuUOSIEDjnd1Lq/z0=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.10/go.mod h1:Qks+dxK3O+Z2deAhNo6cJ8ls1bam3tUGUAcgxQP1c70=
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.10/go.mod h1:Qks+dxK3O+Z2deAhNo6cJ8ls1bam3tUGUAcgxQP1c70=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.19 h1:jrV+VRNrUuzcwTZxdZMi1JtKMk71FN1H7VaF8XjGl44=
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.20 h1:KSvtm1+fPXE0swe9GPjc6msyrdTT0LB/BP8eLugL1FI=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.19/go.mod h1:HGDDjLf/IyINXk4PcEZSEviZulqnePG76iq9/rC5qqo=
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.20/go.mod h1:Mp4XI/CkWGD79AQxZ5lIFlgvC0A+gl+4BmyG1F+SfNc=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.9/go.mod h1:yQowTpvdZkFVuHrLBXmczat4W+WJKg/PafBZnGBLga0=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.9/go.mod h1:yQowTpvdZkFVuHrLBXmczat4W+WJKg/PafBZnGBLga0=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.18 h1:5oiCDEOHnYkk7uTVI8Wv6ftdFfb6YlUUNzkeePVIPjY=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19 h1:GE25AWCdNUPh9AOJzI9KIJnja7IwUc1WyUqz/JTyJ/I=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.18/go.mod h1:QtCDHDOXunxeihz7iU15e09u9gRIeaa5WeE6FZVnGUo=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19/go.mod h1:02CP6iuYP+IVnBX5HULVdSAku/85eHB2Y9EsFhrkEwU=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.9/go.mod h1:Rc5+wn2k8gFSi3V1Ch4mhxOzjMh+bYSXVFfVaqowQOY=
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.9/go.mod h1:Rc5+wn2k8gFSi3V1Ch4mhxOzjMh+bYSXVFfVaqowQOY=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.18 h1:sk9Z5ZwZpLGq3q8ZhOsw8bORT2t8raWPsFrq/yMMbZ0=
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 h1:piDBAaWkaxkkVV3xJJbTehXCZRXYs49kvpi/LG6LR2o=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.18/go.mod h1:O1mfO/JzWKUNujOAqD39r7BXqlvhjh/JiPnQ97tvQMc=
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19/go.mod h1:BmQWRVkLTmyNzYPFAZgon53qKLWBNSvonugD1MrSWUs=
|
||||||
github.com/aws/aws-sdk-go-v2/service/kms v1.18.1/go.mod h1:4PZMUkc9rXHWGVB5J9vKaZy3D7Nai79ORworQ3ASMiM=
|
github.com/aws/aws-sdk-go-v2/service/kms v1.18.1/go.mod h1:4PZMUkc9rXHWGVB5J9vKaZy3D7Nai79ORworQ3ASMiM=
|
||||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.20 h1:jOpM3C6a/W4cd31hj3qok1NZKu3pWYLEg5IwUharV+o=
|
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.21 h1:LpIut7TpOhp8RuTD72PBj8ksPy3+RelT3LPwGgQ8+Hg=
|
||||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.20/go.mod h1:pvYIQ3quYKA9wXvn5oY6Suu4RqjURwN1tERJssL57nQ=
|
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.21/go.mod h1:mRGY+k3s1yt7yQA3AfzJhnr68OCs1xDfQfIABFUk+ek=
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.2/go.mod h1:u+566cosFI+d+motIz3USXEh6sN8Nq4GrNXSg2RXVMo=
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.2/go.mod h1:u+566cosFI+d+motIz3USXEh6sN8Nq4GrNXSg2RXVMo=
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.0 h1:wmROdhyusq7m7HJgSB9Jm955XU4Kvz0FknIbr1dJTjA=
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.1 h1:/EMdFPW/Ppieh0WUtQf1+qCGNLdsq5UWUyevBQ6vMVc=
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.0/go.mod h1:syhASH3D6eA1PCga49mGfvISJh/E2QYaooSIqir3pIM=
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.1/go.mod h1:/NHbqPRiwxSPVOB2Xr+StDEH+GWV/64WwnUjv4KYzV0=
|
||||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.14/go.mod h1:xakbH8KMsQQKqzX87uyyzTHshc/0/Df8bsTneTS5pFU=
|
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.14/go.mod h1:xakbH8KMsQQKqzX87uyyzTHshc/0/Df8bsTneTS5pFU=
|
||||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.3 h1:d5S+OhXne5O3cIo999RARy/N1dgXW2ldWgD53qbEAP4=
|
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.4 h1:Hx79EGrkKNJya2iz2U5A7nyr7DjOu/TGTRefThfBZ1w=
|
||||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.3/go.mod h1:+X/VSQcuvHPWPRlM64HoWUJAPwsD86KpU9Z52lrsodM=
|
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.4/go.mod h1:k6CPuxyzO247nYEM1baEwHH1kRtosRCvgahAepaaShw=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sns v1.17.10/go.mod h1:uITsRNVMeCB3MkWpXxXw0eDz8pW4TYLzj+eyQtbhSxM=
|
github.com/aws/aws-sdk-go-v2/service/sns v1.17.10/go.mod h1:uITsRNVMeCB3MkWpXxXw0eDz8pW4TYLzj+eyQtbhSxM=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sqs v1.19.1/go.mod h1:A94o564Gj+Yn+7QO1eLFeI7UVv3riy/YBFOfICVqFvU=
|
github.com/aws/aws-sdk-go-v2/service/sqs v1.19.1/go.mod h1:A94o564Gj+Yn+7QO1eLFeI7UVv3riy/YBFOfICVqFvU=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.27.6/go.mod h1:fiFzQgj4xNOg4/wqmAiPvzgDMXPD+cUEplX/CYn+0j0=
|
github.com/aws/aws-sdk-go-v2/service/ssm v1.27.6/go.mod h1:fiFzQgj4xNOg4/wqmAiPvzgDMXPD+cUEplX/CYn+0j0=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.13/go.mod h1:d7ptRksDDgvXaUvxyHZ9SYh+iMDymm94JbVcgvSYSzU=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.11.13/go.mod h1:d7ptRksDDgvXaUvxyHZ9SYh+iMDymm94JbVcgvSYSzU=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.24 h1:tNfD0JI7VKcIcEzYeIAXCIr8qnoq6DACg3QRt50ofOY=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 h1:GFZitO48N/7EsFDt8fMa5iYdmWqkUDDB3Eje6z3kbG0=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.24/go.mod h1:7ZC+G3rX2IsGKIhiGDFiul7rgZPApvFy3dDJO7wKtno=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25/go.mod h1:IARHuzTXmj1C0KS35vboR0FeJ89OkEy1M9mWbK2ifCI=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.7 h1:q2FDE8cl8rTPqgrTT0dF7xzIfGAwLMh2P+nU7F2CqVs=
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 h1:jcw6kKZrtNfBPJkaHrscDOZoe5gvi9wjudnxvozYFJo=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.7/go.mod h1:sPh8yf7vmBOI/L9fqP55uq+T9WVoxnqrHMqyvgYC/gA=
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8/go.mod h1:er2JHN+kBY6FcMfcBBKNGCT3CarImmdFzishsqBmSRI=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.10/go.mod h1:cftkHYN6tCDNfkSasAmclSfl4l7cySoay8vz7p/ce0E=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.16.10/go.mod h1:cftkHYN6tCDNfkSasAmclSfl4l7cySoay8vz7p/ce0E=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.0 h1:9S0HcZUxKcU3HdN+M6GgLIvdbg9as5aOoHrvwRsPNYU=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.17.1 h1:KRAix/KHvjGODaHAMXnxRk9t0D+4IJVUuS/uwXxngXk=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.0/go.mod h1:9pZN58zQc5a4Dkdnhu/rI1lNBui1vP5B0giGCuUt2b0=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.17.1/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4=
|
||||||
github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||||
github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA=
|
github.com/aws/smithy-go v1.13.4 h1:/RN2z1txIJWeXeOkzX+Hk/4Uuvv7dWtCjbmVJcrskyk=
|
||||||
github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
github.com/aws/smithy-go v1.13.4/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||||
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
@ -539,8 +541,8 @@ github.com/drakkan/crypto v0.0.0-20221020054403-a265c1cba3cb h1:ex3x8ir969oV6bQ8
|
||||||
github.com/drakkan/crypto v0.0.0-20221020054403-a265c1cba3cb/go.mod h1:IBSs4ri4rdTqz2QKcpTKpwKMdM+WJ7atZeL9lCu2swQ=
|
github.com/drakkan/crypto v0.0.0-20221020054403-a265c1cba3cb/go.mod h1:IBSs4ri4rdTqz2QKcpTKpwKMdM+WJ7atZeL9lCu2swQ=
|
||||||
github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9 h1:LPH1dEblAOO/LoG7yHPMtBLXhQmjaga91/DDjWk9jWA=
|
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/ftp v0.0.0-20201114075148-9b9adce499a9/go.mod h1:2lmrmq866uF2tnje75wQHzmPXhmSWUt7Gyx2vgK1RCU=
|
||||||
github.com/drakkan/net v0.0.0-20221020052826-79457e688bf9 h1:vU78OwgLgNqWDqhsk9So0XtQrPxgMDs85L+A3YotXIA=
|
github.com/drakkan/net v0.0.0-20221026175805-eaebd725b308 h1:F7OUb3MgSa2SuY5mdmseihGXhVhxv1OCuKHrona2eh0=
|
||||||
github.com/drakkan/net v0.0.0-20221020052826-79457e688bf9/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
github.com/drakkan/net v0.0.0-20221026175805-eaebd725b308/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
|
@ -1013,8 +1015,8 @@ github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQ
|
||||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
||||||
github.com/jackc/pgx/v4 v4.16.0/go.mod h1:N0A9sFdWzkw/Jy1lwoiB64F2+ugFZi987zRxcPez/wI=
|
github.com/jackc/pgx/v4 v4.16.0/go.mod h1:N0A9sFdWzkw/Jy1lwoiB64F2+ugFZi987zRxcPez/wI=
|
||||||
github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ=
|
github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ=
|
||||||
github.com/jackc/pgx/v5 v5.0.4-0.20221022150232-3e825ec8982f h1:DEdjdZkMfuJ9Y9sELu1idpOg7101O6YlpdnSXlh0Et8=
|
github.com/jackc/pgx/v5 v5.0.4 h1:r5O6y84qHX/z/HZV40JBdx2obsHz7/uRj5b+CcYEdeY=
|
||||||
github.com/jackc/pgx/v5 v5.0.4-0.20221022150232-3e825ec8982f/go.mod h1:U0ynklHtgg43fue9Ly30w3OCSTDPlXjig9ghrNGaguQ=
|
github.com/jackc/pgx/v5 v5.0.4/go.mod h1:U0ynklHtgg43fue9Ly30w3OCSTDPlXjig9ghrNGaguQ=
|
||||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
|
@ -1060,8 +1062,8 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
||||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
|
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
|
||||||
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.1.2 h1:XhdX4fqAJUA0yj+kUwMavO0hHrSPAecYdYf1ZmxHvak=
|
github.com/klauspost/cpuid/v2 v2.1.2 h1:XhdX4fqAJUA0yj+kUwMavO0hHrSPAecYdYf1ZmxHvak=
|
||||||
github.com/klauspost/cpuid/v2 v2.1.2/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
github.com/klauspost/cpuid/v2 v2.1.2/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
|
@ -1161,12 +1163,12 @@ github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vq
|
||||||
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM=
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
|
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
|
||||||
github.com/mhale/smtpd v0.8.0 h1:5JvdsehCg33PQrZBvFyDMMUDQmvbzVpZgKob7eYBJc0=
|
github.com/mhale/smtpd v0.8.0 h1:5JvdsehCg33PQrZBvFyDMMUDQmvbzVpZgKob7eYBJc0=
|
||||||
github.com/mhale/smtpd v0.8.0/go.mod h1:MQl+y2hwIEQCXtNhe5+55n0GZOjSmeqORDIXbqUL3x4=
|
github.com/mhale/smtpd v0.8.0/go.mod h1:MQl+y2hwIEQCXtNhe5+55n0GZOjSmeqORDIXbqUL3x4=
|
||||||
|
@ -1494,8 +1496,8 @@ github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKv
|
||||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||||
github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
|
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||||
github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||||
|
@ -1519,6 +1521,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
@ -1529,8 +1532,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||||
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/studio-b12/gowebdav v0.0.0-20221015232716-17255f2e7423 h1:Wd8WDEEusB5+En4PiRWJp1cP59QLNsQun+mOTW8+s6s=
|
github.com/studio-b12/gowebdav v0.0.0-20221015232716-17255f2e7423 h1:Wd8WDEEusB5+En4PiRWJp1cP59QLNsQun+mOTW8+s6s=
|
||||||
github.com/studio-b12/gowebdav v0.0.0-20221015232716-17255f2e7423/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
|
github.com/studio-b12/gowebdav v0.0.0-20221015232716-17255f2e7423/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
|
@ -1783,7 +1787,7 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 h1:cu5kTvlzcw1Q5S9f5ip1/cpiB4nXvw1XYzFPGgzLUOY=
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -2104,8 +2108,8 @@ google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6F
|
||||||
google.golang.org/api v0.86.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
google.golang.org/api v0.86.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
||||||
google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
||||||
google.golang.org/api v0.91.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
google.golang.org/api v0.91.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
||||||
google.golang.org/api v0.100.0 h1:LGUYIrbW9pzYQQ8NWXlaIVkgnfubVBZbMFb9P8TK374=
|
google.golang.org/api v0.101.0 h1:lJPPeEBIRxGpGLwnBTam1NPEM8Z2BmmXEd3z812pjwM=
|
||||||
google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
|
google.golang.org/api v0.101.0/go.mod h1:CjxAAWWt3A3VrUE2IGDY2bgK5qhoG/OkyWVlYcP05MY=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
@ -2216,8 +2220,8 @@ google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljW
|
||||||
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
|
google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
|
||||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 h1:U1u4KB2kx6KR/aJDjQ97hZ15wQs8ZPvDcGcRynBhkvg=
|
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 h1:GEgb2jF5zxsFJpJfg9RoDDWm7tiwc/DDSTE2BtLUkXU=
|
||||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55/go.mod h1:45EK0dUbEZ2NHjCeAd2LXmyjAgGUGrpGROgjhC3ADck=
|
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
|
|
@ -462,7 +462,7 @@ func (c *BaseConnection) RemoveDir(virtualPath string) error {
|
||||||
return c.GetFsError(fs, err)
|
return c.GetFsError(fs, err)
|
||||||
}
|
}
|
||||||
if !fi.IsDir() || fi.Mode()&os.ModeSymlink != 0 {
|
if !fi.IsDir() || fi.Mode()&os.ModeSymlink != 0 {
|
||||||
c.Log(logger.LevelError, "cannot remove %#v is not a directory", fsPath)
|
c.Log(logger.LevelError, "cannot remove %q is not a directory", fsPath)
|
||||||
return c.GetGenericError(nil)
|
return c.GetGenericError(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,6 +477,132 @@ func (c *BaseConnection) RemoveDir(virtualPath string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type objectToRemoveMapping struct {
|
||||||
|
fsPath string
|
||||||
|
virtualPath string
|
||||||
|
info os.FileInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// orderDirsToRemove orders directories so that the empty ones will be at slice start
|
||||||
|
func orderDirsToRemove(fs vfs.Fs, dirsToRemove []objectToRemoveMapping) []objectToRemoveMapping {
|
||||||
|
orderedDirs := make([]objectToRemoveMapping, 0, len(dirsToRemove))
|
||||||
|
removedDirs := make([]string, 0, len(dirsToRemove))
|
||||||
|
|
||||||
|
pathSeparator := "/"
|
||||||
|
if vfs.IsLocalOsFs(fs) {
|
||||||
|
pathSeparator = string(os.PathSeparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
for len(orderedDirs) < len(dirsToRemove) {
|
||||||
|
for idx, d := range dirsToRemove {
|
||||||
|
if util.Contains(removedDirs, d.fsPath) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
isEmpty := true
|
||||||
|
for idx1, d1 := range dirsToRemove {
|
||||||
|
if idx == idx1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if util.Contains(removedDirs, d1.fsPath) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(d1.fsPath, d.fsPath+pathSeparator) {
|
||||||
|
isEmpty = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isEmpty {
|
||||||
|
orderedDirs = append(orderedDirs, d)
|
||||||
|
removedDirs = append(removedDirs, d.fsPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return orderedDirs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *BaseConnection) removeDirTree(fs vfs.Fs, fsPath, virtualPath string) error {
|
||||||
|
var dirsToRemove []objectToRemoveMapping
|
||||||
|
var filesToRemove []objectToRemoveMapping
|
||||||
|
|
||||||
|
err := fs.Walk(fsPath, func(walkedPath string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
obj := objectToRemoveMapping{
|
||||||
|
fsPath: walkedPath,
|
||||||
|
virtualPath: fs.GetRelativePath(walkedPath),
|
||||||
|
info: info,
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
err = c.IsRemoveDirAllowed(fs, obj.fsPath, obj.virtualPath)
|
||||||
|
isDuplicated := false
|
||||||
|
for _, d := range dirsToRemove {
|
||||||
|
if d.fsPath == obj.fsPath {
|
||||||
|
isDuplicated = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !isDuplicated {
|
||||||
|
dirsToRemove = append(dirsToRemove, obj)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = c.IsRemoveFileAllowed(obj.virtualPath)
|
||||||
|
filesToRemove = append(filesToRemove, obj)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
c.Log(logger.LevelError, "unable to remove dir tree, object %q->%q cannot be removed: %v",
|
||||||
|
virtualPath, fsPath, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.Log(logger.LevelError, "failed to remove dir tree %q->%q: error: %+v", virtualPath, fsPath, err)
|
||||||
|
return c.GetFsError(fs, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fileObj := range filesToRemove {
|
||||||
|
err = c.RemoveFile(fs, fileObj.fsPath, fileObj.virtualPath, fileObj.info)
|
||||||
|
if err != nil {
|
||||||
|
c.Log(logger.LevelError, "unable to remove dir tree, error removing file %q->%q: %v",
|
||||||
|
fileObj.virtualPath, fileObj.fsPath, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dirObj := range orderDirsToRemove(fs, dirsToRemove) {
|
||||||
|
err = c.RemoveDir(dirObj.virtualPath)
|
||||||
|
if err != nil {
|
||||||
|
c.Log(logger.LevelDebug, "unable to remove dir tree, error removing directory %q->%q: %v",
|
||||||
|
dirObj.virtualPath, dirObj.fsPath, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAll removes the specified path and any children it contains
|
||||||
|
func (c *BaseConnection) RemoveAll(virtualPath string) error {
|
||||||
|
fs, fsPath, err := c.GetFsAndResolvedPath(virtualPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fi, err := fs.Lstat(fsPath)
|
||||||
|
if err != nil {
|
||||||
|
c.Log(logger.LevelDebug, "failed to remove path %q: stat error: %+v", fsPath, err)
|
||||||
|
return c.GetFsError(fs, err)
|
||||||
|
}
|
||||||
|
if fi.IsDir() && fi.Mode()&os.ModeSymlink == 0 {
|
||||||
|
return c.removeDirTree(fs, fsPath, virtualPath)
|
||||||
|
}
|
||||||
|
return c.RemoveFile(fs, fsPath, virtualPath, fi)
|
||||||
|
}
|
||||||
|
|
||||||
// Rename renames (moves) virtualSourcePath to virtualTargetPath
|
// Rename renames (moves) virtualSourcePath to virtualTargetPath
|
||||||
func (c *BaseConnection) Rename(virtualSourcePath, virtualTargetPath string) error {
|
func (c *BaseConnection) Rename(virtualSourcePath, virtualTargetPath string) error {
|
||||||
if virtualSourcePath == virtualTargetPath {
|
if virtualSourcePath == virtualTargetPath {
|
||||||
|
@ -509,7 +635,7 @@ func (c *BaseConnection) Rename(virtualSourcePath, virtualTargetPath string) err
|
||||||
initialSize = dstInfo.Size()
|
initialSize = dstInfo.Size()
|
||||||
}
|
}
|
||||||
if !c.User.HasPerm(dataprovider.PermOverwrite, path.Dir(virtualTargetPath)) {
|
if !c.User.HasPerm(dataprovider.PermOverwrite, path.Dir(virtualTargetPath)) {
|
||||||
c.Log(logger.LevelDebug, "renaming %#v -> %#v is not allowed. Target exists but the user %#v"+
|
c.Log(logger.LevelDebug, "renaming %q -> %q is not allowed. Target exists but the user %q"+
|
||||||
"has no overwrite permission", virtualSourcePath, virtualTargetPath, c.User.Username)
|
"has no overwrite permission", virtualSourcePath, virtualTargetPath, c.User.Username)
|
||||||
return c.GetPermissionDeniedError()
|
return c.GetPermissionDeniedError()
|
||||||
}
|
}
|
||||||
|
@ -824,11 +950,15 @@ func (c *BaseConnection) checkRecursiveRenameDirPermissions(fsSrc, fsDst vfs.Fs,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.GetFsError(fsSrc, err)
|
return c.GetFsError(fsSrc, err)
|
||||||
}
|
}
|
||||||
|
if walkedPath != sourcePath && vfs.HasImplicitAtomicUploads(fsSrc) {
|
||||||
|
c.Log(logger.LevelInfo, "cannot rename non empty directory %q on this filesystem", virtualSourcePath)
|
||||||
|
return c.GetOpUnsupportedError()
|
||||||
|
}
|
||||||
dstPath := strings.Replace(walkedPath, sourcePath, targetPath, 1)
|
dstPath := strings.Replace(walkedPath, sourcePath, targetPath, 1)
|
||||||
virtualSrcPath := fsSrc.GetRelativePath(walkedPath)
|
virtualSrcPath := fsSrc.GetRelativePath(walkedPath)
|
||||||
virtualDstPath := fsDst.GetRelativePath(dstPath)
|
virtualDstPath := fsDst.GetRelativePath(dstPath)
|
||||||
if !c.isRenamePermitted(fsSrc, fsDst, walkedPath, dstPath, virtualSrcPath, virtualDstPath, info) {
|
if !c.isRenamePermitted(fsSrc, fsDst, walkedPath, dstPath, virtualSrcPath, virtualDstPath, info) {
|
||||||
c.Log(logger.LevelInfo, "rename %#v -> %#v is not allowed, virtual destination path: %#v",
|
c.Log(logger.LevelInfo, "rename %q -> %q is not allowed, virtual destination path: %q",
|
||||||
walkedPath, dstPath, virtualDstPath)
|
walkedPath, dstPath, virtualDstPath)
|
||||||
return c.GetPermissionDeniedError()
|
return c.GetPermissionDeniedError()
|
||||||
}
|
}
|
||||||
|
@ -866,7 +996,7 @@ func (c *BaseConnection) isRenamePermitted(fsSrc, fsDst vfs.Fs, fsSourcePath, fs
|
||||||
virtualTargetPath string, fi os.FileInfo,
|
virtualTargetPath string, fi os.FileInfo,
|
||||||
) bool {
|
) bool {
|
||||||
if !c.isSameResourceRename(virtualSourcePath, virtualTargetPath) {
|
if !c.isSameResourceRename(virtualSourcePath, virtualTargetPath) {
|
||||||
c.Log(logger.LevelInfo, "rename %#v->%#v is not allowed: the paths must be on the same resource",
|
c.Log(logger.LevelInfo, "rename %#q->%q is not allowed: the paths must be on the same resource",
|
||||||
virtualSourcePath, virtualTargetPath)
|
virtualSourcePath, virtualTargetPath)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -33,11 +34,17 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/internal/vfs"
|
"github.com/drakkan/sftpgo/v2/internal/vfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errWalkDir = errors.New("err walk dir")
|
||||||
|
errWalkFile = errors.New("err walk file")
|
||||||
|
)
|
||||||
|
|
||||||
// MockOsFs mockable OsFs
|
// MockOsFs mockable OsFs
|
||||||
type MockOsFs struct {
|
type MockOsFs struct {
|
||||||
vfs.Fs
|
vfs.Fs
|
||||||
hasVirtualFolders bool
|
hasVirtualFolders bool
|
||||||
name string
|
name string
|
||||||
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the name for the Fs implementation
|
// Name returns the name for the Fs implementation
|
||||||
|
@ -61,11 +68,22 @@ func (fs *MockOsFs) Chtimes(name string, atime, mtime time.Time, isUploading boo
|
||||||
return vfs.ErrVfsUnsupported
|
return vfs.ErrVfsUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMockOsFs(hasVirtualFolders bool, connectionID, rootDir, name string) vfs.Fs {
|
// Walk returns a duplicate path for testing
|
||||||
|
func (fs *MockOsFs) Walk(root string, walkFn filepath.WalkFunc) error {
|
||||||
|
if fs.err == errWalkDir {
|
||||||
|
walkFn("fsdpath", vfs.NewFileInfo("dpath", true, 0, time.Now(), false), nil) //nolint:errcheck
|
||||||
|
return walkFn("fsdpath", vfs.NewFileInfo("dpath", true, 0, time.Now(), false), nil) //nolint:errcheck
|
||||||
|
}
|
||||||
|
walkFn("fsfpath", vfs.NewFileInfo("fpath", false, 0, time.Now(), false), nil) //nolint:errcheck
|
||||||
|
return fs.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMockOsFs(hasVirtualFolders bool, connectionID, rootDir, name string, err error) vfs.Fs {
|
||||||
return &MockOsFs{
|
return &MockOsFs{
|
||||||
Fs: vfs.NewOsFs(connectionID, rootDir, ""),
|
Fs: vfs.NewOsFs(connectionID, rootDir, ""),
|
||||||
name: name,
|
name: name,
|
||||||
hasVirtualFolders: hasVirtualFolders,
|
hasVirtualFolders: hasVirtualFolders,
|
||||||
|
err: err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +131,7 @@ func TestSetStatMode(t *testing.T) {
|
||||||
}
|
}
|
||||||
user.Permissions = make(map[string][]string)
|
user.Permissions = make(map[string][]string)
|
||||||
user.Permissions["/"] = []string{dataprovider.PermAny}
|
user.Permissions["/"] = []string{dataprovider.PermAny}
|
||||||
fs := newMockOsFs(true, "", user.GetHomeDir(), "")
|
fs := newMockOsFs(true, "", user.GetHomeDir(), "", nil)
|
||||||
conn := NewBaseConnection("", ProtocolWebDAV, "", "", user)
|
conn := NewBaseConnection("", ProtocolWebDAV, "", "", user)
|
||||||
err := conn.handleChmod(fs, fakePath, fakePath, nil)
|
err := conn.handleChmod(fs, fakePath, fakePath, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -148,6 +166,15 @@ func TestRecursiveRenameWalkError(t *testing.T) {
|
||||||
filepath.Join(os.TempDir(), "/target"), "/source", "/target",
|
filepath.Join(os.TempDir(), "/target"), "/source", "/target",
|
||||||
vfs.NewFileInfo("source", true, 0, time.Now(), false))
|
vfs.NewFileInfo("source", true, 0, time.Now(), false))
|
||||||
assert.ErrorIs(t, err, os.ErrNotExist)
|
assert.ErrorIs(t, err, os.ErrNotExist)
|
||||||
|
|
||||||
|
fs = newMockOsFs(false, "mockID", filepath.Clean(os.TempDir()), "S3Fs", errWalkDir)
|
||||||
|
err = conn.checkRecursiveRenameDirPermissions(fs, fs, filepath.Join(os.TempDir(), "/source"),
|
||||||
|
filepath.Join(os.TempDir(), "/target"), "/source", "/target",
|
||||||
|
vfs.NewFileInfo("source", true, 0, time.Now(), false))
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.Equal(t, err.Error(), conn.GetOpUnsupportedError().Error())
|
||||||
|
}
|
||||||
|
|
||||||
conn.User.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
|
conn.User.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
|
||||||
dataprovider.PermDownload, dataprovider.PermRenameFiles}
|
dataprovider.PermDownload, dataprovider.PermRenameFiles}
|
||||||
// no dir rename permission, the quick check path returns permission error without walking
|
// no dir rename permission, the quick check path returns permission error without walking
|
||||||
|
@ -441,7 +468,7 @@ func TestMaxWriteSize(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(90), size)
|
assert.Equal(t, int64(90), size)
|
||||||
|
|
||||||
fs = newMockOsFs(true, fs.ConnectionID(), user.GetHomeDir(), "")
|
fs = newMockOsFs(true, fs.ConnectionID(), user.GetHomeDir(), "", nil)
|
||||||
size, err = conn.GetMaxWriteSize(quotaResult, true, 100, fs.IsUploadResumeSupported())
|
size, err = conn.GetMaxWriteSize(quotaResult, true, 100, fs.IsUploadResumeSupported())
|
||||||
assert.EqualError(t, err, ErrOpUnsupported.Error())
|
assert.EqualError(t, err, ErrOpUnsupported.Error())
|
||||||
assert.Equal(t, int64(0), size)
|
assert.Equal(t, int64(0), size)
|
||||||
|
@ -519,3 +546,98 @@ func TestCheckParentDirsErrors(t *testing.T) {
|
||||||
err = os.RemoveAll(filepath.Join(os.TempDir(), "sub-dir"))
|
err = os.RemoveAll(filepath.Join(os.TempDir(), "sub-dir"))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoveDirTree(t *testing.T) {
|
||||||
|
user := dataprovider.User{
|
||||||
|
BaseUser: sdk.BaseUser{
|
||||||
|
HomeDir: filepath.Clean(os.TempDir()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
user.Permissions = make(map[string][]string)
|
||||||
|
user.Permissions["/"] = []string{dataprovider.PermAny}
|
||||||
|
fs := vfs.NewOsFs("connID", user.HomeDir, "")
|
||||||
|
connection := NewBaseConnection(fs.ConnectionID(), ProtocolWebDAV, "", "", user)
|
||||||
|
|
||||||
|
vpath := path.Join("adir", "missing")
|
||||||
|
p := filepath.Join(user.HomeDir, "adir", "missing")
|
||||||
|
err := connection.removeDirTree(fs, p, vpath)
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.True(t, fs.IsNotExist(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
fs = newMockOsFs(false, "mockID", user.HomeDir, "", nil)
|
||||||
|
err = connection.removeDirTree(fs, p, vpath)
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.True(t, fs.IsNotExist(err), "unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
errFake := errors.New("fake err")
|
||||||
|
fs = newMockOsFs(false, "mockID", user.HomeDir, "", errFake)
|
||||||
|
err = connection.removeDirTree(fs, p, vpath)
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.EqualError(t, err, ErrGenericFailure.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
fs = newMockOsFs(true, "mockID", user.HomeDir, "", errWalkDir)
|
||||||
|
err = connection.removeDirTree(fs, p, vpath)
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.True(t, fs.IsPermission(err), "unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs = newMockOsFs(false, "mockID", user.HomeDir, "", errWalkFile)
|
||||||
|
err = connection.removeDirTree(fs, p, vpath)
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.EqualError(t, err, ErrGenericFailure.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.User.Permissions["/"] = []string{dataprovider.PermListItems}
|
||||||
|
fs = newMockOsFs(false, "mockID", user.HomeDir, "", nil)
|
||||||
|
err = connection.removeDirTree(fs, p, vpath)
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.EqualError(t, err, ErrPermissionDenied.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderDirsToRemove(t *testing.T) {
|
||||||
|
fs := vfs.NewOsFs("id", os.TempDir(), "")
|
||||||
|
dirsToRemove := []objectToRemoveMapping{}
|
||||||
|
|
||||||
|
orderedDirs := orderDirsToRemove(fs, dirsToRemove)
|
||||||
|
assert.Equal(t, len(dirsToRemove), len(orderedDirs))
|
||||||
|
|
||||||
|
dirsToRemove = []objectToRemoveMapping{
|
||||||
|
{
|
||||||
|
fsPath: "dir1",
|
||||||
|
virtualPath: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
orderedDirs = orderDirsToRemove(fs, dirsToRemove)
|
||||||
|
assert.Equal(t, len(dirsToRemove), len(orderedDirs))
|
||||||
|
|
||||||
|
dirsToRemove = []objectToRemoveMapping{
|
||||||
|
{
|
||||||
|
fsPath: "dir1",
|
||||||
|
virtualPath: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fsPath: "dir12",
|
||||||
|
virtualPath: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fsPath: filepath.Join("dir1", "a", "b"),
|
||||||
|
virtualPath: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fsPath: filepath.Join("dir1", "a"),
|
||||||
|
virtualPath: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
orderedDirs = orderDirsToRemove(fs, dirsToRemove)
|
||||||
|
if assert.Equal(t, len(dirsToRemove), len(orderedDirs)) {
|
||||||
|
assert.Equal(t, "dir12", orderedDirs[0].fsPath)
|
||||||
|
assert.Equal(t, filepath.Join("dir1", "a", "b"), orderedDirs[1].fsPath)
|
||||||
|
assert.Equal(t, filepath.Join("dir1", "a"), orderedDirs[2].fsPath)
|
||||||
|
assert.Equal(t, "dir1", orderedDirs[3].fsPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ import (
|
||||||
"github.com/sftpgo/sdk"
|
"github.com/sftpgo/sdk"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/studio-b12/gowebdav"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/internal/common"
|
"github.com/drakkan/sftpgo/v2/internal/common"
|
||||||
|
@ -61,6 +62,7 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/internal/smtp"
|
"github.com/drakkan/sftpgo/v2/internal/smtp"
|
||||||
"github.com/drakkan/sftpgo/v2/internal/util"
|
"github.com/drakkan/sftpgo/v2/internal/util"
|
||||||
"github.com/drakkan/sftpgo/v2/internal/vfs"
|
"github.com/drakkan/sftpgo/v2/internal/vfs"
|
||||||
|
"github.com/drakkan/sftpgo/v2/internal/webdavd"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -68,6 +70,7 @@ const (
|
||||||
httpProxyAddr = "127.0.0.1:7777"
|
httpProxyAddr = "127.0.0.1:7777"
|
||||||
sftpServerAddr = "127.0.0.1:4022"
|
sftpServerAddr = "127.0.0.1:4022"
|
||||||
smtpServerAddr = "127.0.0.1:2525"
|
smtpServerAddr = "127.0.0.1:2525"
|
||||||
|
webDavServerPort = 9191
|
||||||
defaultUsername = "test_common_sftp"
|
defaultUsername = "test_common_sftp"
|
||||||
defaultPassword = "test_password"
|
defaultPassword = "test_password"
|
||||||
defaultSFTPUsername = "test_common_sftpfs_user"
|
defaultSFTPUsername = "test_common_sftpfs_user"
|
||||||
|
@ -145,6 +148,13 @@ func TestMain(m *testing.M) {
|
||||||
httpdConf.Bindings[0].Port = 4080
|
httpdConf.Bindings[0].Port = 4080
|
||||||
httpdtest.SetBaseURL("http://127.0.0.1:4080")
|
httpdtest.SetBaseURL("http://127.0.0.1:4080")
|
||||||
|
|
||||||
|
webDavConf := config.GetWebDAVDConfig()
|
||||||
|
webDavConf.Bindings = []webdavd.Binding{
|
||||||
|
{
|
||||||
|
Port: webDavServerPort,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := sftpdConf.Initialize(configDir); err != nil {
|
if err := sftpdConf.Initialize(configDir); err != nil {
|
||||||
logger.ErrorToConsole("could not start SFTP server: %v", err)
|
logger.ErrorToConsole("could not start SFTP server: %v", err)
|
||||||
|
@ -159,8 +169,16 @@ func TestMain(m *testing.M) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := webDavConf.Initialize(configDir); err != nil {
|
||||||
|
logger.ErrorToConsole("could not start WebDAV server: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
waitTCPListening(sftpdConf.Bindings[0].GetAddress())
|
waitTCPListening(sftpdConf.Bindings[0].GetAddress())
|
||||||
waitTCPListening(httpdConf.Bindings[0].GetAddress())
|
waitTCPListening(httpdConf.Bindings[0].GetAddress())
|
||||||
|
waitTCPListening(webDavConf.Bindings[0].GetAddress())
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// start a test HTTP server to receive action notifications
|
// start a test HTTP server to receive action notifications
|
||||||
|
@ -315,6 +333,50 @@ func TestBaseConnection(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoveAll(t *testing.T) {
|
||||||
|
u := getTestUser()
|
||||||
|
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
webDavClient := getWebDavClient(user)
|
||||||
|
err = webDavClient.RemoveAll("/")
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.True(t, gowebdav.IsErrCode(err, http.StatusForbidden))
|
||||||
|
}
|
||||||
|
|
||||||
|
testDir := "baseDir"
|
||||||
|
err = webDavClient.RemoveAll(testDir)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
conn, client, err := getSftpClient(user)
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
defer conn.Close()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
err = client.Mkdir(testDir)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = writeSFTPFile(path.Join(testDir, testFileName), 1234, client)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = webDavClient.RemoveAll(path.Join(testDir, testFileName))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = client.Stat(path.Join(testDir, testFileName))
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
err = writeSFTPFile(path.Join(testDir, testFileName), 1234, client)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = webDavClient.RemoveAll(testDir)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = client.Stat(testDir)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = os.RemoveAll(user.GetHomeDir())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestRelativeSymlinks(t *testing.T) {
|
func TestRelativeSymlinks(t *testing.T) {
|
||||||
u := getTestUser()
|
u := getTestUser()
|
||||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||||
|
@ -2951,6 +3013,8 @@ func TestResolvePathError(t *testing.T) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
_, err = conn.DoStat(testPath, 0, false)
|
_, err = conn.DoStat(testPath, 0, false)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
err = conn.RemoveAll(testPath)
|
||||||
|
assert.Error(t, err)
|
||||||
err = conn.SetStat(testPath, &common.StatAttributes{
|
err = conn.SetStat(testPath, &common.StatAttributes{
|
||||||
Atime: time.Now(),
|
Atime: time.Now(),
|
||||||
Mtime: time.Now(),
|
Mtime: time.Now(),
|
||||||
|
@ -6409,6 +6473,17 @@ func getSftpClient(user dataprovider.User) (*ssh.Client, *sftp.Client, error) {
|
||||||
return conn, sftpClient, err
|
return conn, sftpClient, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getWebDavClient(user dataprovider.User) *gowebdav.Client {
|
||||||
|
rootPath := fmt.Sprintf("http://localhost:%d/", webDavServerPort)
|
||||||
|
pwd := defaultPassword
|
||||||
|
if user.Password != "" {
|
||||||
|
pwd = user.Password
|
||||||
|
}
|
||||||
|
client := gowebdav.NewClient(rootPath, user.Username, pwd)
|
||||||
|
client.SetTimeout(10 * time.Second)
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
func getTestUser() dataprovider.User {
|
func getTestUser() dataprovider.User {
|
||||||
user := dataprovider.User{
|
user := dataprovider.User{
|
||||||
BaseUser: sdk.BaseUser{
|
BaseUser: sdk.BaseUser{
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestTransferUpdateQuota(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
transfer.ErrTransfer = errFake
|
transfer.ErrTransfer = errFake
|
||||||
transfer.Fs = newMockOsFs(true, "", "", "S3Fs fake")
|
transfer.Fs = newMockOsFs(true, "", "", "S3Fs fake", nil)
|
||||||
assert.False(t, transfer.updateQuota(1, 0))
|
assert.False(t, transfer.updateQuota(1, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,12 +119,12 @@ func deleteUserDir(w http.ResponseWriter, r *http.Request) {
|
||||||
defer common.Connections.Remove(connection.GetID())
|
defer common.Connections.Remove(connection.GetID())
|
||||||
|
|
||||||
name := connection.User.GetCleanedPath(r.URL.Query().Get("path"))
|
name := connection.User.GetCleanedPath(r.URL.Query().Get("path"))
|
||||||
err = connection.RemoveDir(name)
|
err = connection.RemoveAll(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sendAPIResponse(w, r, err, fmt.Sprintf("Unable to delete directory %#v", name), getMappedStatusCode(err))
|
sendAPIResponse(w, r, err, fmt.Sprintf("Unable to delete directory %q", name), getMappedStatusCode(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sendAPIResponse(w, r, nil, fmt.Sprintf("Directory %#v deleted", name), http.StatusOK)
|
sendAPIResponse(w, r, nil, fmt.Sprintf("Directory %q deleted", name), http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserFile(w http.ResponseWriter, r *http.Request) {
|
func getUserFile(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -112,21 +112,7 @@ func (c *Connection) RemoveAll(ctx context.Context, name string) error {
|
||||||
c.UpdateLastActivity()
|
c.UpdateLastActivity()
|
||||||
|
|
||||||
name = util.CleanPath(name)
|
name = util.CleanPath(name)
|
||||||
fs, p, err := c.GetFsAndResolvedPath(name)
|
return c.BaseConnection.RemoveAll(name)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var fi os.FileInfo
|
|
||||||
if fi, err = fs.Lstat(p); err != nil {
|
|
||||||
c.Log(logger.LevelDebug, "failed to remove file %#v: stat error: %+v", p, err)
|
|
||||||
return c.GetFsError(fs, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi.IsDir() && fi.Mode()&os.ModeSymlink == 0 {
|
|
||||||
return c.removeDirTree(fs, p, name)
|
|
||||||
}
|
|
||||||
return c.RemoveFile(fs, p, name, fi)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenFile opens the named file with specified flag.
|
// OpenFile opens the named file with specified flag.
|
||||||
|
@ -290,111 +276,3 @@ func (c *Connection) handleUploadToExistingFile(fs vfs.Fs, resolvedPath, filePat
|
||||||
|
|
||||||
return newWebDavFile(baseTransfer, w, nil), nil
|
return newWebDavFile(baseTransfer, w, nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type objectMapping struct {
|
|
||||||
fsPath string
|
|
||||||
virtualPath string
|
|
||||||
info os.FileInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Connection) removeDirTree(fs vfs.Fs, fsPath, virtualPath string) error {
|
|
||||||
var dirsToRemove []objectMapping
|
|
||||||
var filesToRemove []objectMapping
|
|
||||||
|
|
||||||
err := fs.Walk(fsPath, func(walkedPath string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
obj := objectMapping{
|
|
||||||
fsPath: walkedPath,
|
|
||||||
virtualPath: fs.GetRelativePath(walkedPath),
|
|
||||||
info: info,
|
|
||||||
}
|
|
||||||
if info.IsDir() {
|
|
||||||
err = c.IsRemoveDirAllowed(fs, obj.fsPath, obj.virtualPath)
|
|
||||||
isDuplicated := false
|
|
||||||
for _, d := range dirsToRemove {
|
|
||||||
if d.fsPath == obj.fsPath {
|
|
||||||
isDuplicated = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !isDuplicated {
|
|
||||||
dirsToRemove = append(dirsToRemove, obj)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = c.IsRemoveFileAllowed(obj.virtualPath)
|
|
||||||
filesToRemove = append(filesToRemove, obj)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
c.Log(logger.LevelDebug, "unable to remove dir tree, object %#v->%#v cannot be removed: %v",
|
|
||||||
virtualPath, fsPath, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
c.Log(logger.LevelError, "failed to remove dir tree %#v->%#v: error: %+v", virtualPath, fsPath, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, fileObj := range filesToRemove {
|
|
||||||
err = c.RemoveFile(fs, fileObj.fsPath, fileObj.virtualPath, fileObj.info)
|
|
||||||
if err != nil {
|
|
||||||
c.Log(logger.LevelDebug, "unable to remove dir tree, error removing file %#v->%#v: %v",
|
|
||||||
fileObj.virtualPath, fileObj.fsPath, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, dirObj := range c.orderDirsToRemove(fs, dirsToRemove) {
|
|
||||||
err = c.RemoveDir(dirObj.virtualPath)
|
|
||||||
if err != nil {
|
|
||||||
c.Log(logger.LevelDebug, "unable to remove dir tree, error removing directory %#v->%#v: %v",
|
|
||||||
dirObj.virtualPath, dirObj.fsPath, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// order directories so that the empty ones will be at slice start
|
|
||||||
func (c *Connection) orderDirsToRemove(fs vfs.Fs, dirsToRemove []objectMapping) []objectMapping {
|
|
||||||
orderedDirs := make([]objectMapping, 0, len(dirsToRemove))
|
|
||||||
removedDirs := make([]string, 0, len(dirsToRemove))
|
|
||||||
|
|
||||||
pathSeparator := "/"
|
|
||||||
if vfs.IsLocalOsFs(fs) {
|
|
||||||
pathSeparator = string(os.PathSeparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
for len(orderedDirs) < len(dirsToRemove) {
|
|
||||||
for idx, d := range dirsToRemove {
|
|
||||||
if util.Contains(removedDirs, d.fsPath) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
isEmpty := true
|
|
||||||
for idx1, d1 := range dirsToRemove {
|
|
||||||
if idx == idx1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if util.Contains(removedDirs, d1.fsPath) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(d1.fsPath, d.fsPath+pathSeparator) {
|
|
||||||
isEmpty = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isEmpty {
|
|
||||||
orderedDirs = append(orderedDirs, d)
|
|
||||||
removedDirs = append(removedDirs, d.fsPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return orderedDirs
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -272,11 +271,6 @@ xr5cb9VBRBtB9aOKVfuRhpatAfS2Pzm2Htae9lFn7slGPUmu2hkjDw==
|
||||||
-----END RSA PRIVATE KEY-----`
|
-----END RSA PRIVATE KEY-----`
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
errWalkDir = errors.New("err walk dir")
|
|
||||||
errWalkFile = errors.New("err walk file")
|
|
||||||
)
|
|
||||||
|
|
||||||
// MockOsFs mockable OsFs
|
// MockOsFs mockable OsFs
|
||||||
type MockOsFs struct {
|
type MockOsFs struct {
|
||||||
vfs.Fs
|
vfs.Fs
|
||||||
|
@ -315,86 +309,22 @@ func (fs *MockOsFs) Remove(name string, isDir bool) error {
|
||||||
|
|
||||||
// Rename renames (moves) source to target
|
// Rename renames (moves) source to target
|
||||||
func (fs *MockOsFs) Rename(source, target string) error {
|
func (fs *MockOsFs) Rename(source, target string) error {
|
||||||
if fs.err != nil {
|
|
||||||
return fs.err
|
|
||||||
}
|
|
||||||
return os.Rename(source, target)
|
return os.Rename(source, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk returns a duplicate path for testing
|
|
||||||
func (fs *MockOsFs) Walk(root string, walkFn filepath.WalkFunc) error {
|
|
||||||
if fs.err == errWalkDir {
|
|
||||||
walkFn("fsdpath", vfs.NewFileInfo("dpath", true, 0, time.Now(), false), nil) //nolint:errcheck
|
|
||||||
walkFn("fsdpath", vfs.NewFileInfo("dpath", true, 0, time.Now(), false), nil) //nolint:errcheck
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
walkFn("fsfpath", vfs.NewFileInfo("fpath", false, 0, time.Now(), false), nil) //nolint:errcheck
|
|
||||||
return fs.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMimeType returns the content type
|
// GetMimeType returns the content type
|
||||||
func (fs *MockOsFs) GetMimeType(name string) (string, error) {
|
func (fs *MockOsFs) GetMimeType(name string) (string, error) {
|
||||||
return "application/custom-mime", nil
|
return "application/custom-mime", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMockOsFs(err error, atomicUpload bool, connectionID, rootDir string, reader *pipeat.PipeReaderAt) vfs.Fs {
|
func newMockOsFs(atomicUpload bool, connectionID, rootDir string, reader *pipeat.PipeReaderAt) vfs.Fs {
|
||||||
return &MockOsFs{
|
return &MockOsFs{
|
||||||
Fs: vfs.NewOsFs(connectionID, rootDir, ""),
|
Fs: vfs.NewOsFs(connectionID, rootDir, ""),
|
||||||
err: err,
|
|
||||||
isAtomicUploadSupported: atomicUpload,
|
isAtomicUploadSupported: atomicUpload,
|
||||||
reader: reader,
|
reader: reader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOrderDirsToRemove(t *testing.T) {
|
|
||||||
user := dataprovider.User{}
|
|
||||||
fs := vfs.NewOsFs("id", os.TempDir(), "")
|
|
||||||
connection := &Connection{
|
|
||||||
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
|
|
||||||
request: nil,
|
|
||||||
}
|
|
||||||
dirsToRemove := []objectMapping{}
|
|
||||||
|
|
||||||
orderedDirs := connection.orderDirsToRemove(fs, dirsToRemove)
|
|
||||||
assert.Equal(t, len(dirsToRemove), len(orderedDirs))
|
|
||||||
|
|
||||||
dirsToRemove = []objectMapping{
|
|
||||||
{
|
|
||||||
fsPath: "dir1",
|
|
||||||
virtualPath: "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
orderedDirs = connection.orderDirsToRemove(fs, dirsToRemove)
|
|
||||||
assert.Equal(t, len(dirsToRemove), len(orderedDirs))
|
|
||||||
|
|
||||||
dirsToRemove = []objectMapping{
|
|
||||||
{
|
|
||||||
fsPath: "dir1",
|
|
||||||
virtualPath: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fsPath: "dir12",
|
|
||||||
virtualPath: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fsPath: filepath.Join("dir1", "a", "b"),
|
|
||||||
virtualPath: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fsPath: filepath.Join("dir1", "a"),
|
|
||||||
virtualPath: "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
orderedDirs = connection.orderDirsToRemove(fs, dirsToRemove)
|
|
||||||
if assert.Equal(t, len(dirsToRemove), len(orderedDirs)) {
|
|
||||||
assert.Equal(t, "dir12", orderedDirs[0].fsPath)
|
|
||||||
assert.Equal(t, filepath.Join("dir1", "a", "b"), orderedDirs[1].fsPath)
|
|
||||||
assert.Equal(t, filepath.Join("dir1", "a"), orderedDirs[2].fsPath)
|
|
||||||
assert.Equal(t, "dir1", orderedDirs[3].fsPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUserInvalidParams(t *testing.T) {
|
func TestUserInvalidParams(t *testing.T) {
|
||||||
u := &dataprovider.User{
|
u := &dataprovider.User{
|
||||||
BaseUser: sdk.BaseUser{
|
BaseUser: sdk.BaseUser{
|
||||||
|
@ -643,7 +573,7 @@ func TestFileAccessErrors(t *testing.T) {
|
||||||
assert.ErrorIs(t, err, os.ErrNotExist)
|
assert.ErrorIs(t, err, os.ErrNotExist)
|
||||||
}
|
}
|
||||||
|
|
||||||
fs = newMockOsFs(nil, false, fs.ConnectionID(), user.HomeDir, nil)
|
fs = newMockOsFs(false, fs.ConnectionID(), user.HomeDir, nil)
|
||||||
_, err = connection.handleUploadToExistingFile(fs, p, p, 0, path.Join("adir", missingPath))
|
_, err = connection.handleUploadToExistingFile(fs, p, p, 0, path.Join("adir", missingPath))
|
||||||
if assert.Error(t, err) {
|
if assert.Error(t, err) {
|
||||||
assert.ErrorIs(t, err, os.ErrNotExist)
|
assert.ErrorIs(t, err, os.ErrNotExist)
|
||||||
|
@ -706,59 +636,6 @@ func TestFileAccessErrors(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveDirTree(t *testing.T) {
|
|
||||||
user := dataprovider.User{
|
|
||||||
BaseUser: sdk.BaseUser{
|
|
||||||
HomeDir: filepath.Clean(os.TempDir()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
user.Permissions = make(map[string][]string)
|
|
||||||
user.Permissions["/"] = []string{dataprovider.PermAny}
|
|
||||||
fs := vfs.NewOsFs("connID", user.HomeDir, "")
|
|
||||||
connection := &Connection{
|
|
||||||
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
|
|
||||||
}
|
|
||||||
|
|
||||||
vpath := path.Join("adir", "missing")
|
|
||||||
p := filepath.Join(user.HomeDir, "adir", "missing")
|
|
||||||
err := connection.removeDirTree(fs, p, vpath)
|
|
||||||
if assert.Error(t, err) {
|
|
||||||
assert.True(t, fs.IsNotExist(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
fs = newMockOsFs(nil, false, "mockID", user.HomeDir, nil)
|
|
||||||
err = connection.removeDirTree(fs, p, vpath)
|
|
||||||
if assert.Error(t, err) {
|
|
||||||
assert.True(t, fs.IsNotExist(err), "unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
errFake := errors.New("fake err")
|
|
||||||
fs = newMockOsFs(errFake, false, "mockID", user.HomeDir, nil)
|
|
||||||
err = connection.removeDirTree(fs, p, vpath)
|
|
||||||
if assert.Error(t, err) {
|
|
||||||
assert.EqualError(t, err, errFake.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
fs = newMockOsFs(errWalkDir, true, "mockID", user.HomeDir, nil)
|
|
||||||
err = connection.removeDirTree(fs, p, vpath)
|
|
||||||
if assert.Error(t, err) {
|
|
||||||
assert.True(t, fs.IsPermission(err), "unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fs = newMockOsFs(errWalkFile, false, "mockID", user.HomeDir, nil)
|
|
||||||
err = connection.removeDirTree(fs, p, vpath)
|
|
||||||
if assert.Error(t, err) {
|
|
||||||
assert.EqualError(t, err, errWalkFile.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
connection.User.Permissions["/"] = []string{dataprovider.PermListItems}
|
|
||||||
fs = newMockOsFs(nil, false, "mockID", user.HomeDir, nil)
|
|
||||||
err = connection.removeDirTree(fs, p, vpath)
|
|
||||||
if assert.Error(t, err) {
|
|
||||||
assert.EqualError(t, err, common.ErrPermissionDenied.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContentType(t *testing.T) {
|
func TestContentType(t *testing.T) {
|
||||||
user := dataprovider.User{
|
user := dataprovider.User{
|
||||||
BaseUser: sdk.BaseUser{
|
BaseUser: sdk.BaseUser{
|
||||||
|
@ -775,7 +652,7 @@ func TestContentType(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
baseTransfer := common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath, testFilePath, testFile,
|
baseTransfer := common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath, testFilePath, testFile,
|
||||||
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{})
|
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{})
|
||||||
fs = newMockOsFs(nil, false, fs.ConnectionID(), user.GetHomeDir(), nil)
|
fs = newMockOsFs(false, fs.ConnectionID(), user.GetHomeDir(), nil)
|
||||||
err := os.WriteFile(testFilePath, []byte(""), os.ModePerm)
|
err := os.WriteFile(testFilePath, []byte(""), os.ModePerm)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
davFile := newWebDavFile(baseTransfer, nil, nil)
|
davFile := newWebDavFile(baseTransfer, nil, nil)
|
||||||
|
@ -873,7 +750,7 @@ func TestTransferReadWriteErrors(t *testing.T) {
|
||||||
|
|
||||||
r, w, err = pipeat.Pipe()
|
r, w, err = pipeat.Pipe()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
mockFs := newMockOsFs(nil, false, fs.ConnectionID(), user.HomeDir, r)
|
mockFs := newMockOsFs(false, fs.ConnectionID(), user.HomeDir, r)
|
||||||
baseTransfer = common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath, testFilePath, testFile,
|
baseTransfer = common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath, testFilePath, testFile,
|
||||||
common.TransferDownload, 0, 0, 0, 0, false, mockFs, dataprovider.TransferQuota{})
|
common.TransferDownload, 0, 0, 0, 0, false, mockFs, dataprovider.TransferQuota{})
|
||||||
davFile = newWebDavFile(baseTransfer, nil, nil)
|
davFile = newWebDavFile(baseTransfer, nil, nil)
|
||||||
|
@ -974,13 +851,13 @@ func TestTransferSeek(t *testing.T) {
|
||||||
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{AllowedTotalSize: 100})
|
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{AllowedTotalSize: 100})
|
||||||
davFile = newWebDavFile(baseTransfer, nil, nil)
|
davFile = newWebDavFile(baseTransfer, nil, nil)
|
||||||
davFile.reader = f
|
davFile.reader = f
|
||||||
davFile.Fs = newMockOsFs(nil, true, fs.ConnectionID(), user.GetHomeDir(), nil)
|
davFile.Fs = newMockOsFs(true, fs.ConnectionID(), user.GetHomeDir(), nil)
|
||||||
res, err = davFile.Seek(2, io.SeekStart)
|
res, err = davFile.Seek(2, io.SeekStart)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(2), res)
|
assert.Equal(t, int64(2), res)
|
||||||
|
|
||||||
davFile = newWebDavFile(baseTransfer, nil, nil)
|
davFile = newWebDavFile(baseTransfer, nil, nil)
|
||||||
davFile.Fs = newMockOsFs(nil, true, fs.ConnectionID(), user.GetHomeDir(), nil)
|
davFile.Fs = newMockOsFs(true, fs.ConnectionID(), user.GetHomeDir(), nil)
|
||||||
res, err = davFile.Seek(2, io.SeekEnd)
|
res, err = davFile.Seek(2, io.SeekEnd)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(5), res)
|
assert.Equal(t, int64(5), res)
|
||||||
|
@ -989,7 +866,7 @@ func TestTransferSeek(t *testing.T) {
|
||||||
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{AllowedTotalSize: 100})
|
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{AllowedTotalSize: 100})
|
||||||
|
|
||||||
davFile = newWebDavFile(baseTransfer, nil, nil)
|
davFile = newWebDavFile(baseTransfer, nil, nil)
|
||||||
davFile.Fs = newMockOsFs(nil, true, fs.ConnectionID(), user.GetHomeDir(), nil)
|
davFile.Fs = newMockOsFs(true, fs.ConnectionID(), user.GetHomeDir(), nil)
|
||||||
res, err = davFile.Seek(2, io.SeekEnd)
|
res, err = davFile.Seek(2, io.SeekEnd)
|
||||||
assert.True(t, fs.IsNotExist(err))
|
assert.True(t, fs.IsNotExist(err))
|
||||||
assert.Equal(t, int64(0), res)
|
assert.Equal(t, int64(0), res)
|
||||||
|
|
|
@ -594,8 +594,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
var itemType = getTypeFromMeta(selected);
|
var itemType = getTypeFromMeta(selected);
|
||||||
var itemName = getNameFromMeta(selected);
|
var itemName = getNameFromMeta(selected);
|
||||||
var path;
|
var path;
|
||||||
|
var reqTimeout = 15000;
|
||||||
if (itemType == "1"){
|
if (itemType == "1"){
|
||||||
path = '{{.DirsURL}}';
|
path = '{{.DirsURL}}';
|
||||||
|
reqTimeout = 90000
|
||||||
} else {
|
} else {
|
||||||
path = '{{.FilesURL}}';
|
path = '{{.FilesURL}}';
|
||||||
}
|
}
|
||||||
|
@ -606,7 +608,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
type: 'DELETE',
|
type: 'DELETE',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
headers: { 'X-CSRF-TOKEN': '{{.CSRFToken}}' },
|
headers: { 'X-CSRF-TOKEN': '{{.CSRFToken}}' },
|
||||||
timeout: 60000,
|
timeout: reqTimeout,
|
||||||
success: function (result) {
|
success: function (result) {
|
||||||
index++;
|
index++;
|
||||||
success++;
|
success++;
|
||||||
|
|
Loading…
Reference in a new issue