1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "lokinteractionhandler.hxx"
22 #include <boost/property_tree/json_parser.hpp>
24 #include <rtl/ref.hxx>
25 #include <cppuhelper/supportsservice.hxx>
27 #include <com/sun/star/task/XInteractionAbort.hpp>
28 #include <com/sun/star/task/XInteractionApprove.hpp>
29 #include <com/sun/star/task/XInteractionPassword2.hpp>
30 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
31 #include <com/sun/star/ucb/InteractiveNetworkOffLineException.hpp>
33 #include <com/sun/star/ucb/InteractiveIOException.hpp>
34 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
35 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
36 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
38 #define LOK_USE_UNSTABLE_API
39 #include <../../inc/lib/init.hxx>
41 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
43 using namespace com::sun::star
;
45 LOKInteractionHandler::LOKInteractionHandler(
46 uno::Reference
<uno::XComponentContext
> const & /*rxContext*/,
47 const OString
& rCommand
,
48 desktop::LibLibreOffice_Impl
*const pLOKit
,
49 desktop::LibLODocument_Impl
*const pLOKDocument
)
51 , m_pLOKDocument(pLOKDocument
)
53 , m_usePassword(false)
58 LOKInteractionHandler::~LOKInteractionHandler()
62 OUString SAL_CALL
LOKInteractionHandler::getImplementationName() throw (uno::RuntimeException
, std::exception
)
64 return OUString("com.sun.star.comp.uui.LOKInteractionHandler");
67 sal_Bool SAL_CALL
LOKInteractionHandler::supportsService(OUString
const & rServiceName
) throw (uno::RuntimeException
, std::exception
)
69 return cppu::supportsService(this, rServiceName
);
72 uno::Sequence
< OUString
> SAL_CALL
LOKInteractionHandler::getSupportedServiceNames() throw (uno::RuntimeException
, std::exception
)
74 uno::Sequence
< OUString
> aNames(3);
75 aNames
[0] = "com.sun.star.task.InteractionHandler";
76 // added to indicate support for configuration.backend.MergeRecoveryRequest
77 aNames
[1] = "com.sun.star.configuration.backend.InteractionHandler";
78 aNames
[2] = "com.sun.star.uui.InteractionHandler";
79 // for backwards compatibility
83 void SAL_CALL
LOKInteractionHandler::initialize(uno::Sequence
<uno::Any
> const & /*rArguments*/) throw (uno::Exception
, std::exception
)
87 void SAL_CALL
LOKInteractionHandler::handle(
88 uno::Reference
<task::XInteractionRequest
> const & xRequest
)
89 throw (uno::RuntimeException
, std::exception
)
91 // just do the same thing in both cases
92 handleInteractionRequest(xRequest
);
95 void LOKInteractionHandler::postError(css::task::InteractionClassification classif
, const char* kind
, ErrCode code
, const OUString
&message
)
97 const char *classification
= "error";
100 case task::InteractionClassification_ERROR
: break;
101 case task::InteractionClassification_WARNING
: classification
= "warning"; break;
102 case task::InteractionClassification_INFO
: classification
= "info"; break;
103 case task::InteractionClassification_QUERY
: classification
= "query"; break;
104 default: assert(false); break;
107 // create the JSON representation
108 boost::property_tree::ptree aTree
;
109 aTree
.put("classification", classification
);
110 aTree
.put("cmd", m_command
.getStr());
111 aTree
.put("kind", kind
);
112 aTree
.put("code", code
);
113 aTree
.put("message", message
.toUtf8());
115 std::stringstream aStream
;
116 boost::property_tree::write_json(aStream
, aTree
);
118 if (m_pLOKDocument
&& m_pLOKDocument
->mpCallbackFlushHandler
)
119 m_pLOKDocument
->mpCallbackFlushHandler
->queue(LOK_CALLBACK_ERROR
, aStream
.str().c_str());
120 else if (m_pLOKit
->mpCallback
)
121 m_pLOKit
->mpCallback(LOK_CALLBACK_ERROR
, aStream
.str().c_str(), m_pLOKit
->mpCallbackData
);
126 /// Just approve the interaction.
127 void selectApproved(uno::Sequence
<uno::Reference
<task::XInteractionContinuation
>> const &rContinuations
)
129 for (sal_Int32 i
= 0; i
< rContinuations
.getLength(); ++i
)
131 uno::Reference
<task::XInteractionApprove
> xApprove(rContinuations
[i
], uno::UNO_QUERY
);
139 bool LOKInteractionHandler::handleIOException(const css::uno::Sequence
<css::uno::Reference
<css::task::XInteractionContinuation
>> &rContinuations
, const css::uno::Any
& rRequest
)
141 ucb::InteractiveIOException aIoException
;
142 if (!(rRequest
>>= aIoException
))
145 static ErrCode
const aErrorCode
[ucb::IOErrorCode_WRONG_VERSION
+ 1] =
148 ERRCODE_IO_ACCESSDENIED
,
149 ERRCODE_IO_ALREADYEXISTS
,
151 ERRCODE_IO_CANTCREATE
,
155 ERRCODE_IO_CANTWRITE
,
156 ERRCODE_IO_CURRENTDIR
,
157 ERRCODE_IO_DEVICENOTREADY
,
158 ERRCODE_IO_NOTSAMEDEVICE
,
160 ERRCODE_IO_INVALIDACCESS
,
161 ERRCODE_IO_INVALIDCHAR
,
162 ERRCODE_IO_INVALIDDEVICE
,
163 ERRCODE_IO_INVALIDLENGTH
,
164 ERRCODE_IO_INVALIDPARAMETER
,
165 ERRCODE_IO_ISWILDCARD
,
166 ERRCODE_IO_LOCKVIOLATION
,
167 ERRCODE_IO_MISPLACEDCHAR
,
168 ERRCODE_IO_NAMETOOLONG
,
169 ERRCODE_IO_NOTEXISTS
,
170 ERRCODE_IO_NOTEXISTSPATH
,
171 ERRCODE_IO_NOTSUPPORTED
,
172 ERRCODE_IO_NOTADIRECTORY
,
174 ERRCODE_IO_OUTOFSPACE
,
175 ERRCODE_IO_TOOMANYOPENFILES
,
176 ERRCODE_IO_OUTOFMEMORY
,
178 ERRCODE_IO_RECURSIVE
,
180 ERRCODE_IO_WRITEPROTECTED
,
181 ERRCODE_IO_WRONGFORMAT
,
182 ERRCODE_IO_WRONGVERSION
,
185 postError(aIoException
.Classification
, "io", aErrorCode
[aIoException
.Code
], "");
186 selectApproved(rContinuations
);
191 bool LOKInteractionHandler::handleNetworkException(const uno::Sequence
<uno::Reference
<task::XInteractionContinuation
>> &rContinuations
, const uno::Any
&rRequest
)
193 ucb::InteractiveNetworkException aNetworkException
;
194 if (!(rRequest
>>= aNetworkException
))
200 ucb::InteractiveNetworkOffLineException aOffLineException
;
201 ucb::InteractiveNetworkResolveNameException aResolveNameException
;
202 ucb::InteractiveNetworkConnectException aConnectException
;
203 ucb::InteractiveNetworkReadException aReadException
;
204 ucb::InteractiveNetworkWriteException aWriteException
;
205 if (rRequest
>>= aOffLineException
)
207 nErrorCode
= ERRCODE_INET_OFFLINE
;
209 else if (rRequest
>>= aResolveNameException
)
211 nErrorCode
= ERRCODE_INET_NAME_RESOLVE
;
212 aMessage
= aResolveNameException
.Server
;
214 else if (rRequest
>>= aConnectException
)
216 nErrorCode
= ERRCODE_INET_CONNECT
;
217 aMessage
= aConnectException
.Server
;
219 else if (rRequest
>>= aReadException
)
221 nErrorCode
= ERRCODE_INET_READ
;
222 aMessage
= aReadException
.Diagnostic
;
224 else if (rRequest
>>= aWriteException
)
226 nErrorCode
= ERRCODE_INET_WRITE
;
227 aMessage
= aWriteException
.Diagnostic
;
231 nErrorCode
= ERRCODE_INET_GENERAL
;
234 postError(aNetworkException
.Classification
, "network", nErrorCode
, aMessage
);
235 selectApproved(rContinuations
);
240 bool LOKInteractionHandler::handlePasswordRequest(const uno::Sequence
<uno::Reference
<task::XInteractionContinuation
>> &rContinuations
, const uno::Any
&rRequest
)
242 task::DocumentPasswordRequest2 passwordRequest
;
243 if (!(rRequest
>>= passwordRequest
))
246 if (m_pLOKit
->mpCallback
&&
247 m_pLOKit
->hasOptionalFeature((passwordRequest
.IsRequestPasswordToModify
)
248 ? LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY
249 : LOK_FEATURE_DOCUMENT_PASSWORD
))
251 OString
const url(passwordRequest
.Name
.toUtf8());
252 m_pLOKit
->mpCallback(passwordRequest
.IsRequestPasswordToModify
253 ? LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY
254 : LOK_CALLBACK_DOCUMENT_PASSWORD
,
256 m_pLOKit
->mpCallbackData
);
258 // block until SetPassword is called
259 m_havePassword
.wait();
260 m_havePassword
.reset();
263 for (sal_Int32 i
= 0; i
< rContinuations
.getLength(); ++i
)
267 if (passwordRequest
.IsRequestPasswordToModify
)
269 uno::Reference
<task::XInteractionPassword2
> const xIPW2(rContinuations
[i
], uno::UNO_QUERY
);
270 xIPW2
->setPasswordToModify(m_Password
);
275 uno::Reference
<task::XInteractionPassword
> const xIPW(rContinuations
[i
], uno::UNO_QUERY
);
278 xIPW
->setPassword(m_Password
);
285 if (passwordRequest
.IsRequestPasswordToModify
)
287 uno::Reference
<task::XInteractionPassword2
> const xIPW2(rContinuations
[i
], uno::UNO_QUERY
);
288 xIPW2
->setRecommendReadOnly(true);
293 uno::Reference
<task::XInteractionAbort
> const xAbort(rContinuations
[i
], uno::UNO_QUERY
);
304 sal_Bool SAL_CALL
LOKInteractionHandler::handleInteractionRequest(
305 const uno::Reference
<task::XInteractionRequest
>& xRequest
) throw (uno::RuntimeException
, std::exception
)
307 uno::Sequence
<uno::Reference
<task::XInteractionContinuation
>> const &rContinuations
= xRequest
->getContinuations();
308 uno::Any
const request(xRequest
->getRequest());
310 if (handleIOException(rContinuations
, request
))
313 if (handleNetworkException(rContinuations
, request
))
316 if (handlePasswordRequest(rContinuations
, request
))
319 // TODO: perform more interactions 'for real' like the above
320 selectApproved(rContinuations
);
325 void LOKInteractionHandler::SetPassword(char const*const pPassword
)
329 m_Password
= OUString(pPassword
, strlen(pPassword
), RTL_TEXTENCODING_UTF8
);
330 m_usePassword
= true;
334 m_usePassword
= false;
336 m_havePassword
.set();
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */