20 #include <config_folders.h>
21 #include <config_features.h>
26 #include <rtl/uri.hxx>
27 #include <rtl/digest.h>
28 #include <rtl/random.h>
29 #include <rtl/bootstrap.hxx>
30 #include <rtl/ustrbuf.hxx>
33 #include <osl/file.hxx>
34 #include <osl/pipe.hxx>
35 #include <osl/security.hxx>
36 #include <osl/thread.hxx>
37 #include <com/sun/star/ucb/CommandAbortedException.hpp>
38 #include <com/sun/star/task/XInteractionHandler.hpp>
39 #include <com/sun/star/bridge/BridgeFactory.hpp>
40 #include <com/sun/star/bridge/UnoUrlResolver.hpp>
41 #include <com/sun/star/bridge/XUnoUrlResolver.hpp>
42 #include <com/sun/star/deployment/ExtensionManager.hpp>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <com/sun/star/task/OfficeRestartManager.hpp>
46 #include <string_view>
62 struct UnoRc :
public rtl::StaticWithInit<
63 std::shared_ptr<rtl::Bootstrap>, UnoRc> {
64 std::shared_ptr<rtl::Bootstrap> operator () () {
65 OUString unorc(
"$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE(
"louno") );
66 ::rtl::Bootstrap::expandMacros( unorc );
67 auto ret = std::make_shared<::rtl::Bootstrap>( unorc );
68 OSL_ASSERT( ret->getHandle() != nullptr );
73 struct OfficePipeId :
public rtl::StaticWithInit<OUString, OfficePipeId> {
74 OUString operator () ();
77 OUString OfficePipeId::operator () ()
85 throw Exception(
"Extension Manager: Could not obtain path for UserInstallation.",
nullptr);
88 rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
90 throw RuntimeException(
"cannot get digest rtl_Digest_AlgorithmMD5!",
nullptr );
94 reinterpret_cast<sal_uInt8 const *
>(userPath.getStr());
96 sal_uInt32 md5_key_len = rtl_digest_queryLength( digest );
97 std::unique_ptr<sal_uInt8[]> md5_buf(
new sal_uInt8 [ md5_key_len ] );
99 rtl_digest_init( digest, data, static_cast<sal_uInt32>(size) );
100 rtl_digest_update( digest, data, static_cast<sal_uInt32>(size) );
101 rtl_digest_get( digest, md5_buf.get(), md5_key_len );
102 rtl_digest_destroy( digest );
107 buf.append(
"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();
114 bool existsOfficePipe()
116 OUString
const & pipeId = OfficePipeId::get();
117 if (pipeId.isEmpty())
120 ::osl::Pipe
pipe( pipeId, osl_Pipe_OPEN, sec );
125 bool getModifyTimeTargetFile(
const OUString &rFileURL, TimeValue &rTime)
129 if (aResolver.fetchFileStatus(rFileURL) != osl::FileBase::E_None)
132 rTime = aResolver.m_aStatus.getModifyTime();
140 bool compareExtensionFolderWithLastSynchronizedFile(
141 OUString
const & folderURL, OUString
const & fileURL)
143 bool bNeedsSync =
false;
144 ::osl::DirectoryItem itemExtFolder;
145 ::osl::File::RC err1 =
146 ::osl::DirectoryItem::get(folderURL, itemExtFolder);
148 if (err1 == ::osl::File::E_NOENT)
152 else if (err1 != ::osl::File::E_None)
154 OSL_FAIL(
"Cannot access extension folder");
159 ::osl::DirectoryItem itemFile;
160 ::osl::File::RC err2 = ::osl::DirectoryItem::get(fileURL, itemFile);
161 if (err2 == ::osl::File::E_NOENT)
166 else if (err2 != ::osl::File::E_None)
168 OSL_FAIL(
"Cannot access file lastsynchronized");
174 TimeValue timeFolder;
175 if (getModifyTimeTargetFile(folderURL, timeFolder))
178 if (getModifyTimeTargetFile(fileURL, timeFile))
180 if (timeFile.Seconds < timeFolder.Seconds)
198 bool needToSyncRepository(std::u16string_view name)
202 if ( name == u
"bundled" )
204 folder =
"$BUNDLED_EXTENSIONS";
205 file =
"$BUNDLED_EXTENSIONS_USER/lastsynchronized";
207 else if ( name == u
"shared" )
209 folder =
"$UNO_SHARED_PACKAGES_CACHE/uno_packages";
210 file =
"$SHARED_EXTENSIONS_USER/lastsynchronized";
217 ::rtl::Bootstrap::expandMacros(folder);
218 ::rtl::Bootstrap::expandMacros(file);
219 return compareExtensionFolderWithLastSynchronizedFile(
228 OUString encodeForRcFile( OUString
const & str )
231 OUStringBuffer buf(64);
233 const sal_Int32 len = str.getLength();
234 for ( ; pos < len; ++pos ) {
246 return buf.makeStringAndClear();
251 OUString
makeURL( OUString
const & baseURL, OUString
const & relPath_ )
253 OUStringBuffer buf(128);
254 if (baseURL.getLength() > 1 && baseURL[ baseURL.getLength() - 1 ] ==
'/')
255 buf.append( std::u16string_view(baseURL).substr(0, baseURL.getLength() - 1) );
257 buf.append( baseURL );
258 OUString relPath(relPath_);
259 if( relPath.startsWith(
"/") )
260 relPath = relPath.copy( 1 );
261 if (!relPath.isEmpty())
264 if (baseURL.match(
"vnd.sun.star.expand:" )) {
267 relPath = encodeForRcFile(relPath);
272 relPath = ::rtl::Uri::encode( relPath, rtl_UriCharClassUric,
273 rtl_UriEncodeIgnoreEscapes,
274 RTL_TEXTENCODING_UTF8 );
276 buf.append( relPath );
278 return buf.makeStringAndClear();
283 OSL_ASSERT(segment.indexOf(
u'/') == -1);
286 segment, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
287 RTL_TEXTENCODING_UTF8);
288 return makeURL(baseURL, segment);
294 OUString term(term_);
295 UnoRc::get()->expandMacrosFrom( term );
301 OSL_ASSERT( url.match(
"vnd.sun.star.expand:" ));
302 if (url.match(
"vnd.sun.star.expand:" )) {
304 OUString rcterm( url.copy( sizeof (
"vnd.sun.star.expand:") - 1 ) );
306 rcterm = ::rtl::Uri::decode(
307 rcterm, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
317 if (url.match(
"vnd.sun.star.expand:" )) {
319 OUString rcurl( url.copy( sizeof (
"vnd.sun.star.expand:") - 1 ) );
321 rcurl = ::rtl::Uri::decode(
322 rcurl, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
324 UnoRc::get()->expandMacrosFrom( rcurl );
338 oslProcessError
err = osl_getExecutableFile(& sFile.pData);
340 if (osl_Process_E_None == err)
342 sFile = sFile.copy(sFile.lastIndexOf(
'/') + 1);
348 sFile ==
"soffice.bin" || sFile ==
"soffice.exe" || sFile ==
"soffice.com"
349 || sFile ==
"soffice" || sFile ==
"swriter.exe" || sFile ==
"swriter"
350 || sFile ==
"scalc.exe" || sFile ==
"scalc" || sFile ==
"simpress.exe"
351 || sFile ==
"simpress" || sFile ==
"sdraw.exe" || sFile ==
"sdraw"
352 || sFile ==
"sbase.exe" || sFile ==
"sbase"
356 sFile ==
"soffice.bin"
358 #error
"Unsupported platform"
364 ret = existsOfficePipe();
368 OSL_FAIL(
"NOT osl_Process_E_None ");
370 ret = existsOfficePipe();
380 oslProcess hProcess =
nullptr;
381 oslProcessError rc = osl_executeProcess(
383 reinterpret_cast<rtl_uString **>(
384 const_cast<OUString *>(args.getConstArray()) ),
386 osl_Process_DETACHED,
393 case osl_Process_E_None:
395 case osl_Process_E_NotFound:
397 case osl_Process_E_TimedOut:
399 case osl_Process_E_NoPermission:
401 case osl_Process_E_Unknown:
403 case osl_Process_E_InvalidError:
416 if (s_hPool ==
nullptr)
419 if (rtl_random_getBytes(
424 for (
unsigned char byte : bytes) {
425 buf.append( static_cast<sal_Int32>(
byte), 0x10 );
427 return buf.makeStringAndClear();
432 OUString
const & connectString,
434 AbortChannel
const * abortChannel )
436 Reference<bridge::XUnoUrlResolver> xUnoUrlResolver(
439 for (
int i = 0;
i <= 40; ++
i)
441 if (abortChannel !=
nullptr && abortChannel->isAborted()) {
442 throw ucb::CommandAbortedException(
"abort!" );
445 return xUnoUrlResolver->resolve( connectString );
447 catch (
const connection::NoConnectException &) {
450 ::osl::Thread::wait( std::chrono::milliseconds(500) );
461 fprintf(stream,
"%s", s.getStr());
478 memset(buf, 0, 1024);
480 if (fgets(buf, 1024, stdin) !=
nullptr)
482 OUString
value = OStringToOUString(std::string_view(buf), osl_getThreadTextEncoding());
485 throw css::uno::RuntimeException(
"reading from stdin failed");
490 SAL_INFO(
"desktop.deployment", sText);
494 bool force, Reference<ucb::XCommandEnvironment>
const & xCmdEnv)
497 ::rtl::Bootstrap::get(
"DISABLE_EXTENSION_SYNCHRONIZATION", sDisable, OUString() );
498 if (!sDisable.isEmpty())
501 Reference<deployment::XExtensionManager> xExtensionManager;
504 bool bModified =
false;
505 if (force || needToSyncRepository(
u"shared") || needToSyncRepository(
u"bundled"))
508 deployment::ExtensionManager::get(
511 if (xExtensionManager.is())
513 bModified = xExtensionManager->synchronize(
514 Reference<task::XAbortChannel>(), xCmdEnv);
517 #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)
OUString generateRandomPipeId()
std::vector< sal_uInt8 > bytes
OUString expandUnoRcTerm(OUString const &term_)
void syncRepositories(bool force, Reference< ucb::XCommandEnvironment > const &xCmdEnv)
OUString makeURL(OUString const &baseURL, OUString const &relPath_)
appends a relative path to a url.
OUString makeURLAppendSysPathSegment(OUString const &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)
Reference< XInterface > resolveUnoURL(OUString const &connectString, Reference< XComponentContext > const &xLocalContext, AbortChannel const *abortChannel)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
#define SAL_N_ELEMENTS(arr)
#define SAL_CONFIGFILE(name)
exports com.sun.star.lib.connections. pipe
void writeConsoleError(std::u16string_view sText)
writes the argument to the console using the error stream.
void writeConsole(std::u16string_view sText)
writes the argument string to the console.
oslProcess raiseProcess(OUString const &appURL, Sequence< OUString > const &args)
OUString makeRcTerm(OUString const &url)
exports com.sun.star.chart2. data
OUString expandUnoRcUrl(OUString const &url)
void TRACE(OUString const &sText)
print the text to the console in a debug build.
#define SAL_INFO(area, stream)
exports com.sun.star. bridge
static void writeConsoleWithStream(std::u16string_view sText, FILE *stream)
void disposeBridges(Reference< css::uno::XComponentContext > const &ctx)
Reference< XComponentContext > getProcessComponentContext()
OUString readConsole()
reads from the console.