@@ -42,6 +42,10 @@ public function initialize(\Sabre\DAV\Server $server): void {
4242 }
4343
4444 public function onMkcol (RequestInterface $ request , ResponseInterface $ response ) {
45+ if ($ this ->isChunkedUpload ($ request )) {
46+ return ;
47+ }
48+
4549 if (!$ this ->enabled || $ this ->share === null ) {
4650 return ;
4751 }
@@ -58,7 +62,18 @@ public function onMkcol(RequestInterface $request, ResponseInterface $response)
5862 return false ;
5963 }
6064
65+ private function isChunkedUpload (RequestInterface $ request ): bool {
66+ return str_starts_with (substr ($ request ->getUrl (), strlen ($ request ->getBaseUrl ()) - 1 ), '/uploads/ ' );
67+ }
68+
6169 public function beforeMethod (RequestInterface $ request , ResponseInterface $ response ) {
70+ $ isChunkedUpload = $ this ->isChunkedUpload ($ request );
71+
72+ // For the PUT and MOVE requests of a chunked upload it is necessary to modify the Destination header.
73+ if ($ isChunkedUpload && $ request ->getMethod () !== 'MOVE ' && $ request ->getMethod () !== 'PUT ' ) {
74+ return ;
75+ }
76+
6277 if (!$ this ->enabled || $ this ->share === null ) {
6378 return ;
6479 }
@@ -68,21 +83,25 @@ public function beforeMethod(RequestInterface $request, ResponseInterface $respo
6883 return ;
6984 }
7085
86+ if ($ request ->getMethod () !== 'PUT ' && $ request ->getMethod () !== 'MKCOL ' && (!$ isChunkedUpload || $ request ->getMethod () !== 'MOVE ' )) {
87+ throw new MethodNotAllowed ('Only PUT, MKCOL and MOVE are allowed on files drop ' );
88+ }
89+
90+ // Extract the attributes for the file request
91+ $ isFileRequest = false ;
92+ $ attributes = $ this ->share ->getAttributes ();
93+ if ($ attributes !== null ) {
94+ $ isFileRequest = $ attributes ->getAttribute ('fileRequest ' , 'enabled ' ) === true ;
95+ }
96+
7197 // Retrieve the nickname from the request
7298 $ nickname = $ request ->hasHeader ('X-NC-Nickname ' )
7399 ? trim (urldecode ($ request ->getHeader ('X-NC-Nickname ' )))
74100 : null ;
75101
76- if ($ request ->getMethod () !== 'PUT ' ) {
77- // If uploading subfolders we need to ensure they get created
78- // within the nickname folder
79- if ($ request ->getMethod () === 'MKCOL ' ) {
80- if (!$ nickname ) {
81- throw new BadRequest ('A nickname header is required when uploading subfolders ' );
82- }
83- } else {
84- throw new MethodNotAllowed ('Only PUT is allowed on files drop ' );
85- }
102+ // We need a valid nickname for file requests
103+ if ($ isFileRequest && !$ nickname ) {
104+ throw new BadRequest ('A nickname header is required for file requests ' );
86105 }
87106
88107 // If this is a folder creation request
@@ -95,35 +114,22 @@ public function beforeMethod(RequestInterface $request, ResponseInterface $respo
95114 // full path along the way. We'll only handle conflict
96115 // resolution on file conflicts, but not on folders.
97116
98- // e.g files/dCP8yn3N86EK9sL/Folder/image.jpg
99- $ path = $ request ->getPath ();
117+ if ($ isChunkedUpload ) {
118+ $ destination = $ request ->getHeader ('destination ' );
119+ $ baseUrl = $ request ->getBaseUrl ();
120+ // e.g files/dCP8yn3N86EK9sL/Folder/image.jpg
121+ $ path = substr ($ destination , strpos ($ destination , $ baseUrl ) + strlen ($ baseUrl ));
122+ } else {
123+ // e.g files/dCP8yn3N86EK9sL/Folder/image.jpg
124+ $ path = $ request ->getPath ();
125+ }
126+
100127 $ token = $ this ->share ->getToken ();
101128
102129 // e.g files/dCP8yn3N86EK9sL
103130 $ rootPath = substr ($ path , 0 , strpos ($ path , $ token ) + strlen ($ token ));
104131 // e.g /Folder/image.jpg
105132 $ relativePath = substr ($ path , strlen ($ rootPath ));
106- $ isRootUpload = substr_count ($ relativePath , '/ ' ) === 1 ;
107-
108- // Extract the attributes for the file request
109- $ isFileRequest = false ;
110- $ attributes = $ this ->share ->getAttributes ();
111- if ($ attributes !== null ) {
112- $ isFileRequest = $ attributes ->getAttribute ('fileRequest ' , 'enabled ' ) === true ;
113- }
114-
115- // We need a valid nickname for file requests
116- if ($ isFileRequest && !$ nickname ) {
117- throw new BadRequest ('A nickname header is required for file requests ' );
118- }
119-
120- // We're only allowing the upload of
121- // long path with subfolders if a nickname is set.
122- // This prevents confusion when uploading files and help
123- // classify them by uploaders.
124- if (!$ nickname && !$ isRootUpload ) {
125- throw new BadRequest ('A nickname header is required when uploading subfolders ' );
126- }
127133
128134 if ($ nickname ) {
129135 try {
@@ -187,7 +193,11 @@ public function beforeMethod(RequestInterface $request, ResponseInterface $respo
187193 $ relativePath = substr ($ folder ->getPath (), strlen ($ node ->getPath ()));
188194 $ path = '/files/ ' . $ token . '/ ' . $ relativePath . '/ ' . $ uniqueName ;
189195 $ url = rtrim ($ request ->getBaseUrl (), '/ ' ) . str_replace ('// ' , '/ ' , $ path );
190- $ request ->setUrl ($ url );
196+ if ($ isChunkedUpload ) {
197+ $ request ->setHeader ('destination ' , $ url );
198+ } else {
199+ $ request ->setUrl ($ url );
200+ }
191201 }
192202
193203 private function getPathSegments (string $ path ): array {
0 commit comments