1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26 
27 #include "dp_misc.h"
28 #include "dp_resource.h"
29 #include "osl/module.hxx"
30 #include "osl/mutex.hxx"
31 #include "rtl/ustring.h"
32 #include "cppuhelper/implbase1.hxx"
33 #include "unotools/configmgr.hxx"
34 
35 
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::uno;
38 using ::rtl::OUString;
39 
40 namespace dp_misc {
41 namespace {
42 
43 struct OfficeLocale :
44         public rtl::StaticWithInit<const OUString, OfficeLocale> {
operator ()dp_misc::__anonf7ee8fef0111::OfficeLocale45     const OUString operator () () {
46         OUString slang;
47         if (! (::utl::ConfigManager::GetDirectConfigProperty(
48                    ::utl::ConfigManager::LOCALE ) >>= slang))
49             throw RuntimeException( OUSTR("Cannot determine language!"), 0 );
50         //fallback, the locale is currently only set when the user starts the
51         //office for the first time.
52         if (slang.getLength() == 0)
53             slang =  rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en-US"));
54         return slang;
55     }
56 };
57 
58 struct DeploymentResMgr : public rtl::StaticWithInit<
59     ResMgr *, DeploymentResMgr> {
operator ()dp_misc::__anonf7ee8fef0111::DeploymentResMgr60     ResMgr * operator () () {
61         return ResMgr::CreateResMgr( "deployment", getOfficeLocale() );
62     }
63 };
64 
65 osl::Mutex s_mutex;
66 
67 } // anon namespace
68 
69 //==============================================================================
getResId(sal_uInt16 id)70 ResId getResId( sal_uInt16 id )
71 {
72     const osl::MutexGuard guard( s_mutex );
73     return ResId( id, *DeploymentResMgr::get() );
74 }
75 
76 //==============================================================================
getResourceString(sal_uInt16 id)77 String getResourceString( sal_uInt16 id )
78 {
79     const osl::MutexGuard guard( s_mutex );
80     String ret( ResId( id, *DeploymentResMgr::get() ) );
81     if (ret.SearchAscii( "%PRODUCTNAME" ) != STRING_NOTFOUND) {
82         static String s_brandName;
83         if (s_brandName.Len() == 0) {
84             OUString brandName(
85                 ::utl::ConfigManager::GetDirectConfigProperty(
86                     ::utl::ConfigManager::PRODUCTNAME ).get<OUString>() );
87             s_brandName = brandName;
88         }
89         ret.SearchAndReplaceAllAscii( "%PRODUCTNAME", s_brandName );
90     }
91     return ret;
92 }
93 
94 //throws an Exception on failure
95 //primary subtag 2 or three letters(A-Z, a-z), i or x
checkPrimarySubtag(::rtl::OUString const & tag)96 void checkPrimarySubtag(::rtl::OUString const & tag)
97 {
98 	sal_Int32 len = tag.getLength();
99 	sal_Unicode const * arLang = tag.getStr();
100 	if (len < 1 || len > 3)
101 		throw Exception(OUSTR("Invalid language string."), 0);
102 
103 	if (len == 1
104 		&& (arLang[0] != 'i' && arLang[0] != 'x'))
105 		throw Exception(OUSTR("Invalid language string."), 0);
106 
107 	if (len == 2 || len == 3)
108 	{
109 		for (sal_Int32 i = 0; i < len; i++)
110 		{
111 			if ( !((arLang[i] >= 'A' && arLang[i] <= 'Z')
112 				|| (arLang[i] >= 'a' && arLang[i] <= 'z')))
113 			{
114 				throw Exception(OUSTR("Invalid language string."), 0);
115 			}
116 		}
117 	}
118 }
119 
120 //throws an Exception on failure
121 //second subtag 2 letter country code or 3-8 letter other code(A-Z, a-z, 0-9)
checkSecondSubtag(::rtl::OUString const & tag,bool & bIsCountry)122 void checkSecondSubtag(::rtl::OUString const & tag, bool & bIsCountry)
123 {
124 	sal_Int32 len = tag.getLength();
125 	sal_Unicode const * arLang = tag.getStr();
126 	if (len < 2 || len > 8)
127 		throw Exception(OUSTR("Invalid language string."), 0);
128 	//country code
129 	bIsCountry = false;
130 	if (len == 2)
131 	{
132 		for (sal_Int32 i = 0; i < 2; i++)
133 		{
134 			if (!( (arLang[i] >= 'A' && arLang[i] <= 'Z')
135 				|| (arLang[i] >= 'a' && arLang[i] <= 'z')))
136 			{
137 				throw Exception(OUSTR("Invalid language string."), 0);
138 			}
139 		}
140 		bIsCountry = true;
141 	}
142 
143 	if (len > 2)
144 	{
145 		for (sal_Int32 i = 0; i < len; i++)
146 		{
147 			if (!( (arLang[i] >= 'A' && arLang[i] <= 'Z')
148 				|| (arLang[i] >= 'a' && arLang[i] <= 'z')
149 				|| (arLang[i] >= '0' && arLang[i] <= '9') ))
150 			{
151 				throw Exception(OUSTR("Invalid language string."), 0);
152 			}
153 		}
154 	}
155 }
156 
checkThirdSubtag(::rtl::OUString const & tag)157 void checkThirdSubtag(::rtl::OUString const & tag)
158 {
159 	sal_Int32 len = tag.getLength();
160 	sal_Unicode const * arLang = tag.getStr();
161 	if (len < 1 || len > 8)
162 		throw Exception(OUSTR("Invalid language string."), 0);
163 
164 	for (sal_Int32 i = 0; i < len; i++)
165 	{
166 		if (!( (arLang[i] >= 'A' && arLang[i] <= 'Z')
167 			|| (arLang[i] >= 'a' && arLang[i] <= 'z')
168 			|| (arLang[i] >= '0' && arLang[i] <= '9') ))
169 		{
170 			throw Exception(OUSTR("Invalid language string."), 0);
171 		}
172 	}
173 }
174 
175 //=============================================================================
176 
177 //We parse the string acording to RFC 3066
178 //We only use the primary sub-tag and two subtags. That is lang-country-variant
179 //We do some simple tests if the string is correct. Actually this should do a
180 //validating parser
181 //We may have the case that there is no country tag, for example en-welsh
toLocale(::rtl::OUString const & slang)182 ::com::sun::star::lang::Locale toLocale( ::rtl::OUString const & slang )
183 {
184 	OUString _sLang = slang.trim();
185     ::com::sun::star::lang::Locale locale;
186     sal_Int32 nIndex = 0;
187 	OUString lang = _sLang.getToken( 0, '-', nIndex );
188 	checkPrimarySubtag(lang);
189 	locale.Language = lang;
190 	OUString country = _sLang.getToken( 0, '-', nIndex );
191 	if (country.getLength() > 0)
192 	{
193 		bool bIsCountry = false;
194 		checkSecondSubtag(country, bIsCountry);
195 		if (bIsCountry)
196 		{
197 			locale.Country = country;
198 		}
199 		else
200 		{
201 			 locale.Variant = country;
202 		}
203 	}
204     if (locale.Variant.getLength() == 0)
205 	{
206 		OUString variant = _sLang.getToken( 0, '-', nIndex );
207 		if (variant.getLength() > 0)
208 		{
209 			checkThirdSubtag(variant);
210 			locale.Variant = variant;
211 		}
212 	}
213 
214     return locale;
215 }
216 
217 //==============================================================================
getOfficeLocale()218 lang::Locale getOfficeLocale()
219 {
220     return toLocale(OfficeLocale::get());
221 }
222 
getOfficeLocaleString()223 ::rtl::OUString getOfficeLocaleString()
224 {
225     return OfficeLocale::get();
226 }
227 
228 }
229 
230