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
28#include "DAVResourceAccess.hxx"
29
30#include <com/sun/star/lang/IllegalArgumentException.hpp>
31#include <com/sun/star/io/IOException.hpp>
32#include <utility>
33
34using namespace http_dav_ucp;
35using namespace com::sun::star;
36
37
38// DAVAuthListener_Impl Implementation.
39
40
41// virtual
42int DAVAuthListener_Impl::authenticate(
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<
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
124constexpr size_t g_nRedirectLimit = 5;
125
127 uno::Reference< uno::XComponentContext > xContext,
129 OUString aURL )
130: m_aURL(std::move( aURL )),
131 m_xSessionFactory(std::move( xSessionFactory )),
132 m_xContext(std::move( xContext ))
133{
134}
135
136
137DAVResourceAccess::DAVResourceAccess( const DAVResourceAccess & rOther )
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{
146}
147
148
150 const DAVResourceAccess & rOther )
151{
152 m_aURL = rOther.m_aURL;
153 m_aPath = rOther.m_aPath;
154 m_aFlags = rOther.m_aFlags;
155 m_xSession = rOther.m_xSession;
157 m_xContext = rOther.m_xContext;
159
160 return *this;
161}
162
164 DAVOptions & rOptions,
165 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
166{
167 initialize();
168
169 int errorCount = 0;
170 bool bRetry;
171 do
172 {
173 bRetry = false;
174 try
175 {
176 DAVRequestHeaders aHeaders;
177
180 ucb::WebDAVHTTPMethod_OPTIONS,
181 aHeaders );
182
183 m_xSession->OPTIONS( getRequestURI(),
184 rOptions,
186 new DAVAuthListener_Impl( xEnv, m_aURL ),
187 aHeaders ) );
188 }
189 catch (DAVException const& e)
190 {
191 errorCount++;
192 bRetry = handleException( e, errorCount );
193 if ( !bRetry )
194 throw;
195 }
196 }
197 while ( bRetry );
198}
199
201 const Depth nDepth,
202 const std::vector< OUString > & rPropertyNames,
203 std::vector< DAVResource > & rResources,
204 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
205{
206 initialize();
207
208 int errorCount = 0;
209 bool bRetry;
210 do
211 {
212 bRetry = false;
213 try
214 {
215 DAVRequestHeaders aHeaders;
216
219 ucb::WebDAVHTTPMethod_PROPFIND,
220 aHeaders );
221
222 m_xSession->PROPFIND( getRequestURI(),
223 nDepth,
224 rPropertyNames,
225 rResources,
227 new DAVAuthListener_Impl( xEnv, m_aURL ),
228 aHeaders ) );
229 }
230 catch (DAVException const& e)
231 {
232 errorCount++;
233 bRetry = handleException( e, errorCount );
234 if ( !bRetry )
235 throw;
236 }
237 }
238 while ( bRetry );
239}
240
241
243 const Depth nDepth,
244 std::vector< DAVResourceInfo > & rResInfo,
245 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
246{
247 initialize();
248
249 int errorCount = 0;
250 bool bRetry;
251 do
252 {
253 bRetry = false;
254 try
255 {
256 DAVRequestHeaders aHeaders;
259 ucb::WebDAVHTTPMethod_PROPFIND,
260 aHeaders );
261
262 m_xSession->PROPFIND( getRequestURI(),
263 nDepth,
264 rResInfo,
266 new DAVAuthListener_Impl( xEnv, m_aURL ),
267 aHeaders ) ) ;
268 }
269 catch (DAVException const& e)
270 {
271 errorCount++;
272 bRetry = handleException( e, errorCount );
273 if ( !bRetry )
274 throw;
275 }
276 }
277 while ( bRetry );
278}
279
280
282 const std::vector< ProppatchValue >& rValues,
283 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
284{
285 initialize();
286
287 int errorCount = 0;
288 bool bRetry;
289 do
290 {
291 bRetry = false;
292 try
293 {
294 DAVRequestHeaders aHeaders;
297 ucb::WebDAVHTTPMethod_PROPPATCH,
298 aHeaders );
299
300 m_xSession->PROPPATCH( getRequestURI(),
301 rValues,
303 new DAVAuthListener_Impl( xEnv, m_aURL ),
304 aHeaders ) );
305 }
306 catch (DAVException const& e)
307 {
308 errorCount++;
309 bRetry = handleException( e, errorCount );
310 if ( !bRetry )
311 throw;
312 }
313 }
314 while ( bRetry );
315}
316
317
319 const std::vector< OUString > & rHeaderNames,
320 DAVResource & rResource,
321 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
322{
323 initialize();
324
325 int errorCount = 0;
326 bool bRetry;
327 do
328 {
329 bRetry = false;
330 try
331 {
332 DAVRequestHeaders aHeaders;
335 ucb::WebDAVHTTPMethod_HEAD,
336 aHeaders );
337
338 m_xSession->HEAD( getRequestURI(),
339 rHeaderNames,
340 rResource,
342 new DAVAuthListener_Impl( xEnv, m_aURL ),
343 aHeaders ) );
344 }
345 catch (DAVException const& e)
346 {
347 errorCount++;
348 bRetry = handleException( e, errorCount );
349 if ( !bRetry )
350 throw;
351 }
352 }
353 while ( bRetry );
354}
355
356
357uno::Reference< io::XInputStream > DAVResourceAccess::GET(
358 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
359{
360 initialize();
361
362 uno::Reference< io::XInputStream > xStream;
363 int errorCount = 0;
364 bool bRetry;
365 do
366 {
367 bRetry = false;
368 try
369 {
370 DAVRequestHeaders aHeaders;
373 ucb::WebDAVHTTPMethod_GET,
374 aHeaders );
375
379 xEnv, m_aURL ),
380 aHeaders ) );
381 }
382 catch (DAVException const& e)
383 {
384 errorCount++;
385 bRetry = handleException( e, errorCount );
386 if ( !bRetry )
387 throw;
388 }
389 }
390 while ( bRetry );
391
392 return xStream;
393}
394
395
397 uno::Reference< io::XOutputStream > & rStream,
398 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
399{
400 initialize();
401
402 int errorCount = 0;
403 bool bRetry;
404 do
405 {
406 bRetry = false;
407 try
408 {
409 DAVRequestHeaders aHeaders;
412 ucb::WebDAVHTTPMethod_GET,
413 aHeaders );
414
416 rStream,
418 new DAVAuthListener_Impl( xEnv, m_aURL ),
419 aHeaders ) );
420 }
421 catch (DAVException const& e)
422 {
423 errorCount++;
424 bRetry = handleException( e, errorCount );
425 if ( !bRetry )
426 throw;
427 }
428 }
429 while ( bRetry );
430}
431
432
433uno::Reference< io::XInputStream > DAVResourceAccess::GET(
434 const std::vector< OUString > & rHeaderNames,
435 DAVResource & rResource,
436 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
437{
438 initialize();
439
440 uno::Reference< io::XInputStream > xStream;
441 int errorCount = 0;
442 bool bRetry;
443 do
444 {
445 bRetry = false;
446 try
447 {
448 DAVRequestHeaders aHeaders;
451 ucb::WebDAVHTTPMethod_GET,
452 aHeaders );
453
455 rHeaderNames,
456 rResource,
459 xEnv, m_aURL ),
460 aHeaders ) );
461 }
462 catch (DAVException const& e)
463 {
464 errorCount++;
465 bRetry = handleException( e, errorCount );
466 if ( !bRetry )
467 throw;
468 }
469 }
470 while ( bRetry );
471
472 return xStream;
473}
474
475
476// used as HEAD substitute when HEAD is not implemented on server
478 DAVRequestHeaders &rRequestHeaders,
479 const std::vector< OUString > & rHeaderNames,
480 DAVResource & rResource,
481 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
482{
483 initialize();
484
485 int errorCount = 0;
486 bool bRetry;
487 do
488 {
489 bRetry = false;
490 try
491 {
494 ucb::WebDAVHTTPMethod_GET,
495 rRequestHeaders );
496
498 rHeaderNames,
499 rResource,
502 xEnv, m_aURL ),
503 rRequestHeaders ) );
504 }
505 catch (DAVException const& e)
506 {
507 errorCount++;
508 bRetry = handleException( e, errorCount );
509 if ( !bRetry )
510 throw;
511 }
512 }
513 while ( bRetry );
514}
515
516
518 uno::Reference< io::XOutputStream > & rStream,
519 const std::vector< OUString > & rHeaderNames,
520 DAVResource & rResource,
521 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
522{
523 initialize();
524
525 bool bRetry;
526 int errorCount = 0;
527 do
528 {
529 bRetry = false;
530 try
531 {
532 DAVRequestHeaders aHeaders;
535 ucb::WebDAVHTTPMethod_GET,
536 aHeaders );
537
539 rStream,
540 rHeaderNames,
541 rResource,
543 new DAVAuthListener_Impl( xEnv, m_aURL ),
544 aHeaders ) );
545 }
546 catch (DAVException const& e)
547 {
548 errorCount++;
549 bRetry = handleException( e, errorCount );
550 if ( !bRetry )
551 throw;
552 }
553 }
554 while ( bRetry );
555}
556
557
559{
560 // seems pointless to call initialize() here, but prepare for nullptr
561 decltype(m_xSession) xSession;
562 {
563 osl::Guard<osl::Mutex> const g(m_aMutex);
564 xSession = m_xSession;
565 }
566 if (xSession.is())
567 {
568 xSession->abort();
569 }
570}
571
572
573namespace {
574
576 void resetInputStream( const uno::Reference< io::XInputStream > & rStream )
577 {
578 try
579 {
580 uno::Reference< io::XSeekable > xSeekable(
581 rStream, uno::UNO_QUERY );
582 if ( xSeekable.is() )
583 {
584 xSeekable->seek( 0 );
585 return;
586 }
587 }
588 catch ( lang::IllegalArgumentException const & )
589 {
590 }
591 catch ( io::IOException const & )
592 {
593 }
594
596 }
597
598} // namespace
599
600
602 const uno::Reference< io::XInputStream > & rStream,
603 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
604{
605 initialize();
606
607 // Make stream seekable, if it not. Needed, if request must be retried.
608 uno::Reference< io::XInputStream > xSeekableStream
610 rStream, m_xContext );
611
612 int errorCount = 0;
613 bool bRetry = false;
614 do
615 {
616 if ( bRetry )
617 resetInputStream( xSeekableStream );
618
619 bRetry = false;
620 try
621 {
622 DAVRequestHeaders aHeaders;
625 ucb::WebDAVHTTPMethod_PUT,
626 aHeaders );
627
629 xSeekableStream,
631 new DAVAuthListener_Impl( xEnv, m_aURL ),
632 aHeaders ) );
633 }
634 catch (DAVException const& e)
635 {
636 errorCount++;
637 bRetry = handleException( e, errorCount );
638 if ( !bRetry )
639 throw;
640 }
641 }
642 while ( bRetry );
643}
644
645
646uno::Reference< io::XInputStream > DAVResourceAccess::POST(
647 const OUString & rContentType,
648 const OUString & rReferer,
649 const uno::Reference< io::XInputStream > & rInputStream,
650 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
651{
652 initialize();
653
654 // Make stream seekable, if it not. Needed, if request must be retried.
655 uno::Reference< io::XInputStream > xSeekableStream
657 rInputStream, m_xContext );
658
659 uno::Reference< io::XInputStream > xStream;
660 int errorCount = 0;
661 bool bRetry = false;
662 do
663 {
664 if ( bRetry )
665 {
666 resetInputStream( xSeekableStream );
667 bRetry = false;
668 }
669
670 try
671 {
672 DAVRequestHeaders aHeaders;
675 ucb::WebDAVHTTPMethod_POST,
676 aHeaders );
677
679 rContentType,
680 rReferer,
681 xSeekableStream,
684 xEnv, m_aURL ),
685 aHeaders ) );
686 }
687 catch (DAVException const& e)
688 {
689 errorCount++;
690 bRetry = handleException( e, errorCount );
691 if ( !bRetry )
692 throw;
693
695 {
696 // #i74980# - Upon POST redirect, do a GET.
697 return GET( xEnv );
698 }
699 }
700 }
701 while ( bRetry );
702
703 return xStream;
704}
705
706
708 const OUString & rContentType,
709 const OUString & rReferer,
710 const uno::Reference< io::XInputStream > & rInputStream,
711 uno::Reference< io::XOutputStream > & rOutputStream,
712 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
713{
714 initialize();
715
716 // Make stream seekable, if it not. Needed, if request must be retried.
717 uno::Reference< io::XInputStream > xSeekableStream
719 rInputStream, m_xContext );
720
721 int errorCount = 0;
722 bool bRetry = false;
723 do
724 {
725 if ( bRetry )
726 {
727 resetInputStream( xSeekableStream );
728 bRetry = false;
729 }
730
731 try
732 {
733 DAVRequestHeaders aHeaders;
736 ucb::WebDAVHTTPMethod_POST,
737 aHeaders );
738
739 m_xSession->POST( getRequestURI(),
740 rContentType,
741 rReferer,
742 xSeekableStream,
743 rOutputStream,
745 new DAVAuthListener_Impl( xEnv, m_aURL ),
746 aHeaders ) );
747 }
748 catch (DAVException const& e)
749 {
750 errorCount++;
751 bRetry = handleException( e, errorCount );
752 if ( !bRetry )
753 throw;
754
756 {
757 // #i74980# - Upon POST redirect, do a GET.
758 GET( rOutputStream, xEnv );
759 return;
760 }
761 }
762 }
763 while ( bRetry );
764}
765
766
768 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
769{
770 initialize();
771
772 int errorCount = 0;
773 bool bRetry;
774 do
775 {
776 bRetry = false;
777 try
778 {
779 DAVRequestHeaders aHeaders;
782 ucb::WebDAVHTTPMethod_MKCOL,
783 aHeaders );
784
785 m_xSession->MKCOL( getRequestURI(),
787 new DAVAuthListener_Impl( xEnv, m_aURL ),
788 aHeaders ) );
789 }
790 catch (DAVException const& e)
791 {
792 errorCount++;
793 bRetry = handleException( e, errorCount );
794 if ( !bRetry )
795 throw;
796 }
797 }
798 while ( bRetry );
799}
800
801
803 const OUString & rSourcePath,
804 const OUString & rDestinationURI,
805 bool bOverwrite,
806 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
807{
808 initialize();
809
810 int errorCount = 0;
811 bool bRetry;
812 do
813 {
814 bRetry = false;
815 try
816 {
817 DAVRequestHeaders aHeaders;
820 ucb::WebDAVHTTPMethod_COPY,
821 aHeaders );
822
823 m_xSession->COPY( rSourcePath,
824 rDestinationURI,
826 new DAVAuthListener_Impl( xEnv, m_aURL ),
827 aHeaders ),
828 bOverwrite );
829 }
830 catch (DAVException const& e)
831 {
832 errorCount++;
833 bRetry = handleException( e, errorCount );
834 if ( !bRetry )
835 throw;
836 }
837 }
838 while ( bRetry );
839}
840
841
843 const OUString & rSourcePath,
844 const OUString & rDestinationURI,
845 bool bOverwrite,
846 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
847{
848 initialize();
849
850 int errorCount = 0;
851 bool bRetry;
852 do
853 {
854 bRetry = false;
855 try
856 {
857 DAVRequestHeaders aHeaders;
860 ucb::WebDAVHTTPMethod_MOVE,
861 aHeaders );
862
863 m_xSession->MOVE( rSourcePath,
864 rDestinationURI,
866 new DAVAuthListener_Impl( xEnv, m_aURL ),
867 aHeaders ),
868 bOverwrite );
869 }
870 catch (DAVException const& e)
871 {
872 errorCount++;
873 bRetry = handleException( e, errorCount );
874 if ( !bRetry )
875 throw;
876 }
877 }
878 while ( bRetry );
879}
880
881
883 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
884{
885 initialize();
886
887 int errorCount = 0;
888 bool bRetry;
889 do
890 {
891 bRetry = false;
892 try
893 {
894 DAVRequestHeaders aHeaders;
897 ucb::WebDAVHTTPMethod_DELETE,
898 aHeaders );
899
900 m_xSession->DESTROY( getRequestURI(),
902 new DAVAuthListener_Impl( xEnv, m_aURL ),
903 aHeaders ) );
904 }
905 catch (DAVException const& e)
906 {
907 errorCount++;
908 bRetry = handleException( e, errorCount );
909 if ( !bRetry )
910 throw;
911 }
912 }
913 while ( bRetry );
914}
915
916
917// set new lock.
919 ucb::Lock & inLock,
920 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
921{
922 initialize();
923
924 int errorCount = 0;
925 bool bRetry;
926 do
927 {
928 bRetry = false;
929 try
930 {
931 DAVRequestHeaders aHeaders;
934 ucb::WebDAVHTTPMethod_LOCK,
935 aHeaders );
936
937 m_xSession->LOCK( getRequestURI(),
938 inLock,
940 new DAVAuthListener_Impl( xEnv, m_aURL ),
941 aHeaders ) );
942 }
943 catch (DAVException const& e)
944 {
945 errorCount++;
946 bRetry = handleException( e, errorCount );
947 if ( !bRetry )
948 throw;
949 }
950 }
951 while ( bRetry );
952}
953
955 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
956{
957 initialize();
958
959 int errorCount = 0;
960 bool bRetry;
961 do
962 {
963 bRetry = false;
964 try
965 {
966 DAVRequestHeaders aHeaders;
969 ucb::WebDAVHTTPMethod_UNLOCK,
970 aHeaders );
971
972 m_xSession->UNLOCK( getRequestURI(),
974 new DAVAuthListener_Impl( xEnv, m_aURL ),
975 aHeaders ) );
976 }
977 catch (DAVException const& e)
978 {
979 errorCount++;
980 bRetry = handleException( e, errorCount );
981 if ( !bRetry )
982 throw;
983 }
984 }
985 while ( bRetry );
986}
987
988void DAVResourceAccess::setFlags( const uno::Sequence< beans::NamedValue >& rFlags )
989{
990 osl::Guard< osl::Mutex > aGuard( m_aMutex );
991 m_aFlags = rFlags;
992}
993
994void DAVResourceAccess::setURL( const OUString & rNewURL )
995{
996 osl::Guard< osl::Mutex > aGuard( m_aMutex );
997 m_aURL = rNewURL;
998 m_aPath.clear(); // Next initialize() will create new session.
999}
1000
1001
1002// init dav session and path
1004{
1005 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1006 if ( m_aPath.isEmpty() )
1007 {
1008 CurlUri const aURI( m_aURL );
1009 OUString aPath( aURI.GetRelativeReference() );
1010
1011 /* #134089# - Check URI */
1012 if ( aPath.isEmpty() )
1014
1015 /* #134089# - Check URI */
1016 if ( aURI.GetHost().isEmpty() )
1018
1019 if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL, m_aFlags ) )
1020 {
1021 m_xSession.clear();
1022
1023 // create new webdav session
1025 = m_xSessionFactory->createDAVSession( m_aURL, m_aFlags, m_xContext );
1026
1027 if ( !m_xSession.is() )
1028 return;
1029 }
1030
1031 // Own URI is needed to redirect cycle detection.
1032 m_aRedirectURIs.push_back( aURI );
1033
1034 // Success.
1035 m_aPath = aPath;
1036
1037 // Not only the path has to be encoded
1038 m_aURL = aURI.GetURI();
1039 }
1040}
1041
1042
1043const OUString & DAVResourceAccess::getRequestURI() const
1044{
1045 assert(m_xSession.is() &&
1046 "DAVResourceAccess::getRequestURI - Not initialized!");
1047
1048 // In case a proxy is used we have to use the absolute URI for a request.
1049 if ( m_xSession->UsesProxy() )
1050 return m_aURL;
1051
1052 return m_aPath;
1053}
1054
1055
1056// static
1058 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
1059 const OUString & rURI,
1060 ucb::WebDAVHTTPMethod eMethod,
1061 DAVRequestHeaders & rRequestHeaders )
1062{
1063 if ( !xEnv.is() )
1064 return;
1065
1066 uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv(
1067 xEnv, uno::UNO_QUERY );
1068
1069 if ( !xDAVEnv.is() )
1070 return;
1071
1072 uno::Sequence< beans::StringPair > aRequestHeaders
1073 = xDAVEnv->getUserRequestHeaders( rURI, eMethod );
1074
1075 for ( sal_Int32 n = 0; n < aRequestHeaders.getLength(); ++n )
1076 {
1077 rRequestHeaders.push_back(
1078 DAVRequestHeader( aRequestHeaders[ n ].First,
1079 aRequestHeaders[ n ].Second ) );
1080 }
1081}
1082
1083// This function member implements the control on cyclical redirections
1085 ::std::u16string_view const rRedirectURL)
1086{
1087 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1088
1089 CurlUri const aUri( rRedirectURL );
1090
1091 // Check for maximum number of redirections
1092 // according to <https://tools.ietf.org/html/rfc7231#section-6.4>.
1093 // A practical limit may be 5, due to earlier specifications:
1094 // <https://tools.ietf.org/html/rfc2068#section-10.3>
1095 // it can be raised keeping in mind the added net activity.
1096 if( g_nRedirectLimit <= m_aRedirectURIs.size() )
1097 return true;
1098
1099 // try to detect a cyclical redirection
1100 return std::any_of(m_aRedirectURIs.begin(), m_aRedirectURIs.end(),
1101 [&aUri](const CurlUri& rUri) { return aUri == rUri; });
1102}
1103
1104
1106{
1107 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1108 if ( ! m_aRedirectURIs.empty() )
1109 {
1110 auto const it = m_aRedirectURIs.begin();
1111
1112 CurlUri const aUri( *it );
1113 m_aRedirectURIs.clear();
1114 setURL ( aUri.GetURI() );
1115 initialize();
1116 }
1117}
1118
1119
1120bool DAVResourceAccess::handleException(DAVException const& e, int const errorCount)
1121{
1122 switch ( e.getError() )
1123 {
1125 if ( !detectRedirectCycle( e.getData() ) )
1126 {
1127 // set new URL and path.
1128 setURL( e.getData() );
1129 initialize();
1130 return true;
1131 }
1132 return false;
1133 // i#67048 copy & paste images doesn't display. This bug refers
1134 // to an old OOo problem about getting resources from sites with a bad connection.
1135 // If we have a bad connection try again. Up to three times.
1137 // retry up to three times, if not a client-side error (4xx error codes)
1138 if ( e.getStatus() < SC_BAD_REQUEST && errorCount < 3 )
1139 return true;
1140 // check the server side errors
1141 switch( e.getStatus() )
1142 {
1143 // the HTTP server side response status codes that can be retried
1144 // [Serf TODO? i#119036] case SC_REQUEST_ENTITY_TOO_LARGE:
1145 case SC_BAD_GATEWAY: // retry, can be an excessive load
1146 case SC_GATEWAY_TIMEOUT: // retry, may be we get lucky
1147 case SC_SERVICE_UNAVAILABLE: // retry, the service may become available
1148 case SC_INSUFFICIENT_STORAGE: // space may be freed, retry
1149 {
1150 if ( errorCount < 3 )
1151 return true;
1152 else
1153 return false;
1154 }
1155 break;
1156 // all the other HTTP server response status codes are NOT retry
1157 default:
1158 return false;
1159 }
1160 break;
1161 // if connection has said retry then retry!
1163 return true;
1164 // <--
1165 default:
1166 return false; // Abort
1167 }
1168}
1169
1170/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr size_t g_nRedirectLimit
Reference< XComponentContext > m_xContext
Reference< XInputStream > xStream
css::util::URL m_aURL
static css::uno::Reference< css::io::XInputStream > CheckSeekableCanWrap(const css::uno::Reference< css::io::XInputStream > &xInStream, const css::uno::Reference< css::uno::XComponentContext > &rxContext)
OUString GetRelativeReference() const
Definition: CurlUri.hxx:73
OUString const & GetHost() const
Definition: CurlUri.hxx:70
OUString const & GetURI() const
Definition: CurlUri.hxx:66
const css::uno::Reference< css::ucb::XCommandEnvironment > m_xEnv
const OUString & getData() const
const ExceptionCode & getError() const
sal_uInt16 getStatus() const
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
css::uno::Reference< css::uno::XComponentContext > m_xContext
const OUString & getRequestURI() const
void setFlags(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > &rFlags)
void PUT(const css::uno::Reference< css::io::XInputStream > &rStream, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void PROPFIND(const Depth nDepth, const std::vector< OUString > &rPropertyNames, std::vector< DAVResource > &rResources, 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)
DAVResourceAccess & operator=(const DAVResourceAccess &rOther)
bool detectRedirectCycle(::std::u16string_view rRedirectURL)
void MKCOL(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void HEAD(const std::vector< OUString > &rHeaderNames, DAVResource &rResource, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void DESTROY(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
std::vector< CurlUri > m_aRedirectURIs
bool handleException(DAVException const &e, int errorCount)
void MOVE(const OUString &rSourcePath, const OUString &rDestinationURI, bool bOverwrite, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void PROPPATCH(const std::vector< ProppatchValue > &rValues, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
rtl::Reference< DAVSession > m_xSession
::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > m_aFlags
void UNLOCK(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void setURL(const OUString &rNewURL)
void OPTIONS(DAVOptions &rOptions, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
void LOCK(css::ucb::Lock &inLock, 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)
static void getUserRequestHeaders(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv, const OUString &rURI, css::ucb::WebDAVHTTPMethod eMethod, DAVRequestHeaders &rRequestHeaders)
css::uno::Reference< css::io::XInputStream > GET(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
rtl::Reference< DAVSessionFactory > m_xSessionFactory
URL aURL
sal_Int64 n
const sal_uInt16 SC_BAD_GATEWAY
const sal_uInt16 SC_GATEWAY_TIMEOUT
const sal_uInt16 SC_SERVICE_UNAVAILABLE
const sal_uInt16 SC_INSUFFICIENT_STORAGE
const sal_uInt16 SC_BAD_REQUEST
std::vector< DAVRequestHeader > DAVRequestHeaders
std::pair< OUString, OUString > DAVRequestHeader