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 : using ::rtl::OUString;
52 : using ::rtl::OString;
53 : using ::rtl::OStringBuffer;
54 : using ::rtl::OStringToOUString;
55 :
56 : // Unix specific implementation
57 0 : static bool CheckPlugin( const rtl::OString& rPath, list< PluginDescription* >& rDescriptions )
58 : {
59 : #if OSL_DEBUG_LEVEL > 1
60 : fprintf( stderr, "Trying plugin %s ... ", rPath.getStr() );
61 : #endif
62 :
63 0 : sal_Int32 nPos = rPath.lastIndexOf('/');
64 0 : if (nPos == -1)
65 : {
66 : #if OSL_DEBUG_LEVEL > 1
67 : fprintf( stderr, "no absolute path to plugin\n" );
68 : #endif
69 0 : return false;
70 : }
71 :
72 0 : rtl::OString aBaseName = rPath.copy(nPos+1);
73 0 : if (aBaseName.equalsL(RTL_CONSTASCII_STRINGPARAM("libnullplugin.so")))
74 : {
75 : #if OSL_DEBUG_LEVEL > 1
76 : fprintf( stderr, "don't like %s\n", aBaseName.getStr() );
77 : #endif
78 0 : return false;
79 : }
80 :
81 : struct stat aStat;
82 0 : if (stat(rPath.getStr(), &aStat) || !S_ISREG(aStat.st_mode))
83 : {
84 : #if OSL_DEBUG_LEVEL > 1
85 : fprintf( stderr, "%s is not a regular file\n", rPath.getStr() );
86 : #endif
87 0 : return false;
88 : }
89 :
90 0 : rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
91 :
92 0 : rtl::OString path;
93 0 : if (!UnxPluginComm::getPluginappPath(&path))
94 : {
95 : #if OSL_DEBUG_LEVEL > 1
96 : fprintf( stderr, "cannot construct path to pluginapp.bin\n" );
97 : #endif
98 0 : return false;
99 : }
100 0 : rtl::OStringBuffer cmd;
101 0 : tools::appendUnixShellWord(&cmd, path);
102 0 : cmd.append(' ');
103 0 : tools::appendUnixShellWord(&cmd, rPath);
104 0 : rtl::OString aCommand(cmd.makeStringAndClear());
105 :
106 0 : FILE* pResult = popen( aCommand.getStr(), "r" );
107 0 : int nDescriptions = 0;
108 0 : if( pResult )
109 : {
110 0 : OStringBuffer aMIME;
111 : char buf[256];
112 0 : while( fgets( buf, sizeof( buf ), pResult ) )
113 : {
114 0 : for( size_t i = 0; i < sizeof(buf) && buf[i]; ++i )
115 : {
116 0 : if( buf[i] == '\n' )
117 0 : buf[i] = ';';
118 : }
119 0 : aMIME.append( buf );
120 : }
121 0 : pclose( pResult );
122 :
123 0 : if( aMIME.getLength() > 0 )
124 : {
125 0 : OString aLine = aMIME.makeStringAndClear();
126 :
127 0 : sal_Int32 nIndex = 0;
128 0 : while( nIndex != -1 )
129 : {
130 0 : OString aType = aLine.getToken( 0, ';', nIndex );
131 :
132 0 : sal_Int32 nTypeIndex = 0;
133 0 : OString aMimetype = aType.getToken( 0, ':', nTypeIndex );
134 0 : OString aExtLine = aType.getToken( 0, ':', nTypeIndex );
135 0 : if( nTypeIndex < 0 ) // ensure at least three tokens
136 0 : continue;
137 0 : OString aDesc = aType.getToken( 0, ':', nTypeIndex );
138 :
139 : // create extension list string
140 0 : sal_Int32 nExtIndex = 0;
141 0 : OStringBuffer aExtension;
142 0 : while( nExtIndex != -1 )
143 : {
144 0 : OString aExt = aExtLine.getToken( 0, ',', nExtIndex);
145 0 : if( aExt.indexOf( "*." ) != 0 )
146 0 : aExtension.append( "*." );
147 0 : aExtension.append( aExt );
148 0 : if( nExtIndex != -1 )
149 0 : aExtension.append( ';' );
150 0 : }
151 :
152 0 : PluginDescription* pNew = new PluginDescription;
153 : // set plugin name (path to library)
154 0 : pNew->PluginName = OStringToOUString( rPath, aEncoding );
155 : // set mimetype
156 0 : pNew->Mimetype = OStringToOUString( aMimetype, aEncoding );
157 : // set extension line
158 0 : pNew->Extension = OStringToOUString( aExtension.makeStringAndClear(), aEncoding );
159 : // set description
160 0 : pNew->Description= OStringToOUString( aDesc, aEncoding );
161 0 : rDescriptions.push_back( pNew );
162 : #if OSL_DEBUG_LEVEL > 1
163 : fprintf( stderr, "Mimetype: %s\nExtension: %s\n"
164 : "Description: %s\n",
165 : OUStringToOString( pNew->Mimetype, aEncoding ).getStr(),
166 : OUStringToOString( pNew->Extension, aEncoding ).getStr(),
167 : OUStringToOString( pNew->Description, aEncoding ).getStr()
168 : );
169 : #endif
170 0 : }
171 0 : }
172 : #if OSL_DEBUG_LEVEL > 1
173 : else
174 : fprintf( stderr, "result of \"%s\" contains no mimtype\n",
175 : aCommand.getStr() );
176 : #endif
177 : }
178 : #if OSL_DEBUG_LEVEL > 1
179 : else
180 : fprintf( stderr, "command \"%s\" failed\n", aCommand.getStr() );
181 : #endif
182 0 : return nDescriptions > 0;
183 : }
184 :
185 : union maxDirent
186 : {
187 : char aBuffer[ sizeof( struct dirent ) + _PC_NAME_MAX +1 ];
188 : struct dirent asDirent;
189 : };
190 :
191 0 : static void CheckPluginRegistryFiles( const rtl::OString& rPath, list< PluginDescription* >& rDescriptions )
192 : {
193 0 : rtl::OStringBuffer aPath( 1024 );
194 0 : aPath.append( rPath );
195 0 : aPath.append( "/pluginreg.dat" );
196 0 : FILE* fp = fopen( aPath.getStr(), "r" );
197 0 : if( fp )
198 : {
199 : #if OSL_DEBUG_LEVEL > 1
200 : fprintf( stderr, "parsing %s\n", aPath.getStr() );
201 : #endif
202 : char aLine[1024];
203 0 : while( fgets( aLine, sizeof( aLine ), fp ) )
204 : {
205 0 : int nLineLen = strlen( aLine );
206 : int nDotPos;
207 0 : for( nDotPos = nLineLen-1; nDotPos > 0 && aLine[nDotPos] != ':'; nDotPos-- )
208 : ;
209 0 : if( aLine[0] == '/' && aLine[nDotPos] == ':' && aLine[nDotPos+1] == '$' )
210 0 : CheckPlugin( rtl::OString(aLine, nDotPos), rDescriptions );
211 : }
212 0 : fclose( fp );
213 : }
214 :
215 : // check subdirectories
216 0 : DIR* pDIR = opendir( rPath.getStr() );
217 0 : struct dirent* pDirEnt = NULL;
218 : struct stat aStat;
219 : maxDirent u;
220 0 : while( pDIR && ! readdir_r( pDIR, &u.asDirent, &pDirEnt ) && pDirEnt )
221 : {
222 0 : char* pBaseName = u.asDirent.d_name;
223 0 : if( rtl_str_compare( ".", pBaseName ) && rtl_str_compare( "..", pBaseName ) )
224 : {
225 0 : rtl::OStringBuffer aBuf( 1024 );
226 0 : aBuf.append( rPath );
227 0 : aBuf.append( '/' );
228 0 : aBuf.append( pBaseName );
229 :
230 0 : if( ! stat( aBuf.getStr(), &aStat ) )
231 : {
232 0 : if( S_ISDIR( aStat.st_mode ) )
233 0 : CheckPluginRegistryFiles( aBuf.makeStringAndClear(), rDescriptions );
234 0 : }
235 : }
236 : }
237 0 : if( pDIR )
238 0 : closedir( pDIR );
239 0 : }
240 :
241 0 : Sequence<PluginDescription> XPluginManager_Impl::impl_getPluginDescriptions() throw()
242 : {
243 0 : static Sequence<PluginDescription> aDescriptions;
244 : static sal_Bool bHavePlugins = sal_False;
245 0 : if( ! bHavePlugins )
246 : {
247 0 : rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
248 0 : list<PluginDescription*> aPlugins;
249 : int i;
250 :
251 : // unix: search for plugins in /usr/lib/netscape/plugins,
252 : // ~/.netscape/plugins und NPX_PLUGIN_PATH
253 : // additionally: search in PluginsPath
254 0 : static const char* pHome = getenv( "HOME" );
255 0 : static const char* pNPXPluginPath = getenv( "NPX_PLUGIN_PATH" );
256 :
257 : // netscape!, quick, beam me back to the 90's when Motif roamed the earth
258 0 : rtl::OStringBuffer aSearchBuffer(RTL_CONSTASCII_STRINGPARAM("/usr/lib/netscape/plugins"));
259 0 : if( pHome )
260 0 : aSearchBuffer.append(':').append(pHome).append("/.netscape/plugins");
261 0 : if( pNPXPluginPath )
262 0 : aSearchBuffer.append(':').append(pNPXPluginPath);
263 :
264 0 : const Sequence< ::rtl::OUString >& rPaths( PluginManager::getAdditionalSearchPaths() );
265 0 : for( i = 0; i < rPaths.getLength(); i++ )
266 : {
267 0 : aSearchBuffer.append(':').append(rtl::OUStringToOString(
268 0 : rPaths.getConstArray()[i], aEncoding));
269 : }
270 :
271 0 : rtl::OString aSearchPath = aSearchBuffer.makeStringAndClear();
272 :
273 0 : sal_Int32 nIndex = 0;
274 : maxDirent u;
275 0 : do
276 : {
277 0 : rtl::OString aPath(aSearchPath.getToken(0, ':', nIndex));
278 0 : if (!aPath.isEmpty())
279 : {
280 0 : DIR* pDIR = opendir(aPath.getStr());
281 0 : struct dirent* pDirEnt = NULL;
282 0 : while( pDIR && ! readdir_r( pDIR, &u.asDirent, &pDirEnt ) && pDirEnt )
283 : {
284 0 : char* pBaseName = u.asDirent.d_name;
285 0 : if( pBaseName[0] != '.' ||
286 0 : pBaseName[1] != '.' ||
287 0 : pBaseName[2] != 0 )
288 : {
289 0 : rtl::OStringBuffer aFileName(aPath);
290 0 : aFileName.append('/').append(pBaseName);
291 0 : CheckPlugin( aFileName.makeStringAndClear(), aPlugins );
292 : }
293 : }
294 0 : if( pDIR )
295 0 : closedir( pDIR );
296 0 : }
297 : }
298 : while ( nIndex >= 0 );
299 :
300 : // try ~/.mozilla/pluginreg.dat
301 0 : rtl::OStringBuffer aBuf(256);
302 0 : aBuf.append( pHome );
303 0 : aBuf.append( "/.mozilla" );
304 0 : CheckPluginRegistryFiles( aBuf.makeStringAndClear(), aPlugins );
305 :
306 : // create return value
307 0 : aDescriptions = Sequence<PluginDescription>( aPlugins.size() );
308 : #if OSL_DEBUG_LEVEL > 1
309 : fprintf( stderr, "found %" SAL_PRI_SIZET "u plugins\n", aPlugins.size() );
310 : #endif
311 0 : list<PluginDescription*>::iterator iter;
312 0 : for( iter = aPlugins.begin(), i=0; iter != aPlugins.end(); ++iter ,i++ )
313 : {
314 0 : aDescriptions.getArray()[ i ] = **iter;
315 0 : delete *iter;
316 : }
317 0 : aPlugins.clear();
318 0 : bHavePlugins = sal_True;
319 : }
320 0 : return aDescriptions;
321 : }
322 :
323 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|