LCOV - code coverage report
Current view: top level - unotools/source/ucbhelper - ucbhelper.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 71 193 36.8 %
Date: 2014-04-11 Functions: 10 18 55.6 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "sal/config.h"
      21             : 
      22             : #include <cassert>
      23             : #include <vector>
      24             : 
      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"
      61             : 
      62             : namespace {
      63             : 
      64        6867 : OUString canonic(OUString const & url) {
      65        6867 :     INetURLObject o(url);
      66             :     SAL_WARN_IF(o.HasError(), "unotools.ucbhelper", "Invalid URL \"" << url << '"');
      67        6867 :     return o.GetMainURL(INetURLObject::NO_DECODE);
      68             : }
      69             : 
      70        5879 : ucbhelper::Content content(OUString const & url) {
      71             :     return ucbhelper::Content(
      72             :         canonic(url),
      73             :         css::uno::Reference<css::ucb::XCommandEnvironment>(),
      74        5879 :         comphelper::getProcessComponentContext());
      75             : }
      76             : 
      77         477 : ucbhelper::Content content(INetURLObject const & url) {
      78             :     return ucbhelper::Content(
      79             :         url.GetMainURL(INetURLObject::NO_DECODE),
      80             :         css::uno::Reference<css::ucb::XCommandEnvironment>(),
      81         477 :         comphelper::getProcessComponentContext());
      82             : }
      83             : 
      84           0 : std::vector<OUString> getContents(OUString const & url) {
      85             :     try {
      86           0 :         std::vector<OUString> cs;
      87           0 :         ucbhelper::Content c(content(url));
      88           0 :         css::uno::Sequence<OUString> args(1);
      89           0 :         args[0] = "Title";
      90             :         css::uno::Reference<css::sdbc::XResultSet> res(
      91             :             c.createCursor(args, ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS),
      92           0 :             css::uno::UNO_SET_THROW);
      93             :         css::uno::Reference<com::sun::star::ucb::XContentAccess> acc(
      94           0 :             res, css::uno::UNO_QUERY_THROW);
      95           0 :         while (res->next()) {
      96           0 :             cs.push_back(acc->queryContentIdentifierString());
      97             :         }
      98           0 :         return cs;
      99           0 :     } catch (css::uno::RuntimeException const &) {
     100           0 :         throw;
     101           0 :     } catch (css::ucb::CommandAbortedException const &) {
     102             :         assert(false); // this cannot happen
     103           0 :         throw;
     104           0 :     } catch (css::uno::Exception const &) {
     105           0 :         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           0 :         return std::vector<OUString>();
     111             :     }
     112             : }
     113             : 
     114           0 : OUString getCasePreservingUrl(INetURLObject url) {
     115             :     return
     116             :         content(url).executeCommand(
     117             :             OUString("getCasePreservingURL"),
     118             :             css::uno::Any()).
     119           0 :         get<OUString>();
     120             : }
     121             : 
     122           0 : DateTime convert(css::util::DateTime const & dt) {
     123             :     return DateTime(
     124             :         Date(dt.Day, dt.Month, dt.Year),
     125           0 :         Time(dt.Hours, dt.Minutes, dt.Seconds, dt.NanoSeconds));
     126             : }
     127             : 
     128             : }
     129             : 
     130        2952 : bool utl::UCBContentHelper::IsDocument(OUString const & url) {
     131             :     try {
     132        2952 :         return content(url).isDocument();
     133           0 :     } catch (css::uno::RuntimeException const &) {
     134           0 :         throw;
     135           0 :     } catch (css::ucb::CommandAbortedException const &) {
     136             :         assert(false); // this cannot happen
     137           0 :         throw;
     138        1424 :     } catch (css::uno::Exception const &) {
     139         712 :         css::uno::Any e(cppu::getCaughtException());
     140             :         SAL_INFO(
     141             :             "unotools.ucbhelper",
     142             :             "UCBContentHelper::IsDocument(" << url << ") "
     143             :                 << e.getValueType().getTypeName() << " \""
     144             :                 << e.get<css::uno::Exception>().Message << '"');
     145         712 :         return false;
     146             :     }
     147             : }
     148             : 
     149           0 : css::uno::Any utl::UCBContentHelper::GetProperty(
     150             :     OUString const & url, OUString const & property)
     151             : {
     152             :     try {
     153           0 :         return content(url).getPropertyValue(property);
     154           0 :     } catch (css::uno::RuntimeException const &) {
     155           0 :         throw;
     156           0 :     } catch (css::ucb::CommandAbortedException const &) {
     157             :         assert(false); // this cannot happen
     158           0 :         throw;
     159           0 :     } catch (css::uno::Exception const &) {
     160           0 :         css::uno::Any e(cppu::getCaughtException());
     161             :         SAL_INFO(
     162             :             "unotools.ucbhelper",
     163             :             "UCBContentHelper::GetProperty(" << url << ", " << property << ") "
     164             :                 << e.getValueType().getTypeName() << " \""
     165             :                 << e.get<css::uno::Exception>().Message << '"');
     166           0 :         return css::uno::Any();
     167             :     }
     168             : }
     169             : 
     170        2442 : bool utl::UCBContentHelper::IsFolder(OUString const & url) {
     171             :     try {
     172        2442 :         return content(url).isFolder();
     173           0 :     } catch (css::uno::RuntimeException const &) {
     174           0 :         throw;
     175           0 :     } catch (css::ucb::CommandAbortedException const &) {
     176             :         assert(false); // this cannot happen
     177           0 :         throw;
     178        1346 :     } catch (css::uno::Exception const &) {
     179         673 :         css::uno::Any e(cppu::getCaughtException());
     180             :         SAL_INFO(
     181             :             "unotools.ucbhelper",
     182             :             "UCBContentHelper::IsFolder(" << url << ") "
     183             :                 << e.getValueType().getTypeName() << " \""
     184             :                 << e.get<css::uno::Exception>().Message << '"');
     185         673 :         return false;
     186             :     }
     187             : }
     188             : 
     189           0 : bool utl::UCBContentHelper::GetTitle(
     190             :     OUString const & url, OUString * title)
     191             : {
     192             :     assert(title != 0);
     193             :     try {
     194           0 :         return content(url).getPropertyValue("Title") >>= *title;
     195           0 :     } catch (css::uno::RuntimeException const &) {
     196           0 :         throw;
     197           0 :     } catch (css::ucb::CommandAbortedException const &) {
     198             :         assert(false); // this cannot happen
     199           0 :         throw;
     200           0 :     } catch (css::uno::Exception const &) {
     201           0 :         css::uno::Any e(cppu::getCaughtException());
     202             :         SAL_INFO(
     203             :             "unotools.ucbhelper",
     204             :             "UCBContentHelper::GetTitle(" << url << ") "
     205             :                 << e.getValueType().getTypeName() << " \""
     206             :                 << e.get<css::uno::Exception>().Message << '"');
     207           0 :         return false;
     208             :     }
     209             : }
     210             : 
     211         485 : bool utl::UCBContentHelper::Kill(OUString const & url) {
     212             :     try {
     213             :         content(url).executeCommand(
     214             :             OUString("delete"),
     215         485 :             css::uno::makeAny(true));
     216         485 :         return true;
     217           0 :     } catch (css::uno::RuntimeException const &) {
     218           0 :         throw;
     219           0 :     } catch (css::ucb::CommandAbortedException const &) {
     220             :         assert(false); // this cannot happen
     221           0 :         throw;
     222           0 :     } catch (css::uno::Exception const &) {
     223           0 :         css::uno::Any e(cppu::getCaughtException());
     224             :         SAL_INFO(
     225             :             "unotools.ucbhelper",
     226             :             "UCBContentHelper::Kill(" << url << ") "
     227             :                 << e.getValueType().getTypeName() << " \""
     228             :                 << e.get<css::uno::Exception>().Message << '"');
     229           0 :         return false;
     230             :     }
     231             : }
     232             : 
     233         775 : bool utl::UCBContentHelper::MakeFolder(
     234             :     ucbhelper::Content & parent, OUString const & title,
     235             :     ucbhelper::Content & result, bool exclusive)
     236             : {
     237         775 :     bool exists = false;
     238             :     try {
     239             :         css::uno::Sequence<css::ucb::ContentInfo> info(
     240         775 :             parent.queryCreatableContentsInfo());
     241        1542 :         for (sal_Int32 i = 0; i < info.getLength(); ++i) {
     242             :             // Simply look for the first KIND_FOLDER:
     243        3084 :             if ((info[i].Attributes
     244        1542 :                  & css::ucb::ContentInfoAttribute::KIND_FOLDER)
     245             :                 != 0)
     246             :             {
     247             :                 // Make sure the only required bootstrap property is "Title":
     248         771 :                 if ( info[i].Properties.getLength() != 1 || info[i].Properties[0].Name != "Title" )
     249             :                 {
     250           0 :                     continue;
     251             :                 }
     252         771 :                 css::uno::Sequence<OUString> keys(1);
     253         771 :                 keys[0] = "Title";
     254        1248 :                 css::uno::Sequence<css::uno::Any> values(1);
     255         771 :                 values[0] <<= title;
     256         771 :                 if (parent.insertNewContent(info[i].Type, keys, values, result))
     257             :                 {
     258         294 :                     return true;
     259         477 :                 }
     260             :             }
     261         477 :         }
     262           8 :     } catch (css::ucb::InteractiveIOException const & e) {
     263           4 :         if (e.Code == css::ucb::IOErrorCode_ALREADY_EXISTING) {
     264           0 :             exists = true;
     265             :         } else {
     266             :             SAL_INFO(
     267             :                 "unotools.ucbhelper",
     268             :                 "UCBContentHelper::MakeFolder(" << title
     269             :                     << ") InteractiveIOException \"" << e.Message
     270             :                     << "\", code " << +e.Code);
     271             :         }
     272         954 :     } catch (css::ucb::NameClashException const &) {
     273         477 :         exists = true;
     274           0 :     } catch (css::uno::RuntimeException const &) {
     275           0 :         throw;
     276           0 :     } catch (css::ucb::CommandAbortedException const &) {
     277             :         assert(false); // this cannot happen
     278           0 :         throw;
     279           0 :     } catch (css::uno::Exception const &) {
     280           0 :         css::uno::Any e(cppu::getCaughtException());
     281             :         SAL_INFO(
     282             :             "unotools.ucbhelper",
     283             :             "UCBContentHelper::MakeFolder(" << title << ") "
     284             :                 << e.getValueType().getTypeName() << " \""
     285           0 :                 << e.get<css::uno::Exception>().Message << '"');
     286             :     }
     287         481 :     if (exists && !exclusive) {
     288         477 :         INetURLObject o(parent.getURL());
     289         477 :         o.Append(title);
     290         477 :         result = content(o);
     291         477 :         return true;
     292             :     } else {
     293           4 :         return false;
     294             :     }
     295             : }
     296             : 
     297           0 : sal_Int64 utl::UCBContentHelper::GetSize(OUString const & url) {
     298             :     try {
     299           0 :         sal_Int64 n = 0;
     300           0 :         bool ok = (content(url).getPropertyValue("Size") >>= n);
     301             :         SAL_INFO_IF(
     302             :             !ok, "unotools.ucbhelper",
     303             :             "UCBContentHelper::GetSize(" << url
     304             :                 << "): Size cannot be determined");
     305           0 :         return n;
     306           0 :     } catch (css::uno::RuntimeException const &) {
     307           0 :         throw;
     308           0 :     } catch (css::ucb::CommandAbortedException const &) {
     309             :         assert(false); // this cannot happen
     310           0 :         throw;
     311           0 :     } catch (css::uno::Exception const &) {
     312           0 :         css::uno::Any e(cppu::getCaughtException());
     313             :         SAL_INFO(
     314             :             "unotools.ucbhelper",
     315             :             "UCBContentHelper::GetSize(" << url << ") "
     316             :                 << e.getValueType().getTypeName() << " \""
     317             :                 << e.get<css::uno::Exception>().Message << '"');
     318           0 :         return 0;
     319             :     }
     320             : }
     321             : 
     322           0 : bool utl::UCBContentHelper::IsYounger(
     323             :     OUString const & younger, OUString const & older)
     324             : {
     325             :     try {
     326             :         return
     327             :             convert(
     328             :                 content(younger).getPropertyValue(
     329             :                     OUString("DateModified")).
     330           0 :                 get<css::util::DateTime>())
     331           0 :             > convert(
     332             :                 content(older).getPropertyValue(
     333             :                     OUString("DateModified")).
     334           0 :                 get<css::util::DateTime>());
     335           0 :     } catch (css::uno::RuntimeException const &) {
     336           0 :         throw;
     337           0 :     } catch (css::ucb::CommandAbortedException const &) {
     338             :         assert(false); // this cannot happen
     339           0 :         throw;
     340           0 :     } catch (css::uno::Exception const &) {
     341           0 :         css::uno::Any e(cppu::getCaughtException());
     342             :         SAL_INFO(
     343             :             "unotools.ucbhelper",
     344             :             "UCBContentHelper::IsYounger(" << younger << ", " << older << ") "
     345             :                 << e.getValueType().getTypeName() << " \""
     346             :                 << e.get<css::uno::Exception>().Message << '"');
     347           0 :         return false;
     348             :     }
     349             : }
     350             : 
     351         260 : bool utl::UCBContentHelper::Exists(OUString const & url) {
     352         260 :     OUString pathname;
     353         260 :     if (utl::LocalFileHelper::ConvertURLToPhysicalName(url, pathname)) {
     354             :         // Try to create a directory entry for the given URL:
     355         260 :         OUString url2;
     356         260 :         if (osl::FileBase::getFileURLFromSystemPath(pathname, url2)
     357             :             == osl::FileBase::E_None)
     358             :         {
     359             :             // #106526 osl_getDirectoryItem is an existence check, no further
     360             :             // osl_getFileStatus call necessary:
     361         260 :             osl::DirectoryItem item;
     362         260 :             return osl::DirectoryItem::get(url2, item) == osl::FileBase::E_None;
     363             :         } else {
     364           0 :             return false;
     365         260 :         }
     366             :     } else {
     367             :         // Divide URL into folder and name part:
     368           0 :         INetURLObject o(url);
     369             :         OUString name(
     370             :             o.getName(
     371             :                 INetURLObject::LAST_SEGMENT, true,
     372           0 :                 INetURLObject::DECODE_WITH_CHARSET));
     373           0 :         o.removeSegment();
     374           0 :         o.removeFinalSlash();
     375             :         std::vector<OUString> cs(
     376           0 :             getContents(o.GetMainURL(INetURLObject::NO_DECODE)));
     377           0 :         for (std::vector<OUString>::iterator i(cs.begin()); i != cs.end();
     378             :              ++i)
     379             :         {
     380           0 :             if (INetURLObject(*i).getName(
     381             :                     INetURLObject::LAST_SEGMENT, true,
     382             :                     INetURLObject::DECODE_WITH_CHARSET).
     383           0 :                 equalsIgnoreAsciiCase(name))
     384             :             {
     385           0 :                 return true;
     386             :             }
     387             :         }
     388           0 :         return false;
     389         260 :     }
     390             : }
     391             : 
     392           0 : bool utl::UCBContentHelper::IsSubPath(
     393             :     OUString const & parent, OUString const & child)
     394             : {
     395             :     // The comparison is done in the following way:
     396             :     // - First, compare case sensitively
     397             :     // - If names are different, try a fallback comparing case insensitively
     398             :     // - If the last comparison succeeded, get case preserving normalized names
     399             :     //   for the files and compare them
     400             :     // (The second step is required because retrieving the normalized names
     401             :     // might be very expensive in some cases.)
     402           0 :     INetURLObject candidate(child);
     403           0 :     INetURLObject folder(parent);
     404           0 :     if (candidate.GetProtocol() != folder.GetProtocol()) {
     405           0 :         return false;
     406             :     }
     407           0 :     INetURLObject candidateLower(child.toAsciiLowerCase());
     408           0 :     INetURLObject folderLower(parent.toAsciiLowerCase());
     409             :     try {
     410           0 :         INetURLObject tmp;
     411           0 :         do {
     412           0 :             if (candidate == folder
     413           0 :                 || (candidate.GetProtocol() == INET_PROT_FILE
     414           0 :                     && candidateLower == folderLower
     415           0 :                     && (getCasePreservingUrl(candidate)
     416           0 :                         == getCasePreservingUrl(folder))))
     417             :             {
     418           0 :                 return true;
     419             :             }
     420           0 :             tmp = candidate;
     421           0 :         } while (candidate.removeSegment() && candidateLower.removeSegment()
     422           0 :                  && candidate != tmp);
     423             :             // INetURLObject::removeSegment sometimes returns true without
     424             :             // modifying the URL, e.g., in case of "file:///"
     425           0 :     } catch (css::uno::RuntimeException const &) {
     426           0 :         throw;
     427           0 :     } catch (css::ucb::CommandAbortedException const &) {
     428             :         assert(false); // this cannot happen
     429           0 :         throw;
     430           0 :     } catch (css::uno::Exception const &) {
     431           0 :         css::uno::Any e(cppu::getCaughtException());
     432             :         SAL_INFO(
     433             :             "unotools.ucbhelper",
     434             :             "UCBContentHelper::IsSubPath(" << parent << ", " << child << ") "
     435             :                 << e.getValueType().getTypeName() << " \""
     436           0 :                 << e.get<css::uno::Exception>().Message << '"');
     437             :     }
     438           0 :     return false;
     439             : }
     440             : 
     441         512 : bool utl::UCBContentHelper::EqualURLs(
     442             :     OUString const & url1, OUString const & url2)
     443             : {
     444         512 :     if (url1.isEmpty() || url2.isEmpty()) {
     445          18 :         return false;
     446             :     }
     447             :     css::uno::Reference< css::ucb::XUniversalContentBroker > ucb(
     448             :         css::ucb::UniversalContentBroker::create(
     449         494 :             comphelper::getProcessComponentContext()));
     450             :     return
     451         494 :         ucb->compareContentIds(
     452         988 :             ucb->createContentIdentifier(canonic(url1)),
     453        1976 :             ucb->createContentIdentifier(canonic(url2)))
     454         988 :         == 0;
     455             : }
     456             : 
     457         442 : bool utl::UCBContentHelper::ensureFolder(
     458             :     css::uno::Reference< css::uno::XComponentContext > xCtx,
     459             :     css::uno::Reference< css::ucb::XCommandEnvironment > xEnv,
     460             :     const OUString& rFolder, ucbhelper::Content & result)
     461             : {
     462         442 :     INetURLObject aURL( rFolder );
     463         884 :     OUString aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
     464         442 :     aURL.removeSegment();
     465         884 :     ::ucbhelper::Content aParent;
     466             : 
     467         884 :     if ( ::ucbhelper::Content::create( aURL.GetMainURL( INetURLObject::NO_DECODE ),
     468         884 :                               xEnv, xCtx, aParent ) )
     469             :     {
     470         442 :         return ::utl::UCBContentHelper::MakeFolder(aParent, aTitle, result);
     471             :     }
     472             : 
     473         442 :     return false;
     474             : }
     475             : 
     476             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10