Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/cppuhelper/source/bootstrap.cxx
Line
Count
Source
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 <chrono>
23
#include <cstring>
24
#include <thread>
25
26
#include <rtl/bootstrap.hxx>
27
#include <rtl/random.h>
28
#include <rtl/ustrbuf.hxx>
29
#include <rtl/uri.hxx>
30
#include <osl/file.hxx>
31
#include <osl/security.hxx>
32
#include <osl/thread.hxx>
33
#include <o3tl/char16_t2wchar_t.hxx>
34
#include <osl/process.h>
35
36
#include <cppuhelper/bootstrap.hxx>
37
#include <cppuhelper/findsofficepath.h>
38
39
#include <com/sun/star/bridge/UnoUrlResolver.hpp>
40
#include <com/sun/star/bridge/XUnoUrlResolver.hpp>
41
42
#include "macro_expander.hxx"
43
44
using namespace ::osl;
45
using namespace ::com::sun::star;
46
using namespace ::com::sun::star::uno;
47
48
using rtl::Bootstrap;
49
50
namespace cppu
51
{
52
53
BootstrapException::BootstrapException()
54
0
{
55
0
}
56
57
BootstrapException::BootstrapException( const OUString & rMessage )
58
0
    :m_aMessage( rMessage )
59
0
{
60
0
}
61
62
BootstrapException::BootstrapException( const BootstrapException & e )
63
0
{
64
0
    m_aMessage = e.m_aMessage;
65
0
}
66
67
BootstrapException::~BootstrapException()
68
0
{
69
0
}
70
71
BootstrapException & BootstrapException::operator=( const BootstrapException & e )
72
0
{
73
0
    m_aMessage = e.m_aMessage;
74
0
    return *this;
75
0
}
76
77
const OUString & BootstrapException::getMessage() const
78
0
{
79
0
    return m_aMessage;
80
0
}
81
82
Reference< XComponentContext > SAL_CALL bootstrap()
83
0
{
84
0
    Reference< XComponentContext > xRemoteContext;
85
86
0
    try
87
0
    {
88
0
        auto* p1 = cppuhelper_detail_findSofficePath();
89
0
        if (p1 == nullptr) {
90
0
            throw BootstrapException(
91
0
                u"no soffice installation found!"_ustr);
92
0
        }
93
0
        OUString p2;
94
#if defined(_WIN32)
95
        p2 = o3tl::toU(p1);
96
        free(p1);
97
#else
98
0
        bool bOk = rtl_convertStringToUString(
99
0
                &p2.pData, p1, std::strlen(p1), osl_getThreadTextEncoding(),
100
0
                (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
101
0
                 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
102
0
                 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR));
103
0
        free(p1);
104
0
        if (!bOk)
105
0
        {
106
0
            throw BootstrapException(
107
0
                u"bad characters in soffice installation path!"_ustr);
108
0
        }
109
0
#endif
110
0
        OUString path;
111
0
        if (osl::FileBase::getFileURLFromSystemPath(p2, path) !=
112
0
            osl::FileBase::E_None)
113
0
        {
114
0
            throw BootstrapException(
115
0
                u"cannot convert soffice installation path to URL!"_ustr);
116
0
        }
117
0
        if (!path.isEmpty() && !path.endsWith("/")) {
118
0
            path += "/";
119
0
        }
120
121
0
        OUString uri;
122
0
        if (!Bootstrap::get(u"URE_BOOTSTRAP"_ustr, uri)) {
123
0
            Bootstrap::set(
124
0
                u"URE_BOOTSTRAP"_ustr,
125
0
                Bootstrap::encode(
126
0
                    path +
127
#if defined MACOSX
128
                    "../Resources/"
129
#endif
130
0
                    SAL_CONFIGFILE("fundamental")));
131
0
        }
132
133
        // create default local component context
134
0
        Reference< XComponentContext > xLocalContext(
135
0
            defaultBootstrap_InitialComponentContext() );
136
0
        if ( !xLocalContext.is() )
137
0
            throw BootstrapException( u"no local component context!"_ustr );
138
139
        // create a random pipe name
140
0
        sal_uInt8 bytes[ 16 ];
141
0
        if ( rtl_random_getBytes( nullptr, bytes, std::size( bytes ) )
142
0
            != rtl_Random_E_None )
143
0
            throw BootstrapException( u"random pool error!"_ustr );
144
0
        OUStringBuffer buf("uno");
145
0
        for (unsigned char byte : bytes)
146
0
            buf.append( static_cast< sal_Int32 >( byte ) );
147
0
        OUString sPipeName( buf.makeStringAndClear() );
148
149
        // arguments
150
0
        OUString args [] = {
151
0
            u"--nologo"_ustr,
152
0
            u"--nodefault"_ustr,
153
0
            u"--norestore"_ustr,
154
0
            u"--nolockcheck"_ustr,
155
0
            OUString("--accept=pipe,name=" + sPipeName + ";urp;")
156
0
        };
157
0
        rtl_uString * ar_args [] = {
158
0
            args[ 0 ].pData,
159
0
            args[ 1 ].pData,
160
0
            args[ 2 ].pData,
161
0
            args[ 3 ].pData,
162
0
            args[ 4 ].pData
163
0
        };
164
0
        ::osl::Security sec;
165
166
        // start office process
167
0
        oslProcess hProcess = nullptr;
168
0
        oslProcessError rc = osl_executeProcess(
169
0
            OUString(path + "soffice").pData, ar_args, std::size( ar_args ),
170
0
            osl_Process_DETACHED,
171
0
            sec.getHandle(),
172
0
            nullptr, // => current working dir
173
0
            nullptr, 0, // => no env vars
174
0
            &hProcess );
175
0
        switch ( rc )
176
0
        {
177
0
            case osl_Process_E_None:
178
0
                osl_freeProcessHandle( hProcess );
179
0
                break;
180
0
            case osl_Process_E_NotFound:
181
0
                throw BootstrapException( u"image not found!"_ustr );
182
0
            case osl_Process_E_TimedOut:
183
0
                throw BootstrapException( u"timeout occurred!"_ustr );
184
0
            case osl_Process_E_NoPermission:
185
0
                throw BootstrapException( u"permission denied!"_ustr );
186
0
            case osl_Process_E_Unknown:
187
0
                throw BootstrapException( u"unknown error!"_ustr );
188
0
            case osl_Process_E_InvalidError:
189
0
            default:
190
0
                throw BootstrapException( u"unmapped error!"_ustr );
191
0
        }
192
193
        // create a URL resolver
194
0
        Reference< bridge::XUnoUrlResolver > xUrlResolver(
195
0
            bridge::UnoUrlResolver::create( xLocalContext ) );
196
197
        // connection string
198
0
        OUString sConnectString( "uno:pipe,name=" + sPipeName + ";urp;StarOffice.ComponentContext" );
199
200
        // wait until office is started
201
0
        for ( ; ; )
202
0
        {
203
0
            try
204
0
            {
205
                // try to connect to office
206
0
                xRemoteContext.set(
207
0
                    xUrlResolver->resolve( sConnectString ), UNO_QUERY_THROW );
208
0
                break;
209
0
            }
210
0
            catch ( connection::NoConnectException & )
211
0
            {
212
                // wait 500 ms, then try to connect again
213
0
                std::this_thread::sleep_for(std::chrono::milliseconds(500));
214
0
            }
215
0
        }
216
0
    }
217
0
    catch ( Exception & e )
218
0
    {
219
0
        throw BootstrapException(
220
0
            "unexpected UNO exception caught: " + e.Message );
221
0
    }
222
223
0
    return xRemoteContext;
224
0
}
225
226
312k
OUString bootstrap_expandUri(OUString const & uri) {
227
312k
    OUString rest;
228
312k
    return uri.startsWith("vnd.sun.star.expand:", &rest)
229
312k
        ? cppuhelper::detail::expandMacros(
230
0
            rtl::Uri::decode(
231
0
                rest, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8))
232
312k
        : uri;
233
312k
}
234
235
} // namespace cppu
236
237
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */