Salome HOME
Upgrade to new MG license mechanism and keep compatibility with old ones
[modules/smesh.git] / src / SMESHUtils / SMESH_MGLicenseKeyGen.cxx
1 // Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // File      : SMESHUtils_MGLicenseKeyGen.cxx
20 // Created   : Sat Jul 31 18:54:16 2021
21 // Author    : Edward AGAPOV (OCC)
22
23 #include "SMESH_MGLicenseKeyGen.hxx"
24
25 #include "SMESH_Comment.hxx"
26 #include "SMESH_File.hxx"
27 #include "SMESH_TryCatch.hxx"
28
29 #include <Basics_DirUtils.hxx>
30 #include <Basics_Utils.hxx>
31
32 #include <cstdlib> // getenv, system
33
34 #include <boost/filesystem.hpp>
35 #include <boost/regex.hpp>
36 namespace boofs = boost::filesystem;
37
38 #ifdef WIN32
39
40 #  include <windows.h>
41 #  include <process.h>
42
43 #  define LibHandle HMODULE
44 #  define LoadLib( name ) LoadLibrary( name )
45 #  define GetProc GetProcAddress
46 #  define UnLoadLib( handle ) FreeLibrary( handle );
47
48 #else // WIN32
49
50 #  include <dlfcn.h>
51
52 #  define LibHandle void*
53 #  define LoadLib( name ) dlopen( name, RTLD_LAZY | RTLD_LOCAL )
54 #  define GetProc dlsym
55 #  define UnLoadLib( handle ) dlclose( handle );
56
57 #endif // WIN32
58
59 // to retrieve description of exception caught by SMESH_TRY
60 #undef SMESH_CAUGHT
61 #define SMESH_CAUGHT error =
62
63 constexpr char MESHGEMS_OLD_STYLE[] = "MESHGEMS_OLD_STYLE";
64 constexpr char SPATIAL_LICENSE[] = "SPATIAL_LICENSE";
65
66
67 namespace
68 {
69   static LibHandle theLibraryHandle = nullptr; //!< handle of a loaded library
70
71   const char* theEnvVar = "SALOME_MG_KEYGEN_LIB_PATH"; /* var specifies either full file name
72                                                           of libSalomeMeshGemsKeyGenerator or
73                                                           URL to download the library from */
74
75   const char* theTmpEnvVar = "SALOME_TMP_DIR"; // directory to download the library to
76
77   //-----------------------------------------------------------------------------------
78   /*!
79    * \brief Remove library file at destruction in case if it was downloaded from server
80    */
81   //-----------------------------------------------------------------------------------
82
83   struct LibraryFile
84   {
85     std::string _name; // full file name
86     bool        _isURL;
87
88     LibraryFile(): _isURL( false ) {}
89
90     ~LibraryFile()
91     {
92       if ( _isURL )
93       {
94         if ( theLibraryHandle )
95         {
96           UnLoadLib( theLibraryHandle );
97           theLibraryHandle = nullptr;
98         }
99
100         std::string tmpDir; // tmp dir that should not be removed
101         if ( const char* libPath = getenv( theTmpEnvVar ))
102         {
103           tmpDir = libPath;
104           while (( !tmpDir.empty() ) &&
105                  ( tmpDir.back() == '/' || tmpDir.back() == '\\' ))
106             tmpDir.pop_back();
107         }
108
109         while ( SMESH_File( _name ).remove() )
110         {
111           size_t length = _name.size();
112           _name = boofs::path( _name ).parent_path().string(); // goto parent directory
113           if ( _name.size() == length )
114             break; // no more parents
115
116           if ( _name == tmpDir )
117             break; // don't remove tmp dir
118
119           if ( !Kernel_Utils::IsEmptyDir( _name ))
120             break;
121         }
122       }
123     }
124   };
125
126
127   //================================================================================
128   /*!
129    * \brief Retrieve description of the last error
130    *  \param [out] error - return the description
131    *  \return bool - true if the description found
132    */
133   //================================================================================
134
135   bool getLastError( std::string& error )
136   {
137 #ifndef WIN32
138
139     if ( const char* text = dlerror() )
140     {
141       error = text;
142       return true;
143     }
144     return false;
145
146 #else
147
148     DWORD dw = GetLastError();
149     void* cstr;
150     DWORD msgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
151                                  NULL,
152                                  dw,
153                                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
154                                  (LPTSTR) &cstr,
155                                  0,
156                                  NULL
157                                  );
158     if ( msgLen > 0 ) {
159 #  if defined( UNICODE )
160       error = Kernel_Utils::encode_s((wchar_t*)cstr);
161 #  else
162       error = (char*)cstr;
163 #  endif
164       LocalFree(cstr);
165     }
166
167     return (bool)msgLen;
168
169 #endif
170   }
171
172   //================================================================================
173   /*!
174    * \brief Adjust file extension according to the platform
175    */
176   //================================================================================
177
178   bool setExtension( std::string& fileName, std::string& error )
179   {
180     if ( fileName.empty() )
181     {
182       error = "Library file name is empty";
183       return false;
184     }
185 #if defined(WIN32)
186     std::string ext = ".dll";
187 #elif defined(__APPLE__)
188     std::string ext = ".dylib";
189 #else
190     std::string ext = ".so";
191 #endif
192
193     fileName = fileName.substr( 0, fileName.find_last_of('.')) + ext;
194     return true;
195   }
196
197   //================================================================================
198   /*!
199    * \brief Check if library file name looks like an URL
200    *  \param [in,out] libraryFile - holds file name and returns result in _isURL member field
201    *  \return bool - true if the file name looks like an URL
202    */
203   //================================================================================
204
205   bool isURL( LibraryFile & libraryFile )
206   {
207     {// round1
208       enum { SCHEME = 2, AUTHORITY = 4, PATH = 5 }; // sub-strings
209       boost::regex urlRegex ( R"(^(([^:\/?#]+):)?(//([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)",
210                               boost::regex::extended );
211       boost::smatch matchResult;
212
213       libraryFile._isURL = false;
214       if ( boost::regex_match( libraryFile._name, matchResult, urlRegex ))
215         libraryFile._isURL = ( !matchResult.str( SCHEME    ).empty() &&
216                               !matchResult.str( AUTHORITY ).empty() &&
217                               !matchResult.str( PATH      ).empty() );
218     }
219     if(libraryFile._isURL)
220       return true;
221     {// round2
222       enum { HOST = 2, PORT = 3, PATH = 4 }; // sub-strings
223       boost::regex urlRegex ( R"(^(([^:\/?#]+):)?([^/]+)?(/[^#]*))",
224                               boost::regex::extended );
225       boost::smatch matchResult;
226
227       libraryFile._isURL = false;
228       if ( boost::regex_match( libraryFile._name, matchResult, urlRegex ))
229         libraryFile._isURL = ( !matchResult.str( HOST ).empty() &&
230                               !matchResult.str( PORT ).empty() &&
231                               !matchResult.str( PATH ).empty() );
232     }
233     return libraryFile._isURL;
234   }
235
236   //================================================================================
237   /*!
238    * \brief Download libraryFile._name URL to SALOME_TMP_DIR
239    *  \param [in,out] libraryFile - holds the URL and returns name of a downloaded file
240    *  \param [out] error - return error description
241    *  \return bool - is a success
242    */
243   //================================================================================
244
245   bool downloadLib( LibraryFile& libraryFile, std::string & error )
246   {
247     // check if can write into SALOME_TMP_DIR
248
249     std::string tmpDir = Kernel_Utils::GetTmpDirByEnv( theTmpEnvVar );
250     if ( tmpDir.empty() ||
251          !Kernel_Utils::IsExists( tmpDir ))
252     {
253       error = "Can't download " + libraryFile._name + " as SALOME_TMP_DIR is not correctly set";
254       return false;
255     }
256     if ( !Kernel_Utils::IsWritable( tmpDir ))
257     {
258       error = "Can't download " + libraryFile._name + " as '" + tmpDir + "' is not writable. "
259         "Check SALOME_TMP_DIR environment variable";
260       return false;
261     }
262
263     // Download
264
265     std::string url = libraryFile._name;
266
267 #ifdef WIN32
268
269     std::string outFile = tmpDir + "MeshGemsKeyGenerator.dll";
270
271     // use wget (== Invoke-WebRequest) PowerShell command available since Windows 7
272     std::string psCmd = "wget -Uri " + url + " -OutFile " + outFile;
273     std::string   cmd = "powershell.exe " + psCmd;
274
275 #else
276
277     std::string outFile = tmpDir + "libMeshGemsKeyGenerator.so";
278
279     std::string cmd = "smesh_wget.py " + url + " -O " + outFile;
280
281 #endif
282
283     if ( Kernel_Utils::IsExists( outFile )) // remove existing file
284     {
285       SMESH_File lib( outFile, /*open=*/false );
286       if ( !lib.remove() )
287       {
288         error = lib.error();
289         return false;
290       }
291     }
292
293 #ifndef WIN32
294     //[EDF25906]
295     std::string redirect = tmpDir + "redirect.out";
296     std::ostringstream oss;
297     oss << cmd << " " << redirect;
298     cmd = oss.str();
299 #endif
300
301     system( cmd.c_str() ); // download
302
303 #ifndef WIN32
304     {//[EDF25906]
305       std::ifstream infile(redirect);
306       infile.seekg(0, std::ios::end);
307       size_t length = infile.tellg();
308       infile.seekg(0, std::ios::beg);
309       std::unique_ptr<char []> buffer(new char[length+1]);
310       buffer[length] = '\0';
311       infile.read(const_cast<char *>( buffer.get() ),length);
312
313       MESSAGE( buffer.get() );
314     }
315     {
316       SMESH_File redirectFile( redirect, /*open=*/false );
317       redirectFile.remove();
318     }
319 #endif
320
321     SMESH_File resultFile( outFile, /*open=*/false );
322     bool ok = ( resultFile.exists() && resultFile.size() > 0 );
323
324     if ( ok )
325       libraryFile._name = outFile;
326     else
327       error = "Can't download file " + url;
328
329     return ok;
330   }
331
332   //================================================================================
333   /*!
334    * \brief Load libMeshGemsKeyGenerator.so
335    *  \param [out] error - return error description
336    *  \param [out] libraryFile - return library file name and _isURL flag
337    *  \return bool - is a success
338    */
339   //================================================================================
340
341   bool loadLibrary( std::string& error, LibraryFile& libraryFile )
342   {
343     if ( theLibraryHandle )
344       return true;
345
346     const char* libPath = getenv( theEnvVar );
347     if ( !libPath )
348     {
349       error = SMESH_Comment( "Environment variable ") <<  theEnvVar << " is not set";
350       return false;
351     }
352
353     libraryFile._name = libPath;
354     // if ( !setExtension( libraryFile._name, error )) // is it necessary?
355     //   return false;
356
357     if ( isURL( libraryFile ))
358     {
359       if ( !downloadLib( libraryFile, error ))
360       {
361         // try to fix extension
362         std::string url = libraryFile._name;
363         if ( !setExtension( libraryFile._name, error ))
364           return false;
365         if ( url == libraryFile._name )
366           return false; // extension not changed
367
368         if ( !downloadLib( libraryFile, error ))
369           return false;
370       }
371     }
372
373 #if defined( WIN32 ) && defined( UNICODE )
374     std::wstring encodePath = Kernel_Utils::utf8_decode_s( libraryFile._name );
375     const wchar_t*     path = encodePath.c_str();
376 #else
377     const char*        path = libraryFile._name.c_str();
378 #endif
379
380     theLibraryHandle = LoadLib( path );
381     if ( !theLibraryHandle )
382     {
383       if ( ! getLastError( error ))
384         error = "Can't load library '" + libraryFile._name + "'";
385     }
386
387     return theLibraryHandle;
388   }
389
390 } // anonymous namespace
391
392
393 namespace SMESHUtils_MGLicenseKeyGen // API implementation
394 {
395   //================================================================================
396   /*!
397    * \brief Sign a CAD
398    *  \param [in] meshgems_cad - pointer to a MG CAD object (meshgems_cad_t)
399    *  \param [out] error - return error description
400    *  \return bool - is a success
401    */
402   //================================================================================
403
404   bool SignCAD_After( void* meshgems_cad, std::string& error )
405   {
406     LibraryFile libraryFile;
407     if ( !loadLibrary( error, libraryFile ))
408       return false;
409
410     bool ok = false;
411     typedef bool (*SignFun)(void* );
412     SignFun signFun = (SignFun) GetProc( theLibraryHandle, "SignCAD" );
413     if ( !signFun )
414     {
415       if ( ! getLastError( error ))
416         error = SMESH_Comment( "Can't find symbol 'SignCAD' in '") << getenv( theEnvVar ) << "'";
417     }
418     else
419     {
420       SMESH_TRY;
421
422       ok = signFun( meshgems_cad );
423
424       SMESH_CATCH( SMESH::returnError );
425
426       if ( !error.empty() )
427         ok = false;
428       else if ( !ok )
429         error = "SignCAD() failed (located in '" + libraryFile._name + "')";
430     }
431     return ok;
432   }
433   
434   bool SignCAD( void* meshgems_cad, std::string& error )
435   {
436     const char *meshGemsOldStyleEnvVar( getenv( MESHGEMS_OLD_STYLE ) );
437     if ( !meshGemsOldStyleEnvVar || strlen(meshGemsOldStyleEnvVar) == 0 )
438       return SignCAD_After(meshgems_cad, error);
439     else
440       return true;
441   }
442
443   //================================================================================
444   /*!
445    * \brief Sign a mesh
446    *  \param [in] meshgems_mesh - pointer to a MG mesh (meshgems_mesh_t)
447    *  \param [out] error - return error description
448    *  \return bool - is a success
449    */
450   //================================================================================
451
452   bool SignMesh_After( void* meshgems_mesh, std::string& error )
453   {
454     LibraryFile libraryFile;
455     if ( !loadLibrary( error, libraryFile ))
456       return false;
457
458     bool ok = false;
459     typedef bool (*SignFun)(void* );
460     SignFun signFun = (SignFun) GetProc( theLibraryHandle, "SignMesh" );
461     if ( !signFun )
462     {
463       if ( ! getLastError( error ))
464         error = SMESH_Comment( "Can't find symbol 'SignMesh' in '") << getenv( theEnvVar ) << "'";
465     }
466     else
467     {
468       SMESH_TRY;
469
470       ok = signFun( meshgems_mesh );
471
472       SMESH_CATCH( SMESH::returnError );
473
474       if ( !error.empty() )
475         ok = false;
476       else if ( !ok )
477         error = "SignMesh() failed (located in '" + libraryFile._name + "')";
478     }
479     return ok;
480   }
481   
482   bool SignMesh( void* meshgems_mesh, std::string& error )
483   {
484     const char *meshGemsOldStyleEnvVar( getenv( MESHGEMS_OLD_STYLE ) );
485     if ( !meshGemsOldStyleEnvVar || strlen(meshGemsOldStyleEnvVar) == 0 )
486       // sign the mesh (MG 2.13 and 2.14)
487       return SignMesh_After(meshgems_mesh, error);
488     else
489       // use DLIM8 server (nothing to do here)
490       return true;
491   }
492
493   //================================================================================
494   /*!
495    * \brief Return a license key to pass as argument to a MG mesher executable
496    *  \param [in] gmfFile - path to an input mesh file
497    *  \param [in] nb* - nb of entities in the input mesh
498    *  \param [out] error - return error description
499    *  \return std::string - the key
500    */
501   //================================================================================
502
503   std::string GetKey_After(const std::string& gmfFile,
504                             int                nbVertex,
505                             int                nbEdge,
506                             int                nbFace,
507                             int                nbVol,
508                             std::string&       error)
509   {
510     std::string key;
511     LibraryFile libraryFile;
512     if ( !loadLibrary( error, libraryFile ))
513       return key;
514
515     typedef std::string (*GetKeyFun)(std::string const &, int, int, int, int );
516     GetKeyFun keyFun = (GetKeyFun) GetProc( theLibraryHandle, "GetKey" );
517     if ( !keyFun )
518     {
519       if ( ! getLastError( error ))
520         error = SMESH_Comment( "Can't find symbol 'GetKey' in '") << getenv( theEnvVar ) << "'";
521     }
522     else
523     {
524       key = keyFun( gmfFile, nbVertex, nbEdge, nbFace, nbVol );
525     }
526     if ( key.empty() )
527       error = "GetKey() failed (located in '" + libraryFile._name + "')";
528
529     return key;
530   }
531
532   //================================================================================
533   /*!
534    * \brief Return a license key to pass as argument to a MG mesher executable (>2.15)
535    *  \param [out] error - return error description
536    *  \return std::string - the key
537    */
538   //================================================================================
539
540   std::string GetKey_After(std::string&       error)
541   {
542     std::string key;
543     LibraryFile libraryFile;
544     if ( !loadLibrary( error, libraryFile ))
545       return key;
546
547     typedef std::string (*GetKeyFun)();
548     GetKeyFun keyFun = (GetKeyFun) GetProc( theLibraryHandle, "GetKey" );
549     if ( !keyFun )
550     {
551       if ( ! getLastError( error ))
552         error = SMESH_Comment( "Can't find symbol 'GetKey' in '") << getenv( theEnvVar ) << "'";
553     }
554     else
555     {
556       key = keyFun( );
557     }
558     if ( key.empty() )
559       error = "GetKey() failed (located in '" + libraryFile._name + "')";
560
561     return key;
562   }
563
564
565   //================================================================================
566   /*!
567    * \brief Get MeshGems version from the keygen library and meshgems built-in functions
568    *  \param [out] error - return error description
569    *  \return int - the version
570    */
571   //================================================================================
572   int GetMGVersionHex(std::string&       error)
573   {
574     // get minor version
575     int v_min = -1;
576     LibraryFile libraryFile;
577     if ( !loadLibrary( error, libraryFile ))
578       return v_min;
579
580     typedef int (*GetKeyFun)();
581     GetKeyFun keyFun = (GetKeyFun) GetProc( theLibraryHandle, "meshgems_core_get_version_minor" );
582     if ( !keyFun )
583     {
584       if ( ! getLastError( error ))
585         error = SMESH_Comment( "Can't find symbol 'meshgems_core_get_version_minor' in '") << getenv( theEnvVar ) << "'";
586     }
587     else
588     {
589         v_min = keyFun( );
590     }
591     if ( v_min==-1 )
592       error = "meshgems_core_get_version_minor() failed (located in '" + libraryFile._name + "')";
593
594     MESSAGE("meshgems_core_get_version_minor: " << v_min);
595
596     // get major version
597     int v_maj = -1;
598
599     typedef int (*GetKeyFun)();
600     keyFun = (GetKeyFun) GetProc( theLibraryHandle, "meshgems_core_get_version_major" );
601     if ( !keyFun )
602     {
603       if ( ! getLastError( error ))
604         error = SMESH_Comment( "Can't find symbol 'meshgems_core_get_version_major' in '") << getenv( theEnvVar ) << "'";
605     }
606     else
607     {
608         v_maj = keyFun( );
609     }
610     if ( v_maj==-1 )
611       error = "meshgems_core_get_version_major() failed (located in '" + libraryFile._name + "')";
612
613     MESSAGE("meshgems_core_get_version_major: " << v_maj);
614
615     // get patch version
616     int v_patch = -1;
617
618     typedef int (*GetKeyFun)();
619     keyFun = (GetKeyFun) GetProc( theLibraryHandle, "meshgems_core_get_version_patch" );
620     if ( !keyFun )
621     {
622       if ( ! getLastError( error ))
623         error = SMESH_Comment( "Can't find symbol 'meshgems_core_get_version_patch' in '") << getenv( theEnvVar ) << "'";
624     }
625     else
626     {
627         v_patch = keyFun( );
628     }
629     if ( v_patch==-1 )
630       error = "meshgems_core_get_version_patch() failed (located in '" + libraryFile._name + "')";
631
632     MESSAGE("meshgems_core_get_version_patch: " << v_patch );
633
634     int v_hex = (v_maj << 16 | v_min << 8 | v_patch);
635
636     MESSAGE("v_hex: " << v_hex);
637
638     return v_hex;
639   }
640
641   //================================================================================
642   /*!
643    * \brief Guess if the Spatial license is needed (if MeshGems is > 2.15.0)
644    *  \param [out] error - return error description
645    *  \return bool - true if MeshGems is > 2.15.0
646    */
647   //================================================================================
648   bool NeedsMGSpatialEnvLicense(std::string& error)
649   {
650     // if MeshGems version is > 2.15.0, need to set SPATIAL_LICENSE
651     int v_hex = GetMGVersionHex(error);
652     bool ok = (v_hex > MESHGEMS_215);
653     if (ok)
654       MESSAGE("MeshGems version is > 2.15.0, need to set SPATIAL_LICENSE");
655     return ok;
656   }
657
658   //================================================================================
659   /*!
660    * \brief Set the SPATIAL_LICENSE environment variable
661    *  \param [out] error - return error description
662    *  \return bool - true in case of success
663    */
664   //================================================================================
665   bool SetMGSpatialEnvLicense(std::string& error)
666   {
667     int ok;
668     std::string key = GetKey(error);
669 #ifndef WIN32
670     ok = setenv(SPATIAL_LICENSE, key.c_str(), 0); // 0 means do not overwrite
671 #else
672     ok = Kernel_Utils::setenv(SPATIAL_LICENSE, key.c_str(), 0 );
673 #endif
674     MESSAGE("Set SPATIAL_LICENSE");
675     return (ok==0);
676   }
677
678   //================================================================================
679   /*!
680    * \brief Get the license key from libMeshGemsKeyGenerator.so or $SPATIAL_LICENSE
681    * Called by plugins calling MG products as executables.
682    * If MESHGEMS_OLD_STYLE is set, return "0", to use old DLIM8 server license
683    * instead of the key.
684    *  \param [in] gmfFile - path to an input mesh file
685    *  \param [in] nb* - nb of entities in the input mesh
686    *  \param [out] error - return error description
687    *  \return std::string - the key
688    */
689   //================================================================================
690   std::string GetKey(const std::string& gmfFile,
691                     int                nbVertex,
692                     int                nbEdge,
693                     int                nbFace,
694                     int                nbVol,
695                     std::string&       error)
696   {
697     // default key if MESHGEMS_OLD_STYLE or SPATIAL_LICENSE is set
698     std::string key("0");
699     const char *meshGemsOldStyleEnvVar( getenv( MESHGEMS_OLD_STYLE ) );
700     if ( !meshGemsOldStyleEnvVar || strlen(meshGemsOldStyleEnvVar) == 0 )
701       {
702         const char *spatialLicenseEnvVar( getenv( SPATIAL_LICENSE ) );
703         if ( !spatialLicenseEnvVar || strlen(spatialLicenseEnvVar) == 0 )
704           {
705             if (NeedsMGSpatialEnvLicense(error))
706               {
707                 // if MG version > 2.15, set environment license, don't return it as a key
708                 // otherwise it will be printed in the command line
709                 MESSAGE("SPATIAL_LICENSE not in env => we add it from MGKeygen .so");
710                 SetMGSpatialEnvLicense(error);
711               }
712             else
713               {
714                 // generate the key from the mesh info (MG 2.13 and 2.14)
715                 MESSAGE("MG < 2.15 => get the key from MGKeygen .so and this mesh info");
716                 key = GetKey_After(gmfFile,nbVertex,nbEdge,nbFace,nbVol,error);
717               }
718           }
719         else
720           MESSAGE("SPATIAL_LICENSE already in env => we use it");
721       }
722     if (! error.empty())
723       std::cerr << error;
724     return key;
725   }
726
727   //================================================================================
728   /*!
729    * \brief Get the license key from libMeshGemsKeyGenerator.so or $SPATIAL_LICENSE
730    * Called for MG 2.15 by CADSurf and MG plugins calling MG products as library,
731    * i.e. compiled as library with -DSALOME_USE_MG_LIBS=ON
732    *  \param [out] error - return error description
733    *  \return std::string - the key
734    */
735   //================================================================================
736   std::string GetKey(std::string&       error)
737   {
738     // default key if not found in .so or in SPATIAL_LICENSE
739     std::string key("0");
740     const char *meshGemsOldStyleEnvVar( getenv( MESHGEMS_OLD_STYLE ) );
741     if ( !meshGemsOldStyleEnvVar || strlen(meshGemsOldStyleEnvVar) == 0 ){
742       const char *spatialLicenseEnvVar( getenv( SPATIAL_LICENSE ) );
743       if ( !spatialLicenseEnvVar || strlen(spatialLicenseEnvVar) == 0 )
744         {
745           MESSAGE("SPATIAL_LICENSE not in env => we add it from MGKeygen .so");
746           // use new style, i.e. key in a library
747           key = GetKey_After(error);
748         }
749       else
750         {
751           MESSAGE("SPATIAL_LICENSE already in env => we use it");
752           key = std::string(spatialLicenseEnvVar);
753         }
754     }
755     if (! error.empty())
756       std::cerr << error;
757     return key;
758   }
759
760   //================================================================================
761   /*!
762    * \brief Return false if libMeshGemsKeyGenerator.so is not functional
763    *  \param [out] error - return error description
764    *  \return bool - is a success
765    */
766   //================================================================================
767
768   bool CheckKeyGenLibrary( std::string& error )
769   {
770     return !GetKey("",4,0,2,0,error ).empty();
771   }
772
773   //================================================================================
774   /*!
775    * \brief Return KeyGenerator library name
776    */
777   //================================================================================
778
779   std::string GetLibraryName()
780   {
781     std::string libName, error;
782     if ( const char* libPath = getenv( theEnvVar ))
783     {
784       libName = Kernel_Utils::GetBaseName( libPath );
785     }
786     else
787     {
788       libName = "libSalomeMeshGemsKeyGenerator";
789     }
790     setExtension( libName, error );
791     return libName;
792   }
793 }