Back to index

lightning-sunbird  0.9+nobinonly
nsReadConfig.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Mitesh Shah <mitesh@netscape.com>
00024  *   Chip Clark  <chipc@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #ifdef MOZ_LOGGING
00041 // sorry, this has to be before the pre-compiled header
00042 #define FORCE_PR_LOG /* Allow logging in the release build */
00043 #endif
00044 #include "nsReadConfig.h"
00045 #include "nsAppDirectoryServiceDefs.h"
00046 #include "nsIAppStartup.h"
00047 #include "nsDirectoryServiceDefs.h"
00048 #include "nsIAutoConfig.h"
00049 #include "nsIComponentManager.h"
00050 #include "nsIFile.h"
00051 #include "nsIObserverService.h"
00052 #include "nsIPrefBranch.h"
00053 #include "nsIPrefService.h"
00054 #include "nsIPromptService.h"
00055 #include "nsIServiceManager.h"
00056 #include "nsIStringBundle.h"
00057 #include "nsXPFEComponentsCID.h"
00058 #include "nsXPIDLString.h"
00059 #include "nsNetUtil.h"
00060 #include "prmem.h"
00061 #include "nsString.h"
00062 #include "nsCRT.h"
00063 #include "nspr.h"
00064 
00065 extern PRLogModuleInfo *MCD;
00066 
00067 extern nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
00068                                           const char *filename, 
00069                                           PRBool bGlobalContext, 
00070                                           PRBool bCallbacks, 
00071                                           PRBool skipFirstLine);
00072 extern nsresult CentralizedAdminPrefManagerInit();
00073 extern nsresult CentralizedAdminPrefManagerFinish();
00074 
00075 
00076 static void DisplayError(void)
00077 {
00078     nsresult rv;
00079 
00080     nsCOMPtr<nsIPromptService> promptService = do_GetService("@mozilla.org/embedcomp/prompt-service;1");
00081     if (!promptService)
00082         return;
00083 
00084     nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
00085     if (!bundleService)
00086         return;
00087 
00088     nsCOMPtr<nsIStringBundle> bundle;
00089     bundleService->CreateBundle("chrome://autoconfig/locale/autoconfig.properties",
00090                                 getter_AddRefs(bundle));
00091     if (!bundle)
00092         return;
00093 
00094     nsXPIDLString title;
00095     rv = bundle->GetStringFromName(NS_LITERAL_STRING("readConfigTitle").get(), getter_Copies(title));
00096     if (NS_FAILED(rv))
00097         return;
00098 
00099     nsXPIDLString err;
00100     rv = bundle->GetStringFromName(NS_LITERAL_STRING("readConfigMsg").get(), getter_Copies(err));
00101     if (NS_FAILED(rv))
00102         return;
00103 
00104     promptService->Alert(nsnull, title.get(), err.get());
00105 }
00106 
00107 // nsISupports Implementation
00108 
00109 NS_IMPL_THREADSAFE_ISUPPORTS2(nsReadConfig, nsIReadConfig, nsIObserver)
00110 
00111 nsReadConfig::nsReadConfig() :
00112     mRead(PR_FALSE)
00113 {
00114     if (!MCD)
00115       MCD = PR_NewLogModule("MCD");
00116 }
00117 
00118 nsresult nsReadConfig::Init()
00119 {
00120     nsresult rv;
00121     
00122     nsCOMPtr<nsIObserverService> observerService = 
00123         do_GetService("@mozilla.org/observer-service;1", &rv);
00124 
00125     if (observerService) {
00126         rv = observerService->AddObserver(this, NS_PREFSERVICE_READ_TOPIC_ID, PR_FALSE);
00127     }
00128     return(rv);
00129 }
00130 
00131 nsReadConfig::~nsReadConfig()
00132 {
00133     CentralizedAdminPrefManagerFinish();
00134 }
00135 
00136 NS_IMETHODIMP nsReadConfig::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
00137 {
00138     nsresult rv = NS_OK;
00139 
00140     if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
00141         rv = readConfigFile();
00142         if (NS_FAILED(rv)) {
00143             DisplayError();
00144 
00145             nsCOMPtr<nsIAppStartup> appStartup =
00146                 do_GetService(NS_APPSTARTUP_CONTRACTID);
00147             if (appStartup)
00148                 appStartup->Quit(nsIAppStartup::eAttemptQuit);
00149         }
00150     }
00151     return rv;
00152 }
00153 
00154 
00155 nsresult nsReadConfig::readConfigFile()
00156 {
00157     nsresult rv = NS_OK;
00158     nsXPIDLCString lockFileName;
00159     nsXPIDLCString lockVendor;
00160     PRUint32 fileNameLen = 0;
00161     
00162     nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
00163     nsCOMPtr<nsIPrefService> prefService = 
00164         do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00165     if (NS_FAILED(rv))
00166         return rv;
00167 
00168     rv = prefService->GetDefaultBranch(nsnull, getter_AddRefs(defaultPrefBranch));
00169     if (NS_FAILED(rv))
00170         return rv;
00171         
00172     // This preference is set in the all.js or all-ns.js (depending whether 
00173     // running mozilla or netscp6)
00174 
00175     rv = defaultPrefBranch->GetCharPref("general.config.filename", 
00176                                   getter_Copies(lockFileName));
00177 
00178 
00179     PR_LOG(MCD, PR_LOG_DEBUG, ("general.config.filename = %s\n", lockFileName.get()));
00180     if (NS_FAILED(rv))
00181         return rv;
00182 
00183     // This needs to be read only once.
00184     //
00185     if (!mRead) {
00186         // Initiate the new JS Context for Preference management
00187         
00188         rv = CentralizedAdminPrefManagerInit();
00189         if (NS_FAILED(rv))
00190             return rv;
00191         
00192         // Open and evaluate function calls to set/lock/unlock prefs
00193         rv = openAndEvaluateJSFile("prefcalls.js", 0, PR_FALSE, PR_FALSE);
00194         if (NS_FAILED(rv)) 
00195             return rv;
00196 
00197         // Evaluate platform specific directives
00198         rv = openAndEvaluateJSFile("platform.js", 0, PR_FALSE, PR_FALSE);
00199         if (NS_FAILED(rv)) 
00200             return rv;
00201 
00202         mRead = PR_TRUE;
00203     }
00204     // If the lockFileName is NULL return ok, because no lockFile will be used
00205   
00206   
00207     // Once the config file is read, we should check that the vendor name 
00208     // is consistent By checking for the vendor name after reading the config 
00209     // file we allow for the preference to be set (and locked) by the creator 
00210     // of the cfg file meaning the file can not be renamed (successfully).
00211 
00212     nsCOMPtr<nsIPrefBranch> prefBranch;
00213     rv = prefService->GetBranch(nsnull, getter_AddRefs(prefBranch));
00214     NS_ENSURE_SUCCESS(rv, rv);
00215 
00216     PRInt32 obscureValue = 0;
00217     (void) defaultPrefBranch->GetIntPref("general.config.obscure_value", &obscureValue);
00218     PR_LOG(MCD, PR_LOG_DEBUG, ("evaluating .cfg file %s with obscureValue %d\n", lockFileName.get(), obscureValue));
00219     rv = openAndEvaluateJSFile(lockFileName.get(), PR_TRUE, obscureValue, PR_TRUE);
00220     if (NS_FAILED(rv))
00221     {
00222       PR_LOG(MCD, PR_LOG_DEBUG, ("error evaluating .cfg file %s %x\n", lockFileName.get(), rv));
00223       return rv;
00224     }
00225     
00226     rv = prefBranch->GetCharPref("general.config.filename", 
00227                                   getter_Copies(lockFileName));
00228     if (NS_FAILED(rv))
00229         // There is NO REASON we should ever get here. This is POST reading 
00230         // of the config file.
00231         return NS_ERROR_FAILURE;
00232 
00233   
00234     rv = prefBranch->GetCharPref("general.config.vendor", 
00235                                   getter_Copies(lockVendor));
00236     // If vendor is not NULL, do this check
00237     if (NS_SUCCEEDED(rv)) {
00238 
00239         fileNameLen = PL_strlen(lockFileName);
00240     
00241         // lockVendor and lockFileName should be the same with the addtion of 
00242         // .cfg to the filename by checking this post reading of the cfg file 
00243         // this value can be set within the cfg file adding a level of security.
00244     
00245         if (PL_strncmp(lockFileName, lockVendor, fileNameLen - 4) != 0)
00246             return NS_ERROR_FAILURE;
00247     }
00248   
00249     // get the value of the autoconfig url
00250     nsXPIDLCString urlName;
00251     rv = prefBranch->GetCharPref("autoadmin.global_config_url",
00252                                   getter_Copies(urlName));
00253     if (NS_SUCCEEDED(rv) && !urlName.IsEmpty()) {
00254 
00255         // Instantiating nsAutoConfig object if the pref is present
00256         mAutoConfig = do_CreateInstance(NS_AUTOCONFIG_CONTRACTID, &rv);
00257         if (NS_FAILED(rv))
00258             return NS_ERROR_OUT_OF_MEMORY;
00259 
00260         rv = mAutoConfig->SetConfigURL(urlName);
00261         if (NS_FAILED(rv))
00262             return NS_ERROR_FAILURE;
00263 
00264     }
00265   
00266     return NS_OK;
00267 } // ReadConfigFile
00268 
00269 
00270 nsresult nsReadConfig::openAndEvaluateJSFile(const char *aFileName, PRBool isEncoded, 
00271                                              PRInt32 obscureValue,
00272                                              PRBool isBinDir)
00273 {
00274     nsresult rv;
00275     nsCOMPtr<nsIFile> jsFile;
00276 
00277     if (isBinDir) {
00278         rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, 
00279                                     getter_AddRefs(jsFile));
00280         if (NS_FAILED(rv)) 
00281             return rv;
00282         
00283 #ifdef XP_MAC
00284         jsFile->AppendNative(NS_LITERAL_CSTRING("Essential Files"));
00285 #endif
00286     } else {
00287         rv = NS_GetSpecialDirectory(NS_APP_DEFAULTS_50_DIR,
00288                                     getter_AddRefs(jsFile));
00289         if (NS_FAILED(rv)) 
00290             return rv;
00291         rv = jsFile->AppendNative(NS_LITERAL_CSTRING("autoconfig"));
00292         if (NS_FAILED(rv))
00293             return rv;
00294     }
00295     rv = jsFile->AppendNative(nsDependentCString(aFileName));
00296     if (NS_FAILED(rv)) 
00297         return rv;
00298 
00299     nsCOMPtr<nsIInputStream> inStr;
00300     rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), jsFile);
00301     if (NS_FAILED(rv)) 
00302         return rv;        
00303         
00304     PRInt64 fileSize;
00305     PRUint32 fs, amt = 0;
00306     jsFile->GetFileSize(&fileSize);
00307     LL_L2UI(fs, fileSize); // Converting 64 bit structure to unsigned int
00308 
00309     char *buf = (char *)PR_Malloc(fs * sizeof(char));
00310     if (!buf) 
00311         return NS_ERROR_OUT_OF_MEMORY;
00312       
00313     rv = inStr->Read(buf, fs, &amt);
00314     NS_ASSERTION((amt == fs), "failed to read the entire configuration file!!");
00315     if (NS_SUCCEEDED(rv)) {
00316         if (obscureValue > 0) {
00317 
00318             // Unobscure file by subtracting some value from every char. 
00319             for (PRUint32 i = 0; i < amt; i++)
00320                 buf[i] -= obscureValue;
00321         }
00322         nsCAutoString path;
00323 
00324         jsFile->GetNativePath(path);
00325         nsCAutoString fileURL;
00326         fileURL = NS_LITERAL_CSTRING("file:///") + path;
00327         rv = EvaluateAdminConfigScript(buf, amt, fileURL.get(), 
00328                                        PR_FALSE, PR_TRUE, 
00329                                        isEncoded ? PR_TRUE:PR_FALSE);
00330     }
00331     inStr->Close();
00332     PR_Free(buf);
00333     
00334     return rv;
00335 }