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<
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 uno::Reference< uno::XComponentContext > xContext,
128 OUString aURL )
129: m_aURL(std::move( aURL )),
130 m_xSessionFactory(std::move( xSessionFactory )),
131 m_xContext(std::move( xContext ))
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
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
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;
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;
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;
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
359uno::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;
375 ucb::WebDAVHTTPMethod_GET,
376 aHeaders );
377
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;
414 ucb::WebDAVHTTPMethod_GET,
415 aHeaders );
416
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
435uno::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;
453 ucb::WebDAVHTTPMethod_GET,
454 aHeaders );
455
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 {
496 ucb::WebDAVHTTPMethod_GET,
497 rRequestHeaders );
498
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;
537 ucb::WebDAVHTTPMethod_GET,
538 aHeaders );
539
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
575namespace {
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;
627 ucb::WebDAVHTTPMethod_PUT,
628 aHeaders );
629
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
648uno::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;
677 ucb::WebDAVHTTPMethod_POST,
678 aHeaders );
679
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;
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;
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;
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;
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;
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;
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;
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
990void DAVResourceAccess::setFlags( const uno::Sequence< beans::NamedValue >& rFlags )
991{
992 osl::Guard< osl::Mutex > aGuard( m_aMutex );
993 m_aFlags = rFlags;
994}
995
996void 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
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
1045const 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
1122bool 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: */
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