Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*************************************************************************
3 : *
4 : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : *
6 : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : *
8 : * OpenOffice.org - a multi-platform office productivity suite
9 : *
10 : * This file is part of OpenOffice.org.
11 : *
12 : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : * it under the terms of the GNU Lesser General Public License version 3
14 : * only, as published by the Free Software Foundation.
15 : *
16 : * OpenOffice.org is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : * GNU Lesser General Public License version 3 for more details
20 : * (a copy is included in the LICENSE file that accompanied this code).
21 : *
22 : * You should have received a copy of the GNU Lesser General Public License
23 : * version 3 along with OpenOffice.org. If not, see
24 : * <http://www.openoffice.org/license.html>
25 : * for a copy of the LGPLv3 License.
26 : *
27 : ************************************************************************/
28 :
29 :
30 : #ifdef AIX
31 : #define _LINUX_SOURCE_COMPAT
32 : #include <sys/timer.h>
33 : #undef _LINUX_SOURCE_COMPAT
34 : #endif
35 :
36 : #include <cstdarg>
37 : #include <sys/stat.h>
38 : #include <sys/types.h>
39 : #include <dirent.h>
40 : #include <osl/thread.h>
41 : #include <rtl/strbuf.hxx>
42 : #include <tools/appendunixshellword.hxx>
43 :
44 : #include <vcl/svapp.hxx>
45 : #include <plugin/impl.hxx>
46 :
47 : using namespace std;
48 : using namespace com::sun::star::uno;
49 : using namespace com::sun::star::plugin;
50 :
51 :
52 : // Unix specific implementation
53 0 : static bool CheckPlugin( const OString& rPath, list< PluginDescription* >& rDescriptions )
54 : {
55 : #if OSL_DEBUG_LEVEL > 1
56 : fprintf( stderr, "Trying plugin %s ... ", rPath.getStr() );
57 : #endif
58 :
59 0 : sal_Int32 nPos = rPath.lastIndexOf('/');
60 0 : if (nPos == -1)
61 : {
62 : #if OSL_DEBUG_LEVEL > 1
63 : fprintf( stderr, "no absolute path to plugin\n" );
64 : #endif
65 0 : return false;
66 : }
67 :
68 0 : OString aBaseName = rPath.copy(nPos+1);
69 0 : if (aBaseName == "libnullplugin.so")
70 : {
71 : #if OSL_DEBUG_LEVEL > 1
72 : fprintf( stderr, "don't like %s\n", aBaseName.getStr() );
73 : #endif
74 0 : return false;
75 : }
76 :
77 : struct stat aStat;
78 0 : if (stat(rPath.getStr(), &aStat) || !S_ISREG(aStat.st_mode))
79 : {
80 : #if OSL_DEBUG_LEVEL > 1
81 : fprintf( stderr, "%s is not a regular file\n", rPath.getStr() );
82 : #endif
83 0 : return false;
84 : }
85 :
86 0 : rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
87 :
88 0 : OString path;
89 0 : if (!UnxPluginComm::getPluginappPath(&path))
90 : {
91 : #if OSL_DEBUG_LEVEL > 1
92 : fprintf( stderr, "cannot construct path to pluginapp.bin\n" );
93 : #endif
94 0 : return false;
95 : }
96 0 : OStringBuffer cmd;
97 0 : tools::appendUnixShellWord(&cmd, path);
98 0 : cmd.append(' ');
99 0 : tools::appendUnixShellWord(&cmd, rPath);
100 0 : OString aCommand(cmd.makeStringAndClear());
101 :
102 0 : FILE* pResult = popen( aCommand.getStr(), "r" );
103 0 : int nDescriptions = 0;
104 0 : if( pResult )
105 : {
106 0 : OStringBuffer aMIME;
107 : char buf[256];
108 0 : while( fgets( buf, sizeof( buf ), pResult ) )
109 : {
110 0 : for( size_t i = 0; i < sizeof(buf) && buf[i]; ++i )
111 : {
112 0 : if( buf[i] == '\n' )
113 0 : buf[i] = ';';
114 : }
115 0 : aMIME.append( buf );
116 : }
117 0 : pclose( pResult );
118 :
119 0 : if( !aMIME.isEmpty() )
120 : {
121 0 : OString aLine = aMIME.makeStringAndClear();
122 :
123 0 : sal_Int32 nIndex = 0;
124 0 : while( nIndex != -1 )
125 : {
126 0 : OString aType = aLine.getToken( 0, ';', nIndex );
127 :
128 0 : sal_Int32 nTypeIndex = 0;
129 0 : OString aMimetype = aType.getToken( 0, ':', nTypeIndex );
130 0 : OString aExtLine = aType.getToken( 0, ':', nTypeIndex );
131 0 : if( nTypeIndex < 0 ) // ensure at least three tokens
132 0 : continue;
133 0 : OString aDesc = aType.getToken( 0, ':', nTypeIndex );
134 :
135 : // create extension list string
136 0 : sal_Int32 nExtIndex = 0;
137 0 : OStringBuffer aExtension;
138 0 : while( nExtIndex != -1 )
139 : {
140 0 : OString aExt = aExtLine.getToken( 0, ',', nExtIndex);
141 0 : if( aExt.indexOf( "*." ) != 0 )
142 0 : aExtension.append( "*." );
143 0 : aExtension.append( aExt );
144 0 : if( nExtIndex != -1 )
145 0 : aExtension.append( ';' );
146 0 : }
147 :
148 0 : PluginDescription* pNew = new PluginDescription;
149 : // set plugin name (path to library)
150 0 : pNew->PluginName = OStringToOUString( rPath, aEncoding );
151 : // set mimetype
152 0 : pNew->Mimetype = OStringToOUString( aMimetype, aEncoding );
153 : // set extension line
154 0 : pNew->Extension = OStringToOUString( aExtension.makeStringAndClear(), aEncoding );
155 : // set description
156 0 : pNew->Description= OStringToOUString( aDesc, aEncoding );
157 0 : rDescriptions.push_back( pNew );
158 : #if OSL_DEBUG_LEVEL > 1
159 : fprintf( stderr, "Mimetype: %s\nExtension: %s\n"
160 : "Description: %s\n",
161 : OUStringToOString( pNew->Mimetype, aEncoding ).getStr(),
162 : OUStringToOString( pNew->Extension, aEncoding ).getStr(),
163 : OUStringToOString( pNew->Description, aEncoding ).getStr()
164 : );
165 : #endif
166 0 : }
167 0 : }
168 : #if OSL_DEBUG_LEVEL > 1
169 : else
170 : fprintf( stderr, "result of \"%s\" contains no mimtype\n",
171 : aCommand.getStr() );
172 : #endif
173 : }
174 : #if OSL_DEBUG_LEVEL > 1
175 : else
176 : fprintf( stderr, "command \"%s\" failed\n", aCommand.getStr() );
177 : #endif
178 0 : return nDescriptions > 0;
179 : }
180 :
181 : union maxDirent
182 : {
183 : char aBuffer[ sizeof( struct dirent ) + PATH_MAX +1 ];
184 : struct dirent asDirent;
185 : };
186 :
187 0 : static void CheckPluginRegistryFiles( const OString& rPath, list< PluginDescription* >& rDescriptions )
188 : {
189 0 : OStringBuffer aPath( 1024 );
190 0 : aPath.append( rPath );
191 0 : aPath.append( "/pluginreg.dat" );
192 0 : FILE* fp = fopen( aPath.getStr(), "r" );
193 0 : if( fp )
194 : {
195 : #if OSL_DEBUG_LEVEL > 1
196 : fprintf( stderr, "parsing %s\n", aPath.getStr() );
197 : #endif
198 : char aLine[1024];
199 0 : while( fgets( aLine, sizeof( aLine ), fp ) )
200 : {
201 0 : int nLineLen = strlen( aLine );
202 : int nDotPos;
203 0 : for( nDotPos = nLineLen-1; nDotPos > 0 && aLine[nDotPos] != ':'; nDotPos-- )
204 : ;
205 0 : if( aLine[0] == '/' && aLine[nDotPos] == ':' && aLine[nDotPos+1] == '$' )
206 0 : CheckPlugin( OString(aLine, nDotPos), rDescriptions );
207 : }
208 0 : fclose( fp );
209 : }
210 :
211 : // check subdirectories
212 0 : DIR* pDIR = opendir( rPath.getStr() );
213 0 : struct dirent* pDirEnt = NULL;
214 : struct stat aStat;
215 : maxDirent u;
216 0 : while( pDIR && ! readdir_r( pDIR, &u.asDirent, &pDirEnt ) && pDirEnt )
217 : {
218 0 : char* pBaseName = u.asDirent.d_name;
219 0 : if( rtl_str_compare( ".", pBaseName ) && rtl_str_compare( "..", pBaseName ) )
220 : {
221 0 : OStringBuffer aBuf( 1024 );
222 0 : aBuf.append( rPath );
223 0 : aBuf.append( '/' );
224 0 : aBuf.append( pBaseName );
225 :
226 0 : if( ! stat( aBuf.getStr(), &aStat ) )
227 : {
228 0 : if( S_ISDIR( aStat.st_mode ) )
229 0 : CheckPluginRegistryFiles( aBuf.makeStringAndClear(), rDescriptions );
230 0 : }
231 : }
232 : }
233 0 : if( pDIR )
234 0 : closedir( pDIR );
235 0 : }
236 :
237 0 : Sequence<PluginDescription> XPluginManager_Impl::impl_getPluginDescriptions() throw(css::uno::RuntimeException, std::exception)
238 : {
239 0 : static Sequence<PluginDescription> aDescriptions;
240 : static bool bHavePlugins = false;
241 0 : if( ! bHavePlugins )
242 : {
243 0 : rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
244 0 : list<PluginDescription*> aPlugins;
245 : int i;
246 :
247 : // unix: search for plugins in /usr/lib/netscape/plugins,
248 : // ~/.netscape/plugins und NPX_PLUGIN_PATH
249 : // additionally: search in PluginsPath
250 0 : static const char* pHome = getenv( "HOME" );
251 0 : static const char* pNPXPluginPath = getenv( "NPX_PLUGIN_PATH" );
252 :
253 : // netscape!, quick, beam me back to the 90's when Motif roamed the earth
254 0 : OStringBuffer aSearchBuffer("/usr/lib/netscape/plugins");
255 0 : if( pHome )
256 0 : aSearchBuffer.append(':').append(pHome).append("/.netscape/plugins");
257 0 : if( pNPXPluginPath )
258 0 : aSearchBuffer.append(':').append(pNPXPluginPath);
259 :
260 0 : const Sequence< OUString >& rPaths( PluginManager::getAdditionalSearchPaths() );
261 0 : for( i = 0; i < rPaths.getLength(); i++ )
262 : {
263 0 : aSearchBuffer.append(':').append(OUStringToOString(
264 0 : rPaths.getConstArray()[i], aEncoding));
265 : }
266 :
267 0 : OString aSearchPath = aSearchBuffer.makeStringAndClear();
268 :
269 0 : sal_Int32 nIndex = 0;
270 : maxDirent u;
271 0 : do
272 : {
273 0 : OString aPath(aSearchPath.getToken(0, ':', nIndex));
274 0 : if (!aPath.isEmpty())
275 : {
276 0 : DIR* pDIR = opendir(aPath.getStr());
277 0 : struct dirent* pDirEnt = NULL;
278 0 : while( pDIR && ! readdir_r( pDIR, &u.asDirent, &pDirEnt ) && pDirEnt )
279 : {
280 0 : char* pBaseName = u.asDirent.d_name;
281 0 : if( pBaseName[0] != '.' ||
282 0 : pBaseName[1] != '.' ||
283 0 : pBaseName[2] != 0 )
284 : {
285 0 : OStringBuffer aFileName(aPath);
286 0 : aFileName.append('/').append(pBaseName);
287 0 : CheckPlugin( aFileName.makeStringAndClear(), aPlugins );
288 : }
289 : }
290 0 : if( pDIR )
291 0 : closedir( pDIR );
292 0 : }
293 : }
294 0 : while ( nIndex >= 0 );
295 :
296 : // try ~/.mozilla/pluginreg.dat
297 0 : OStringBuffer aBuf(256);
298 0 : aBuf.append( pHome );
299 0 : aBuf.append( "/.mozilla" );
300 0 : CheckPluginRegistryFiles( aBuf.makeStringAndClear(), aPlugins );
301 :
302 : // create return value
303 0 : aDescriptions = Sequence<PluginDescription>( aPlugins.size() );
304 : #if OSL_DEBUG_LEVEL > 1
305 : fprintf( stderr, "found %" SAL_PRI_SIZET "u plugins\n", aPlugins.size() );
306 : #endif
307 0 : list<PluginDescription*>::iterator iter;
308 0 : for( iter = aPlugins.begin(), i=0; iter != aPlugins.end(); ++iter ,i++ )
309 : {
310 0 : aDescriptions.getArray()[ i ] = **iter;
311 0 : delete *iter;
312 : }
313 0 : aPlugins.clear();
314 0 : bHavePlugins = true;
315 : }
316 0 : return aDescriptions;
317 : }
318 :
319 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|