LibreOffice Module ucb (master)  1
DAVResourceAccess.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <com/sun/star/task/XInteractionAbort.hpp>
22 #include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
23 
26 #include <sal/log.hxx>
27 
28 #include "DAVAuthListenerImpl.hxx"
29 #include "DAVResourceAccess.hxx"
30 
31 #include <com/sun/star/lang/IllegalArgumentException.hpp>
32 #include <com/sun/star/io/IOException.hpp>
33 
34 using namespace http_dav_ucp;
35 using namespace com::sun::star;
36 
37 
38 // DAVAuthListener_Impl Implementation.
39 
40 
41 // virtual
43  const OUString & inRealm,
44  const OUString & inHostName,
45  OUString & inoutUserName,
46  OUString & outPassWord,
47  bool bCanUseSystemCredentials,
48  bool bUsePreviousCredentials )
49 {
50  if ( m_xEnv.is() )
51  {
52  uno::Reference< task::XInteractionHandler > xIH
53  = m_xEnv->getInteractionHandler();
54 
55  if ( xIH.is() )
56  {
57  // Providing previously retrieved credentials will cause the password
58  // container to reject these. Thus, the credential input dialog will be shown again.
59  // #102871# - Supply username and password from previous try.
60  // Password container service depends on this!
61  if ( inoutUserName.isEmpty() && bUsePreviousCredentials )
62  inoutUserName = m_aPrevUsername;
63 
64  if ( outPassWord.isEmpty() && bUsePreviousCredentials )
65  outPassWord = m_aPrevPassword;
66 
69  m_aURL, inHostName, inRealm, inoutUserName,
70  outPassWord,
71  bCanUseSystemCredentials );
72  xIH->handle( xRequest );
73 
75  = xRequest->getSelection();
76 
77  if ( xSelection.is() )
78  {
79  // Handler handled the request.
80  uno::Reference< task::XInteractionAbort > xAbort(
81  xSelection.get(), uno::UNO_QUERY );
82  if ( !xAbort.is() )
83  {
84  const rtl::Reference<
85  ucbhelper::InteractionSupplyAuthentication > & xSupp
86  = xRequest->getAuthenticationSupplier();
87 
88  bool bUseSystemCredentials = false;
89 
90  if ( bCanUseSystemCredentials )
91  bUseSystemCredentials
92  = xSupp->getUseSystemCredentials();
93 
94  if ( bUseSystemCredentials )
95  {
96  // This is the (strange) way to tell neon to use
97  // system credentials.
98  inoutUserName.clear();
99  outPassWord.clear();
100  }
101  else
102  {
103  inoutUserName = xSupp->getUserName();
104  outPassWord = xSupp->getPassword();
105  }
106 
107  // #102871# - Remember username and password.
108  m_aPrevUsername = inoutUserName;
109  m_aPrevPassword = outPassWord;
110 
111  // go on.
112  return 0;
113  }
114  }
115  }
116  }
117  // Abort.
118  return -1;
119 }
120 
121 
122 // DAVResourceAccess Implementation.
123 
124 
126  const uno::Reference< uno::XComponentContext > & rContext,
127  rtl::Reference< DAVSessionFactory > const & rSessionFactory,
128  const OUString & rURL )
129 : m_aURL( rURL ),
130  m_xSessionFactory( rSessionFactory ),
131  m_xContext( rContext )
132 , m_nRedirectLimit( 5 )
133 {
134 }
135 
136 
138 : m_aURL( rOther.m_aURL ),
139  m_aPath( rOther.m_aPath ),
140  m_aFlags( rOther.m_aFlags ),
141  m_xSession( rOther.m_xSession ),
142  m_xSessionFactory( rOther.m_xSessionFactory ),
143  m_xContext( rOther.m_xContext ),
144  m_aRedirectURIs( rOther.m_aRedirectURIs ),
145  m_nRedirectLimit( rOther.m_nRedirectLimit )
146 {
147 }
148 
149 
151  const DAVResourceAccess & rOther )
152 {
153  m_aURL = rOther.m_aURL;
154  m_aPath = rOther.m_aPath;
155  m_aFlags = rOther.m_aFlags;
156  m_xSession = rOther.m_xSession;
158  m_xContext = rOther.m_xContext;
161 
162  return *this;
163 }
164 
166  DAVOptions & rOptions,
167  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
168 {
169  initialize();
170 
171  int errorCount = 0;
172  bool bRetry;
173  do
174  {
175  bRetry = false;
176  try
177  {
178  DAVRequestHeaders aHeaders;
179 
180  getUserRequestHeaders( xEnv,
181  getRequestURI(),
182  ucb::WebDAVHTTPMethod_OPTIONS,
183  aHeaders );
184 
185  m_xSession->OPTIONS( getRequestURI(),
186  rOptions,
188  new DAVAuthListener_Impl( xEnv, m_aURL ),
189  aHeaders ) );
190  }
191  catch (DAVException const& e)
192  {
193  errorCount++;
194  bRetry = handleException( e, errorCount );
195  if ( !bRetry )
196  throw;
197  }
198  }
199  while ( bRetry );
200 }
201 
203  const Depth nDepth,
204  const std::vector< OUString > & rPropertyNames,
205  std::vector< DAVResource > & rResources,
206  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
207 {
208  initialize();
209 
210  int errorCount = 0;
211  bool bRetry;
212  do
213  {
214  bRetry = false;
215  try
216  {
217  DAVRequestHeaders aHeaders;
218 
219  getUserRequestHeaders( xEnv,
220  getRequestURI(),
221  ucb::WebDAVHTTPMethod_PROPFIND,
222  aHeaders );
223 
224  m_xSession->PROPFIND( getRequestURI(),
225  nDepth,
226  rPropertyNames,
227  rResources,
229  new DAVAuthListener_Impl( xEnv, m_aURL ),
230  aHeaders ) );
231  }
232  catch (DAVException const& e)
233  {
234  errorCount++;
235  bRetry = handleException( e, errorCount );
236  if ( !bRetry )
237  throw;
238  }
239  }
240  while ( bRetry );
241 }
242 
243 
245  const Depth nDepth,
246  std::vector< DAVResourceInfo > & rResInfo,
247  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
248 {
249  initialize();
250 
251  int errorCount = 0;
252  bool bRetry;
253  do
254  {
255  bRetry = false;
256  try
257  {
258  DAVRequestHeaders aHeaders;
259  getUserRequestHeaders( xEnv,
260  getRequestURI(),
261  ucb::WebDAVHTTPMethod_PROPFIND,
262  aHeaders );
263 
264  m_xSession->PROPFIND( getRequestURI(),
265  nDepth,
266  rResInfo,
268  new DAVAuthListener_Impl( xEnv, m_aURL ),
269  aHeaders ) ) ;
270  }
271  catch (DAVException const& e)
272  {
273  errorCount++;
274  bRetry = handleException( e, errorCount );
275  if ( !bRetry )
276  throw;
277  }
278  }
279  while ( bRetry );
280 }
281 
282 
284  const std::vector< ProppatchValue >& rValues,
285  const uno::Reference< ucb::XCommandEnvironment >& xEnv )
286 {
287  initialize();
288 
289  int errorCount = 0;
290  bool bRetry;
291  do
292  {
293  bRetry = false;
294  try
295  {
296  DAVRequestHeaders aHeaders;
297  getUserRequestHeaders( xEnv,
298  getRequestURI(),
299  ucb::WebDAVHTTPMethod_PROPPATCH,
300  aHeaders );
301 
302  m_xSession->PROPPATCH( getRequestURI(),
303  rValues,
305  new DAVAuthListener_Impl( xEnv, m_aURL ),
306  aHeaders ) );
307  }
308  catch (DAVException const& e)
309  {
310  errorCount++;
311  bRetry = handleException( e, errorCount );
312  if ( !bRetry )
313  throw;
314  }
315  }
316  while ( bRetry );
317 }
318 
319 
321  const std::vector< OUString > & rHeaderNames,
322  DAVResource & rResource,
323  const uno::Reference< ucb::XCommandEnvironment >& xEnv )
324 {
325  initialize();
326 
327  int errorCount = 0;
328  bool bRetry;
329  do
330  {
331  bRetry = false;
332  try
333  {
334  DAVRequestHeaders aHeaders;
335  getUserRequestHeaders( xEnv,
336  getRequestURI(),
337  ucb::WebDAVHTTPMethod_HEAD,
338  aHeaders );
339 
340  m_xSession->HEAD( getRequestURI(),
341  rHeaderNames,
342  rResource,
344  new DAVAuthListener_Impl( xEnv, m_aURL ),
345  aHeaders ) );
346  }
347  catch (DAVException const& e)
348  {
349  errorCount++;
350  bRetry = handleException( e, errorCount );
351  if ( !bRetry )
352  throw;
353  }
354  }
355  while ( bRetry );
356 }
357 
358 
359 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
360  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
361 {
362  initialize();
363 
364  uno::Reference< io::XInputStream > xStream;
365  int errorCount = 0;
366  bool bRetry;
367  do
368  {
369  bRetry = false;
370  try
371  {
372  DAVRequestHeaders aHeaders;
373  getUserRequestHeaders( xEnv,
374  getRequestURI(),
375  ucb::WebDAVHTTPMethod_GET,
376  aHeaders );
377 
378  xStream = m_xSession->GET( getRequestURI(),
381  xEnv, m_aURL ),
382  aHeaders ) );
383  }
384  catch (DAVException const& e)
385  {
386  errorCount++;
387  bRetry = handleException( e, errorCount );
388  if ( !bRetry )
389  throw;
390  }
391  }
392  while ( bRetry );
393 
394  return xStream;
395 }
396 
397 
399  uno::Reference< io::XOutputStream > & rStream,
400  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
401 {
402  initialize();
403 
404  int errorCount = 0;
405  bool bRetry;
406  do
407  {
408  bRetry = false;
409  try
410  {
411  DAVRequestHeaders aHeaders;
412  getUserRequestHeaders( xEnv,
413  getRequestURI(),
414  ucb::WebDAVHTTPMethod_GET,
415  aHeaders );
416 
417  m_xSession->GET( getRequestURI(),
418  rStream,
420  new DAVAuthListener_Impl( xEnv, m_aURL ),
421  aHeaders ) );
422  }
423  catch (DAVException const& e)
424  {
425  errorCount++;
426  bRetry = handleException( e, errorCount );
427  if ( !bRetry )
428  throw;
429  }
430  }
431  while ( bRetry );
432 }
433 
434 
435 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
436  const std::vector< OUString > & rHeaderNames,
437  DAVResource & rResource,
438  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
439 {
440  initialize();
441 
442  uno::Reference< io::XInputStream > xStream;
443  int errorCount = 0;
444  bool bRetry;
445  do
446  {
447  bRetry = false;
448  try
449  {
450  DAVRequestHeaders aHeaders;
451  getUserRequestHeaders( xEnv,
452  getRequestURI(),
453  ucb::WebDAVHTTPMethod_GET,
454  aHeaders );
455 
456  xStream = m_xSession->GET( getRequestURI(),
457  rHeaderNames,
458  rResource,
461  xEnv, m_aURL ),
462  aHeaders ) );
463  }
464  catch (DAVException const& e)
465  {
466  errorCount++;
467  bRetry = handleException( e, errorCount );
468  if ( !bRetry )
469  throw;
470  }
471  }
472  while ( bRetry );
473 
474  return xStream;
475 }
476 
477 
478 // used as HEAD substitute when HEAD is not implemented on server
480  DAVRequestHeaders &rRequestHeaders,
481  const std::vector< OUString > & rHeaderNames,
482  DAVResource & rResource,
483  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
484 {
485  initialize();
486 
487  int errorCount = 0;
488  bool bRetry;
489  do
490  {
491  bRetry = false;
492  try
493  {
494  getUserRequestHeaders( xEnv,
495  getRequestURI(),
496  ucb::WebDAVHTTPMethod_GET,
497  rRequestHeaders );
498 
499  m_xSession->GET( getRequestURI(),
500  rHeaderNames,
501  rResource,
504  xEnv, m_aURL ),
505  rRequestHeaders ) );
506  }
507  catch (DAVException const& e)
508  {
509  errorCount++;
510  bRetry = handleException( e, errorCount );
511  if ( !bRetry )
512  throw;
513  }
514  }
515  while ( bRetry );
516 }
517 
518 
520  uno::Reference< io::XOutputStream > & rStream,
521  const std::vector< OUString > & rHeaderNames,
522  DAVResource & rResource,
523  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
524 {
525  initialize();
526 
527  bool bRetry;
528  int errorCount = 0;
529  do
530  {
531  bRetry = false;
532  try
533  {
534  DAVRequestHeaders aHeaders;
535  getUserRequestHeaders( xEnv,
536  getRequestURI(),
537  ucb::WebDAVHTTPMethod_GET,
538  aHeaders );
539 
540  m_xSession->GET( getRequestURI(),
541  rStream,
542  rHeaderNames,
543  rResource,
545  new DAVAuthListener_Impl( xEnv, m_aURL ),
546  aHeaders ) );
547  }
548  catch (DAVException const& e)
549  {
550  errorCount++;
551  bRetry = handleException( e, errorCount );
552  if ( !bRetry )
553  throw;
554  }
555  }
556  while ( bRetry );
557 }
558 
559 
561 {
562  // seems pointless to call initialize() here, but prepare for nullptr
563  decltype(m_xSession) xSession;
564  {
565  osl::Guard<osl::Mutex> const g(m_aMutex);
566  xSession = m_xSession;
567  }
568  if (xSession.is())
569  {
570  xSession->abort();
571  }
572 }
573 
574 
575 namespace {
576 
578  void resetInputStream( const uno::Reference< io::XInputStream > & rStream )
579  {
580  try
581  {
582  uno::Reference< io::XSeekable > xSeekable(
583  rStream, uno::UNO_QUERY );
584  if ( xSeekable.is() )
585  {
586  xSeekable->seek( 0 );
587  return;
588  }
589  }
590  catch ( lang::IllegalArgumentException const & )
591  {
592  }
593  catch ( io::IOException const & )
594  {
595  }
596 
598  }
599 
600 } // namespace
601 
602 
604  const uno::Reference< io::XInputStream > & rStream,
605  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
606 {
607  initialize();
608 
609  // Make stream seekable, if it not. Needed, if request must be retried.
610  uno::Reference< io::XInputStream > xSeekableStream
612  rStream, m_xContext );
613 
614  int errorCount = 0;
615  bool bRetry = false;
616  do
617  {
618  if ( bRetry )
619  resetInputStream( xSeekableStream );
620 
621  bRetry = false;
622  try
623  {
624  DAVRequestHeaders aHeaders;
625  getUserRequestHeaders( xEnv,
626  getRequestURI(),
627  ucb::WebDAVHTTPMethod_PUT,
628  aHeaders );
629 
630  m_xSession->PUT( getRequestURI(),
631  xSeekableStream,
633  new DAVAuthListener_Impl( xEnv, m_aURL ),
634  aHeaders ) );
635  }
636  catch (DAVException const& e)
637  {
638  errorCount++;
639  bRetry = handleException( e, errorCount );
640  if ( !bRetry )
641  throw;
642  }
643  }
644  while ( bRetry );
645 }
646 
647 
648 uno::Reference< io::XInputStream > DAVResourceAccess::POST(
649  const OUString & rContentType,
650  const OUString & rReferer,
651  const uno::Reference< io::XInputStream > & rInputStream,
652  const uno::Reference< ucb::XCommandEnvironment >& xEnv )
653 {
654  initialize();
655 
656  // Make stream seekable, if it not. Needed, if request must be retried.
657  uno::Reference< io::XInputStream > xSeekableStream
659  rInputStream, m_xContext );
660 
661  uno::Reference< io::XInputStream > xStream;
662  int errorCount = 0;
663  bool bRetry = false;
664  do
665  {
666  if ( bRetry )
667  {
668  resetInputStream( xSeekableStream );
669  bRetry = false;
670  }
671 
672  try
673  {
674  DAVRequestHeaders aHeaders;
675  getUserRequestHeaders( xEnv,
676  getRequestURI(),
677  ucb::WebDAVHTTPMethod_POST,
678  aHeaders );
679 
680  xStream = m_xSession->POST( getRequestURI(),
681  rContentType,
682  rReferer,
683  xSeekableStream,
686  xEnv, m_aURL ),
687  aHeaders ) );
688  }
689  catch (DAVException const& e)
690  {
691  errorCount++;
692  bRetry = handleException( e, errorCount );
693  if ( !bRetry )
694  throw;
695 
697  {
698  // #i74980# - Upon POST redirect, do a GET.
699  return GET( xEnv );
700  }
701  }
702  }
703  while ( bRetry );
704 
705  return xStream;
706 }
707 
708 
710  const OUString & rContentType,
711  const OUString & rReferer,
712  const uno::Reference< io::XInputStream > & rInputStream,
713  uno::Reference< io::XOutputStream > & rOutputStream,
714  const uno::Reference< ucb::XCommandEnvironment >& xEnv )
715 {
716  initialize();
717 
718  // Make stream seekable, if it not. Needed, if request must be retried.
719  uno::Reference< io::XInputStream > xSeekableStream
721  rInputStream, m_xContext );
722 
723  int errorCount = 0;
724  bool bRetry = false;
725  do
726  {
727  if ( bRetry )
728  {
729  resetInputStream( xSeekableStream );
730  bRetry = false;
731  }
732 
733  try
734  {
735  DAVRequestHeaders aHeaders;
736  getUserRequestHeaders( xEnv,
737  getRequestURI(),
738  ucb::WebDAVHTTPMethod_POST,
739  aHeaders );
740 
741  m_xSession->POST( getRequestURI(),
742  rContentType,
743  rReferer,
744  xSeekableStream,
745  rOutputStream,
747  new DAVAuthListener_Impl( xEnv, m_aURL ),
748  aHeaders ) );
749  }
750  catch (DAVException const& e)
751  {
752  errorCount++;
753  bRetry = handleException( e, errorCount );
754  if ( !bRetry )
755  throw;
756 
758  {
759  // #i74980# - Upon POST redirect, do a GET.
760  GET( rOutputStream, xEnv );
761  return;
762  }
763  }
764  }
765  while ( bRetry );
766 }
767 
768 
770  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
771 {
772  initialize();
773 
774  int errorCount = 0;
775  bool bRetry;
776  do
777  {
778  bRetry = false;
779  try
780  {
781  DAVRequestHeaders aHeaders;
782  getUserRequestHeaders( xEnv,
783  getRequestURI(),
784  ucb::WebDAVHTTPMethod_MKCOL,
785  aHeaders );
786 
787  m_xSession->MKCOL( getRequestURI(),
789  new DAVAuthListener_Impl( xEnv, m_aURL ),
790  aHeaders ) );
791  }
792  catch (DAVException const& e)
793  {
794  errorCount++;
795  bRetry = handleException( e, errorCount );
796  if ( !bRetry )
797  throw;
798  }
799  }
800  while ( bRetry );
801 }
802 
803 
805  const OUString & rSourcePath,
806  const OUString & rDestinationURI,
807  bool bOverwrite,
808  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
809 {
810  initialize();
811 
812  int errorCount = 0;
813  bool bRetry;
814  do
815  {
816  bRetry = false;
817  try
818  {
819  DAVRequestHeaders aHeaders;
820  getUserRequestHeaders( xEnv,
821  getRequestURI(),
822  ucb::WebDAVHTTPMethod_COPY,
823  aHeaders );
824 
825  m_xSession->COPY( rSourcePath,
826  rDestinationURI,
828  new DAVAuthListener_Impl( xEnv, m_aURL ),
829  aHeaders ),
830  bOverwrite );
831  }
832  catch (DAVException const& e)
833  {
834  errorCount++;
835  bRetry = handleException( e, errorCount );
836  if ( !bRetry )
837  throw;
838  }
839  }
840  while ( bRetry );
841 }
842 
843 
845  const OUString & rSourcePath,
846  const OUString & rDestinationURI,
847  bool bOverwrite,
848  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
849 {
850  initialize();
851 
852  int errorCount = 0;
853  bool bRetry;
854  do
855  {
856  bRetry = false;
857  try
858  {
859  DAVRequestHeaders aHeaders;
860  getUserRequestHeaders( xEnv,
861  getRequestURI(),
862  ucb::WebDAVHTTPMethod_MOVE,
863  aHeaders );
864 
865  m_xSession->MOVE( rSourcePath,
866  rDestinationURI,
868  new DAVAuthListener_Impl( xEnv, m_aURL ),
869  aHeaders ),
870  bOverwrite );
871  }
872  catch (DAVException const& e)
873  {
874  errorCount++;
875  bRetry = handleException( e, errorCount );
876  if ( !bRetry )
877  throw;
878  }
879  }
880  while ( bRetry );
881 }
882 
883 
885  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
886 {
887  initialize();
888 
889  int errorCount = 0;
890  bool bRetry;
891  do
892  {
893  bRetry = false;
894  try
895  {
896  DAVRequestHeaders aHeaders;
897  getUserRequestHeaders( xEnv,
898  getRequestURI(),
899  ucb::WebDAVHTTPMethod_DELETE,
900  aHeaders );
901 
902  m_xSession->DESTROY( getRequestURI(),
904  new DAVAuthListener_Impl( xEnv, m_aURL ),
905  aHeaders ) );
906  }
907  catch (DAVException const& e)
908  {
909  errorCount++;
910  bRetry = handleException( e, errorCount );
911  if ( !bRetry )
912  throw;
913  }
914  }
915  while ( bRetry );
916 }
917 
918 
919 // set new lock.
921  ucb::Lock & inLock,
922  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
923 {
924  initialize();
925 
926  int errorCount = 0;
927  bool bRetry;
928  do
929  {
930  bRetry = false;
931  try
932  {
933  DAVRequestHeaders aHeaders;
934  getUserRequestHeaders( xEnv,
935  getRequestURI(),
936  ucb::WebDAVHTTPMethod_LOCK,
937  aHeaders );
938 
939  m_xSession->LOCK( getRequestURI(),
940  inLock,
942  new DAVAuthListener_Impl( xEnv, m_aURL ),
943  aHeaders ) );
944  }
945  catch (DAVException const& e)
946  {
947  errorCount++;
948  bRetry = handleException( e, errorCount );
949  if ( !bRetry )
950  throw;
951  }
952  }
953  while ( bRetry );
954 }
955 
957  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
958 {
959  initialize();
960 
961  int errorCount = 0;
962  bool bRetry;
963  do
964  {
965  bRetry = false;
966  try
967  {
968  DAVRequestHeaders aHeaders;
969  getUserRequestHeaders( xEnv,
970  getRequestURI(),
971  ucb::WebDAVHTTPMethod_UNLOCK,
972  aHeaders );
973 
974  m_xSession->UNLOCK( getRequestURI(),
976  new DAVAuthListener_Impl( xEnv, m_aURL ),
977  aHeaders ) );
978  }
979  catch (DAVException const& e)
980  {
981  errorCount++;
982  bRetry = handleException( e, errorCount );
983  if ( !bRetry )
984  throw;
985  }
986  }
987  while ( bRetry );
988 }
989 
990 void DAVResourceAccess::setFlags( const uno::Sequence< beans::NamedValue >& rFlags )
991 {
992  osl::Guard< osl::Mutex > aGuard( m_aMutex );
993  m_aFlags = rFlags;
994 }
995 
996 void DAVResourceAccess::setURL( const OUString & rNewURL )
997 {
998  osl::Guard< osl::Mutex > aGuard( m_aMutex );
999  m_aURL = rNewURL;
1000  m_aPath.clear(); // Next initialize() will create new session.
1001 }
1002 
1003 
1004 // init dav session and path
1006 {
1007  osl::Guard< osl::Mutex > aGuard( m_aMutex );
1008  if ( m_aPath.isEmpty() )
1009  {
1010  CurlUri const aURI( m_aURL );
1011  OUString aPath( aURI.GetRelativeReference() );
1012 
1013  /* #134089# - Check URI */
1014  if ( aPath.isEmpty() )
1016 
1017  /* #134089# - Check URI */
1018  if ( aURI.GetHost().isEmpty() )
1020 
1021  if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL, m_aFlags ) )
1022  {
1023  m_xSession.clear();
1024 
1025  // create new webdav session
1026  m_xSession
1027  = m_xSessionFactory->createDAVSession( m_aURL, m_aFlags, m_xContext );
1028 
1029  if ( !m_xSession.is() )
1030  return;
1031  }
1032 
1033  // Own URI is needed to redirect cycle detection.
1034  m_aRedirectURIs.push_back( aURI );
1035 
1036  // Success.
1037  m_aPath = aPath;
1038 
1039  // Not only the path has to be encoded
1040  m_aURL = aURI.GetURI();
1041  }
1042 }
1043 
1044 
1045 const OUString & DAVResourceAccess::getRequestURI() const
1046 {
1047  assert(m_xSession.is() &&
1048  "DAVResourceAccess::getRequestURI - Not initialized!");
1049 
1050  // In case a proxy is used we have to use the absolute URI for a request.
1051  if ( m_xSession->UsesProxy() )
1052  return m_aURL;
1053 
1054  return m_aPath;
1055 }
1056 
1057 
1058 // static
1060  const uno::Reference< ucb::XCommandEnvironment > & xEnv,
1061  const OUString & rURI,
1062  ucb::WebDAVHTTPMethod eMethod,
1063  DAVRequestHeaders & rRequestHeaders )
1064 {
1065  if ( !xEnv.is() )
1066  return;
1067 
1068  uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv(
1069  xEnv, uno::UNO_QUERY );
1070 
1071  if ( !xDAVEnv.is() )
1072  return;
1073 
1074  uno::Sequence< beans::StringPair > aRequestHeaders
1075  = xDAVEnv->getUserRequestHeaders( rURI, eMethod );
1076 
1077  for ( sal_Int32 n = 0; n < aRequestHeaders.getLength(); ++n )
1078  {
1079  rRequestHeaders.push_back(
1080  DAVRequestHeader( aRequestHeaders[ n ].First,
1081  aRequestHeaders[ n ].Second ) );
1082  }
1083 }
1084 
1085 // This function member implements the control on cyclical redirections
1087  ::std::u16string_view const rRedirectURL)
1088 {
1089  osl::Guard< osl::Mutex > aGuard( m_aMutex );
1090 
1091  CurlUri const aUri( rRedirectURL );
1092 
1093  // Check for maximum number of redirections
1094  // according to <https://tools.ietf.org/html/rfc7231#section-6.4>.
1095  // A practical limit may be 5, due to earlier specifications:
1096  // <https://tools.ietf.org/html/rfc2068#section-10.3>
1097  // it can be raised keeping in mind the added net activity.
1098  if( static_cast< size_t >( m_nRedirectLimit ) <= m_aRedirectURIs.size() )
1099  return true;
1100 
1101  // try to detect a cyclical redirection
1102  return std::any_of(m_aRedirectURIs.begin(), m_aRedirectURIs.end(),
1103  [&aUri](const CurlUri& rUri) { return aUri == rUri; });
1104 }
1105 
1106 
1108 {
1109  osl::Guard< osl::Mutex > aGuard( m_aMutex );
1110  if ( ! m_aRedirectURIs.empty() )
1111  {
1112  auto const it = m_aRedirectURIs.begin();
1113 
1114  CurlUri const aUri( *it );
1115  m_aRedirectURIs.clear();
1116  setURL ( aUri.GetURI() );
1117  initialize();
1118  }
1119 }
1120 
1121 
1122 bool DAVResourceAccess::handleException(DAVException const& e, int const errorCount)
1123 {
1124  switch ( e.getError() )
1125  {
1127  if ( !detectRedirectCycle( e.getData() ) )
1128  {
1129  // set new URL and path.
1130  setURL( e.getData() );
1131  initialize();
1132  return true;
1133  }
1134  return false;
1135  // i#67048 copy & paste images doesn't display. This bug refers
1136  // to an old OOo problem about getting resources from sites with a bad connection.
1137  // If we have a bad connection try again. Up to three times.
1139  // retry up to three times, if not a client-side error (4xx error codes)
1140  if ( e.getStatus() < SC_BAD_REQUEST && errorCount < 3 )
1141  return true;
1142  // check the server side errors
1143  switch( e.getStatus() )
1144  {
1145  // the HTTP server side response status codes that can be retried
1146  // [Serf TODO? i#119036] case SC_REQUEST_ENTITY_TOO_LARGE:
1147  case SC_BAD_GATEWAY: // retry, can be an excessive load
1148  case SC_GATEWAY_TIMEOUT: // retry, may be we get lucky
1149  case SC_SERVICE_UNAVAILABLE: // retry, the service may become available
1150  case SC_INSUFFICIENT_STORAGE: // space may be freed, retry
1151  {
1152  if ( errorCount < 3 )
1153  return true;
1154  else
1155  return false;
1156  }
1157  break;
1158  // all the other HTTP server response status codes are NOT retry
1159  default:
1160  return false;
1161  }
1162  break;
1163  // if connection has said retry then retry!
1165  return true;
1166  // <--
1167  default:
1168  return false; // Abort
1169  }
1170 }
1171 
1172 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const sal_uInt16 SC_SERVICE_UNAVAILABLE
void HEAD(const std::vector< OUString > &rHeaderNames, DAVResource &rResource, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
std::vector< DAVRequestHeader > DAVRequestHeaders
OUString GetRelativeReference() const
Definition: CurlUri.hxx:73
void PROPPATCH(const std::vector< ProppatchValue > &rValues, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
const ExceptionCode & getError() const
void OPTIONS(DAVOptions &rOptions, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
DAVResourceAccess & operator=(const DAVResourceAccess &rOther)
sal_Int64 n
bool handleException(DAVException const &e, int errorCount)
const OUString & getData() const
void UNLOCK(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
css::uno::Reference< css::io::XInputStream > POST(const OUString &rContentType, const OUString &rReferer, const css::uno::Reference< css::io::XInputStream > &rInputStream, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void MKCOL(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void COPY(const OUString &rSourcePath, const OUString &rDestinationURI, bool bOverwrite, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void setFlags(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > &rFlags)
static void getUserRequestHeaders(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv, const OUString &rURI, css::ucb::WebDAVHTTPMethod eMethod, DAVRequestHeaders &rRequestHeaders)
void PUT(const css::uno::Reference< css::io::XInputStream > &rStream, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
Reference< XInputStream > xStream
std::vector< CurlUri > m_aRedirectURIs
void GET0(DAVRequestHeaders &rRequestHeaders, const std::vector< OUString > &rHeaderNames, DAVResource &rResource, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
used as HEAD substitute when HEAD is not implemented on server
rtl::Reference< DAVSession > m_xSession
css::uno::Reference< css::uno::XComponentContext > m_xContext
css::util::URL m_aURL
css::uno::Reference< css::io::XInputStream > GET(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void setURL(const OUString &rNewURL)
const sal_uInt16 SC_BAD_GATEWAY
OUString const & GetURI() const
Definition: CurlUri.hxx:66
std::pair< OUString, OUString > DAVRequestHeader
void PROPFIND(const Depth nDepth, const std::vector< OUString > &rPropertyNames, std::vector< DAVResource > &rResources, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
rtl::Reference< DAVSessionFactory > m_xSessionFactory
void MOVE(const OUString &rSourcePath, const OUString &rDestinationURI, bool bOverwrite, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > m_aFlags
static css::uno::Reference< css::io::XInputStream > CheckSeekableCanWrap(const css::uno::Reference< css::io::XInputStream > &xInStream, const css::uno::Reference< css::uno::XComponentContext > &rxContext)
bool detectRedirectCycle(::std::u16string_view rRedirectURL)
const OUString & getRequestURI() const
void DESTROY(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
const sal_uInt16 SC_INSUFFICIENT_STORAGE
const sal_uInt16 SC_GATEWAY_TIMEOUT
virtual int authenticate(const OUString &inRealm, const OUString &inHostName, OUString &inoutUserName, OUString &outPassWord, bool bCanUseSystemCredentials, bool bUsePreviousCredentials=true) override
void LOCK(css::ucb::Lock &inLock, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
sal_uInt16 getStatus() const
Reference< XComponentContext > m_xContext
OUString const & GetHost() const
Definition: CurlUri.hxx:70
const sal_uInt16 SC_BAD_REQUEST