1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
15 * The Original Code is the string bundle override service.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corp.
19 * Portions created by the Initial Developer are Copyright (C) 2002
20 * the Initial Developer. All Rights Reserved.
23 * Alec Flett <alecf@netscape.com>
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.
37 * ***** END LICENSE BLOCK ***** */
40 #include "nsStringBundleTextOverride.h"
44 #include "nsNetUtil.h"
45 #include "nsAppDirectoryServiceDefs.h"
47 static NS_DEFINE_CID(kPersistentPropertiesCID
, NS_IPERSISTENTPROPERTIES_CID
);
50 // first we need a simple class which wraps a nsIPropertyElement and
51 // cuts out the leading URL from the key
52 class URLPropertyElement
: public nsIPropertyElement
55 URLPropertyElement(nsIPropertyElement
*aRealElement
, PRUint32 aURLLength
) :
56 mRealElement(aRealElement
),
57 mURLLength(aURLLength
)
59 virtual ~URLPropertyElement() {}
62 NS_DECL_NSIPROPERTYELEMENT
65 nsCOMPtr
<nsIPropertyElement
> mRealElement
;
69 NS_IMPL_ISUPPORTS1(URLPropertyElement
, nsIPropertyElement
)
71 // we'll tweak the key on the way through, and remove the url prefix
73 URLPropertyElement::GetKey(nsACString
& aKey
)
75 nsresult rv
= mRealElement
->GetKey(aKey
);
76 if (NS_FAILED(rv
)) return rv
;
79 aKey
.Cut(0, mURLLength
);
84 // values are unaffected
86 URLPropertyElement::GetValue(nsAString
& aValue
)
88 return mRealElement
->GetValue(aValue
);
91 // setters are kind of strange, hopefully we'll never be called
93 URLPropertyElement::SetKey(const nsACString
& aKey
)
95 // this is just wrong - ideally you'd take the key, append it to
96 // the url, and set that as the key. However, that would require
97 // us to hold onto a copy of the string, and that's a waste,
98 // considering nobody should ever be calling this.
99 NS_ASSERTION(0, "This makes no sense!");
100 return NS_ERROR_NOT_IMPLEMENTED
;
104 URLPropertyElement::SetValue(const nsAString
& aValue
)
106 return mRealElement
->SetValue(aValue
);
110 // this is a special enumerator which returns only the elements which
111 // are prefixed with a particular url
112 class nsPropertyEnumeratorByURL
: public nsISimpleEnumerator
115 nsPropertyEnumeratorByURL(const nsACString
& aURL
,
116 nsISimpleEnumerator
* aOuter
) :
120 // prepare the url once so we can use its value later
121 // persistent properties uses ":" as a delimiter, so escape
123 mURL
.ReplaceSubstring(":", "%3A");
124 // there is always a # between the url and the real key
129 NS_DECL_NSISIMPLEENUMERATOR
131 virtual ~nsPropertyEnumeratorByURL() {}
134 // actual enumerator of all strings from nsIProperties
135 nsCOMPtr
<nsISimpleEnumerator
> mOuter
;
137 // the current element that is valid for this url
138 nsCOMPtr
<nsIPropertyElement
> mCurrent
;
140 // the url in question, pre-escaped and with the # already in it
145 // nsStringBundleTextOverride implementation
147 NS_IMPL_ISUPPORTS1(nsStringBundleTextOverride
,
148 nsIStringBundleOverride
)
151 nsStringBundleTextOverride::Init()
155 // check for existence of custom-strings.txt
157 nsCOMPtr
<nsIFile
> customStringsFile
;
158 rv
= NS_GetSpecialDirectory(NS_APP_CHROME_DIR
,
159 getter_AddRefs(customStringsFile
));
161 if (NS_FAILED(rv
)) return rv
;
163 // bail if not found - this will cause the service creation to
164 // bail as well, and cause this object to go away
166 customStringsFile
->AppendNative(NS_LITERAL_CSTRING("custom-strings.txt"));
169 rv
= customStringsFile
->Exists(&exists
);
170 if (NS_FAILED(rv
) || !exists
)
171 return NS_ERROR_FAILURE
;
173 NS_WARNING("Using custom-strings.txt to override string bundles.");
174 // read in the custom bundle. Keys are in the form
175 // chrome://package/locale/foo.properties:keyname
177 nsCAutoString customStringsURLSpec
;
178 rv
= NS_GetURLSpecFromFile(customStringsFile
, customStringsURLSpec
);
179 if (NS_FAILED(rv
)) return rv
;
181 nsCOMPtr
<nsIURI
> uri
;
182 rv
= NS_NewURI(getter_AddRefs(uri
), customStringsURLSpec
);
183 if (NS_FAILED(rv
)) return rv
;
185 nsCOMPtr
<nsIInputStream
> in
;
186 rv
= NS_OpenURI(getter_AddRefs(in
), uri
);
187 if (NS_FAILED(rv
)) return rv
;
189 mValues
= do_CreateInstance(kPersistentPropertiesCID
, &rv
);
190 if (NS_FAILED(rv
)) return rv
;
192 rv
= mValues
->Load(in
);
194 // turn this on to see the contents of custom-strings.txt
196 nsCOMPtr
<nsISimpleEnumerator
> enumerator
;
197 mValues
->Enumerate(getter_AddRefs(enumerator
));
198 NS_ASSERTION(enumerator
, "no enumerator!\n");
200 printf("custom-strings.txt contains:\n");
201 printf("----------------------------\n");
204 enumerator
->HasMoreElements(&hasMore
);
206 nsCOMPtr
<nsISupports
> sup
;
207 enumerator
->GetNext(getter_AddRefs(sup
));
209 nsCOMPtr
<nsIPropertyElement
> prop
= do_QueryInterface(sup
);
214 prop
->GetValue(value
);
216 printf("%s = '%s'\n", key
.get(), NS_ConvertUTF16toUTF8(value
).get());
218 enumerator
->HasMoreElements(&hasMore
);
226 nsStringBundleTextOverride::GetStringFromName(const nsACString
& aURL
,
227 const nsACString
& key
,
230 // concatenate url#key to get the key to read
231 nsCAutoString
combinedURL(aURL
+ NS_LITERAL_CSTRING("#") + key
);
233 // persistent properties uses ":" as a delimiter, so escape that character
234 combinedURL
.ReplaceSubstring(":", "%3A");
236 return mValues
->GetStringProperty(combinedURL
, aResult
);
240 nsStringBundleTextOverride::EnumerateKeysInBundle(const nsACString
& aURL
,
241 nsISimpleEnumerator
** aResult
)
243 // enumerate all strings, and let the enumerator know
244 nsCOMPtr
<nsISimpleEnumerator
> enumerator
;
245 mValues
->Enumerate(getter_AddRefs(enumerator
));
247 // make the enumerator wrapper and pass it off
248 nsPropertyEnumeratorByURL
* propEnum
=
249 new nsPropertyEnumeratorByURL(aURL
, enumerator
);
251 if (!propEnum
) return NS_ERROR_OUT_OF_MEMORY
;
253 NS_ADDREF(*aResult
= propEnum
);
260 // nsPropertyEnumeratorByURL implementation
264 NS_IMPL_ISUPPORTS1(nsPropertyEnumeratorByURL
, nsISimpleEnumerator
)
267 nsPropertyEnumeratorByURL::GetNext(nsISupports
**aResult
)
269 if (!mCurrent
) return NS_ERROR_UNEXPECTED
;
271 // wrap mCurrent instead of returning it
272 *aResult
= new URLPropertyElement(mCurrent
, mURL
.Length());
275 // release it so we don't return it twice
282 nsPropertyEnumeratorByURL::HasMoreElements(PRBool
* aResult
)
285 mOuter
->HasMoreElements(&hasMore
);
288 nsCOMPtr
<nsISupports
> supports
;
289 mOuter
->GetNext(getter_AddRefs(supports
));
291 mCurrent
= do_QueryInterface(supports
);
294 nsCAutoString curKey
;
295 mCurrent
->GetKey(curKey
);
297 if (StringBeginsWith(curKey
, mURL
))
301 mOuter
->HasMoreElements(&hasMore
);
307 *aResult
= mCurrent
? PR_TRUE
: PR_FALSE
;