/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sal/config.h>
#include <dp_misc.h>
#include <dp_ucb.h>
#include <rtl/uri.hxx>
#include <rtl/ustrbuf.hxx>
#include <ucbhelper/content.hxx>
#include <xmlscript/xml_helper.hxx>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/ucb/CommandFailedException.hpp>
#include <com/sun/star/ucb/ContentInfo.hpp>
#include <com/sun/star/ucb/ContentInfoAttribute.hpp>
#include <com/sun/star/ucb/ContentCreationException.hpp>
#include <comphelper/processfactory.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::ucb;
namespace dp_misc
{
bool create_ucb_content(
::ucbhelper::Content * ret_ucbContent, OUString const & url,
Reference<XCommandEnvironment> const & xCmdEnv,
bool throw_exc )
{
try {
// Existence check...
// content ctor/isFolder() will throw exception in case the resource
// does not exist.
// dilemma: no chance to use the given handler here, because it would
// raise no such file dialogs, else no interaction for
// passwords, ...? xxx todo
::ucbhelper::Content ucbContent(
url, Reference<XCommandEnvironment>(),
comphelper::getProcessComponentContext() );
ucbContent.isFolder();
if (ret_ucbContent != nullptr)
{
ucbContent.setCommandEnvironment( xCmdEnv );
*ret_ucbContent = std::move(ucbContent);
}
return true;
}
catch (const RuntimeException &) {
throw;
}
catch (const Exception &) {
if (throw_exc)
throw;
}
return false;
}
bool create_folder(
::ucbhelper::Content * ret_ucb_content, OUString const & url_,
Reference<XCommandEnvironment> const & xCmdEnv, bool throw_exc )
{
::ucbhelper::Content ucb_content;
if (create_ucb_content(
&ucb_content, url_, xCmdEnv, false /* no throw */ ))
{
if (ucb_content.isFolder()) {
if (ret_ucb_content != nullptr)
*ret_ucb_content = ucb_content;
return true;
}
}
OUString url( url_ );
// xxx todo: find parent
sal_Int32 slash = url.lastIndexOf( '/' );
if (slash < 0) {
// fallback:
url = expandUnoRcUrl( url );
slash = url.lastIndexOf( '/' );
}
if (slash < 0) {
// invalid: has to be at least "auth:/..."
if (throw_exc)
throw ContentCreationException(
"Cannot create folder (invalid path): '" + url + "'",
Reference<XInterface>(), ContentCreationError_UNKNOWN );
return false;
}
::ucbhelper::Content parentContent;
if (! create_folder(
&parentContent, url.copy( 0, slash ), xCmdEnv, throw_exc ))
return false;
const Any title( ::rtl::Uri::decode( url.copy( slash + 1 ),
rtl_UriDecodeWithCharset,
RTL_TEXTENCODING_UTF8 ) );
const Sequence<ContentInfo> infos(
parentContent.queryCreatableContentsInfo() );
for ( ContentInfo const & info : infos )
{
// look KIND_FOLDER:
if ((info.Attributes & ContentInfoAttribute::KIND_FOLDER) != 0)
{
// make sure the only required bootstrap property is "Title":
Sequence<beans::Property> const & rProps = info.Properties;
if ( rProps.getLength() != 1 || rProps[ 0 ].Name != "Title" )
continue;
try {
if (parentContent.insertNewContent(
info.Type,
StrTitle::getTitleSequence(),
Sequence<Any>( &title, 1 ),
ucb_content )) {
if (ret_ucb_content != nullptr)
*ret_ucb_content = ucb_content;
return true;
}
}
catch (const RuntimeException &) {
throw;
}
catch (const CommandFailedException &) {
// Interaction Handler already handled the error
// that has occurred...
}
catch (const Exception &) {
if (throw_exc)
throw;
return false;
}
}
}
if (throw_exc)
throw ContentCreationException(
"Cannot create folder: '" + url + "'",
Reference<XInterface>(), ContentCreationError_UNKNOWN );
return false;
}
bool erase_path( OUString const & url,
Reference<XCommandEnvironment> const & xCmdEnv,
bool throw_exc )
{
::ucbhelper::Content ucb_content;
if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ ))
{
try {
ucb_content.executeCommand(
u"delete"_ustr, Any( true /* delete physically */ ) );
}
catch (const RuntimeException &) {
throw;
}
catch (const Exception &) {
if (throw_exc)
throw;
return false;
}
}
return true;
}
std::vector<sal_Int8> readFile( ::ucbhelper::Content & ucb_content )
{
std::vector<sal_Int8> bytes;
Reference<io::XOutputStream> xStream(
::xmlscript::createOutputStream( &bytes ) );
if (! ucb_content.openStream( xStream ))
throw RuntimeException(
u"::ucbhelper::Content::openStream( XOutputStream ) failed!"_ustr,
nullptr );
return bytes;
}
bool readLine( OUString * res, std::u16string_view startingWith,
::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc )
{
// read whole file:
std::vector<sal_Int8> bytes( readFile( ucb_content ) );
OUString file( reinterpret_cast<char const *>(bytes.data()),
bytes.size(), textenc );
sal_Int32 pos = 0;
for (;;)
{
if (file.match( startingWith, pos ))
{
OUStringBuffer buf;
sal_Int32 start = pos;
pos += startingWith.size();
for (;;)
{
pos = file.indexOf( LF, pos );
if (pos < 0) { // EOF
buf.append( file.subView(start) );
}
else
{
if (pos > 0 && file[ pos - 1 ] == CR)
{
// consume extra CR
buf.append( file.subView(start, pos - start - 1) );
++pos;
}
else
buf.append( file.subView(start, pos - start) );
++pos; // consume LF
// check next line:
if (pos < file.getLength() &&
(file[ pos ] == ' ' || file[ pos ] == '\t'))
{
buf.append( ' ' );
++pos;
start = pos;
continue;
}
}
break;
}
*res = buf.makeStringAndClear();
return true;
}
// next line:
sal_Int32 next_lf = file.indexOf( LF, pos );
if (next_lf < 0) // EOF
break;
pos = next_lf + 1;
}
return false;
}
bool readProperties( std::vector< std::pair< OUString, OUString> > & out_result,
::ucbhelper::Content & ucb_content )
{
// read whole file:
std::vector<sal_Int8> bytes( readFile( ucb_content ) );
OUString file( reinterpret_cast<char const *>(bytes.data()),
bytes.size(), RTL_TEXTENCODING_UTF8);
sal_Int32 pos = 0;
for (;;)
{
OUStringBuffer buf;
sal_Int32 start = pos;
bool bEOF = false;
pos = file.indexOf( LF, pos );
if (pos < 0) { // EOF
buf.append( file.subView(start) );
bEOF = true;
}
else
{
if (pos > 0 && file[ pos - 1 ] == CR)
// consume extra CR
buf.append( file.subView(start, pos - start - 1) );
else
buf.append( file.subView(start, pos - start) );
pos++;
}
OUString aLine = buf.makeStringAndClear();
sal_Int32 posEqual = aLine.indexOf('=');
if (posEqual > 0 && (posEqual + 1) < aLine.getLength())
{
OUString name = aLine.copy(0, posEqual);
OUString value = aLine.copy(posEqual + 1);
out_result.emplace_back(name, value);
}
if (bEOF)
break;
}
return false;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.