20#include <config_folders.h>
21#include <config_features.h>
29#include <rtl/digest.h>
30#include <rtl/random.h>
31#include <rtl/bootstrap.hxx>
32#include <rtl/ustrbuf.hxx>
35#include <osl/file.hxx>
36#include <osl/pipe.hxx>
37#include <osl/security.hxx>
38#include <osl/thread.hxx>
39#include <com/sun/star/ucb/CommandAbortedException.hpp>
40#include <com/sun/star/task/XInteractionHandler.hpp>
41#include <com/sun/star/bridge/BridgeFactory.hpp>
42#include <com/sun/star/bridge/UnoUrlResolver.hpp>
43#include <com/sun/star/bridge/XUnoUrlResolver.hpp>
44#include <com/sun/star/deployment/ExtensionManager.hpp>
45#include <com/sun/star/lang/DisposedException.hpp>
46#include <com/sun/star/task/OfficeRestartManager.hpp>
65std::shared_ptr<rtl::Bootstrap> & UnoRc()
67 static std::shared_ptr<rtl::Bootstrap> theRc = []()
69 OUString unorc(
"$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE(
"louno") );
70 ::rtl::Bootstrap::expandMacros( unorc );
71 auto ret = std::make_shared<::rtl::Bootstrap>( unorc );
72 OSL_ASSERT( ret->getHandle() !=
nullptr );
78OUString generateOfficePipeId()
86 throw Exception(
"Extension Manager: Could not obtain path for UserInstallation.",
nullptr);
89 rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
91 throw RuntimeException(
"cannot get digest rtl_Digest_AlgorithmMD5!",
nullptr );
95 reinterpret_cast<sal_uInt8 const *
>(userPath.getStr());
97 sal_uInt32 md5_key_len = rtl_digest_queryLength( digest );
98 std::unique_ptr<sal_uInt8[]> md5_buf(
new sal_uInt8 [ md5_key_len ] );
100 rtl_digest_init( digest, data,
static_cast<sal_uInt32
>(size) );
101 rtl_digest_update( digest, data,
static_cast<sal_uInt32
>(size) );
102 rtl_digest_get( digest, md5_buf.get(), md5_key_len );
103 rtl_digest_destroy( digest );
107 OUStringBuffer buf(
"SingleOfficeIPC_" );
108 for ( sal_uInt32 i = 0;
i < md5_key_len; ++
i ) {
109 buf.append(
static_cast<sal_Int32
>(md5_buf[ i ]), 0x10 );
111 return buf.makeStringAndClear();
114bool existsOfficePipe()
116 static OUString OfficePipeId = generateOfficePipeId();
118 OUString
const & pipeId = OfficePipeId;
119 if (pipeId.isEmpty())
122 ::osl::Pipe pipe( pipeId, osl_Pipe_OPEN, sec );
127bool getModifyTimeTargetFile(
const OUString &rFileURL, TimeValue &rTime)
131 if (aResolver.fetchFileStatus(rFileURL) != osl::FileBase::E_None)
134 rTime = aResolver.m_aStatus.getModifyTime();
142bool compareExtensionFolderWithLastSynchronizedFile(
143 OUString
const & folderURL, OUString
const & fileURL)
145 bool bNeedsSync =
false;
146 ::osl::DirectoryItem itemExtFolder;
147 ::osl::File::RC err1 =
148 ::osl::DirectoryItem::get(folderURL, itemExtFolder);
150 if (err1 == ::osl::File::E_NOENT)
154 else if (err1 != ::osl::File::E_None)
156 OSL_FAIL(
"Cannot access extension folder");
161 ::osl::DirectoryItem itemFile;
162 ::osl::File::RC err2 = ::osl::DirectoryItem::get(fileURL, itemFile);
163 if (err2 == ::osl::File::E_NOENT)
168 else if (err2 != ::osl::File::E_None)
170 OSL_FAIL(
"Cannot access file lastsynchronized");
176 TimeValue timeFolder;
177 if (getModifyTimeTargetFile(folderURL, timeFolder))
180 if (getModifyTimeTargetFile(fileURL, timeFile))
182 if (timeFile.Seconds < timeFolder.Seconds)
200bool needToSyncRepository(std::u16string_view name)
204 if ( name == u
"bundled" )
206 folder =
"$BUNDLED_EXTENSIONS";
207 file =
"$BUNDLED_EXTENSIONS_USER/lastsynchronized";
209 else if ( name == u
"shared" )
211 folder =
"$UNO_SHARED_PACKAGES_CACHE/uno_packages";
212 file =
"$SHARED_EXTENSIONS_USER/lastsynchronized";
219 ::rtl::Bootstrap::expandMacros(folder);
220 ::rtl::Bootstrap::expandMacros(file);
221 return compareExtensionFolderWithLastSynchronizedFile(
230OUString encodeForRcFile( std::u16string_view str )
233 OUStringBuffer buf(64);
235 const size_t len = str.size();
236 for ( ;
pos < len; ++
pos ) {
248 return buf.makeStringAndClear();
253OUString
makeURL( std::u16string_view baseURL, OUString
const & relPath_ )
255 OUStringBuffer buf(128);
256 if (baseURL.size() > 1 && baseURL[ baseURL.size() - 1 ] ==
'/')
257 buf.append( baseURL.substr(0, baseURL.size() - 1) );
259 buf.append( baseURL );
260 OUString relPath(relPath_);
261 if( relPath.startsWith(
"/") )
262 relPath = relPath.copy( 1 );
263 if (!relPath.isEmpty())
269 relPath = encodeForRcFile(relPath);
274 relPath = ::rtl::Uri::encode( relPath, rtl_UriCharClassUric,
275 rtl_UriEncodeIgnoreEscapes,
276 RTL_TEXTENCODING_UTF8 );
278 buf.append( relPath );
280 return buf.makeStringAndClear();
285 OSL_ASSERT(segment.indexOf(
u'/') == -1);
288 segment, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
289 RTL_TEXTENCODING_UTF8);
290 return makeURL(baseURL, segment);
296 OUString term(term_);
297 UnoRc()->expandMacrosFrom( term );
303 OSL_ASSERT( url.match(
"vnd.sun.star.expand:" ));
304 if (OUString rcterm; url.startsWithIgnoreAsciiCase(
"vnd.sun.star.expand:", &rcterm)) {
306 rcterm = ::rtl::Uri::decode(
307 rcterm, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
317 if (OUString rcurl; url.startsWithIgnoreAsciiCase(
"vnd.sun.star.expand:", &rcurl)) {
319 rcurl = ::rtl::Uri::decode(
320 rcurl, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
322 UnoRc()->expandMacrosFrom( rcurl );
336 oslProcessError
err = osl_getExecutableFile(& sFile.pData);
338 if (osl_Process_E_None ==
err)
340 sFile = sFile.copy(sFile.lastIndexOf(
'/') + 1);
346 sFile ==
"soffice.bin" || sFile ==
"soffice.exe" || sFile ==
"soffice.com"
347 || sFile ==
"soffice" || sFile ==
"swriter.exe" || sFile ==
"swriter"
348 || sFile ==
"scalc.exe" || sFile ==
"scalc" || sFile ==
"simpress.exe"
349 || sFile ==
"simpress" || sFile ==
"sdraw.exe" || sFile ==
"sdraw"
350 || sFile ==
"sbase.exe" || sFile ==
"sbase"
354 sFile ==
"soffice.bin"
356#error
"Unsupported platform"
362 ret = existsOfficePipe();
366 OSL_FAIL(
"NOT osl_Process_E_None ");
368 ret = existsOfficePipe();
375 OUString
const & appURL, Sequence<OUString>
const & args )
378 oslProcess hProcess =
nullptr;
379 oslProcessError rc = osl_executeProcess(
381 reinterpret_cast<rtl_uString **
>(
382 const_cast<OUString *
>(
args.getConstArray()) ),
384 osl_Process_DETACHED,
391 case osl_Process_E_None:
393 case osl_Process_E_NotFound:
395 case osl_Process_E_TimedOut:
397 case osl_Process_E_NoPermission:
399 case osl_Process_E_Unknown:
401 case osl_Process_E_InvalidError:
414 if (s_hPool ==
nullptr)
417 if (rtl_random_getBytes(
418 s_hPool,
bytes, std::size(
bytes) ) != rtl_Random_E_None) {
422 for (
unsigned char byte :
bytes) {
423 buf.append(
static_cast<sal_Int32
>(
byte), 0x10 );
425 return buf.makeStringAndClear();
430 OUString
const & connectString,
431 Reference<XComponentContext>
const & xLocalContext,
432 AbortChannel
const * abortChannel )
434 Reference<bridge::XUnoUrlResolver> xUnoUrlResolver(
437 for (
int i = 0;
i <= 40; ++
i)
439 if (abortChannel !=
nullptr && abortChannel->isAborted()) {
440 throw ucb::CommandAbortedException(
"abort!" );
443 return xUnoUrlResolver->resolve( connectString );
445 catch (
const connection::NoConnectException &) {
448 std::this_thread::sleep_for( std::chrono::milliseconds(500) );
459 fprintf(
stream,
"%s", s.getStr());
476 memset(buf, 0, 1024);
478 if (fgets(buf, 1024, stdin) !=
nullptr)
480 OUString
value = OStringToOUString(std::string_view(buf), osl_getThreadTextEncoding());
483 throw css::uno::RuntimeException(
"reading from stdin failed");
488 SAL_INFO(
"desktop.deployment", sText);
492 bool force, Reference<ucb::XCommandEnvironment>
const & xCmdEnv)
495 ::rtl::Bootstrap::get(
"DISABLE_EXTENSION_SYNCHRONIZATION", sDisable, OUString() );
496 if (!sDisable.isEmpty())
499 Reference<deployment::XExtensionManager> xExtensionManager;
502 bool bModified =
false;
503 if (force || needToSyncRepository(
u"shared") || needToSyncRepository(
u"bundled"))
506 deployment::ExtensionManager::get(
509 if (xExtensionManager.is())
511 bModified = xExtensionManager->synchronize(
512 Reference<task::XAbortChannel>(), xCmdEnv);
515#if HAVE_FEATURE_MACOSX_SANDBOX
523 restarter->requestRestart(xCmdEnv.is() ? xCmdEnv->getInteractionHandler() :
524 Reference<task::XInteractionHandler>());
537 const Sequence< Reference<css::bridge::XBridge> >seqBridges = bridgeFac->getExistingBridges();
538 for (
const Reference<css::bridge::XBridge>& bridge : seqBridges)
540 Reference<css::lang::XComponent>
comp(bridge, UNO_QUERY);
546 catch (
const css::lang::DisposedException& )
static PathStatus locateUserInstallation(OUString &_rURL)
#define SAL_CONFIGFILE(name)
Reference< XOutputStream > stream
OUString DpResId(TranslateId aId)
#define SAL_INFO(area, stream)
std::locale Create(std::string_view aPrefixName, const LanguageTag &rLocale)
OUString get(TranslateId sContextAndId, const std::locale &loc)
Reference< XComponentContext > getProcessComponentContext()
OUString makeURL(std::u16string_view baseURL, OUString const &relPath_)
appends a relative path to a url.
void syncRepositories(bool force, Reference< ucb::XCommandEnvironment > const &xCmdEnv)
OUString makeRcTerm(OUString const &url)
OUString expandUnoRcUrl(OUString const &url)
OUString readConsole()
reads from the console.
void writeConsoleError(std::u16string_view sText)
writes the argument to the console using the error stream.
void TRACE(OUString const &sText)
print the text to the console in a debug build.
Reference< XInterface > resolveUnoURL(OUString const &connectString, Reference< XComponentContext > const &xLocalContext, AbortChannel const *abortChannel)
static void writeConsoleWithStream(std::u16string_view sText, FILE *stream)
OUString generateRandomPipeId()
OUString expandUnoRcTerm(OUString const &term_)
void writeConsole(std::u16string_view sText)
writes the argument string to the console.
oslProcess raiseProcess(OUString const &appURL, Sequence< OUString > const &args)
void disposeBridges(Reference< css::uno::XComponentContext > const &ctx)
OUString makeURLAppendSysPathSegment(std::u16string_view baseURL, OUString const &segment)
appends a relative path to a url.
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
std::vector< sal_uInt8 > bytes