Update ooo320-m1
[ooovba.git] / desktop / source / deployment / misc / dp_misc.cxx
blobc067b26d1a9af16c527f9f406dded8c165c3a955
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dp_misc.cxx,v $
10 * $Revision: 1.19.8.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_desktop.hxx"
35 #include "dp_misc.h"
36 #include "dp_interact.h"
37 #include "rtl/uri.hxx"
38 #include "rtl/digest.h"
39 #include "rtl/random.h"
40 #include "rtl/bootstrap.hxx"
41 #include "unotools/bootstrap.hxx"
42 #include "osl/file.hxx"
43 #include "osl/pipe.hxx"
44 #include "osl/security.hxx"
45 #include "osl/thread.hxx"
46 #include "osl/mutex.hxx"
47 #include "com/sun/star/ucb/CommandAbortedException.hpp"
48 #include "com/sun/star/bridge/UnoUrlResolver.hpp"
49 #include "com/sun/star/bridge/XUnoUrlResolver.hpp"
50 #include "boost/scoped_array.hpp"
51 #include "boost/shared_ptr.hpp"
53 #ifdef WNT
54 //#include "tools/prewin.h"
55 #define UNICODE
56 #define _UNICODE
57 #define WIN32_LEAN_AND_MEAN
58 #include <Windows.h>
59 //#include "tools/postwin.h"
60 #endif
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::uno;
64 using ::rtl::OUString;
65 using ::rtl::OString;
68 #define SOFFICE1 "soffice.exe"
69 #define SOFFICE2 "soffice.bin"
70 #define SBASE "sbase.exe"
71 #define SCALC "scalc.exe"
72 #define SDRAW "sdraw.exe"
73 #define SIMPRESS "simpress.exe"
74 #define SWRITER "swriter.exe"
76 namespace dp_misc {
77 namespace {
79 struct UnoRc : public rtl::StaticWithInit<
80 const boost::shared_ptr<rtl::Bootstrap>, UnoRc> {
81 const boost::shared_ptr<rtl::Bootstrap> operator () () {
82 OUString unorc( RTL_CONSTASCII_USTRINGPARAM(
83 "$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")) );
84 ::rtl::Bootstrap::expandMacros( unorc );
85 ::boost::shared_ptr< ::rtl::Bootstrap > ret(
86 new ::rtl::Bootstrap( unorc ) );
87 OSL_ASSERT( ret->getHandle() != 0 );
88 return ret;
92 struct OfficePipeId : public rtl::StaticWithInit<const OUString, OfficePipeId> {
93 const OUString operator () ();
96 const OUString OfficePipeId::operator () ()
98 OUString userPath;
99 ::utl::Bootstrap::PathStatus aLocateResult =
100 ::utl::Bootstrap::locateUserInstallation( userPath );
101 if (!(aLocateResult == ::utl::Bootstrap::PATH_EXISTS ||
102 aLocateResult == ::utl::Bootstrap::PATH_VALID))
104 throw Exception(OUSTR("Extension Manager: Could not obtain path for UserInstallation."), 0);
107 rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
108 if (digest <= 0) {
109 throw RuntimeException(
110 OUSTR("cannot get digest rtl_Digest_AlgorithmMD5!"), 0 );
113 sal_uInt8 const * data =
114 reinterpret_cast<sal_uInt8 const *>(userPath.getStr());
115 sal_Size size = (userPath.getLength() * sizeof (sal_Unicode));
116 sal_uInt32 md5_key_len = rtl_digest_queryLength( digest );
117 ::boost::scoped_array<sal_uInt8> md5_buf( new sal_uInt8 [ md5_key_len ] );
119 rtl_digest_init( digest, data, static_cast<sal_uInt32>(size) );
120 rtl_digest_update( digest, data, static_cast<sal_uInt32>(size) );
121 rtl_digest_get( digest, md5_buf.get(), md5_key_len );
122 rtl_digest_destroy( digest );
124 // create hex-value string from the MD5 value to keep
125 // the string size minimal
126 ::rtl::OUStringBuffer buf;
127 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("SingleOfficeIPC_") );
128 for ( sal_uInt32 i = 0; i < md5_key_len; ++i ) {
129 buf.append( static_cast<sal_Int32>(md5_buf[ i ]), 0x10 );
131 return buf.makeStringAndClear();
134 bool existsOfficePipe()
136 OUString const & pipeId = OfficePipeId::get();
137 if (pipeId.getLength() == 0)
138 return false;
139 ::osl::Security sec;
140 ::osl::Pipe pipe( pipeId, osl_Pipe_OPEN, sec );
141 return pipe.is();
144 } // anon namespace
146 //==============================================================================
148 namespace {
149 inline OUString encodeForRcFile( OUString const & str )
151 // escape $\{} (=> rtl bootstrap files)
152 ::rtl::OUStringBuffer buf;
153 sal_Int32 pos = 0;
154 const sal_Int32 len = str.getLength();
155 for ( ; pos < len; ++pos ) {
156 sal_Unicode c = str[ pos ];
157 switch (c) {
158 case '$':
159 case '\\':
160 case '{':
161 case '}':
162 buf.append( static_cast<sal_Unicode>('\\') );
163 break;
165 buf.append( c );
167 return buf.makeStringAndClear();
171 //==============================================================================
172 OUString makeURL( OUString const & baseURL, OUString const & relPath_ )
174 ::rtl::OUStringBuffer buf;
175 if (baseURL.getLength() > 1 && baseURL[ baseURL.getLength() - 1 ] == '/')
176 buf.append( baseURL.copy( 0, baseURL.getLength() - 1 ) );
177 else
178 buf.append( baseURL );
179 OUString relPath(relPath_);
180 if (relPath.getLength() > 0 && relPath[ 0 ] == '/')
181 relPath = relPath.copy( 1 );
182 if (relPath.getLength() > 0)
184 buf.append( static_cast<sal_Unicode>('/') );
185 if (baseURL.matchAsciiL(
186 RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) {
187 // encode for macro expansion: relPath is supposed to have no
188 // macros, so encode $, {} \ (bootstrap mimic)
189 relPath = encodeForRcFile(relPath);
191 // encode once more for vnd.sun.star.expand schema:
192 // vnd.sun.star.expand:$UNO_...
193 // will expand to file-url
194 relPath = ::rtl::Uri::encode( relPath, rtl_UriCharClassUric,
195 rtl_UriEncodeIgnoreEscapes,
196 RTL_TEXTENCODING_UTF8 );
198 buf.append( relPath );
200 return buf.makeStringAndClear();
203 //==============================================================================
204 OUString expandUnoRcTerm( OUString const & term_ )
206 OUString term(term_);
207 UnoRc::get()->expandMacrosFrom( term );
208 return term;
211 //==============================================================================
212 OUString expandUnoRcUrl( OUString const & url )
214 if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) {
215 // cut protocol:
216 OUString rcurl( url.copy( sizeof ("vnd.sun.star.expand:") - 1 ) );
217 // decode uric class chars:
218 rcurl = ::rtl::Uri::decode(
219 rcurl, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
220 // expand macro string:
221 UnoRc::get()->expandMacrosFrom( rcurl );
222 return rcurl;
224 else {
225 return url;
229 //==============================================================================
230 bool office_is_running()
232 //We need to check if we run within the office process. Then we must not use the pipe, because
233 //this could cause a deadlock. This is actually a workaround for i82778
234 OUString sFile;
235 oslProcessError err = osl_getExecutableFile(& sFile.pData);
236 bool ret = false;
237 if (osl_Process_E_None == err)
239 sFile = sFile.copy(sFile.lastIndexOf('/') + 1);
240 if (
241 #if defined UNIX
242 sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE2)))
243 #elif defined WNT || defined OS2
244 //osl_getExecutableFile should deliver "soffice.bin" on windows
245 //even if swriter.exe, scalc.exe etc. was started. This is a bug
246 //in osl_getExecutableFile
247 sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE1)))
248 || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE2)))
249 || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SBASE)))
250 || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SCALC)))
251 || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SDRAW)))
252 || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SIMPRESS)))
253 || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SWRITER)))
254 #else
255 #error "Unsupported platform"
256 #endif
259 ret = true;
260 else
261 ret = existsOfficePipe();
263 else
265 OSL_ENSURE(0, "NOT osl_Process_E_None ");
266 //if osl_getExecutable file than we take the risk of creating a pipe
267 ret = existsOfficePipe();
269 return ret;
272 //==============================================================================
273 oslProcess raiseProcess(
274 OUString const & appURL, Sequence<OUString> const & args )
276 ::osl::Security sec;
277 oslProcess hProcess = 0;
278 oslProcessError rc = osl_executeProcess(
279 appURL.pData,
280 reinterpret_cast<rtl_uString **>(
281 const_cast<OUString *>(args.getConstArray()) ),
282 args.getLength(),
283 osl_Process_DETACHED,
284 sec.getHandle(),
285 0, // => current working dir
286 0, 0, // => no env vars
287 &hProcess );
289 switch (rc) {
290 case osl_Process_E_None:
291 break;
292 case osl_Process_E_NotFound:
293 throw RuntimeException( OUSTR("image not found!"), 0 );
294 case osl_Process_E_TimedOut:
295 throw RuntimeException( OUSTR("timout occured!"), 0 );
296 case osl_Process_E_NoPermission:
297 throw RuntimeException( OUSTR("permission denied!"), 0 );
298 case osl_Process_E_Unknown:
299 throw RuntimeException( OUSTR("unknown error!"), 0 );
300 case osl_Process_E_InvalidError:
301 default:
302 throw RuntimeException( OUSTR("unmapped error!"), 0 );
305 return hProcess;
308 //==============================================================================
309 OUString generateRandomPipeId()
311 // compute some good pipe id:
312 static rtlRandomPool s_hPool = rtl_random_createPool();
313 if (s_hPool == 0)
314 throw RuntimeException( OUSTR("cannot create random pool!?"), 0 );
315 sal_uInt8 bytes[ 32 ];
316 if (rtl_random_getBytes(
317 s_hPool, bytes, ARLEN(bytes) ) != rtl_Random_E_None) {
318 throw RuntimeException( OUSTR("random pool error!?"), 0 );
320 ::rtl::OUStringBuffer buf;
321 for ( sal_uInt32 i = 0; i < ARLEN(bytes); ++i ) {
322 buf.append( static_cast<sal_Int32>(bytes[ i ]), 0x10 );
324 return buf.makeStringAndClear();
327 //==============================================================================
328 Reference<XInterface> resolveUnoURL(
329 OUString const & connectString,
330 Reference<XComponentContext> const & xLocalContext,
331 AbortChannel * abortChannel )
333 Reference<bridge::XUnoUrlResolver> xUnoUrlResolver(
334 bridge::UnoUrlResolver::create( xLocalContext ) );
336 for (;;)
338 if (abortChannel != 0 && abortChannel->isAborted()) {
339 throw ucb::CommandAbortedException(
340 OUSTR("abort!"), Reference<XInterface>() );
342 try {
343 return xUnoUrlResolver->resolve( connectString );
345 catch (connection::NoConnectException &) {
346 TimeValue tv = { 0 /* secs */, 500000000 /* nanosecs */ };
347 ::osl::Thread::wait( tv );
352 OUString getExtensionDefaultUpdateURL()
354 ::rtl::OUString sUrl(
355 RTL_CONSTASCII_USTRINGPARAM(
356 "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version")
357 ":Version:ExtensionUpdateURL}"));
358 ::rtl::Bootstrap::expandMacros(sUrl);
359 return sUrl;
363 #ifdef WNT
364 void writeConsoleWithStream(::rtl::OUString const & sText, HANDLE stream)
366 DWORD nWrittenChars = 0;
367 WriteFile(stream, sText.getStr(),
368 sText.getLength() * 2, &nWrittenChars, NULL);
370 #else
371 void writeConsoleWithStream(::rtl::OUString const & sText, FILE * stream)
373 OString s = OUStringToOString(sText, osl_getThreadTextEncoding());
374 fprintf(stream, "%s", s.getStr());
375 fflush(stream);
377 #endif
379 #ifdef WNT
380 void writeConsoleWithStream(::rtl::OString const & sText, HANDLE stream)
382 writeConsoleWithStream(OStringToOUString(
383 sText, RTL_TEXTENCODING_UTF8), stream);
385 #else
386 void writeConsoleWithStream(::rtl::OString const & sText, FILE * stream)
388 fprintf(stream, "%s", sText.getStr());
389 fflush(stream);
391 #endif
393 void writeConsole(::rtl::OUString const & sText)
395 #ifdef WNT
396 writeConsoleWithStream(sText, GetStdHandle(STD_OUTPUT_HANDLE));
397 #else
398 writeConsoleWithStream(sText, stdout);
399 #endif
402 void writeConsole(::rtl::OString const & sText)
404 #ifdef WNT
405 writeConsoleWithStream(sText, GetStdHandle(STD_OUTPUT_HANDLE));
406 #else
407 writeConsoleWithStream(sText, stdout);
408 #endif
411 void writeConsoleError(::rtl::OUString const & sText)
413 #ifdef WNT
414 writeConsoleWithStream(sText, GetStdHandle(STD_ERROR_HANDLE));
415 #else
416 writeConsoleWithStream(sText, stderr);
417 #endif
421 void writeConsoleError(::rtl::OString const & sText)
423 #ifdef WNT
424 writeConsoleWithStream(sText, GetStdHandle(STD_ERROR_HANDLE));
425 #else
426 writeConsoleWithStream(sText, stderr);
427 #endif
432 OUString readConsole()
434 #ifdef WNT
435 sal_Unicode aBuffer[1024];
436 DWORD dwRead = 0;
437 //unopkg.com feeds unopkg.exe with wchar_t|s
438 if (ReadFile( GetStdHandle(STD_INPUT_HANDLE), &aBuffer, sizeof(aBuffer), &dwRead, NULL ) )
440 OSL_ASSERT((dwRead % 2) == 0);
441 OUString value( aBuffer, dwRead / 2);
442 value = value.trim();
443 return value;
445 return OUString();
447 #else
448 char buf[1024];
449 rtl_zeroMemory(buf, 1024);
450 // read one char less so that the last char in buf is always zero
451 fgets(buf, 1024, stdin);
452 OUString value = ::rtl::OStringToOUString(::rtl::OString(buf), osl_getThreadTextEncoding());
453 return value.trim();
454 #endif
457 void TRACE(::rtl::OUString const & sText)
459 (void) sText;
460 #if OSL_DEBUG_LEVEL > 1
461 writeConsole(sText);
462 #endif
465 void TRACE(::rtl::OString const & sText)
467 (void) sText;
468 #if OSL_DEBUG_LEVEL > 1
469 writeConsole(sText);
470 #endif