Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifdef MOZ_LOGGING
7 // sorry, this has to be before the pre-compiled header
8 #define FORCE_PR_LOG /* Allow logging in the release build */
9 #endif
10 #include "nsReadConfig.h"
11 #include "nsAppDirectoryServiceDefs.h"
12 #include "nsIAppStartup.h"
13 #include "nsDirectoryServiceDefs.h"
14 #include "nsIAutoConfig.h"
15 #include "nsIComponentManager.h"
16 #include "nsIFile.h"
17 #include "nsIObserverService.h"
18 #include "nsIPrefBranch.h"
19 #include "nsIPrefService.h"
20 #include "nsIPromptService.h"
21 #include "nsIServiceManager.h"
22 #include "nsIStringBundle.h"
23 #include "nsToolkitCompsCID.h"
24 #include "nsXPIDLString.h"
25 #include "nsNetUtil.h"
26 #include "prmem.h"
27 #include "nsString.h"
28 #include "nsCRT.h"
29 #include "nspr.h"
30 #include "nsXULAppAPI.h"
32 extern PRLogModuleInfo *MCD;
34 extern nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
35 const char *filename,
36 bool bGlobalContext,
37 bool bCallbacks,
38 bool skipFirstLine);
39 extern nsresult CentralizedAdminPrefManagerInit();
40 extern nsresult CentralizedAdminPrefManagerFinish();
43 static void DisplayError(void)
44 {
45 nsresult rv;
47 nsCOMPtr<nsIPromptService> promptService = do_GetService("@mozilla.org/embedcomp/prompt-service;1");
48 if (!promptService)
49 return;
51 nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
52 if (!bundleService)
53 return;
55 nsCOMPtr<nsIStringBundle> bundle;
56 bundleService->CreateBundle("chrome://autoconfig/locale/autoconfig.properties",
57 getter_AddRefs(bundle));
58 if (!bundle)
59 return;
61 nsXPIDLString title;
62 rv = bundle->GetStringFromName(MOZ_UTF16("readConfigTitle"), getter_Copies(title));
63 if (NS_FAILED(rv))
64 return;
66 nsXPIDLString err;
67 rv = bundle->GetStringFromName(MOZ_UTF16("readConfigMsg"), getter_Copies(err));
68 if (NS_FAILED(rv))
69 return;
71 promptService->Alert(nullptr, title.get(), err.get());
72 }
74 // nsISupports Implementation
76 NS_IMPL_ISUPPORTS(nsReadConfig, nsIReadConfig, nsIObserver)
78 nsReadConfig::nsReadConfig() :
79 mRead(false)
80 {
81 if (!MCD)
82 MCD = PR_NewLogModule("MCD");
83 }
85 nsresult nsReadConfig::Init()
86 {
87 nsresult rv;
89 nsCOMPtr<nsIObserverService> observerService =
90 do_GetService("@mozilla.org/observer-service;1", &rv);
92 if (observerService) {
93 rv = observerService->AddObserver(this, NS_PREFSERVICE_READ_TOPIC_ID, false);
94 }
95 return(rv);
96 }
98 nsReadConfig::~nsReadConfig()
99 {
100 CentralizedAdminPrefManagerFinish();
101 }
103 NS_IMETHODIMP nsReadConfig::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
104 {
105 nsresult rv = NS_OK;
107 if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
108 rv = readConfigFile();
109 if (NS_FAILED(rv)) {
110 DisplayError();
112 nsCOMPtr<nsIAppStartup> appStartup =
113 do_GetService(NS_APPSTARTUP_CONTRACTID);
114 if (appStartup)
115 appStartup->Quit(nsIAppStartup::eAttemptQuit);
116 }
117 }
118 return rv;
119 }
122 nsresult nsReadConfig::readConfigFile()
123 {
124 nsresult rv = NS_OK;
125 nsXPIDLCString lockFileName;
126 nsXPIDLCString lockVendor;
127 uint32_t fileNameLen = 0;
129 nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
130 nsCOMPtr<nsIPrefService> prefService =
131 do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
132 if (NS_FAILED(rv))
133 return rv;
135 rv = prefService->GetDefaultBranch(nullptr, getter_AddRefs(defaultPrefBranch));
136 if (NS_FAILED(rv))
137 return rv;
139 // This preference is set in the all.js or all-ns.js (depending whether
140 // running mozilla or netscp6)
142 rv = defaultPrefBranch->GetCharPref("general.config.filename",
143 getter_Copies(lockFileName));
146 PR_LOG(MCD, PR_LOG_DEBUG, ("general.config.filename = %s\n", lockFileName.get()));
147 if (NS_FAILED(rv))
148 return rv;
150 // This needs to be read only once.
151 //
152 if (!mRead) {
153 // Initiate the new JS Context for Preference management
155 rv = CentralizedAdminPrefManagerInit();
156 if (NS_FAILED(rv))
157 return rv;
159 // Open and evaluate function calls to set/lock/unlock prefs
160 rv = openAndEvaluateJSFile("prefcalls.js", 0, false, false);
161 if (NS_FAILED(rv))
162 return rv;
164 // Evaluate platform specific directives
165 rv = openAndEvaluateJSFile("platform.js", 0, false, false);
166 if (NS_FAILED(rv))
167 return rv;
169 mRead = true;
170 }
171 // If the lockFileName is nullptr return ok, because no lockFile will be used
174 // Once the config file is read, we should check that the vendor name
175 // is consistent By checking for the vendor name after reading the config
176 // file we allow for the preference to be set (and locked) by the creator
177 // of the cfg file meaning the file can not be renamed (successfully).
179 nsCOMPtr<nsIPrefBranch> prefBranch;
180 rv = prefService->GetBranch(nullptr, getter_AddRefs(prefBranch));
181 NS_ENSURE_SUCCESS(rv, rv);
183 int32_t obscureValue = 0;
184 (void) defaultPrefBranch->GetIntPref("general.config.obscure_value", &obscureValue);
185 PR_LOG(MCD, PR_LOG_DEBUG, ("evaluating .cfg file %s with obscureValue %d\n", lockFileName.get(), obscureValue));
186 rv = openAndEvaluateJSFile(lockFileName.get(), obscureValue, true, true);
187 if (NS_FAILED(rv))
188 {
189 PR_LOG(MCD, PR_LOG_DEBUG, ("error evaluating .cfg file %s %x\n", lockFileName.get(), rv));
190 return rv;
191 }
193 rv = prefBranch->GetCharPref("general.config.filename",
194 getter_Copies(lockFileName));
195 if (NS_FAILED(rv))
196 // There is NO REASON we should ever get here. This is POST reading
197 // of the config file.
198 return NS_ERROR_FAILURE;
201 rv = prefBranch->GetCharPref("general.config.vendor",
202 getter_Copies(lockVendor));
203 // If vendor is not nullptr, do this check
204 if (NS_SUCCEEDED(rv)) {
206 fileNameLen = strlen(lockFileName);
208 // lockVendor and lockFileName should be the same with the addtion of
209 // .cfg to the filename by checking this post reading of the cfg file
210 // this value can be set within the cfg file adding a level of security.
212 if (PL_strncmp(lockFileName, lockVendor, fileNameLen - 4) != 0)
213 return NS_ERROR_FAILURE;
214 }
216 // get the value of the autoconfig url
217 nsXPIDLCString urlName;
218 rv = prefBranch->GetCharPref("autoadmin.global_config_url",
219 getter_Copies(urlName));
220 if (NS_SUCCEEDED(rv) && !urlName.IsEmpty()) {
222 // Instantiating nsAutoConfig object if the pref is present
223 mAutoConfig = do_CreateInstance(NS_AUTOCONFIG_CONTRACTID, &rv);
224 if (NS_FAILED(rv))
225 return NS_ERROR_OUT_OF_MEMORY;
227 rv = mAutoConfig->SetConfigURL(urlName);
228 if (NS_FAILED(rv))
229 return NS_ERROR_FAILURE;
231 }
233 return NS_OK;
234 } // ReadConfigFile
237 nsresult nsReadConfig::openAndEvaluateJSFile(const char *aFileName, int32_t obscureValue,
238 bool isEncoded,
239 bool isBinDir)
240 {
241 nsresult rv;
243 nsCOMPtr<nsIInputStream> inStr;
244 if (isBinDir) {
245 nsCOMPtr<nsIFile> jsFile;
246 rv = NS_GetSpecialDirectory(XRE_EXECUTABLE_FILE,
247 getter_AddRefs(jsFile));
248 if (NS_FAILED(rv))
249 return rv;
251 rv = jsFile->SetNativeLeafName(nsDependentCString(aFileName));
252 if (NS_FAILED(rv))
253 return rv;
255 rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), jsFile);
256 if (NS_FAILED(rv))
257 return rv;
259 } else {
260 nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
261 if (NS_FAILED(rv))
262 return rv;
264 nsAutoCString location("resource://gre/defaults/autoconfig/");
265 location += aFileName;
267 nsCOMPtr<nsIURI> uri;
268 rv = ioService->NewURI(location, nullptr, nullptr, getter_AddRefs(uri));
269 if (NS_FAILED(rv))
270 return rv;
272 nsCOMPtr<nsIChannel> channel;
273 rv = ioService->NewChannelFromURI(uri, getter_AddRefs(channel));
274 if (NS_FAILED(rv))
275 return rv;
277 rv = channel->Open(getter_AddRefs(inStr));
278 if (NS_FAILED(rv))
279 return rv;
280 }
282 uint64_t fs64;
283 uint32_t amt = 0;
284 rv = inStr->Available(&fs64);
285 if (NS_FAILED(rv))
286 return rv;
287 // PR_Malloc dones't support over 4GB
288 if (fs64 > UINT32_MAX)
289 return NS_ERROR_FILE_TOO_BIG;
290 uint32_t fs = (uint32_t)fs64;
292 char *buf = (char *)PR_Malloc(fs * sizeof(char));
293 if (!buf)
294 return NS_ERROR_OUT_OF_MEMORY;
296 rv = inStr->Read(buf, (uint32_t)fs, &amt);
297 NS_ASSERTION((amt == fs), "failed to read the entire configuration file!!");
298 if (NS_SUCCEEDED(rv)) {
299 if (obscureValue > 0) {
301 // Unobscure file by subtracting some value from every char.
302 for (uint32_t i = 0; i < amt; i++)
303 buf[i] -= obscureValue;
304 }
305 rv = EvaluateAdminConfigScript(buf, amt, aFileName,
306 false, true,
307 isEncoded ? true:false);
308 }
309 inStr->Close();
310 PR_Free(buf);
312 return rv;
313 }