1414use  OCA \Richdocuments \Db \WopiMapper ;
1515use  OCA \Richdocuments \Exceptions \ExpiredTokenException ;
1616use  OCA \Richdocuments \Exceptions \UnknownTokenException ;
17+ use  OCA \Richdocuments \Exceptions \WopiException ;
1718use  OCA \Richdocuments \Helper ;
19+ use  OCA \Richdocuments \Service \DiscoveryService ;
20+ use  OCA \Richdocuments \Service \ProofKeyService ;
1821use  OCP \AppFramework \Http ;
1922use  OCP \AppFramework \Http \JSONResponse ;
2023use  OCP \AppFramework \Http \Response ;
2124use  OCP \AppFramework \Middleware ;
2225use  OCP \Files \NotPermittedException ;
2326use  OCP \IConfig ;
2427use  OCP \IRequest ;
28+ use  OCP \IURLGenerator ;
2529use  Psr \Log \LoggerInterface ;
2630use  ReflectionClass ;
2731use  ReflectionMethod ;
3034class  WOPIMiddleware extends  Middleware {
3135	public  function  __construct (
3236		private  IConfig $ config
37+ 		private  IURLGenerator $ urlGenerator
3338		private  IRequest $ request
39+ 		private  DiscoveryService $ discoveryService
3440		private  WopiMapper $ wopiMapper
3541		private  LoggerInterface $ logger
42+ 		private  ProofKeyService $ proofKeyService
3643		private  bool  $ isWOPIRequestfalse ,
3744	) {
3845	}
@@ -56,13 +63,52 @@ public function beforeController($controller, $methodName) {
5663			return ;
5764		}
5865
59- 		if  (strpos ($ this request ->getRequestUri (), 'wopi/settings/upload ' ) !==  false ) {
66+ 		if  (str_contains ($ this request ->getRequestUri (), '/ wopi/settings/upload )) {
6067			return ;
6168		}
6269
6370		try  {
64- 			$ fileId$ this request ->getParam ('fileId ' );
6571			$ accessToken$ this request ->getParam ('access_token ' );
72+ 			$ isWopiSettingsUrlstr_contains ($ this request ->getRequestUri (), '/wopi/settings ' );
73+ 
74+ 			if  (!$ isWopiSettingsUrl
75+ 				$ wopiProof$ this request ->getHeader ('X-WOPI-Proof ' );
76+ 				$ wopiProofOld$ this request ->getHeader ('X-WOPI-ProofOld ' );
77+ 				$ hasProofKey$ this discoveryService ->hasProofKey ();
78+ 
79+ 				// This could mean the discovery cache needs to be updated 
80+ 				//     e.g. if Collabora sends a WOPI proof but the cached discovery 
81+ 				//          says there is not one, then we should re-fetch it 
82+ 				if  ($ hasProofKeybool )$ wopiProof
83+ 					$ this discoveryService ->fetch ();
84+ 					$ hasProofKey$ this discoveryService ->hasProofKey ();
85+ 				}
86+ 
87+ 				if  ($ hasProofKey
88+ 					$ wopiTimestamp$ this request ->getHeader ('X-WOPI-TimeStamp ' );
89+ 					$ wopiTimestampIsOld$ this proofKeyService ->isOldTimestamp ((int )$ wopiTimestamp
90+ 
91+ 					if  ($ wopiTimestampIsOld
92+ 						throw  new  WopiException ('X-WOPI-TimeStamp header is older than 20 minutes ' );
93+ 					}
94+ 
95+ 					$ url$ this urlGenerator ->getBaseUrl () . $ this request ->getRequestUri ();
96+ 
97+ 					$ isProofValid$ this proofKeyService ->isProofValid (
98+ 						$ accessToken
99+ 						$ url
100+ 						$ wopiTimestamp
101+ 						$ wopiProof
102+ 						$ wopiProofOld
103+ 					);
104+ 
105+ 					if  (!$ isProofValid
106+ 						throw  new  WopiException ('Invalid WOPI proof ' );
107+ 					}
108+ 				}
109+ 			}
110+ 
111+ 			$ fileId$ this request ->getParam ('fileId ' );
66112			[$ fileIdparseFileId ($ fileId
67113			$ wopi$ this wopiMapper ->getWopiForToken ($ accessToken
68114			if  ((int )$ fileId$ wopigetFileid () && (int )$ fileId$ wopigetTemplateId ()) {
@@ -75,6 +121,11 @@ public function beforeController($controller, $methodName) {
75121				$ this logger ->info ('Invalid token for WOPI access ' , [ 'exception '  => $ e
76122			}
77123			throw  new  NotPermittedException ();
124+ 		} catch  (WopiException $ e
125+ 			$ this logger ->error ('WOPI error:  '  . $ egetMessage (), [
126+ 				'exception '  => $ e
127+ 			]);
128+ 			throw  new  WopiException ();
78129		} catch  (\Exception   $ e
79130			$ this logger ->error ('Failed to validate WOPI access ' , [ 'exception '  => $ e
80131			throw  new  NotPermittedException ();
@@ -84,6 +135,10 @@ public function beforeController($controller, $methodName) {
84135	}
85136
86137	public  function  afterException ($ controller$ methodName\Exception   $ exceptionResponse 
138+ 		if  ($ exceptioninstanceof  WopiException && $ controllerinstanceof  WopiController) {
139+ 			return  new  JSONResponse ([], Http::STATUS_INTERNAL_SERVER_ERROR );
140+ 		}
141+ 
87142		if  ($ exceptioninstanceof  NotPermittedException && $ controllerinstanceof  WopiController) {
88143			return  new  JSONResponse ([], Http::STATUS_FORBIDDEN );
89144		}
0 commit comments