VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp@ 33977

最後變更 在這個檔案從33977是 33977,由 vboxsync 提交於 14 年 前

*: replaced a bunch of sprintf() by snprintf()

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 16.3 KB
 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is Mozilla Communicator.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corp.
19 * Portions created by the Initial Developer are Copyright (C) 2003
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 * Sean Su <[email protected]>
24 *
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39#include "nsBuildID.h"
40
41#include "nsEmbedString.h"
42#include "nsXPCOMPrivate.h"
43#include "nsXPCOMGlue.h"
44#include "nsILocalFile.h"
45#include "nsIDirectoryService.h"
46#include "nsDirectoryServiceDefs.h"
47#include "nsCOMPtr.h"
48
49#include "nspr.h"
50#include "plstr.h"
51
52#ifdef XP_WIN32
53#include <windows.h>
54#include <stdlib.h>
55#elif defined(XP_OS2)
56#define INCL_DOS
57#include <os2.h>
58#include <stdlib.h>
59#include <stdio.h>
60#include "prenv.h"
61#elif defined(XP_MACOSX)
62#include <Processes.h>
63#include <CFBundle.h>
64#elif defined(XP_UNIX)
65#include <unistd.h>
66#include <stdlib.h>
67#include <sys/param.h>
68#include <dlfcn.h>
69#include "prenv.h"
70#elif defined(XP_BEOS)
71#include <FindDirectory.h>
72#include <Path.h>
73#include <unistd.h>
74#include <stdlib.h>
75#include <sys/param.h>
76#include <OS.h>
77#include <image.h>
78#include "prenv.h"
79#endif
80
81#include <sys/stat.h>
82
83#include "nsGREDirServiceProvider.h"
84
85PRBool GRE_GetCurrentProcessDirectory(char* buffer);
86PRBool GRE_GetPathFromConfigDir(const char* dirname, char* buffer);
87PRBool GRE_GetPathFromConfigFile(const char* dirname, char* buffer);
88
89//*****************************************************************************
90// nsGREDirServiceProvider::nsISupports
91//*****************************************************************************
92
93NS_IMPL_ISUPPORTS1(nsGREDirServiceProvider, nsIDirectoryServiceProvider)
94
95//*****************************************************************************
96// nsGREDirServiceProvider::nsIDirectoryServiceProvider
97//*****************************************************************************
98
99NS_IMETHODIMP
100nsGREDirServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
101{
102 *_retval = nsnull;
103 *persistant = PR_TRUE;
104
105 //---------------------------------------------------------------
106 // Note that by returning a valid localFile's for NS_GRE_DIR,
107 // your app is indicating to XPCOM that it found a GRE version
108 // with which it's compatible with and intends to be "run against"
109 // that GRE.
110 //
111 // Please see http://www.mozilla.org/projects/embedding/GRE.html
112 // for more info on GRE.
113 //---------------------------------------------------------------
114 if(strcmp(prop, NS_GRE_DIR) == 0)
115 {
116 nsILocalFile* lfile = nsnull;
117 nsresult rv = GRE_GetGREDirectory(&lfile);
118 *_retval = lfile;
119 return rv;
120 }
121
122 return NS_ERROR_FAILURE;
123}
124
125//*****************************************************************************
126// Implementations from nsXPCOMGlue.h and helper functions.
127//*****************************************************************************
128
129PRBool
130GRE_GetCurrentProcessDirectory(char* buffer)
131{
132 *buffer = '\0';
133
134#ifdef XP_WIN
135 if ( ::GetModuleFileName(0, buffer, MAXPATHLEN) ) {
136 // chop of the executable name by finding the rightmost backslash
137 char* lastSlash = PL_strrchr(buffer, '\\');
138 if (lastSlash) {
139 *(lastSlash) = '\0';
140 return PR_TRUE;
141 }
142 }
143
144#elif defined(XP_MACOSX)
145 // Works even if we're not bundled.
146 CFBundleRef appBundle = CFBundleGetMainBundle();
147 if (appBundle != nsnull)
148 {
149 CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
150 if (bundleURL != nsnull)
151 {
152 CFURLRef parentURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, bundleURL);
153 if (parentURL)
154 {
155 CFStringRef path = CFURLCopyFileSystemPath(parentURL, kCFURLPOSIXPathStyle);
156 if (path)
157 {
158 CFStringGetCString(path, buffer, MAXPATHLEN, kCFStringEncodingUTF8);
159 CFRelease(path);
160 }
161 CFRelease(parentURL);
162 }
163 CFRelease(bundleURL);
164 }
165#if 0 /* bird: Causes crashes in objc_msgSend() later if released. I dunno why really.
166 Something could be seriously screwed up somewhere else, but this'll have
167 to do for now. (appBundle isn't released in the other place it's used.) */
168 CFRelease(appBundle);
169#endif
170 }
171 if (*buffer) return PR_TRUE;
172
173#elif defined(XP_UNIX)
174
175#if 0 /* we need .so location. */
176 // Actually we have a way on linux.
177 static volatile bool fPathSet = false;
178 static char szPath[MAXPATHLEN];
179 if (!fPathSet)
180 {
181 char buf2[MAXPATHLEN + 3];
182 buf2[0] = '\0';
183
184 /*
185 * Env.var. VBOX_XPCOM_HOME first.
186 */
187 char *psz = PR_GetEnv("VBOX_XPCOM_HOME");
188 if (psz)
189 {
190 if (strlen(psz) < MAXPATHLEN)
191 {
192 if (!realpath(psz, buf2))
193 strcpy(buf2, psz);
194 strcat(buf2, "/x"); /* for the filename stripping */
195 }
196 }
197
198 /*
199 * The dynamic loader.
200 */
201 if (!buf2[0])
202 {
203 Dl_info DlInfo = {0};
204 if ( !dladdr((const void *)GRE_GetCurrentProcessDirectory, &DlInfo)
205 && DlInfo.dli_fname)
206 {
207 if (!realpath(DlInfo.dli_fname, buf2))
208 buf2[0] = '\0';
209 }
210 }
211
212 /*
213 * Executable location.
214 */
215 if (!buf2[0])
216 {
217 char buf[MAXPATHLEN];
218 int cchLink = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
219 if (cchLink > 0 || cchLink != sizeof(buf) - 1)
220 {
221 buf[cchLink] = '\0';
222 if (!realpath(buf, buf2))
223 buf2[0] = '\0';
224 }
225 }
226
227 /*
228 * Copy to static buffer on success.
229 */
230 if (buf2[0])
231 {
232 char *p = strrchr(buf2, '/');
233 if (p)
234 {
235 p[p == buf2] = '\0';
236 #ifdef DEBUG
237 printf("debug: (1) VBOX_XPCOM_HOME=%s\n", buf2);
238 #endif
239 strcpy(szPath, buf2);
240 fPathSet = true;
241 }
242 }
243 }
244 if (fPathSet)
245 {
246 strcpy(buffer, szPath);
247 return PR_TRUE;
248 }
249#endif
250
251 // In the absence of a good way to get the executable directory let
252 // us try this for unix:
253 // - if VBOX_XPCOM_HOME is defined, that is it
254 // - else give the current directory
255
256 // The MOZ_DEFAULT_VBOX_XPCOM_HOME variable can be set at configure time with
257 // a --with-default-mozilla-five-home=foo autoconf flag.
258 //
259 // The idea here is to allow for builds that have a default VBOX_XPCOM_HOME
260 // regardless of the environment. This makes it easier to write apps that
261 // embed mozilla without having to worry about setting up the environment
262 //
263 // We do this py putenv()ing the default value into the environment. Note that
264 // we only do this if it is not already set.
265#ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME
266 if (PR_GetEnv("VBOX_XPCOM_HOME") == nsnull)
267 {
268 putenv("VBOX_XPCOM_HOME=" MOZ_DEFAULT_VBOX_XPCOM_HOME);
269 }
270#endif
271
272 char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
273
274 if (moz5 && *moz5)
275 {
276 if (!realpath(moz5, buffer))
277 strcpy(buffer, moz5);
278
279 return PR_TRUE;
280 }
281 else
282 {
283#if defined(DEBUG)
284 static PRBool firstWarning = PR_TRUE;
285
286 if(firstWarning) {
287 // Warn that VBOX_XPCOM_HOME not set, once.
288 printf("Warning: VBOX_XPCOM_HOME not set.\n");
289 firstWarning = PR_FALSE;
290 }
291#endif /* DEBUG */
292
293 // Fall back to current directory.
294 if (getcwd(buffer, MAXPATHLEN))
295 {
296 return PR_TRUE;
297 }
298 }
299
300#elif defined(XP_OS2)
301 PPIB ppib;
302 PTIB ptib;
303 char* p;
304 DosGetInfoBlocks( &ptib, &ppib);
305 DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, buffer);
306 p = strrchr( buffer, '\\'); // XXX DBCS misery
307 if (p) {
308 *p = '\0';
309 return PR_TRUE;
310 }
311
312#elif defined(XP_BEOS)
313
314 char *moz5 = getenv("VBOX_XPCOM_HOME");
315 if (moz5)
316 {
317 strcpy(buffer, moz5);
318 return PR_TRUE;
319 }
320 else
321 {
322 int32 cookie = 0;
323 image_info info;
324 char *p;
325 *buffer = 0;
326 if(get_next_image_info(0, &cookie, &info) == B_OK)
327 {
328 strcpy(buffer, info.name);
329 if((p = strrchr(buffer, '/')) != 0)
330 {
331 *p = 0;
332
333 return PR_TRUE;
334 }
335 }
336 }
337
338#endif
339
340 return PR_FALSE;
341}
342
343/**
344 * the GRE location is stored in a static buffer so that we don't have
345 * to compute it multiple times.
346 */
347
348static char sGRELocation[MAXPATHLEN] = "";
349
350extern "C" char const *
351GRE_GetGREPath()
352{
353 // we've already done this...
354 if (*sGRELocation)
355 return sGRELocation;
356
357 char buffer[MAXPATHLEN];
358
359 // If the xpcom library exists in the current process directory,
360 // then we will not use any GRE. The assumption here is that the
361 // GRE is in the same directory as the executable.
362 if (GRE_GetCurrentProcessDirectory(buffer)) {
363 PRUint32 pathlen = strlen(buffer);
364 strcpy(buffer + pathlen, XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL);
365
366 struct stat libStat;
367 int statResult = stat(buffer, &libStat);
368
369 if (statResult != -1) {
370 //found our xpcom lib in the current process directory
371 buffer[pathlen] = '\0';
372 strcpy(sGRELocation, buffer);
373 return sGRELocation;
374 }
375 }
376
377 // if GRE_HOME is in the environment, use that GRE
378 const char* env = PR_GetEnv("GRE_HOME");
379 if (env && *env) {
380#if XP_UNIX
381 if (!realpath(env, sGRELocation))
382 strcpy(sGRELocation, env);
383#elif XP_WIN32
384 if (!_fullpath(sGRELocation, env, MAXPATHLEN))
385 strcpy(sGRELocation, env);
386#endif
387 // xxxbsmedberg: it would help that other platforms had a "make absolute" function
388 return sGRELocation;
389 }
390
391 // the Gecko bits that sit next to the application or in the LD_LIBRARY_PATH
392 env = PR_GetEnv("USE_LOCAL_GRE");
393 if (env && *env)
394 return nsnull;
395
396#if XP_UNIX
397 // check in the HOME directory
398 env = PR_GetEnv("HOME");
399 if (env && *env) {
400# ifdef VBOX
401 snprintf(buffer, sizeof(buffer), "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env);
402# else
403 sprintf(buffer, "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env);
404# endif
405
406 if (GRE_GetPathFromConfigFile(buffer, sGRELocation)) {
407 return sGRELocation;
408 }
409 }
410#endif
411
412 env = PR_GetEnv("MOZ_GRE_CONF");
413 if (env) {
414 if (GRE_GetPathFromConfigFile(env, sGRELocation)) {
415 return sGRELocation;
416 }
417 }
418
419#if XP_UNIX
420 // Look for a group of config files in /etc/gre.d/
421 if (GRE_GetPathFromConfigDir(GRE_CONF_DIR, sGRELocation)) {
422 return sGRELocation;
423 }
424
425 // Look for a global /etc/gre.conf file
426 if (GRE_GetPathFromConfigFile(GRE_CONF_PATH, sGRELocation)) {
427 return sGRELocation;
428 }
429#endif
430
431#if XP_WIN32
432 char szKey[256];
433 HKEY hRegKey = NULL;
434 DWORD dwLength = MAXPATHLEN;
435
436 // A couple of key points here:
437 // 1. Note the usage of the "Software\\Mozilla\\GRE" subkey - this allows
438 // us to have multiple versions of GREs on the same machine by having
439 // subkeys such as 1.0, 1.1, 2.0 etc. under it.
440 // 2. In this sample below we're looking for the location of GRE version 1.2
441 // i.e. we're compatible with GRE 1.2 and we're trying to find it's install
442 // location.
443 //
444 // Please see http://www.mozilla.org/projects/embedding/GRE.html for
445 // more info.
446 //
447 strcpy(szKey, GRE_WIN_REG_LOC GRE_BUILD_ID);
448
449 if (::RegOpenKeyEx(HKEY_CURRENT_USER, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
450 if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
451 *sGRELocation = '\0';
452 }
453 ::RegCloseKey(hRegKey);
454
455 if (*sGRELocation)
456 return sGRELocation;
457 }
458
459 if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
460 if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
461 *sGRELocation = '\0';
462 }
463 ::RegCloseKey(hRegKey);
464
465 if (*sGRELocation)
466 return sGRELocation;
467 }
468#endif
469
470 return nsnull;
471}
472
473PRBool
474GRE_GetPathFromConfigDir(const char* dirname, char* buffer)
475{
476 // Open the directory provided and try to read any files in that
477 // directory that end with .conf. We look for an entry that might
478 // point to the GRE that we're interested in.
479 PRDir *dir = PR_OpenDir(dirname);
480 if (!dir)
481 return nsnull;
482
483 PRBool found = PR_FALSE;
484 PRDirEntry *entry;
485
486 while (!found && (entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
487
488 // Only look for files that end in .conf
489 char *offset = PL_strrstr(entry->name, ".conf");
490 if (!offset)
491 continue;
492
493 if (offset != entry->name + strlen(entry->name) - 5)
494 continue;
495
496 nsEmbedCString fullPath;
497 NS_CStringAppendData(fullPath, dirname);
498 NS_CStringAppendData(fullPath, XPCOM_FILE_PATH_SEPARATOR);
499 NS_CStringAppendData(fullPath, entry->name);
500
501 found = GRE_GetPathFromConfigFile(fullPath.get(), buffer);
502 }
503
504 PR_CloseDir(dir);
505
506 return found;
507}
508
509PRBool
510GRE_GetPathFromConfigFile(const char* filename, char* pathBuffer)
511{
512 *pathBuffer = '\0';
513 char buffer[1024];
514 FILE *cfg;
515 PRBool foundHeader = PR_FALSE;
516 PRInt32 versionLen = sizeof(GRE_BUILD_ID)-1;
517
518 if((cfg=fopen(filename,"r"))==nsnull) {
519 return nsnull;
520 }
521
522 while (fgets(buffer, 1024, cfg) != nsnull) {
523 // skip over comment lines and blank lines
524 if (buffer[0] == '#' || buffer[0] == '\n') {
525 continue;
526 }
527
528 // we found a section heading, check to see if it is the one we are intersted in.
529 if (buffer[0] == '[') {
530 if (!strncmp (buffer+1, GRE_BUILD_ID, versionLen)) {
531 foundHeader = PR_TRUE;
532 }
533 continue;
534 }
535
536 if (foundHeader && !strncmp (buffer, "GRE_PATH=", 9)) {
537 strcpy(pathBuffer, buffer + 9);
538 // kill the line feed if any
539 PRInt32 len = strlen(pathBuffer);
540 len--;
541
542 if (pathBuffer[len] == '\n')
543 pathBuffer[len] = '\0';
544 break;
545 }
546 }
547 fclose(cfg);
548 return (*pathBuffer != '\0');
549}
550
551extern "C" nsresult
552GRE_GetGREDirectory(nsILocalFile* *_retval)
553{
554 NS_ENSURE_ARG_POINTER(_retval);
555 nsresult rv = NS_ERROR_FAILURE;
556
557 // Get the path of the GRE which is compatible with our embedding application
558 // from the registry
559
560 const char *pGREDir = GRE_GetGREPath();
561 if(pGREDir) {
562 nsCOMPtr<nsILocalFile> tempLocal;
563 nsEmbedCString leaf;
564 NS_CStringSetData(leaf, pGREDir);
565 rv = NS_NewNativeLocalFile(leaf, PR_TRUE, getter_AddRefs(tempLocal));
566
567 if (NS_SUCCEEDED(rv)) {
568 *_retval = tempLocal;
569 NS_ADDREF(*_retval);
570 }
571 }
572 return rv;
573}
574
575static char sXPCOMPath[MAXPATHLEN];
576
577extern "C" const char*
578GRE_GetXPCOMPath()
579{
580 const char* grePath = GRE_GetGREPath();
581
582 if (!grePath) {
583 grePath = PR_GetEnv("VBOX_XPCOM_HOME");
584 if (!grePath || !*grePath) {
585 return nsnull;
586 }
587 }
588
589#ifdef VBOX
590 snprintf(sXPCOMPath, sizeof(sXPCOMPath), "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath);
591#else
592 sprintf(sXPCOMPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath);
593#endif
594
595 return sXPCOMPath;
596}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette