1#Licensed to the Apache Software Foundation (ASF) under one 2#or more contributor license agreements. See the NOTICE file 3#distributed with this work for additional information 4#regarding copyright ownership. The ASF licenses this file 5#to you under the Apache License, Version 2.0 (the 6#"License"); you may not use this file except in compliance 7#with the License. You may obtain a copy of the License at 8 9# http://www.apache.org/licenses/LICENSE-2.0 10 11#Unless required by applicable law or agreed to in writing, software 12#distributed under the License is distributed on an "AS IS" BASIS, 13#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14#See the License for the specific language governing permissions and 15#limitations under the License. 16# $Id:types.py 6172 2007-05-22 20:26:54Z zim $ 17# 18#------------------------------------------------------------------------------ 19 20""" Higher level data types and type related classes. 21 22 Supported Types (Verification and Display): 23 24 address - validates ip:port and host:port tcp addresses 25 ip_address - validates and IP address 26 net_address - validates an IP like address, ie netmask 27 hostname - validates a hostname with DNS 28 eaddress - validates a single email address or a comma 29 seperated list of email addresses 30 http_version - validates a value is a http version (1.0/1.1) 31 tcp_port - validates a value to be a valid tcp port (2-65535) 32 bool - validates value is (0, 1, true, false) / converts 33 true -> 1 and false -> 0 34 directory - validates a values is a directory / resolves path to 35 absolute path 36 file - validates a value is a file / resolves path to absolute 37 path 38 float - validates a value is a float, converts string to float 39 pos_float - validates a value is a float and >= 0, converts string 40 to float 41 pos_num - same as pos_float 42 neg_float - validates a value is a float and < 0, converts string to 43 float 44 int - validates a value is an integer, converts string to 45 integer 46 pos_int - validates a value is an integer and >= 0, converts 47 string to integer 48 neg_int - validates a values is an integer and < 0, converts 49 striing to integer 50 freq - frequency, positive integer 51 size - validates a size in bytes, kb, mb, kb, and tb 52 (int > 0 post fixed with K, M, G, or T) also converts 53 value to integer bytes 54 range - numeric range, x-y normalized to a tuple, if a single 55 number is supplie a single element tuple is returned 56 timestamp - utc timestamp of the form YYYYMMDDHHMMSS 57 user_account - UNIX user account name 58 user_group - UNIX group name 59 string - arbitrarily long string 60 list - comma seperated list of strings of arbitrary length, 61 keyval - comma seperated list of key=value pairs, key does not 62 need to be unique. 63 uri - a uri """ 64 65import sys, os, socket, pwd, grp, stat, re, re, string, pprint, urlparse 66 67from tcp import tcpSocket, check_net_address, check_ip_address 68from util import check_timestamp 69 70types = { 'directory' : { 'db' : 'string', 71 'units' : None }, 72 73 'address' : { 'db' : 'string', 74 'units' : None }, 75 76 'ip_address' : { 'db' : 'string', 77 'units' : None }, 78 79 'net_address' : { 'db' : 'string', 80 'units' : None }, 81 82 'bool' : { 'db' : 'bool', 83 'units' : None }, 84 85 'int' : { 'db' : 'integer', 86 'units' : None }, 87 88 'float' : { 'db' : 'float', 89 'units' : None }, 90 91 'pos_int' : { 'db' : 'integer', 92 'units' : None }, 93 94 'neg_int' : { 'db' : 'integer', 95 'units' : None }, 96 97 'pos_num' : { 'db' : 'float', 98 'units' : None }, 99 100 'pos_float' : { 'db' : 'float', 101 'units' : None }, 102 103 'neg_float' : { 'db' : 'float', 104 'units' : None }, 105 106 'string' : { 'db' : 'string', 107 'units' : None }, 108 109 'list' : { 'db' : 'string', 110 'units' : None }, 111 112 'file' : { 'db' : 'string', 113 'units' : None }, 114 115 'size' : { 'db' : 'integer', 116 'units' : 'bytes' }, 117 118 'freq' : { 'db' : 'integer', 119 'units' : 'hz' }, 120 121 'eaddress' : { 'db' : 'string', 122 'units' : None }, 123 124 'tcp_port' : { 'db' : 'integer', 125 'units' : None }, 126 127 'http_version' : { 'db' : 'float', 128 'units' : None }, 129 130 'range' : { 'db' : 'string', 131 'units' : None }, 132 133 'hostname' : { 'db' : 'string', 134 'units' : None }, 135 136 'user_account' : { 'db' : 'string', 137 'units' : None }, 138 139 'user_group' : { 'db' : 'string', 140 'units' : None }, 141 142 'timestamp' : { 'db' : 'timestamp', 143 'units' : None }, 144 145 'keyval' : { 'db' : 'string', 146 'units' : None }, 147 148 'uri' : { 'db' : 'string', 149 'units' : None }, 150 151 '' : { 'db' : 'string', 152 'units' : None }} 153 154dbTypes = { 'string' : { 'type' : 'varchar', 155 'store' : 'type_strings_0', 156 'table' : True }, 157 158 'integer' : { 'type' : 'bigint', 159 'store' : 'integers', 160 'table' : False }, 161 162 'float' : { 'type' : 'real', 163 'store' : 'floats', 164 'table' : False }, 165 166 'bool' : { 'type' : 'boolean', 167 'store' : 'bools', 168 'table' : False }, 169 170 'timestamp' : { 'type' : 'timestamp(0)', 171 'store' : 'timestamps', 172 'table' : False }} 173 174reSizeFormat = re.compile("^(\d+)(k|m|g|t|p|kb|mb|gb|tb|pb)$", flags=2) 175reDash = re.compile("\s*-\s*") 176 177sizeFactors = { 'b' : 1, 178 'bytes' : 1, 179 'k' : 1024, 180 'kb' : 1024, 181 'm' : 1048576, 182 'mb' : 1048576, 183 'g' : 1073741824, 184 'gb' : 1073741824, 185 't' : 1099511627776, 186 'tb' : 1099511627776, 187 'p' : 1125899906842624, 188 'pb' : 1125899906842624 } 189 190freqFactors = { 'hz' : 1, 191 'khz' : 1000, 192 'mhz' : 1000000, 193 'ghz' : 1000000000, 194 'thz' : 1000000000000, 195 'phz' : 1000000000000000 } 196 197sizeMap = [ { 'factor' : sizeFactors['b'], 198 'long' : 'byte', 199 'short' : 'byte' }, 200 201 { 'factor' : sizeFactors['k'], 202 'long' : 'Kilobyte', 203 'short' : 'KB' }, 204 205 { 'factor' : sizeFactors['m'], 206 'long' : 'Megabyte', 207 'short' : 'MB' }, 208 209 { 'factor' : sizeFactors['g'], 210 'long' : 'Gigabyte', 211 'short' : 'GB' }, 212 213 { 'factor' : sizeFactors['t'], 214 'long' : 'Terabyte', 215 'short' : 'TB' }, 216 217 { 'factor' : sizeFactors['p'], 218 'long' : 'Petabyte', 219 'short' : 'PB' } ] 220 221freqMap = [ { 'factor' : freqFactors['hz'], 222 'long' : 'Hertz', 223 'short' : 'Hz' }, 224 225 { 'factor' : freqFactors['khz'], 226 'long' : 'Kilohertz', 227 'short' : 'KHz' }, 228 229 { 'factor' : freqFactors['mhz'], 230 'long' : 'Megahertz', 231 'short' : 'MHz' }, 232 233 { 'factor' : freqFactors['ghz'], 234 'long' : 'Gigahertz', 235 'short' : 'GHz' }, 236 237 { 'factor' : freqFactors['thz'], 238 'long' : 'Terahertz', 239 'short' : 'THz' }, 240 241 { 'factor' : freqFactors['phz'], 242 'long' : 'Petahertz', 243 'short' : 'PHz' } ] 244 245reListString = r"(?<!\\)," 246reList = re.compile(reListString) 247 248reKeyVal = r"(?<!\\)=" 249reKeyVal = re.compile(reKeyVal) 250 251class typeToString: 252 """Provides method for converting normalized types to strings.""" 253 def __init__(self): 254 self.toStringFunctions = {} 255 self.__build_to_string_functions() 256 257 def __call__(self, type, value): 258 return self.toStringFunctions[type](value) 259 260 def __build_to_string_functions(self): 261 functions = {} 262 for function in dir(self): 263 functions[function] = 1 264 265 for type in types.keys(): 266 # kinda bad, need to find out how to know the name of the class 267 # I'm in. But it works. 268 functionName = "_typeToString__tostring_%s" % type 269 if functions.has_key(functionName): 270 self.toStringFunctions[type] = getattr(self, functionName) 271 else: 272 if type == '': 273 self.toStringFunctions[type] = self.__tostring_nothing 274 else: 275 error = "To string function %s for type %s does not exist." \ 276 % (functionName, type) 277 raise Exception(error) 278 sys.exit(1) 279 280 def __tostring(self, value): 281 return str(value) 282 283 def __tostring_directory(self, value): 284 return self.__tostring(value) 285 286 def __tostring_address(self, value): 287 return "%s:%s" % (value[0], value[1]) 288 289 def __tostring_ip_address(self, value): 290 return self.__tostring(value) 291 292 def __tostring_net_address(self, value): 293 return self.__tostring(value) 294 295 def __tostring_bool(self, value): 296 if value == False: 297 return 'false' 298 elif value == True: 299 return 'true' 300 else: 301 return str(value) 302 303 def __tostring_int(self, value): 304 return self.__tostring(value) 305 306 def __tostring_float(self, value): 307 return self.__tostring(value) 308 309 def __tostring_pos_int(self, value): 310 return self.__tostring(value) 311 312 def __tostring_neg_int(self, value): 313 return self.__tostring(value) 314 315 def __tostring_freq(self, value): 316 return self.__tostring(value) 317 318 def __tostring_pos_float(self, value): 319 return self.__tostring(value) 320 321 def __tostring_pos_num(self, value): 322 return self.__tostring(value) 323 324 def __tostring_neg_float(self, value): 325 return self.__tostring(value) 326 327 def __tostring_string(self, value): 328 return value 329 330 def __tostring_keyval(self, value): 331 string = '"' # to protect from shell escapes 332 for key in value: 333 # for item in value[key]: 334 # string = "%s%s=%s," % (string, key, item) 335 # Quotes still cannot protect Double-slashes. 336 # Dealing with them separately 337 val = re.sub(r"\\\\",r"\\\\\\\\",value[key]) 338 339 string = "%s%s=%s," % (string, key, val) 340 341 return string[:-1] + '"' 342 343 def __tostring_list(self, value): 344 string = '' 345 for item in value: 346 string = "%s%s," % (string, item) 347 348 return string[:-1] 349 350 def __tostring_file(self, value): 351 return self.__tostring(value) 352 353 def __tostring_size(self, value): 354 return self.__tostring(value) 355 356 def __tostring_eaddress(self, value): 357 return self.__tostring(value) 358 359 def __tostring_tcp_port(self, value): 360 return self.__tostring(value) 361 362 def __tostring_http_version(self, value): 363 return self.__tostring(value) 364 365 def __tostring_range(self, value): 366 if len(value) < 2: 367 return value[0] 368 else: 369 return "%s-%s" % (value[0], value[1]) 370 371 def __tostring_timestamp(self, value): 372 return self.__tostring(value) 373 374 def __tostring_hostname(self, value): 375 return self.__tostring(value) 376 377 def __tostring_user_account(self, value): 378 return self.__tostring(value) 379 380 def __tostring_user_group(self, value): 381 return self.__tostring(value) 382 383 def __tostring_uri(self, value): 384 return self.__tostring(value) 385 386 def __tostring_nothing(self, value): 387 return value 388 389class typeValidator: 390 """Type validation class used to normalize values or validated 391 single/large sets of values by type.""" 392 393 def __init__(self, originalDir=None): 394 self.verifyFunctions = {} 395 self.__build_verify_functions() 396 397 self.validateList = [] 398 self.validatedInfo = [] 399 self.__originalDir = originalDir 400 401 def __getattr__(self, attrname): 402 """validateList = [ { 'func' : <bound method configValidator>, 403 'name' : 'SA_COMMON.old_xml_dir', 404 'value': 'var/data/old' }, 405 406 { 'func' : <bound method configValidator>, 407 'name' : 'SA_COMMON.log_level', 408 'value': '4' } ] 409 410 validatedInfo = [ { # name supplied to add() 411 'name' : 'SA_COMMON.tmp_xml_dir', 412 413 # is valid or not 414 'isValid' : 1 415 416 # normalized value 417 'normalized' : /var/data/tmp, 418 419 # error string ? 420 'errorData' : 0 }, 421 422 { 'name' : 'SA_COMMON.new_xml_dir', 423 'isValid' : 1 424 'normalized' : /var/data/new, 425 'errorData' : 0 } ]""" 426 427 if attrname == "validateList": 428 return self.validateList # list of items to be validated 429 elif attrname == "validatedInfo": 430 return self.validatedInfo # list of validation results 431 else: raise AttributeError, attrname 432 433 def __build_verify_functions(self): 434 functions = {} 435 for function in dir(self): 436 functions[function] = 1 437 438 for type in types.keys(): 439 # kinda bad, need to find out how to know the name of the class 440 # I'm in. But it works. 441 functionName = "_typeValidator__verify_%s" % type 442 if functions.has_key(functionName): 443 self.verifyFunctions[type] = getattr(self, functionName) 444 else: 445 if type == '': 446 self.verifyFunctions[type] = self.__verify_nothing 447 else: 448 error = "Verify function %s for type %s does not exist." \ 449 % (functionName, type) 450 raise Exception(error) 451 sys.exit(1) 452 453 def __get_value_info(self): 454 valueInfo = { 'isValid' : 0, 'normalized' : 0, 'errorData' : 0 } 455 456 return valueInfo 457 458 def __set_value_info(self, valueInfo, **valueData): 459 try: 460 valueInfo['normalized'] = valueData['normalized'] 461 valueInfo['isValid'] = 1 462 except KeyError: 463 valueInfo['isValid'] = 0 464 try: 465 valueInfo['errorData'] = valueData['errorData'] 466 except: 467 pass 468 469 # start of 'private' verification methods, each one should correspond to a 470 # type string (see self.verify_config()) 471 def __verify_directory(self, type, value): 472 valueInfo = self.__get_value_info() 473 474 if os.path.isdir(value): 475 self.__set_value_info(valueInfo, normalized=self.normalize(type, 476 value)) 477 else: 478 self.__set_value_info(valueInfo) 479 480 return valueInfo 481 482 def __norm_directory(self, value): 483 return self.__normalizedPath(value) 484 485 def __verify_address(self, type, value): 486 valueInfo = self.__get_value_info() 487 488 try: 489 socket = tcpSocket(value) 490 if socket.verify(): 491 self.__set_value_info(valueInfo, normalized=self.normalize(type, 492 value)) 493 else: 494 self.__set_value_info(valueInfo) 495 except: 496 self.__set_value_info(valueInfo) 497 498 return valueInfo 499 500 def __norm_address(self, value): 501 return value.split(':') 502 503 def __verify_ip_address(self, type, value): 504 valueInfo = self.__get_value_info() 505 506 if check_ip_address(value): 507 self.__set_value_info(valueInfo, normalized=self.normalize(type, 508 value)) 509 else: 510 self.__set_value_info(valueInfo) 511 512 return valueInfo 513 514 def __verify_net_address(self, type, value): 515 valueInfo = self.__get_value_info() 516 517 if check_net_address(value): 518 self.__set_value_info(valueInfo, normalized=self.normalize(type, 519 value)) 520 else: 521 self.__set_value_info(valueInfo) 522 523 return valueInfo 524 525 def __verify_bool(self, type, value): 526 valueInfo = self.__get_value_info() 527 528 value = str(value) 529 if re.match("^false|0|f|no$", value, 2): 530 self.__set_value_info(valueInfo, normalized=False) 531 elif re.match("^true|1|t|yes$", value, 2): 532 self.__set_value_info(valueInfo, normalized=True) 533 else: 534 self.__set_value_info(valueInfo) 535 536 return valueInfo 537 538 def __norm_bool(self, value): 539 value = str(value) 540 norm = "" 541 if re.match("^false|0|f|no$", value, 2): 542 norm = False 543 elif re.match("^true|1|t|yes$", value, 2): 544 norm = True 545 else: 546 raise Exception("invalid bool specified: %s" % value) 547 548 return norm 549 550 def __verify_int(self, type, value): 551 valueInfo = self.__get_value_info() 552 553 try: 554 self.__set_value_info(valueInfo, normalized=self.normalize(type, 555 value)) 556 except: 557 self.__set_value_info(valueInfo) 558 559 return valueInfo 560 561 def __norm_int(self, value): 562 return int(value) 563 564 def __verify_float(self, type, value): 565 valueInfo = self.__get_value_info() 566 567 try: 568 self.__set_value_info(valueInfo, normalized=self.normalize(type, 569 value)) 570 except: 571 self.__set_value_info(valueInfo) 572 573 return valueInfo 574 575 def __norm_float(self, value): 576 return float(value) 577 578 def __verify_pos_int(self, type, value): 579 valueInfo = self.__get_value_info() 580 581 try: 582 value = self.normalize(type, value) 583 except: 584 self.__set_value_info(valueInfo) 585 else: 586 self.__set_value_info(valueInfo, normalized=value) 587 588 return valueInfo 589 590 def __norm_pos_int(self, value): 591 value = int(value) 592 if value < 0: 593 raise Exception("value is not positive: %s" % value) 594 595 return value 596 597 def __verify_neg_int(self, type, value): 598 valueInfo = self.__get_value_info() 599 600 try: 601 value = self.normalize(type, value) 602 except: 603 self.__set_value_info(valueInfo) 604 else: 605 self.__set_value_info(valueInfo, normalized=value) 606 607 return valueInfo 608 609 def __norm_neg_int(self, type, value): 610 value = int(value) 611 if value > 0: 612 raise Exception("value is not negative: %s" % value) 613 614 return value 615 616 def __verify_freq(self, type, value): 617 return self.__verify_pos_int(type, value) 618 619 def __norm_freq(self, value): 620 return self.__norm_pos_int(value) 621 622 def __verify_pos_float(self, type, value): 623 valueInfo = self.__get_value_info() 624 625 try: 626 value = self.normalize(type, value) 627 except: 628 self.__set_value_info(valueInfo) 629 else: 630 self.__set_value_info(valueInfo, normalized=value) 631 632 return valueInfo 633 634 def __norm_pos_float(self, value): 635 value = float(value) 636 if value < 0: 637 raise Exception("value is not positive: %s" % value) 638 639 return value 640 641 def __verify_pos_num(self, type, value): 642 return self.__verify_pos_float(value) 643 644 def __norm_pos_num(self, value): 645 return self.__norm_pos_float(value) 646 647 def __verify_neg_float(self, type, value): 648 valueInfo = self.__get_value_info() 649 650 try: 651 value = self.normalize(type, value) 652 except: 653 self.__set_value_info(valueInfo) 654 else: 655 self.__set_value_info(valueInfo, normalized=value) 656 657 return valueInfo 658 659 def __norm_neg_float(self, value): 660 value = float(value) 661 if value >= 0: 662 raise Exception("value is not negative: %s" % value) 663 664 return value 665 666 def __verify_string(self, type, value): 667 valueInfo = self.__get_value_info() 668 self.__set_value_info(valueInfo, normalized=self.normalize(type, 669 value)) 670 671 return valueInfo 672 673 def __norm_string(self, value): 674 return str(value) 675 676 def __verify_keyval(self, type, value): 677 valueInfo = self.__get_value_info() 678 679 if reKeyVal.search(value): 680 try: 681 self.__set_value_info(valueInfo, normalized=self.normalize(type, 682 value)) 683 except: 684 self.__set_value_info(valueInfo, errorData = \ 685 "invalid list of key-value pairs : [ %s ]" % value) 686 else: 687 msg = "No key value pairs found?" 688 self.__set_value_info(valueInfo, errorData=msg) 689 690 return valueInfo 691 692 def __norm_keyval(self, value): 693 list = self.__norm_list(value) 694 keyValue = {} 695 for item in list: 696 (key, value) = reKeyVal.split(item) 697 #if not keyValue.has_key(key): 698 # keyValue[key] = [] 699 #keyValue[key].append(value) 700 keyValue[key] = value 701 return keyValue 702 703 def __verify_list(self, type, value): 704 valueInfo = self.__get_value_info() 705 706 self.__set_value_info(valueInfo, normalized=self.normalize(type,value)) 707 708 return valueInfo 709 710 def __norm_list(self, value): 711 norm = [] 712 if reList.search(value): 713 norm = reList.split(value) 714 else: 715 norm = [value,] 716 717 return norm 718 719 def __verify_file(self, type, value): 720 valueInfo = self.__get_value_info() 721 722 if os.path.isfile(value): 723 self.__set_value_info(valueInfo, normalized=self.normalize(type, 724 value)) 725 else: 726 self.__set_value_info(valueInfo) 727 728 return valueInfo 729 730 def __norm_file(self, value): 731 return self.__normalizedPath(value) 732 733 def __verify_size(self, type, value): 734 valueInfo = self.__get_value_info() 735 736 value = str(value) 737 if reSizeFormat.match(value): 738 numberPart = int(reSizeFormat.sub("\g<1>", value)) 739 factorPart = reSizeFormat.sub("\g<2>", value) 740 try: 741 normalized = normalize_size(numberPart, factorPart) 742 self.__set_value_info(valueInfo, 743 normalized=normalized) 744 except: 745 self.__set_value_info(valueInfo) 746 else: 747 try: 748 value = int(value) 749 except: 750 self.__set_value_info(valueInfo) 751 else: 752 if value >= 0: 753 self.__set_value_info(valueInfo, normalized=value) 754 else: 755 self.__set_value_info(valueInfo) 756 757 return valueInfo 758 759 def __norm_size(self, file): 760 norm = None 761 if reSizeFormat.match(value): 762 numberPart = int(reSizeFormat.sub("\g<1>", value)) 763 factorPart = reSizeFormat.sub("\g<2>", value) 764 norm = normalize_size(numberPart, factorPart) 765 else: 766 norm = int(value) 767 768 return norm 769 770 771 def __verify_eaddress(self, type, value): 772 valueInfo = self.__get_value_info() 773 774 emailList = reComma.split(value) 775 776 for emailAddress in emailList: 777 if reEmailAddress.match(emailAddress): 778 emailParts = reEmailDelimit.split(emailAddress) 779 try: 780 socket.gethostbyname(emailParts[1]) 781 self.__set_value_info(valueInfo, normalized=self.normalize( 782 type, value)) 783 except: 784 errorString = "%s is invalid (domain lookup failed)" % \ 785 emailAddress 786 self.__set_value_info(valueInfo, errorData=errorString) 787 else: 788 errorString = "%s is invalid" % emailAddress 789 self.__set_value_info(valueInfo, errorData=errorString) 790 791 return valueInfo 792 793 def __verify_tcp_port(self, type, value): 794 valueInfo = self.__get_value_info() 795 796 try: 797 value = self.__norm_tcp_port(value) 798 except: 799 self.__set_value_info(valueInfo) 800 else: 801 if value in range(2, 65536): 802 self.__set_value_info(valueInfo, normalized=value) 803 else: 804 self.__set_value_info(valueInfo) 805 806 return valueInfo 807 808 def __norm_tcp_port(self, value): 809 return int(value) 810 811 def __verify_http_version(self, type, value): 812 valueInfo = self.__get_value_info() 813 814 if value in ('1.0', '1.1'): 815 self.__set_value_info(valueInfo, normalized=float(value)) 816 else: 817 self.__set_value_info(valueInfo) 818 819 return valueInfo 820 821 def __verify_range(self, type, value): 822 valueInfo = self.__get_value_info() 823 824 range = reDash.split(value) 825 826 try: 827 if len(range) > 1: 828 start = int(range[0]) 829 end = int(range[1]) 830 else: 831 start = int(range[0]) 832 end = None 833 except: 834 self.__set_value_info(valueInfo) 835 else: 836 if end: 837 if end - start != 0: 838 self.__set_value_info(valueInfo, normalized=(start, end)) 839 else: 840 self.__set_value_info(valueInfo) 841 else: 842 self.__set_value_info(valueInfo, normalized=(start,)) 843 844 return valueInfo 845 846 def __norm_range(self, value): 847 range = reDash.split(value) 848 if len(range) > 1: 849 start = int(range[0]) 850 end = int(range[1]) 851 else: 852 start = int(range[0]) 853 end = None 854 855 return (start, end) 856 857 def __verify_uri(self, type, value): 858 valueInfo = self.__get_value_info() 859 860 _norm = None 861 try: 862 uriComponents = urlparse.urlparse(value) 863 if uriComponents[0] == '' or uriComponents[0] == 'file': 864 # if scheme is '' or 'file' 865 if not os.path.isfile(uriComponents[2]) and \ 866 not os.path.isdir(uriComponents[2]): 867 raise Exception("Invalid local URI") 868 else: 869 self.__set_value_info(valueInfo, normalized=self.normalize( 870 type,value)) 871 else: 872 # other schemes 873 # currently not checking anything. TODO 874 self.__set_value_info(valueInfo, normalized=self.normalize( 875 type,value)) 876 except: 877 errorString = "%s is an invalid uri" % value 878 self.__set_value_info(valueInfo, errorData=errorString) 879 880 return valueInfo 881 882 def __norm_uri(self, value): 883 uriComponents = list(urlparse.urlparse(value)) 884 if uriComponents[0] == '': 885 # if scheme is ''' 886 return self.__normalizedPath(uriComponents[2]) 887 elif uriComponents[0] == 'file': 888 # if scheme is 'file' 889 normalizedPath = self.__normalizedPath(uriComponents[2]) 890 return urlparse.urlunsplit(uriComponents[0:1] + [normalizedPath] + uriComponents[3:]) 891 892 # Not dealing with any other case right now 893 return value 894 895 def __verify_timestamp(self, type, value): 896 valueInfo = self.__get_value_info() 897 898 if check_timestamp(value): 899 self.__set_value_info(valueInfo, normalized=self.normalize(type, 900 value)) 901 else: 902 self.__set_value_info(valueInfo) 903 904 return valueInfo 905 906 def __verify_hostname(self, type, value): 907 valueInfo = self.__get_value_info() 908 909 try: 910 socket.gethostbyname(value) 911 self.__set_value_info(valueInfo, normalized=self.normalize(type, 912 value)) 913 except: 914 errorString = "%s is invalid (domain lookup failed)" % value 915 self.__set_value_info(valueInfo, errorData=errorString) 916 917 return valueInfo 918 919 def __verify_user_account(self, type, value): 920 valueInfo = self.__get_value_info() 921 922 try: 923 pwd.getpwnam(value) 924 except: 925 errorString = "'%s' user account does not exist" % value 926 self.__set_value_info(valueInfo, errorData=errorString) 927 else: 928 self.__set_value_info(valueInfo, normalized=self.normalize(type, 929 value)) 930 931 return valueInfo 932 933 def __verify_user_group(self, type, value): 934 valueInfo = self.__get_value_info() 935 936 try: 937 grp.getgrnam(value) 938 except: 939 errorString = "'%s' group does not exist" % value 940 self.__set_value_info(valueInfo, errorData=errorString) 941 else: 942 self.__set_value_info(valueInfo, normalized=self.normalize(type, 943 value)) 944 945 return valueInfo 946 947 def __verify_nothing(self, type, value): 948 valueInfo = self.__get_value_info() 949 950 self.__set_value_info(valueInfo, normalized=self.normalize(type, 951 value)) 952 953 return valueInfo 954 955 #-------------------------------------------------------------------------- 956 957 def normalize(self, type, value): 958 try: 959 normFunc = getattr(self, "_typeValidator__norm_%s" % type) 960 return normFunc(value) 961 except AttributeError, A: 962 # this exception should occur only when we don't have corresponding normalize function 963 return value 964 965 def verify(self, type, value, allowNone=False): 966 """Verifies a value based on its type. 967 968 type - supported configValidator type 969 value - data to be validated 970 allowNone - don't freak out if None or '' is supplied 971 972 returns a valueInfo dictionary: 973 974 valueInfo = { 'isValid' : 1, 'normalized' : 5, 'errorData' : 0 } 975 976 where: 977 978 isValid - true or false (0/1) 979 normalized - the normalized value 980 errorData - if invalid an error string 981 982 supported types: 983 984 see top level""" 985 986 result = None 987 if allowNone: 988 if value == '' or value == None: 989 result = self.__verify_nothing(None, None) 990 result['normalized'] = None 991 else: 992 result = self.verifyFunctions[type](type, value) 993 else: 994 result = self.verifyFunctions[type](type, value) 995 996 return result 997 998 def is_valid_type(self, type): 999 """Returns true if type is valid.""" 1000 1001 return types.has_key(type) 1002 1003 def type_info(self, type): 1004 """Returns type info dictionary.""" 1005 1006 dbInfo = dbTypes[types[type]['db']] 1007 typeInfo = types[type].copy() 1008 typeInfo['db'] = dbInfo 1009 1010 return typeInfo 1011 1012 def add(self, name, type, value): 1013 """Adds a value and type by name to the configValidate object to be 1014 verified using validate(). 1015 1016 name - name used to key values and access the results of the 1017 validation 1018 type - configValidator type 1019 value - data to be verified""" 1020 1021 self.validateList.append({ 'name' : name, 1022 'type' : type, 1023 'value': value }) 1024 1025 def validate(self, allowNone=False): 1026 """Validates configValidate object populating validatedInfo with 1027 valueInfo dictionaries for each value added to the object.""" 1028 1029 for valItem in self.validateList: 1030 valueInfo = self.verify(valItem['type'], valItem['value'], 1031 allowNone) 1032 if valueInfo: 1033 valueInfo['name'] = valItem['name'] 1034 self.validatedInfo.append(valueInfo) 1035 else: 1036 raise Exception("\nMissing a return value: valueInfo\n%s" % \ 1037 self.verifyFunctions[valItem['type']](valItem['value'])) 1038 1039 def __normalizedPath(self, value): 1040 oldWd = os.getcwd() 1041 if self.__originalDir: 1042 os.chdir(self.__originalDir) 1043 normPath = os.path.realpath(value) 1044 os.chdir(oldWd) 1045 return normPath 1046 1047 1048class display: 1049 def __init__(self): 1050 self.displayFunctions = {} 1051 self.__build_dispaly_functions() 1052 1053 def __build_dispaly_functions(self): 1054 functions = {} 1055 for function in dir(self): 1056 functions[function] = 1 1057 1058 for type in types.keys(): 1059 # kinda bad, need to find out how to know the name of the class 1060 # I'm in. But it works. 1061 functionName = "_cisplay__display_%s" % type 1062 if functions.has_key(functionName): 1063 self.displayFunctions[type] = getattr(self, functionName) 1064 else: 1065 if type == '': 1066 self.displayFunctions[type] = self.__display_default 1067 else: 1068 error = "Display function %s for type %s does not exist." \ 1069 % (functionName, type) 1070 raise Exception(error) 1071 sys.exit(1) 1072 1073 def __display_default(self, value, style): 1074 return value 1075 1076 def __display_generic_number(self, value): 1077 displayNumber = '' 1078 splitNum = string.split(str(value), sep='.') 1079 numList = list(str(splitNum[0])) 1080 numList.reverse() 1081 length = len(numList) 1082 counter = 0 1083 for char in numList: 1084 counter = counter + 1 1085 if counter % 3 or counter == length: 1086 displayNumber = "%s%s" % (char, displayNumber) 1087 else: 1088 displayNumber = ",%s%s" % (char, displayNumber) 1089 1090 if len(splitNum) > 1: 1091 displayNumber = "%s.%s" % (displayNumber, splitNum[1]) 1092 1093 return displayNumber 1094 1095 def __display_generic_mappable(self, map, value, style, plural=True): 1096 displayValue = '' 1097 length = len(str(value)) 1098 if length > 3: 1099 for factorSet in map: 1100 displayValue = float(value) / factorSet['factor'] 1101 if len(str(int(displayValue))) <= 3 or \ 1102 factorSet['factor'] == map[-1]['factor']: 1103 displayValue = "%10.2f" % displayValue 1104 if displayValue[-1] == '0': 1105 if displayValue > 1 and style != 'short' and plural: 1106 displayValue = "%s %ss" % (displayValue[:-1], 1107 factorSet[style]) 1108 else: 1109 displayValue = "%s %s" % (displayValue[:-1], 1110 factorSet[style]) 1111 else: 1112 if displayValue > 1 and style != 'short' and plural: 1113 displayValue = "%s %ss" % (displayValue, 1114 factorSet[style]) 1115 else: 1116 displayValue = "%s %s" % (displayValue, 1117 factorSet[style]) 1118 break 1119 1120 return displayValue 1121 1122 def __display_directory(self, value, style): 1123 return self.__display_default(value, style) 1124 1125 def __display_address(self, value, style): 1126 return self.__display_default(value, style) 1127 1128 def __display_ip_address(self, value, style): 1129 return self.__display_default(value, style) 1130 1131 def __display_net_address(self, value, style): 1132 return self.__display_default(value, style) 1133 1134 def __display_bool(self, value, style): 1135 displayValue = value 1136 1137 if not isinstance(displayValue, bool): 1138 if re.match("^false|0|f|no$", value, 2): 1139 displayValue=False 1140 elif re.match("^true|1|t|yes$", value, 2): 1141 displayValue=True 1142 1143 return displayValue 1144 1145 def __display_int(self, value, style): 1146 return self.__display_generic_number(value) 1147 1148 def __display_float(self, value, style): 1149 return self.__display_generic_number(value) 1150 1151 def __display_pos_int(self, value, style): 1152 return self.__display_generic_number(value) 1153 1154 def __display_neg_int(self, value, style): 1155 return self.__display_generic_number(value) 1156 1157 def __display_pos_num(self, value, style): 1158 return self.__display_generic_number(value) 1159 1160 def __display_pos_float(self, value, style): 1161 return self.__display_generic_number(value) 1162 1163 def __display_neg_float(self, value, style): 1164 return self.__display_generic_number(value) 1165 1166 def __display_string(self, value, style): 1167 return self.__display_default(value, style) 1168 1169 def __display_list(self, value, style): 1170 value = value.rstrip() 1171 return value.rstrip(',') 1172 1173 def __display_keyval(self, value, style): 1174 value = value.rstrip() 1175 return value.rstrip(',') 1176 1177 def __display_file(self, value, style): 1178 return self.__display_default(value, style) 1179 1180 def __display_size(self, value, style): 1181 return self.__display_generic_mappable(sizeMap, value, style) 1182 1183 def __display_freq(self, value, style): 1184 return self.__display_generic_mappable(freqMap, value, style, False) 1185 1186 def __display_eaddress(self, value, style): 1187 return self.__display_default(value, style) 1188 1189 def __display_tcp_port(self, value, style): 1190 return self.__display_default(value, style) 1191 1192 def __display_http_version(self, value, style): 1193 return self.__display_default(value, style) 1194 1195 def __display_range(self, value, style): 1196 return self.__display_default(value, style) 1197 1198 def __display_hostname(self, value, style): 1199 return self.__display_default(value, style) 1200 1201 def __display_user_account(self, value, style): 1202 return self.__display_default(value, style) 1203 1204 def __display_user_group(self, value, style): 1205 return self.__display_default(value, style) 1206 1207 def __display_timestamp(self, value, style): 1208 return self.__display_default(value, style) 1209 1210 def display(self, type, value, style='short'): 1211 displayValue = value 1212 if value != None: 1213 displayValue = self.displayFunctions[type](value, style) 1214 1215 return displayValue 1216 1217typeValidatorInstance = typeValidator() 1218 1219def is_valid_type(type): 1220 """Returns true if type is valid.""" 1221 1222 return typeValidatorInstance.is_valid_type(type) 1223 1224def type_info(type): 1225 """Returns type info dictionary.""" 1226 1227 return typeValidatorInstance.type_info(type) 1228 1229def verify(type, value, allowNone=False): 1230 """Returns a normalized valueInfo dictionary.""" 1231 1232 return typeValidatorInstance.verify(type, value, allowNone) 1233 1234def __normalize(map, val, factor): 1235 normFactor = string.lower(factor) 1236 normVal = float(val) 1237 return int(normVal * map[normFactor]) 1238 1239def normalize_size(size, factor): 1240 """ Normalize a size to bytes. 1241 1242 size - number of B, KB, MB, GB, TB, or PB 1243 factor - size factor (case insensitive): 1244 b | bytes - bytes 1245 k | kb - kilobytes 1246 m | mb - megabytes 1247 g | gb - gigabytes 1248 t | tb - terabytes 1249 p | pb - petabytes 1250 """ 1251 1252 return __normalize(sizeFactors, size, factor) 1253 1254def normalize_freq(freq, factor): 1255 """ Normalize a frequency to hertz. 1256 1257 freq - number of Hz, Khz, Mhz, Ghz, Thz, or Phz 1258 factor - size factor (case insensitive): 1259 Hz - Hertz 1260 Mhz - Megahertz 1261 Ghz - Gigahertz 1262 Thz - Terahertz 1263 Phz - Petahertz 1264 """ 1265 1266 return __normalize(freqFactors, freq, factor) 1267