304 lines
9.5 KiB
C++
304 lines
9.5 KiB
C++
/* -*- 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: */
|