00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "stdmisc.h"
00025
00026 #ifdef NL_OS_WINDOWS
00027 # define NOMINMAX
00028 # include <windows.h>
00029 # include <io.h>
00030 # include <tchar.h>
00031 #elif defined NL_OS_UNIX
00032 # include <unistd.h>
00033 # include <cstring>
00034 # include <cerrno>
00035 # include <csignal>
00036 # include <pthread.h>
00037 # include <sched.h>
00038 #endif
00039
00040 #include "nel/misc/command.h"
00041 #include "nel/misc/path.h"
00042
00043 using namespace std;
00044
00045 #ifdef NL_OS_WINDOWS
00046 # pragma message( " " )
00047
00048 # if FINAL_VERSION
00049 # pragma message( "************************" )
00050 # pragma message( "**** FINAL_VERSION *****" )
00051 # pragma message( "************************" )
00052 # else
00053 # pragma message( "Not using FINAL_VERSION")
00054 # endif // FINAL_VERSION
00055
00056 # ifdef ASSERT_THROW_EXCEPTION
00057 # pragma message( "nlassert throws exceptions" )
00058 # else
00059 # pragma message( "nlassert does not throw exceptions" )
00060 # endif // ASSERT_THROW_EXCEPTION
00061
00062 # ifdef _STLPORT_VERSION
00063 # pragma message( "Using STLport" )
00064 # else
00065 # pragma message( "Using standard STL" )
00066 # endif // _STLPORT_VERSION
00067
00068 # pragma message( " " )
00069
00070 # if (_MSC_VER >= 1200) && (_MSC_VER < 1400) && (WINVER < 0x0500)
00071
00072 extern "C" long _ftol2( double dblSource ) { return _ftol( dblSource ); }
00073 # endif
00074
00075
00076 #endif // NL_OS_WINDOWS
00077
00078
00079
00080 namespace NLMISC
00081 {
00082
00083
00084
00085
00086
00087 void nlSleep( uint32 ms )
00088 {
00089 #ifdef NL_OS_WINDOWS
00090
00091 #ifdef NL_DEBUG
00092
00093 ms = max(ms, (uint32)1);
00094 #endif
00095
00096 Sleep( ms );
00097
00098 #elif defined NL_OS_UNIX
00099
00100
00101 timespec ts;
00102 ts.tv_sec = ms/1000;
00103 ts.tv_nsec = (ms%1000)*1000000;
00104 int res;
00105 do
00106 {
00107 res = nanosleep( &ts, &ts );
00108 }
00109 while ( (res != 0) && (errno==EINTR) );
00110 #endif
00111 }
00112
00113
00114
00115
00116
00117 uint getThreadId()
00118 {
00119 #ifdef NL_OS_WINDOWS
00120 return GetCurrentThreadId();
00121 #elif defined NL_OS_UNIX
00122 return uint(pthread_self());
00123
00124 #endif
00125
00126 }
00127
00128
00129
00130
00131
00132 string stringFromVector( const vector<uint8>& v, bool limited )
00133 {
00134 string s;
00135
00136 if (!v.empty())
00137 {
00138 int size = v.size ();
00139 if (limited && size > 1000)
00140 {
00141 string middle = "...<buf too big,skip middle part>...";
00142 s.resize (1000 + middle.size());
00143 memcpy (&*s.begin(), &*v.begin(), 500);
00144 memcpy (&*s.begin()+500, &*middle.begin(), middle.size());
00145 memcpy (&*s.begin()+500+middle.size(), &*v.begin()+size-500, 500);
00146 }
00147 else
00148 {
00149 s.resize (size);
00150 memcpy( &*s.begin(), &*v.begin(), v.size() );
00151 }
00152
00153
00154 string::iterator is;
00155 for ( is=s.begin(); is!=s.end(); ++is )
00156 {
00157
00158 if ( ! isprint((uint8)(*is)) || (*is) == '%')
00159 {
00160 (*is) = '?';
00161 }
00162 }
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 return s;
00183 }
00184
00185
00186 sint smprintf( char *buffer, size_t count, const char *format, ... )
00187 {
00188 sint ret;
00189
00190 va_list args;
00191 va_start( args, format );
00192 ret = vsnprintf( buffer, count, format, args );
00193 if ( ret == -1 )
00194 {
00195 buffer[count-1] = '\0';
00196 }
00197 va_end( args );
00198
00199 return( ret );
00200 }
00201
00202
00203 sint64 atoiInt64 (const char *ident, sint64 base)
00204 {
00205 sint64 number = 0;
00206 bool neg = false;
00207
00208
00209 nlassert (ident != NULL);
00210
00211
00212 if (*ident == '\0') goto end;
00213
00214
00215 if (*ident == '+') ident++;
00216
00217
00218 if (*ident == '-') { neg = true; ident++; }
00219
00220 while (*ident != '\0')
00221 {
00222 if (isdigit((unsigned char)*ident))
00223 {
00224 number *= base;
00225 number += (*ident)-'0';
00226 }
00227 else if (base > 10 && islower((unsigned char)*ident))
00228 {
00229 number *= base;
00230 number += (*ident)-'a'+10;
00231 }
00232 else if (base > 10 && isupper((unsigned char)*ident))
00233 {
00234 number *= base;
00235 number += (*ident)-'A'+10;
00236 }
00237 else
00238 {
00239 goto end;
00240 }
00241 ident++;
00242 }
00243 end:
00244 if (neg) number = -number;
00245 return number;
00246 }
00247
00248 void itoaInt64 (sint64 number, char *str, sint64 base)
00249 {
00250 str[0] = '\0';
00251 char b[256];
00252 if(!number)
00253 {
00254 str[0] = '0';
00255 str[1] = '\0';
00256 return;
00257 }
00258 memset(b,'\0',255);
00259 memset(b,'0',64);
00260 sint n;
00261 sint64 x = number;
00262 if (x < 0) x = -x;
00263 char baseTable[] = "0123456789abcdefghijklmnopqrstuvwyz";
00264 for(n = 0; n < 64; n ++)
00265 {
00266 sint num = (sint)(x % base);
00267 b[64 - n] = baseTable[num];
00268 if(!x)
00269 {
00270 int k;
00271 int j = 0;
00272
00273 if (number < 0)
00274 {
00275 str[j++] = '-';
00276 }
00277
00278 for(k = 64 - n + 1; k <= 64; k++)
00279 {
00280 str[j ++] = b[k];
00281 }
00282 str[j] = '\0';
00283 break;
00284 }
00285 x /= base;
00286 }
00287 }
00288
00289 uint raiseToNextPowerOf2(uint v)
00290 {
00291 uint res=1;
00292 while(res<v)
00293 res<<=1;
00294
00295 return res;
00296 }
00297
00298 uint getPowerOf2(uint v)
00299 {
00300 uint res=1;
00301 uint ret=0;
00302 while(res<v)
00303 {
00304 ret++;
00305 res<<=1;
00306 }
00307
00308 return ret;
00309 }
00310
00311 bool isPowerOf2(sint32 v)
00312 {
00313 while(v)
00314 {
00315 if(v&1)
00316 {
00317 v>>=1;
00318 if(v)
00319 return false;
00320 }
00321 else
00322 v>>=1;
00323 }
00324
00325 return true;
00326 }
00327
00328 string bytesToHumanReadable (const std::string &bytes)
00329 {
00330 return bytesToHumanReadable (atoiInt64(bytes.c_str()));
00331 }
00332
00333 string bytesToHumanReadable (uint64 bytes)
00334 {
00335 static const char *divTable[]= { "B", "KB", "MB", "GB", "TB" };
00336 uint div = 0;
00337 uint64 res = bytes;
00338 uint64 newres = res;
00339 for(;;)
00340 {
00341 newres /= 1024;
00342 if(newres < 8 || div > 3)
00343 break;
00344 div++;
00345 res = newres;
00346 }
00347 return toString ("%"NL_I64"u%s", res, divTable[div]);
00348 }
00349
00350 uint32 humanReadableToBytes (const string &str)
00351 {
00352 uint32 res;
00353
00354 if(str.empty())
00355 return 0;
00356
00357
00358 if(str[0]<'0' || str[0]>'9')
00359 return 0;
00360
00361 res = atoi (str.c_str());
00362
00363 if(str[str.size()-1] == 'B')
00364 {
00365 if (str.size()<3)
00366 return res;
00367
00368
00369 switch (str[str.size()-2])
00370 {
00371 case 'G': res *= 1024;
00372 case 'M': res *= 1024;
00373 case 'K': res *= 1024;
00374 default: ;
00375 }
00376 }
00377
00378 return res;
00379 }
00380
00381
00382 NLMISC_CATEGORISED_COMMAND(nel,btohr, "Convert a bytes number into an human readable number", "<int>")
00383 {
00384 if (args.size() != 1)
00385 return false;
00386
00387 log.displayNL("%s -> %s", args[0].c_str(), bytesToHumanReadable(args[0]).c_str());
00388
00389 return true;
00390 }
00391
00392
00393 NLMISC_CATEGORISED_COMMAND(nel,hrtob, "Convert a human readable number into a bytes number", "<hr>")
00394 {
00395 if (args.size() != 1)
00396 return false;
00397
00398 log.displayNL("%s -> %u", args[0].c_str(), humanReadableToBytes(args[0]));
00399
00400 return true;
00401 }
00402
00403
00404 string secondsToHumanReadable (uint32 time)
00405 {
00406 static const char *divTable[] = { "s", "mn", "h", "d" };
00407 static uint divCoef[] = { 60, 60, 24 };
00408 uint div = 0;
00409 uint32 res = time;
00410 uint32 newres = res;
00411 for(;;)
00412 {
00413 if(div > 2)
00414 break;
00415
00416 newres /= divCoef[div];
00417
00418 if(newres < 3)
00419 break;
00420
00421 div++;
00422 res = newres;
00423 }
00424 return toString ("%u%s", res, divTable[div]);
00425 }
00426
00427 uint32 fromHumanReadable (const std::string &str)
00428 {
00429 if (str.size() == 0)
00430 return 0;
00431
00432 uint32 val;
00433 fromString(str, val);
00434
00435 switch (str[str.size()-1])
00436 {
00437 case 's': return val;
00438 case 'n': return val*60;
00439 case 'h': return val*60*60;
00440 case 'd': return val*60*60*24;
00441 case 'b':
00442 switch (str[str.size()-2])
00443 {
00444 case 'k': return val*1024;
00445 case 'm': return val*1024*1024;
00446 case 'g': return val*1024*1024*1024;
00447 default : return val;
00448 }
00449 default: return val;
00450 }
00451 return 0;
00452 }
00453
00454
00455 NLMISC_CATEGORISED_COMMAND(nel,stohr, "Convert a second number into an human readable time", "<int>")
00456 {
00457 if (args.size() != 1)
00458 return false;
00459
00460 uint32 seconds;
00461 fromString(args[0], seconds);
00462 log.displayNL("%s -> %s", args[0].c_str(), secondsToHumanReadable(seconds).c_str());
00463
00464 return true;
00465 }
00466
00467
00468 std::string toLower(const std::string &str)
00469 {
00470 string res;
00471 res.reserve(str.size());
00472 for(uint i = 0; i < str.size(); i++)
00473 {
00474 if( (str[i] >= 'A') && (str[i] <= 'Z') )
00475 res += str[i] - 'A' + 'a';
00476 else
00477 res += str[i];
00478 }
00479 return res;
00480 }
00481
00482 char toLower(const char ch)
00483 {
00484 if( (ch >= 'A') && (ch <= 'Z') )
00485 {
00486 return ch - 'A' + 'a';
00487 }
00488 else
00489 {
00490 return ch;
00491 }
00492 }
00493
00494 void toLower(char *str)
00495 {
00496 if (str == 0)
00497 return;
00498
00499 while(*str != '\0')
00500 {
00501 if( (*str >= 'A') && (*str <= 'Z') )
00502 {
00503 *str = *str - 'A' + 'a';
00504 }
00505 str++;
00506 }
00507 }
00508
00509 std::string toUpper(const std::string &str)
00510 {
00511 string res;
00512 res.reserve(str.size());
00513 for(uint i = 0; i < str.size(); i++)
00514 {
00515 if( (str[i] >= 'a') && (str[i] <= 'z') )
00516 res += str[i] - 'a' + 'A';
00517 else
00518 res += str[i];
00519 }
00520 return res;
00521 }
00522
00523 void toUpper(char *str)
00524 {
00525 if (str == 0)
00526 return;
00527
00528 while(*str != '\0')
00529 {
00530 if( (*str >= 'a') && (*str <= 'z') )
00531 {
00532 *str = *str - 'a' + 'A';
00533 }
00534 str++;
00535 }
00536 }
00537
00538
00539
00540
00541
00542
00543 Exception::Exception() : _Reason("Unknown Exception")
00544 {
00545
00546 }
00547
00548 Exception::Exception(const std::string &reason) : _Reason(reason)
00549 {
00550 nlinfo("Exception will be launched: %s", _Reason.c_str());
00551 }
00552
00553 Exception::Exception(const char *format, ...)
00554 {
00555 NLMISC_CONVERT_VARGS (_Reason, format, NLMISC::MaxCStringSize);
00556 nlinfo("Exception will be launched: %s", _Reason.c_str());
00557 }
00558
00559 const char *Exception::what() const throw()
00560 {
00561 return _Reason.c_str();
00562 }
00563
00564 bool killProgram(uint32 pid)
00565 {
00566 #ifdef NL_OS_UNIX
00567 int res = kill(pid, SIGKILL);
00568 if(res == -1)
00569 {
00570 char *err = strerror (errno);
00571 nlwarning("Failed to kill '%d' err %d: '%s'", pid, errno, err);
00572 }
00573 return res == 0;
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 #else
00584 nlwarning("kill not implemented on this OS");
00585 return false;
00586 #endif
00587 }
00588
00589 bool abortProgram(uint32 pid)
00590 {
00591 #ifdef NL_OS_UNIX
00592 int res = kill(pid, SIGABRT);
00593 if(res == -1)
00594 {
00595 char *err = strerror (errno);
00596 nlwarning("Failed to abort '%d' err %d: '%s'", pid, errno, err);
00597 }
00598 return res == 0;
00599 #else
00600 nlwarning("abort not implemented on this OS");
00601 return false;
00602 #endif
00603 }
00604
00605 bool launchProgram (const std::string &programName, const std::string &arguments)
00606 {
00607
00608 #ifdef NL_OS_WINDOWS
00609 STARTUPINFOA si;
00610 PROCESS_INFORMATION pi;
00611
00612 memset(&si, 0, sizeof(si));
00613 memset(&pi, 0, sizeof(pi));
00614
00615 si.cb = sizeof(si);
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 const TCHAR *SE_TRANSLATOR_IN_MAIN_MODULE = _T("NEL_SE_TRANS");
00637 TCHAR envBuf [2];
00638 if ( GetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, envBuf, 2 ) != 0)
00639 {
00640 SetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, NULL );
00641 }
00642
00643 string arg = " " + arguments;
00644 BOOL res = CreateProcessA(programName.c_str(), (char*)arg.c_str(), 0, 0, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, 0, 0, &si, &pi);
00645
00646 if (res)
00647 {
00648
00649 CloseHandle( pi.hProcess );
00650 CloseHandle( pi.hThread );
00651 return true;
00652 }
00653 else
00654 {
00655 LPVOID lpMsgBuf;
00656 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
00657 nlwarning("LAUNCH: Failed launched '%s' with arg '%s' err %d: '%s'", programName.c_str(), arguments.c_str(), GetLastError (), lpMsgBuf);
00658 LocalFree(lpMsgBuf);
00659 CloseHandle( pi.hProcess );
00660 CloseHandle( pi.hThread );
00661 }
00662
00663 #elif defined(NL_OS_UNIX)
00664
00665 static bool firstLaunchProgram = true;
00666 if (firstLaunchProgram)
00667 {
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 signal(SIGCHLD,SIG_IGN);
00680
00681 firstLaunchProgram = false;
00682 }
00683
00684
00685 vector<string> args;
00686 string::size_type pos1 = 0, pos2 = 0;
00687 do
00688 {
00689 pos1 = arguments.find_first_not_of (" ", pos2);
00690 if (pos1 == string::npos) break;
00691 pos2 = arguments.find_first_of (" ", pos1);
00692 args.push_back (arguments.substr (pos1, pos2-pos1));
00693 }
00694 while (pos2 != string::npos);
00695
00696
00697 vector<char *> argv(args.size()+2);
00698 uint i = 0;
00699 argv[i] = (char *)programName.c_str();
00700 for (; i < args.size(); i++)
00701 {
00702 argv[i+1] = (char *) args[i].c_str();
00703 }
00704 argv[i+1] = NULL;
00705
00706 int status = vfork ();
00711 if (status == -1)
00712 {
00713 char *err = strerror (errno);
00714 nlwarning("LAUNCH: Failed launched '%s' with arg '%s' err %d: '%s'", programName.c_str(), arguments.c_str(), errno, err);
00715 }
00716 else if (status == 0)
00717 {
00718
00719
00720 status = execvp(programName.c_str(), &argv.front());
00721
00722 if (status == -1)
00723 {
00724 perror("Failed launched");
00725 _exit(EXIT_FAILURE);
00726 }
00727 }
00728 else
00729 {
00730
00731 return true;
00732 }
00733 #else
00734 nlwarning ("LAUNCH: launchProgram() not implemented");
00735 #endif
00736
00737 return false;
00738
00739 }
00740
00741
00742
00743
00744 void displayByteBits( uint8 b, uint nbits, sint beginpos, bool displayBegin, NLMISC::CLog *log )
00745 {
00746 string s1, s2;
00747 sint i;
00748 for ( i=nbits-1; i!=-1; --i )
00749 {
00750 s1 += ( (b >> i) & 1 ) ? '1' : '0';
00751 }
00752 log->displayRawNL( "%s", s1.c_str() );
00753 if ( displayBegin )
00754 {
00755 for ( i=nbits; i>beginpos+1; --i )
00756 {
00757 s2 += " ";
00758 }
00759 s2 += "^";
00760 log->displayRawNL( "%s beginpos=%u", s2.c_str(), beginpos );
00761 }
00762 }
00763
00764
00765
00766
00767
00768
00769
00770 void displayDwordBits( uint32 b, uint nbits, sint beginpos, bool displayBegin, NLMISC::CLog *log )
00771 {
00772 string s1, s2;
00773 sint i;
00774 for ( i=nbits-1; i!=-1; --i )
00775 {
00776 s1 += ( (b >> i) & 1 ) ? '1' : '0';
00777 }
00778 log->displayRawNL( "%s", s1.c_str() );
00779 if ( displayBegin )
00780 {
00781 for ( i=nbits; i>beginpos+1; --i )
00782 {
00783 s2 += " ";
00784 }
00785 s2 += "^";
00786 log->displayRawNL( "%s beginpos=%u", s2.c_str(), beginpos );
00787 }
00788 }
00789
00790
00791 int nlfseek64( FILE *stream, sint64 offset, int origin )
00792 {
00793 #ifdef NL_OS_WINDOWS
00794
00795
00796 fpos_t pos64 = 0;
00797 switch (origin)
00798 {
00799 case SEEK_CUR:
00800 if (fgetpos(stream, &pos64) != 0)
00801 return -1;
00802 case SEEK_END:
00803 pos64 = _filelengthi64(_fileno(stream));
00804 if (pos64 == -1L)
00805 return -1;
00806 };
00807
00808
00809 pos64 += offset;
00810
00811
00812 return fsetpos (stream, &pos64);
00813
00814 #else // NL_OS_WINDOWS
00815
00816
00817
00818
00819 nlassert ((offset < SINT64_CONSTANT(2147483647)) && (offset > SINT64_CONSTANT(-2147483648)));
00820
00821 bool first = true;
00822 do
00823 {
00824
00825 sint nextSeek;
00826 if (offset > 0)
00827 nextSeek = (sint)std::min ((sint64)SINT64_CONSTANT(2147483647), offset);
00828 else
00829 nextSeek = (sint)std::max ((sint64)-SINT64_CONSTANT(2147483648), offset);
00830
00831
00832 int result = fseek ( stream, nextSeek, first?origin:SEEK_CUR );
00833 if (result != 0)
00834 return result;
00835
00836
00837 offset -= nextSeek;
00838 first = false;
00839 }
00840 while (offset);
00841
00842 return 0;
00843
00844 #endif // NL_OS_WINDOWS
00845 }
00846
00847 sint64 nlftell64(FILE *stream)
00848 {
00849 #ifdef NL_OS_WINDOWS
00850 fpos_t pos64 = 0;
00851 if (fgetpos(stream, &pos64) == 0)
00852 {
00853 return (sint64) pos64;
00854 }
00855 else return -1;
00856 #else
00857 nlerror("Not implemented");
00858 return -1;
00859 #endif
00860 }
00861
00862
00868
00869 NLMISC_CATEGORISED_COMMAND(nel, sleep, "Freeze the service for N seconds (for debug purpose)", "<N>")
00870 {
00871 if(args.size() != 1) return false;
00872
00873 sint32 n = atoi (args[0].c_str());
00874
00875 log.displayNL ("Sleeping during %d seconds", n);
00876
00877 nlSleep(n * 1000);
00878 return true;
00879 }
00880
00881 NLMISC_CATEGORISED_COMMAND(nel, system, "Execute the command line using system() function call (wait until the end of the command)", "<commandline>")
00882 {
00883 if(args.size() != 1) return false;
00884
00885 string cmd = args[0];
00886 log.displayNL ("Executing '%s'", cmd.c_str());
00887 system(cmd.c_str());
00888 log.displayNL ("End of Execution of '%s'", cmd.c_str());
00889 return true;
00890 }
00891
00892 NLMISC_CATEGORISED_COMMAND(nel, launchProgram, "Execute the command line using launcProgram() function call (launch in background task without waiting the end of the execution)", "<programName> <arguments>")
00893 {
00894 if(args.size() != 2) return false;
00895
00896 string cmd = args[0];
00897 string arg = args[1];
00898 log.displayNL ("Executing '%s' with argument '%s'", cmd.c_str(), arg.c_str());
00899 launchProgram(cmd, arg);
00900 log.displayNL ("End of Execution of '%s' with argument '%s'", cmd.c_str(), arg.c_str());
00901 return true;
00902 }
00903
00904 NLMISC_CATEGORISED_COMMAND(nel, killProgram, "kill a program given the pid", "<pid>")
00905 {
00906 if(args.size() != 1) return false;
00907 uint32 pid;
00908 fromString(args[0], pid);
00909 killProgram(pid);
00910 return true;
00911 }
00912
00913 #ifdef NL_OS_WINDOWS
00914 LONG GetRegKey(HKEY key, LPCSTR subkey, LPSTR retdata)
00915 {
00916 HKEY hkey;
00917 LONG retval = RegOpenKeyExA(key, subkey, 0, KEY_QUERY_VALUE, &hkey);
00918
00919 if (retval == ERROR_SUCCESS)
00920 {
00921 long datasize = MAX_PATH;
00922 char data[MAX_PATH];
00923 RegQueryValueA(hkey, NULL, data, &datasize);
00924 lstrcpyA(retdata,data);
00925 RegCloseKey(hkey);
00926 }
00927
00928 return retval;
00929 }
00930 #endif // NL_OS_WINDOWS
00931
00932 bool openURL (const char *url)
00933 {
00934 #ifdef NL_OS_WINDOWS
00935 char key[1024];
00936 if (GetRegKey(HKEY_CLASSES_ROOT, ".html", key) == ERROR_SUCCESS)
00937 {
00938 lstrcatA(key, "\\shell\\open\\command");
00939
00940 if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS)
00941 {
00942 char *pos;
00943 pos = strstr(key, "\"%1\"");
00944 if (pos == NULL) {
00945 pos = strstr(key, "%1");
00946 if (pos == NULL)
00947 pos = key+lstrlenA(key)-1;
00948 else
00949 *pos = '\0';
00950 }
00951 else
00952 *pos = '\0';
00953
00954 lstrcatA(pos, " ");
00955 lstrcatA(pos, url);
00956 int res = WinExec(key,SW_SHOWDEFAULT);
00957 return (res>31);
00958 }
00959 }
00960 #elif defined(NL_OS_MAC)
00961 return launchProgram("open", url);
00962 #elif defined(NL_OS_UNIX)
00963 return launchProgram("/etc/alternatives/x-www-browser", url);
00964 #else
00965 nlwarning("openURL() is not implemented for this OS");
00966 #endif // NL_OS_WINDOWS
00967 return false;
00968 }
00969
00970 bool openDoc (const char *document)
00971 {
00972 #ifdef NL_OS_WINDOWS
00973 string ext = CFile::getExtension (document);
00974 char key[MAX_PATH + MAX_PATH];
00975
00976
00977 HINSTANCE result = ShellExecuteA(NULL, "open", document, NULL,NULL, SW_SHOWDEFAULT);
00978
00979
00980 if ((UINT)result <= HINSTANCE_ERROR)
00981 {
00982 if (GetRegKey(HKEY_CLASSES_ROOT, ext.c_str(), key) == ERROR_SUCCESS)
00983 {
00984 lstrcatA(key, "\\shell\\open\\command");
00985
00986 if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS)
00987 {
00988 char *pos;
00989 pos = strstr(key, "\"%1\"");
00990 if (pos == NULL) {
00991 pos = strstr(key, "%1");
00992 if (pos == NULL)
00993 pos = key+lstrlenA(key)-1;
00994 else
00995 *pos = '\0';
00996 }
00997 else
00998 *pos = '\0';
00999
01000 lstrcatA(pos, " ");
01001 lstrcatA(pos, document);
01002 int res = WinExec(key,SW_SHOWDEFAULT);
01003 return (res>31);
01004 }
01005 }
01006 }
01007 else
01008 return true;
01009 #endif // NL_OS_WINDOWS
01010 return false;
01011 }
01012
01013 }