update emoji autocorrect entries from po-files
[LibreOffice.git] / unotools / source / ucbhelper / ucbhelper.cxx
blob1cb9ad65b58c604522add2846dca9fe16a94a2d1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <sal/config.h>
22 #include <cassert>
23 #include <vector>
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 #include <com/sun/star/sdbc/XResultSet.hpp>
27 #include <com/sun/star/task/XInteractionHandler.hpp>
28 #include <com/sun/star/ucb/CommandAbortedException.hpp>
29 #include <com/sun/star/ucb/ContentInfo.hpp>
30 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
31 #include <com/sun/star/ucb/IOErrorCode.hpp>
32 #include <com/sun/star/ucb/InteractiveIOException.hpp>
33 #include <com/sun/star/ucb/NameClashException.hpp>
34 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
35 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
36 #include <com/sun/star/ucb/XContentAccess.hpp>
37 #include <com/sun/star/ucb/XContentIdentifier.hpp>
38 #include <com/sun/star/ucb/XProgressHandler.hpp>
39 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
40 #include <com/sun/star/uno/Any.hxx>
41 #include <com/sun/star/uno/Exception.hpp>
42 #include <com/sun/star/uno/Reference.hxx>
43 #include <com/sun/star/uno/RuntimeException.hpp>
44 #include <com/sun/star/uno/Sequence.hxx>
45 #include <com/sun/star/uno/XComponentContext.hpp>
46 #include <com/sun/star/util/DateTime.hpp>
47 #include <comphelper/processfactory.hxx>
48 #include <cppuhelper/exc_hlp.hxx>
49 #include <osl/file.hxx>
50 #include <rtl/string.h>
51 #include <rtl/ustring.h>
52 #include <rtl/ustring.hxx>
53 #include <sal/log.hxx>
54 #include <sal/types.h>
55 #include <tools/datetime.hxx>
56 #include <tools/urlobj.hxx>
57 #include <ucbhelper/commandenvironment.hxx>
58 #include <ucbhelper/content.hxx>
59 #include <unotools/localfilehelper.hxx>
60 #include <unotools/ucbhelper.hxx>
62 namespace {
64 OUString canonic(OUString const & url) {
65 INetURLObject o(url);
66 SAL_WARN_IF(o.HasError(), "unotools.ucbhelper", "Invalid URL \"" << url << '"');
67 return o.GetMainURL(INetURLObject::NO_DECODE);
70 ucbhelper::Content content(OUString const & url) {
71 return ucbhelper::Content(
72 canonic(url),
73 css::uno::Reference<css::ucb::XCommandEnvironment>(),
74 comphelper::getProcessComponentContext());
77 ucbhelper::Content content(INetURLObject const & url) {
78 return ucbhelper::Content(
79 url.GetMainURL(INetURLObject::NO_DECODE),
80 css::uno::Reference<css::ucb::XCommandEnvironment>(),
81 comphelper::getProcessComponentContext());
84 std::vector<OUString> getContents(OUString const & url) {
85 try {
86 std::vector<OUString> cs;
87 ucbhelper::Content c(content(url));
88 css::uno::Sequence<OUString> args(1);
89 args[0] = "Title";
90 css::uno::Reference<css::sdbc::XResultSet> res(
91 c.createCursor(args, ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS),
92 css::uno::UNO_SET_THROW);
93 css::uno::Reference<com::sun::star::ucb::XContentAccess> acc(
94 res, css::uno::UNO_QUERY_THROW);
95 while (res->next()) {
96 cs.push_back(acc->queryContentIdentifierString());
98 return cs;
99 } catch (css::uno::RuntimeException const &) {
100 throw;
101 } catch (css::ucb::CommandAbortedException const &) {
102 assert(false && "this cannot happen");
103 throw;
104 } catch (css::uno::Exception const &) {
105 css::uno::Any e(cppu::getCaughtException());
106 SAL_INFO(
107 "unotools.ucbhelper",
108 "getContents(" << url << ") " << e.getValueType().getTypeName()
109 << " \"" << e.get<css::uno::Exception>().Message << '"');
110 return std::vector<OUString>();
114 OUString getCasePreservingUrl(const INetURLObject& url) {
115 return
116 content(url).executeCommand(
117 OUString("getCasePreservingURL"),
118 css::uno::Any()).
119 get<OUString>();
122 DateTime convert(css::util::DateTime const & dt) {
123 return DateTime(dt);
128 bool utl::UCBContentHelper::IsDocument(OUString const & url) {
129 try {
130 return content(url).isDocument();
131 } catch (css::uno::RuntimeException const &) {
132 throw;
133 } catch (css::ucb::CommandAbortedException const &) {
134 assert(false && "this cannot happen");
135 throw;
136 } catch (css::uno::Exception const &) {
137 css::uno::Any e(cppu::getCaughtException());
138 SAL_INFO(
139 "unotools.ucbhelper",
140 "UCBContentHelper::IsDocument(" << url << ") "
141 << e.getValueType().getTypeName() << " \""
142 << e.get<css::uno::Exception>().Message << '"');
143 return false;
147 css::uno::Any utl::UCBContentHelper::GetProperty(
148 OUString const & url, OUString const & property)
150 try {
151 return content(url).getPropertyValue(property);
152 } catch (css::uno::RuntimeException const &) {
153 throw;
154 } catch (css::ucb::CommandAbortedException const &) {
155 assert(false && "this cannot happen");
156 throw;
157 } catch (css::uno::Exception const &) {
158 css::uno::Any e(cppu::getCaughtException());
159 SAL_INFO(
160 "unotools.ucbhelper",
161 "UCBContentHelper::GetProperty(" << url << ", " << property << ") "
162 << e.getValueType().getTypeName() << " \""
163 << e.get<css::uno::Exception>().Message << '"');
164 return css::uno::Any();
168 bool utl::UCBContentHelper::IsFolder(OUString const & url) {
169 try {
170 return content(url).isFolder();
171 } catch (css::uno::RuntimeException const &) {
172 throw;
173 } catch (css::ucb::CommandAbortedException const &) {
174 assert(false && "this cannot happen");
175 throw;
176 } catch (css::uno::Exception const &) {
177 css::uno::Any e(cppu::getCaughtException());
178 SAL_INFO(
179 "unotools.ucbhelper",
180 "UCBContentHelper::IsFolder(" << url << ") "
181 << e.getValueType().getTypeName() << " \""
182 << e.get<css::uno::Exception>().Message << '"');
183 return false;
187 bool utl::UCBContentHelper::GetTitle(
188 OUString const & url, OUString * title)
190 assert(title != 0);
191 try {
192 return content(url).getPropertyValue("Title") >>= *title;
193 } catch (css::uno::RuntimeException const &) {
194 throw;
195 } catch (css::ucb::CommandAbortedException const &) {
196 assert(false && "this cannot happen");
197 throw;
198 } catch (css::uno::Exception const &) {
199 css::uno::Any e(cppu::getCaughtException());
200 SAL_INFO(
201 "unotools.ucbhelper",
202 "UCBContentHelper::GetTitle(" << url << ") "
203 << e.getValueType().getTypeName() << " \""
204 << e.get<css::uno::Exception>().Message << '"');
205 return false;
209 bool utl::UCBContentHelper::Kill(OUString const & url) {
210 try {
211 content(url).executeCommand(
212 OUString("delete"),
213 css::uno::makeAny(true));
214 return true;
215 } catch (css::uno::RuntimeException const &) {
216 throw;
217 } catch (css::ucb::CommandAbortedException const &) {
218 assert(false && "this cannot happen");
219 throw;
220 } catch (css::uno::Exception const &) {
221 css::uno::Any e(cppu::getCaughtException());
222 SAL_INFO(
223 "unotools.ucbhelper",
224 "UCBContentHelper::Kill(" << url << ") "
225 << e.getValueType().getTypeName() << " \""
226 << e.get<css::uno::Exception>().Message << '"');
227 return false;
231 bool utl::UCBContentHelper::MakeFolder(
232 ucbhelper::Content & parent, OUString const & title,
233 ucbhelper::Content & result, bool exclusive)
235 bool exists = false;
236 try {
237 css::uno::Sequence<css::ucb::ContentInfo> info(
238 parent.queryCreatableContentsInfo());
239 for (sal_Int32 i = 0; i < info.getLength(); ++i) {
240 // Simply look for the first KIND_FOLDER:
241 if ((info[i].Attributes
242 & css::ucb::ContentInfoAttribute::KIND_FOLDER)
243 != 0)
245 // Make sure the only required bootstrap property is "Title":
246 if ( info[i].Properties.getLength() != 1 || info[i].Properties[0].Name != "Title" )
248 continue;
250 css::uno::Sequence<OUString> keys(1);
251 keys[0] = "Title";
252 css::uno::Sequence<css::uno::Any> values(1);
253 values[0] <<= title;
254 if (parent.insertNewContent(info[i].Type, keys, values, result))
256 return true;
260 } catch (css::ucb::InteractiveIOException const & e) {
261 if (e.Code == css::ucb::IOErrorCode_ALREADY_EXISTING) {
262 exists = true;
263 } else {
264 SAL_INFO(
265 "unotools.ucbhelper",
266 "UCBContentHelper::MakeFolder(" << title
267 << ") InteractiveIOException \"" << e.Message
268 << "\", code " << +e.Code);
270 } catch (css::ucb::NameClashException const &) {
271 exists = true;
272 } catch (css::uno::RuntimeException const &) {
273 throw;
274 } catch (css::ucb::CommandAbortedException const &) {
275 assert(false && "this cannot happen");
276 throw;
277 } catch (css::uno::Exception const &) {
278 css::uno::Any e(cppu::getCaughtException());
279 SAL_INFO(
280 "unotools.ucbhelper",
281 "UCBContentHelper::MakeFolder(" << title << ") "
282 << e.getValueType().getTypeName() << " \""
283 << e.get<css::uno::Exception>().Message << '"');
285 if (exists && !exclusive) {
286 INetURLObject o(parent.getURL());
287 o.Append(title);
288 result = content(o);
289 return true;
290 } else {
291 return false;
295 sal_Int64 utl::UCBContentHelper::GetSize(OUString const & url) {
296 try {
297 sal_Int64 n = 0;
298 bool ok = (content(url).getPropertyValue("Size") >>= n);
299 SAL_INFO_IF(
300 !ok, "unotools.ucbhelper",
301 "UCBContentHelper::GetSize(" << url
302 << "): Size cannot be determined");
303 return n;
304 } catch (css::uno::RuntimeException const &) {
305 throw;
306 } catch (css::ucb::CommandAbortedException const &) {
307 assert(false && "this cannot happen");
308 throw;
309 } catch (css::uno::Exception const &) {
310 css::uno::Any e(cppu::getCaughtException());
311 SAL_INFO(
312 "unotools.ucbhelper",
313 "UCBContentHelper::GetSize(" << url << ") "
314 << e.getValueType().getTypeName() << " \""
315 << e.get<css::uno::Exception>().Message << '"');
316 return 0;
320 bool utl::UCBContentHelper::IsYounger(
321 OUString const & younger, OUString const & older)
323 try {
324 return
325 convert(
326 content(younger).getPropertyValue(
327 OUString("DateModified")).
328 get<css::util::DateTime>())
329 > convert(
330 content(older).getPropertyValue(
331 OUString("DateModified")).
332 get<css::util::DateTime>());
333 } catch (css::uno::RuntimeException const &) {
334 throw;
335 } catch (css::ucb::CommandAbortedException const &) {
336 assert(false && "this cannot happen");
337 throw;
338 } catch (css::uno::Exception const &) {
339 css::uno::Any e(cppu::getCaughtException());
340 SAL_INFO(
341 "unotools.ucbhelper",
342 "UCBContentHelper::IsYounger(" << younger << ", " << older << ") "
343 << e.getValueType().getTypeName() << " \""
344 << e.get<css::uno::Exception>().Message << '"');
345 return false;
349 bool utl::UCBContentHelper::Exists(OUString const & url) {
350 OUString pathname;
351 if (utl::LocalFileHelper::ConvertURLToPhysicalName(url, pathname)) {
352 // Try to create a directory entry for the given URL:
353 OUString url2;
354 if (osl::FileBase::getFileURLFromSystemPath(pathname, url2)
355 == osl::FileBase::E_None)
357 // #106526 osl_getDirectoryItem is an existence check, no further
358 // osl_getFileStatus call necessary:
359 osl::DirectoryItem item;
360 return osl::DirectoryItem::get(url2, item) == osl::FileBase::E_None;
361 } else {
362 return false;
364 } else {
365 // Divide URL into folder and name part:
366 INetURLObject o(url);
367 OUString name(
368 o.getName(
369 INetURLObject::LAST_SEGMENT, true,
370 INetURLObject::DECODE_WITH_CHARSET));
371 o.removeSegment();
372 o.removeFinalSlash();
373 std::vector<OUString> cs(
374 getContents(o.GetMainURL(INetURLObject::NO_DECODE)));
375 for (std::vector<OUString>::iterator i(cs.begin()); i != cs.end();
376 ++i)
378 if (INetURLObject(*i).getName(
379 INetURLObject::LAST_SEGMENT, true,
380 INetURLObject::DECODE_WITH_CHARSET).
381 equalsIgnoreAsciiCase(name))
383 return true;
386 return false;
390 bool utl::UCBContentHelper::IsSubPath(
391 OUString const & parent, OUString const & child)
393 // The comparison is done in the following way:
394 // - First, compare case sensitively
395 // - If names are different, try a fallback comparing case insensitively
396 // - If the last comparison succeeded, get case preserving normalized names
397 // for the files and compare them
398 // (The second step is required because retrieving the normalized names
399 // might be very expensive in some cases.)
400 INetURLObject candidate(child);
401 INetURLObject folder(parent);
402 if (candidate.GetProtocol() != folder.GetProtocol()) {
403 return false;
405 INetURLObject candidateLower(child.toAsciiLowerCase());
406 INetURLObject folderLower(parent.toAsciiLowerCase());
407 try {
408 INetURLObject tmp;
409 do {
410 if (candidate == folder
411 || (candidate.GetProtocol() == INetProtocol::File
412 && candidateLower == folderLower
413 && (getCasePreservingUrl(candidate)
414 == getCasePreservingUrl(folder))))
416 return true;
418 tmp = candidate;
419 } while (candidate.removeSegment() && candidateLower.removeSegment()
420 && candidate != tmp);
421 // INetURLObject::removeSegment sometimes returns true without
422 // modifying the URL, e.g., in case of "file:///"
423 } catch (css::uno::RuntimeException const &) {
424 throw;
425 } catch (css::ucb::CommandAbortedException const &) {
426 assert(false && "this cannot happen");
427 throw;
428 } catch (css::uno::Exception const &) {
429 css::uno::Any e(cppu::getCaughtException());
430 SAL_INFO(
431 "unotools.ucbhelper",
432 "UCBContentHelper::IsSubPath(" << parent << ", " << child << ") "
433 << e.getValueType().getTypeName() << " \""
434 << e.get<css::uno::Exception>().Message << '"');
436 return false;
439 bool utl::UCBContentHelper::EqualURLs(
440 OUString const & url1, OUString const & url2)
442 if (url1.isEmpty() || url2.isEmpty()) {
443 return false;
445 css::uno::Reference< css::ucb::XUniversalContentBroker > ucb(
446 css::ucb::UniversalContentBroker::create(
447 comphelper::getProcessComponentContext()));
448 return
449 ucb->compareContentIds(
450 ucb->createContentIdentifier(canonic(url1)),
451 ucb->createContentIdentifier(canonic(url2)))
452 == 0;
455 bool utl::UCBContentHelper::ensureFolder(
456 css::uno::Reference< css::uno::XComponentContext > xCtx,
457 css::uno::Reference< css::ucb::XCommandEnvironment > xEnv,
458 const OUString& rFolder, ucbhelper::Content & result) throw()
462 INetURLObject aURL( rFolder );
463 OUString aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
464 aURL.removeSegment();
465 ::ucbhelper::Content aParent;
467 if ( ::ucbhelper::Content::create( aURL.GetMainURL( INetURLObject::NO_DECODE ),
468 xEnv, xCtx, aParent ) )
470 return ::utl::UCBContentHelper::MakeFolder(aParent, aTitle, result);
473 catch (...)
477 return false;
480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */