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