source: trunk/Lucide/gui/pluginman.cpp @ 399

Last change on this file since 399 was 367, checked in by dmik, 12 years ago

Merged bramches/kmk (r294:365) to trunk.

File size: 10.0 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2 * Version: CDDL 1.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the COMMON DEVELOPMENT AND
5 * DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6 * this file except in compliance with the License. You may obtain a copy of
7 * the License at http://www.sun.com/cddl/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Initial Developer of the Original Code is
15 * Eugene Romanenko, netlabs.org.
16 * Portions created by the Initial Developer are Copyright (C) 2006
17 * the Initial Developer. All Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the terms of
22 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
23 * in which case the provisions of the LGPL are applicable instead of those
24 * above. If you wish to allow use of your version of this file only under the
25 * terms of the LGPL, and not to allow others to use your version of this file
26 * under the terms of the CDDL, indicate your decision by deleting the
27 * provisions above and replace them with the notice and other provisions
28 * required by the LGPL. If you do not delete the provisions above, a recipient
29 * may use your version of this file under the terms of any one of the CDDL
30 * or the LGPL.
31 *
32 * ***** END LICENSE BLOCK ***** */
33
34
35#include "os2all.h"
36
37#include "pluginman.h"
38#include "luutils.h"
39#if defined(__WATCOM__)
40#include <dos.h>
41#elif defined(__EMX__)
42#include <unistd.h>
43#include <emx/syscalls.h>
44typedef _find find_t;
45#define find_t_name(find_t) find_t.szName
46#define _dos_findfirst __findfirst
47#define _dos_findnext __findnext
48#define _dos_findclose(a) do {} while(0)
49#endif
50#include <fcntl.h>
51#include <stdio.h>
52#include <ludoc.xh>
53
54
55PluginManager::PluginManager()
56{
57    plugins = new PluginInfoList;
58
59    // Find exe path
60    char buffer[ _MAX_PATH ];
61    char path[ _MAX_PATH ];
62    char drive[ _MAX_DRIVE ];
63    char dir[ _MAX_DIR ];
64#if defined(__WATCOM__)
65    _splitpath( __argv[0], drive, dir, NULL, NULL );
66#else
67    _execname( buffer, sizeof(buffer) );
68    _splitpath( buffer, drive, dir, NULL, NULL );
69#endif
70    _makepath( path, drive, dir, NULL, NULL );
71    strcpy( buffer, path );
72    strcat( buffer, "LU*.DLL" );
73
74    // enum plugins, (LU*.DLL) except for LUDOC.DLL, which is 'null' plugin
75    // and Lucide.dll, which is not a plugin.
76    find_t ffblk;
77    unsigned done = _dos_findfirst( buffer, _A_RDONLY | _A_NORMAL, &ffblk );
78    while ( done == 0 )
79    {
80        if ( ( stricmp( find_t_name( ffblk ), "LUDOC.DLL" ) != 0 ) &&
81             ( stricmp( find_t_name( ffblk ), "LUCIDE.DLL" ) != 0 ) )
82        {
83            loadPlugin( path, find_t_name( ffblk ) );
84        }
85        done = _dos_findnext( &ffblk );
86    }
87    _dos_findclose( &ffblk );
88}
89
90PluginManager::~PluginManager()
91{
92    for ( int i = 0; i < plugins->size(); i++ )
93    {
94        PluginInfo *pi = &(*plugins)[ i ];
95        DosFreeModule( pi->handle );
96        //printf( "NAME: %s  EXT: %s  DESC: %s\n", pi->name.c_str(),
97        //        pi->extensions.c_str(), pi->description.c_str() );
98    }
99    delete plugins;
100}
101
102void PluginManager::loadPlugin( const char *path, const char *dllname )
103{
104    // Function pointer variables
105    LuDocument       * APIENTRY (*pCreateObject)()           = NULL;
106    char             * APIENTRY (*pGetSupportedExtensions)() = NULL;
107    char             * APIENTRY (*pGetDescription)()         = NULL;
108    LuSignatureCheck * APIENTRY (*pGetSignatureCheck)()      = NULL;
109
110    std::string fulldllname = path;
111    fulldllname += dllname;
112
113    // cut DLL name at last point
114    char *lpoint = strrchr( dllname, '.' );
115    *lpoint = '\0';
116
117    // load a DLL
118    HMODULE h = NULLHANDLE;
119    bool res = false;
120    do
121    {
122        if ( DosLoadModule( NULL, 0, fulldllname.c_str(), &h ) != 0 )
123            break;
124        if ( DosQueryProcAddr( h, 0, "createObject", (PFN *)&pCreateObject ) != 0 )
125            break;
126        if ( DosQueryProcAddr( h, 0, "getSupportedExtensions", (PFN *)&pGetSupportedExtensions ) != 0 )
127            break;
128        if ( DosQueryProcAddr( h, 0, "getDescription", (PFN *)&pGetDescription ) != 0 )
129            break;
130
131        // optional
132        if ( DosQueryProcAddr( h, 0, "getSignatureCheck", (PFN *)&pGetSignatureCheck ) != 0 ) {
133            pGetSignatureCheck = NULL;
134        }
135
136        res = true;
137    } while (0);
138
139    if ( res )
140    {
141        PluginInfo pi;
142        pi.handle      = h;
143        pi.name        = dllname;
144        pi.extensions  = pGetSupportedExtensions();
145        pi.description = pGetDescription();
146        pi.signatures  = ( pGetSignatureCheck == NULL ) ? NULL : pGetSignatureCheck();
147
148        plugins->push_back( pi );
149    }
150}
151
152static LuDocument *createDocFromDll( HMODULE handle, bool checkOnly )
153{
154    LuDocument * APIENTRY (*pCreateObject)() = NULL;
155
156    if ( DosQueryProcAddr( handle, 0, "createObject", (PFN *)&pCreateObject ) == 0 )
157    {
158        if ( checkOnly ) {
159            return (LuDocument *)TRUE;
160        }
161        else {
162            return pCreateObject();
163        }
164    }
165
166    return NULL;
167}
168
169// returns NULL if no suitable plugin found
170// if checkOnly is true - just check if suitable plugin exist
171LuDocument *PluginManager::createDocumentForExt( const char *ext, bool checkOnly )
172{
173    if ( ext == NULL ) {
174        return NULL;
175    }
176
177    for ( int i = 0; i < plugins->size(); i++ )
178    {
179        PluginInfo *pi = &(*plugins)[ i ];
180
181        char *cExt = new char[ strlen( ext ) + 5 ];
182        strcpy( cExt, ";" );
183        strcat( cExt, ext );
184        strcat( cExt, ";" );
185        strupr( cExt );
186
187        char *cExts = new char[ pi->extensions.length() + 5 ];
188        strcpy( cExts, ";" );
189        strcat( cExts, pi->extensions.c_str() );
190        strcat( cExts, ";" );
191        strupr( cExts );
192
193        if ( strstr( cExts, cExt ) != NULL )
194        {
195            LuDocument *d = createDocFromDll( pi->handle, checkOnly );
196            if ( d != NULL )
197            {
198                delete cExt;
199                delete cExts;
200                return d;
201            }
202        }
203
204        delete cExt;
205        delete cExts;
206    }
207
208    return NULL;
209}
210
211static bool checkSignature( LuSignature *signature, int h )
212{
213    lseek( h, signature->offset, ( signature->origin == 0 ) ? SEEK_SET : SEEK_END );
214    char *buf = new char[ signature->length ];
215    read( h, buf, signature->length );
216    bool result = ( memcmp( signature->data, buf, signature->length ) == 0 );
217    delete buf;
218    return result;
219}
220
221static bool checkSignatureList( LuSignatureList *siglist, int h )
222{
223    bool result = true;
224
225    // all signatures must be checked for positive result
226    for ( unsigned long i = 0; i < siglist->count; i++ )
227    {
228        if ( !checkSignature( &(siglist->signatures[ i ]), h ) ) {
229            result = false;
230            break;
231        }
232    }
233
234    return result;
235}
236
237static bool checkSignatures( LuSignatureCheck *signatures, const char *file )
238{
239    int h = open( file, O_RDONLY | O_BINARY );
240
241    if ( h == -1 ) {
242        return false;
243    }
244
245    bool result = false;
246
247    // if one signature list checked - result is positive
248    for ( unsigned long i = 0; i < signatures->count; i++ )
249    {
250        if ( result = checkSignatureList( &(signatures->slists[ i ]), h ) ) {
251            break;
252        }
253    }
254    close( h );
255
256    return result;
257}
258
259// returns NULL if no suitable plugin found
260// if checkOnly is true - just check if suitable plugin exist
261LuDocument *PluginManager::createDocumentForFile( const char *file, bool checkOnly )
262{
263    LuDocument *ld = NULL;
264
265    // Search by extension
266    char *ext = strrchr( file, '.' );
267    if ( ext != NULL ) {
268        ld = createDocumentForExt( ext + 1, checkOnly );
269    }
270
271    if ( ld != NULL ) {
272        return ld;
273    }
274
275    // Search by checkstruct
276    for ( int i = 0; i < plugins->size(); i++ )
277    {
278        PluginInfo *pi = &(*plugins)[ i ];
279
280        if ( pi->signatures != NULL )
281        {
282            if ( checkSignatures( pi->signatures, file ) )
283            {
284                LuDocument *d = createDocFromDll( pi->handle, checkOnly );
285                if ( d != NULL ) {
286                    return d;
287                }
288            }
289        }
290    }
291
292
293    // Search by isFileSupported()
294    BOOL APIENTRY (*pIsFileSupported)(PCSZ) = NULL;
295
296    for ( int i = 0; i < plugins->size(); i++ )
297    {
298        PluginInfo *pi = &(*plugins)[ i ];
299
300        if ( DosQueryProcAddr( pi->handle, 0, "isFileSupported",
301                               (PFN *)&pIsFileSupported ) == 0 )
302        {
303            if ( pIsFileSupported( file ) )
304            {
305                LuDocument *d = createDocFromDll( pi->handle, checkOnly );
306                if ( d != NULL ) {
307                    return d;
308                }
309            }
310        }
311    }
312
313    return NULL;
314}
315
316std::string PluginManager::getExtsMask()
317{
318    std::string cRet = "";
319
320    for ( int i = 0; i < plugins->size(); i++ )
321    {
322        PluginInfo *pi = &(*plugins)[ i ];
323        char *tmpexts = newstrdup( pi->extensions.c_str() );
324        char *p = strtok( tmpexts, ";" );
325        while ( p != NULL ) {
326            cRet += "*.";
327            cRet += p;
328            cRet += ';';
329            p = strtok( NULL, ";" );
330        }
331        delete tmpexts;
332    }
333    return cRet;
334}
335
336void PluginManager::getExtsList( std::vector<std::string> *list )
337{
338    for ( int i = 0; i < plugins->size(); i++ )
339    {
340        PluginInfo *pi = &(*plugins)[ i ];
341        char *tmpexts = newstrdup( pi->extensions.c_str() );
342        char *p = strtok( tmpexts, ";" );
343        while ( p != NULL ) {
344            list->push_back( p );
345            p = strtok( NULL, ";" );
346        }
347        delete tmpexts;
348    }
349}
350
351
Note: See TracBrowser for help on using the repository browser.