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