| 
									
										
										
										
											2012-06-22 21:12:59 +02:00
										 |  |  | #! /usr/bin/env python3 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-22 22:07:01 +02:00
										 |  |  | """
 | 
					
						
							|  |  |  | This script should be called *manually* when we want to upgrade SSLError | 
					
						
							|  |  |  | `library` and `reason` mnemnonics to a more recent OpenSSL version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It takes two arguments: | 
					
						
							|  |  |  | - the path to the OpenSSL include files' directory | 
					
						
							|  |  |  |   (e.g. openssl-1.0.1-beta3/include/openssl/) | 
					
						
							|  |  |  | - the path to the C file to be generated | 
					
						
							|  |  |  |   (probably Modules/_ssl_data.h) | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-22 21:12:59 +02:00
										 |  |  | import datetime | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import re | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def parse_error_codes(h_file, prefix): | 
					
						
							|  |  |  |     pat = re.compile(r"#define\W+(%s([\w]+))\W+(\d+)\b" % re.escape(prefix)) | 
					
						
							|  |  |  |     codes = [] | 
					
						
							|  |  |  |     with open(h_file, "r", encoding="latin1") as f: | 
					
						
							|  |  |  |         for line in f: | 
					
						
							|  |  |  |             match = pat.search(line) | 
					
						
							|  |  |  |             if match: | 
					
						
							|  |  |  |                 code, name, num = match.groups() | 
					
						
							|  |  |  |                 num = int(num) | 
					
						
							|  |  |  |                 codes.append((code, name, num)) | 
					
						
							|  |  |  |     return codes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     openssl_inc = sys.argv[1] | 
					
						
							|  |  |  |     outfile = sys.argv[2] | 
					
						
							|  |  |  |     use_stdout = outfile == '-' | 
					
						
							|  |  |  |     f = sys.stdout if use_stdout else open(outfile, "w") | 
					
						
							|  |  |  |     error_libraries = ( | 
					
						
							|  |  |  |         # (library code, mnemonic, error prefix, header file) | 
					
						
							|  |  |  |         ('ERR_LIB_PEM', 'PEM', 'PEM_R_', 'pem.h'), | 
					
						
							|  |  |  |         ('ERR_LIB_SSL', 'SSL', 'SSL_R_', 'ssl.h'), | 
					
						
							|  |  |  |         ('ERR_LIB_X509', 'X509', 'X509_R_', 'x509.h'), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     def w(l): | 
					
						
							|  |  |  |         f.write(l + "\n") | 
					
						
							|  |  |  |     w("/* File generated by Tools/ssl/make_ssl_data.py */") | 
					
						
							|  |  |  |     w("/* Generated on %s */" % datetime.datetime.now().isoformat()) | 
					
						
							|  |  |  |     w("") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     w("static struct py_ssl_library_code library_codes[] = {") | 
					
						
							|  |  |  |     for libcode, mnemo, _, _ in error_libraries: | 
					
						
							|  |  |  |         w('    {"%s", %s},' % (mnemo, libcode)) | 
					
						
							|  |  |  |     w('    { NULL }') | 
					
						
							|  |  |  |     w('};') | 
					
						
							|  |  |  |     w("") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     w("static struct py_ssl_error_code error_codes[] = {") | 
					
						
							|  |  |  |     for libcode, _, prefix, h_file in error_libraries: | 
					
						
							|  |  |  |         codes = parse_error_codes(os.path.join(openssl_inc, h_file), prefix) | 
					
						
							|  |  |  |         for code, name, num in sorted(codes): | 
					
						
							|  |  |  |             w('  #ifdef %s' % (code)) | 
					
						
							|  |  |  |             w('    {"%s", %s, %s},' % (name, libcode, code)) | 
					
						
							|  |  |  |             w('  #else') | 
					
						
							|  |  |  |             w('    {"%s", %s, %d},' % (name, libcode, num)) | 
					
						
							|  |  |  |             w('  #endif') | 
					
						
							|  |  |  |     w('    { NULL }') | 
					
						
							|  |  |  |     w('};') | 
					
						
							|  |  |  |     if not use_stdout: | 
					
						
							|  |  |  |         f.close() |