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_registry.hxx"
26
27 #include "registry/registry.hxx"
28 #include "registry/reflread.hxx"
29 #include "fileurl.hxx"
30 #include "options.hxx"
31
32 #include "rtl/ustring.hxx"
33 #include "osl/diagnose.h"
34
35 #include <stdio.h>
36 #include <string.h>
37
38 #include <vector>
39 #include <string>
40
41 using namespace rtl;
42 using namespace registry::tools;
43
44 #define U2S( s ) \
45 OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr()
46 #define S2U( s ) \
47 OStringToOUString(s, RTL_TEXTENCODING_UTF8)
48
49 class Options_Impl : public Options
50 {
51 public:
Options_Impl(char const * program)52 explicit Options_Impl(char const * program)
53 : Options (program), m_bForceOutput(false)
54 {}
55
getIndexReg() const56 std::string const & getIndexReg() const
57 { return m_indexRegName; }
getTypeReg() const58 std::string const & getTypeReg() const
59 { return m_typeRegName; }
hasBase() const60 bool hasBase() const
61 { return (m_base.getLength() > 0); }
getBase() const62 const OString & getBase() const
63 { return m_base; }
forceOutput() const64 bool forceOutput() const
65 { return m_bForceOutput; }
66
67 protected:
68 virtual void printUsage_Impl() const;
69 virtual bool initOptions_Impl (std::vector< std::string > & rArgs);
70
71 std::string m_indexRegName;
72 std::string m_typeRegName;
73 OString m_base;
74 bool m_bForceOutput;
75 };
76
77 // virtual
printUsage_Impl() const78 void Options_Impl::printUsage_Impl() const
79 {
80 std::string const & rProgName = getProgramName();
81 fprintf(stderr,
82 "Usage: %s -r<filename> -o<filename> [-options] | @<filename>\n", rProgName.c_str()
83 );
84 fprintf(stderr,
85 " -o<filename> = filename specifies the name of the new singleton index registry.\n"
86 " -r<filename> = filename specifies the name of the type registry.\n"
87 " @<filename> = filename specifies a command file.\n"
88 "Options:\n"
89 " -b<name> = name specifies the name of a start key. The types will be searched\n"
90 " under this key in the type registry.\n"
91 " -f = force the output of all found singletons.\n"
92 " -h|-? = print this help message and exit.\n"
93 );
94 fprintf(stderr,
95 "\n%s Version 1.0\n\n", rProgName.c_str()
96 );
97 }
98
99 // virtual
initOptions_Impl(std::vector<std::string> & rArgs)100 bool Options_Impl::initOptions_Impl(std::vector< std::string > & rArgs)
101 {
102 std::vector< std::string >::const_iterator first = rArgs.begin(), last = rArgs.end();
103 for (; first != last; ++first)
104 {
105 std::string option (*first);
106 if ((*first)[0] != '-')
107 {
108 return badOption("invalid", option.c_str());
109 }
110 switch ((*first)[1])
111 {
112 case 'r':
113 case 'R':
114 {
115 if (!((++first != last) && ((*first)[0] != '-')))
116 {
117 return badOption("invalid", option.c_str());
118 }
119 m_typeRegName = *first;
120 break;
121 }
122 case 'o':
123 case 'O':
124 {
125 if (!((++first != last) && ((*first)[0] != '-')))
126 {
127 return badOption("invalid", option.c_str());
128 }
129 m_indexRegName = (*first);
130 break;
131 }
132 case 'b':
133 case 'B':
134 {
135 if (!((++first != last) && ((*first)[0] != '-')))
136 {
137 return badOption("invalid", option.c_str());
138 }
139 m_base = OString((*first).c_str(), (*first).size());
140 break;
141 }
142 case 'f':
143 case 'F':
144 {
145 if ((*first).size() > 2)
146 {
147 return badOption("invalid", option.c_str());
148 }
149 m_bForceOutput = sal_True;
150 break;
151 }
152 case 'h':
153 case '?':
154 {
155 if ((*first).size() > 2)
156 {
157 return badOption("invalid", option.c_str());
158 }
159 return printUsage();
160 // break; // unreachable
161 }
162 default:
163 return badOption("unknown", option.c_str());
164 // break; // unreachable
165 }
166 }
167 return true;
168 }
169
checkSingletons(Options_Impl const & options,RegistryKey & singletonKey,RegistryKey & typeKey)170 static sal_Bool checkSingletons(Options_Impl const & options, RegistryKey& singletonKey, RegistryKey& typeKey)
171 {
172 RegValueType valueType = RG_VALUETYPE_NOT_DEFINED;
173 sal_uInt32 size = 0;
174 OUString tmpName;
175 sal_Bool bRet = sal_False;
176
177 RegError e = typeKey.getValueInfo(tmpName, &valueType, &size);
178 if ((e != REG_VALUE_NOT_EXISTS) && (e != REG_INVALID_VALUE) && (valueType == RG_VALUETYPE_BINARY))
179 {
180 std::vector< sal_uInt8 > value(size);
181 typeKey.getValue(tmpName, &value[0]); // @@@ broken api: write to buffer w/o buffer size.
182
183 RegistryTypeReader reader(&value[0], value.size(), sal_False);
184 if ( reader.isValid() && reader.getTypeClass() == RT_TYPE_SINGLETON )
185 {
186 RegistryKey entryKey;
187 OUString singletonName = reader.getTypeName().replace('/', '.');
188 if ( singletonKey.createKey(singletonName, entryKey) )
189 {
190 fprintf(stderr, "%s: could not create SINGLETONS entry for \"%s\"\n",
191 options.getProgramName().c_str(), U2S( singletonName ));
192 }
193 else
194 {
195 bRet = sal_True;
196 OUString value2 = reader.getSuperTypeName();
197
198 if ( entryKey.setValue(tmpName, RG_VALUETYPE_UNICODE,
199 (RegValue)value2.getStr(), sizeof(sal_Unicode)* (value2.getLength()+1)) )
200 {
201 fprintf(stderr, "%s: could not create data entry for singleton \"%s\"\n",
202 options.getProgramName().c_str(), U2S( singletonName ));
203 }
204
205 if ( options.forceOutput() )
206 {
207 fprintf(stderr, "%s: create SINGLETON entry for \"%s\" -> \"%s\"\n",
208 options.getProgramName().c_str(), U2S( singletonName ), U2S(value2));
209 }
210 }
211 }
212 }
213
214 RegistryKeyArray subKeys;
215 typeKey.openSubKeys(tmpName, subKeys);
216
217 sal_uInt32 length = subKeys.getLength();
218 for (sal_uInt32 i = 0; i < length; i++)
219 {
220 RegistryKey elementKey = subKeys.getElement(i);
221 if ( checkSingletons(options, singletonKey, elementKey) )
222 {
223 bRet = sal_True;
224 }
225 }
226 return bRet;
227 }
228
229 #if (defined UNX) || (defined OS2) || (defined __MINGW32__)
main(int argc,char * argv[])230 int main( int argc, char * argv[] )
231 #else
232 int _cdecl main( int argc, char * argv[] )
233 #endif
234 {
235 std::vector< std::string > args;
236 for (int i = 1; i < argc; i++)
237 {
238 int result = Options::checkArgument(args, argv[i], strlen(argv[i]));
239 if (result != 0)
240 {
241 // failure.
242 return (result);
243 }
244 }
245
246 Options_Impl options(argv[0]);
247 if (!options.initOptions(args))
248 {
249 options.printUsage();
250 return (1);
251 }
252
253 OUString indexRegName( convertToFileUrl(options.getIndexReg().c_str(), options.getIndexReg().size()) );
254 Registry indexReg;
255 if ( indexReg.open(indexRegName, REG_READWRITE) )
256 {
257 if ( indexReg.create(indexRegName) )
258 {
259 fprintf(stderr, "%s: open registry \"%s\" failed\n",
260 options.getProgramName().c_str(), options.getIndexReg().c_str());
261 return (2);
262 }
263 }
264
265 OUString typeRegName( convertToFileUrl(options.getTypeReg().c_str(), options.getTypeReg().size()) );
266 Registry typeReg;
267 if ( typeReg.open(typeRegName, REG_READONLY) )
268 {
269 fprintf(stderr, "%s: open registry \"%s\" failed\n",
270 options.getProgramName().c_str(), options.getTypeReg().c_str());
271 return (3);
272 }
273
274 RegistryKey indexRoot;
275 if ( indexReg.openRootKey(indexRoot) )
276 {
277 fprintf(stderr, "%s: open root key of registry \"%s\" failed\n",
278 options.getProgramName().c_str(), options.getIndexReg().c_str());
279 return (4);
280 }
281
282 RegistryKey typeRoot;
283 if ( typeReg.openRootKey(typeRoot) )
284 {
285 fprintf(stderr, "%s: open root key of registry \"%s\" failed\n",
286 options.getProgramName().c_str(), options.getTypeReg().c_str());
287 return (5);
288 }
289
290 RegistryKey typeKey;
291 if ( options.hasBase() )
292 {
293 if ( typeRoot.openKey(S2U(options.getBase()), typeKey) )
294 {
295 fprintf(stderr, "%s: open base key of registry \"%s\" failed\n",
296 options.getProgramName().c_str(), options.getTypeReg().c_str());
297 return (6);
298 }
299 }
300 else
301 {
302 typeKey = typeRoot;
303 }
304
305 RegistryKey singletonKey;
306 if ( indexRoot.createKey(OUString::createFromAscii("SINGLETONS"), singletonKey) )
307 {
308 fprintf(stderr, "%s: open/create SINGLETONS key of registry \"%s\" failed\n",
309 options.getProgramName().c_str(), options.getIndexReg().c_str());
310 return (7);
311 }
312
313 sal_Bool bSingletonsExist = checkSingletons(options, singletonKey, typeKey);
314
315 indexRoot.releaseKey();
316 typeRoot.releaseKey();
317 typeKey.releaseKey();
318 singletonKey.releaseKey();
319 if ( indexReg.close() )
320 {
321 fprintf(stderr, "%s: closing registry \"%s\" failed\n",
322 options.getProgramName().c_str(), options.getIndexReg().c_str());
323 return (9);
324 }
325 if ( !bSingletonsExist )
326 {
327 if ( indexReg.destroy(OUString()) )
328 {
329 fprintf(stderr, "%s: destroy registry \"%s\" failed\n",
330 options.getProgramName().c_str(), options.getIndexReg().c_str());
331 return (10);
332 }
333 }
334 if ( typeReg.close() )
335 {
336 fprintf(stderr, "%s: closing registry \"%s\" failed\n",
337 options.getProgramName().c_str(), options.getTypeReg().c_str());
338 return (11);
339 }
340 }
341