1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
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"
54 //#include "tools/prewin.h"
57 #define WIN32_LEAN_AND_MEAN
59 //#include "tools/postwin.h"
62 using namespace ::com::sun::star
;
63 using namespace ::com::sun::star::uno
;
64 using ::rtl::OUString
;
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"
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 );
92 struct OfficePipeId
: public rtl::StaticWithInit
<const OUString
, OfficePipeId
> {
93 const OUString
operator () ();
96 const OUString
OfficePipeId::operator () ()
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
);
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)
140 ::osl::Pipe
pipe( pipeId
, osl_Pipe_OPEN
, sec
);
146 //==============================================================================
149 inline OUString
encodeForRcFile( OUString
const & str
)
151 // escape $\{} (=> rtl bootstrap files)
152 ::rtl::OUStringBuffer buf
;
154 const sal_Int32 len
= str
.getLength();
155 for ( ; pos
< len
; ++pos
) {
156 sal_Unicode c
= str
[ pos
];
162 buf
.append( static_cast<sal_Unicode
>('\\') );
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 ) );
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
);
211 //==============================================================================
212 OUString
expandUnoRcUrl( OUString
const & url
)
214 if (url
.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) {
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
);
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
235 oslProcessError err
= osl_getExecutableFile(& sFile
.pData
);
237 if (osl_Process_E_None
== err
)
239 sFile
= sFile
.copy(sFile
.lastIndexOf('/') + 1);
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
)))
255 #error "Unsupported platform"
261 ret
= existsOfficePipe();
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();
272 //==============================================================================
273 oslProcess
raiseProcess(
274 OUString
const & appURL
, Sequence
<OUString
> const & args
)
277 oslProcess hProcess
= 0;
278 oslProcessError rc
= osl_executeProcess(
280 reinterpret_cast<rtl_uString
**>(
281 const_cast<OUString
*>(args
.getConstArray()) ),
283 osl_Process_DETACHED
,
285 0, // => current working dir
286 0, 0, // => no env vars
290 case osl_Process_E_None
:
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
:
302 throw RuntimeException( OUSTR("unmapped error!"), 0 );
308 //==============================================================================
309 OUString
generateRandomPipeId()
311 // compute some good pipe id:
312 static rtlRandomPool s_hPool
= rtl_random_createPool();
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
) );
338 if (abortChannel
!= 0 && abortChannel
->isAborted()) {
339 throw ucb::CommandAbortedException(
340 OUSTR("abort!"), Reference
<XInterface
>() );
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
);
364 void writeConsoleWithStream(::rtl::OUString
const & sText
, HANDLE stream
)
366 DWORD nWrittenChars
= 0;
367 WriteFile(stream
, sText
.getStr(),
368 sText
.getLength() * 2, &nWrittenChars
, NULL
);
371 void writeConsoleWithStream(::rtl::OUString
const & sText
, FILE * stream
)
373 OString s
= OUStringToOString(sText
, osl_getThreadTextEncoding());
374 fprintf(stream
, "%s", s
.getStr());
380 void writeConsoleWithStream(::rtl::OString
const & sText
, HANDLE stream
)
382 writeConsoleWithStream(OStringToOUString(
383 sText
, RTL_TEXTENCODING_UTF8
), stream
);
386 void writeConsoleWithStream(::rtl::OString
const & sText
, FILE * stream
)
388 fprintf(stream
, "%s", sText
.getStr());
393 void writeConsole(::rtl::OUString
const & sText
)
396 writeConsoleWithStream(sText
, GetStdHandle(STD_OUTPUT_HANDLE
));
398 writeConsoleWithStream(sText
, stdout
);
402 void writeConsole(::rtl::OString
const & sText
)
405 writeConsoleWithStream(sText
, GetStdHandle(STD_OUTPUT_HANDLE
));
407 writeConsoleWithStream(sText
, stdout
);
411 void writeConsoleError(::rtl::OUString
const & sText
)
414 writeConsoleWithStream(sText
, GetStdHandle(STD_ERROR_HANDLE
));
416 writeConsoleWithStream(sText
, stderr
);
421 void writeConsoleError(::rtl::OString
const & sText
)
424 writeConsoleWithStream(sText
, GetStdHandle(STD_ERROR_HANDLE
));
426 writeConsoleWithStream(sText
, stderr
);
432 OUString
readConsole()
435 sal_Unicode aBuffer
[1024];
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();
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());
457 void TRACE(::rtl::OUString
const & sText
)
460 #if OSL_DEBUG_LEVEL > 1
465 void TRACE(::rtl::OString
const & sText
)
468 #if OSL_DEBUG_LEVEL > 1