|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
hashgen.cpp
Abstract:
Table Generator for hhead.cxx, which contains all known HTTP headers for wininet project. This is also the location where all known HTTP headers must be added.
Author:
Arthur Bierer (arthurbi) 12-Jan-1998
Revision History:
--*/
//
// Instructions for adding new HTTP header:
// 1. Update wininet.w and rebuild wininet.h with new HTTP_QUERY_ code
// 2. Add/Edit header to this file/program, hashgen.cpp with the
// new header string (see Items[] array below)
// 3. Compile new hashgen.exe, Execute with -o, write down a good seed
// note that this may take all night to find a good seed which
// give a nice smaller table size. (note this can be skipped if
// you just need a quick table for dev purposes)
// 4. Re-Execute hashgen.exe with -b# set with your seed to generate
// hhead.cxx
// 5. Transfer new hhead.cxx file to wininet\http
// 6. Update const defines MAX_HEADER_HASH_SIZE and HEADER_HASH_SEED
// from new hhead.cxx to wininet\http\headers.h
// 7. Transfer and checkin hashgen.cpp, wininet.w, headers,h, hhead.cxx
// in their appropriate directories.
//
//
// Includes...
//
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <search.h>
#include <wininet.h>
//
// macros
//
#define IS_ARG(c) ((c) == '-')
#define DIM(x) (sizeof(x) / sizeof(x[0]))
#define ENUMDEF(x, y) ,x, #x, #y
#define OUTPUT_CODE_FILE "hhead.cxx"
#define MAX_SIZE_HASHARRAY_TO_ATTEMPT 600
#define UNKNOWN_HASH_ENTRY 0 // character to put in array when when its not valid
//
// Items - This is the array that must be edited for Wininet to process new
// HTTP headers
//
// Things to keep in mind before you add to this array
// 1. Headers are Alphatized for convience sake
// 2. All NULL entries MUST be at the end of the array
// 3. All HTTP_QUERY_* codes in wininet.h MUST have an entry even if they are not strings
// 4. Entries are as follows:
// header string, HTTP_QUERY_* code in wininet.h, flags used in wininet\http\query.cxx
// 5. All entries must be in lowercase.
//
struct Item { char *ptok; DWORD id; char *pidName; char *pFlagsName; } Items[] = { { "Accept" ENUMDEF(HTTP_QUERY_ACCEPT, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Accept-Charset" ENUMDEF(HTTP_QUERY_ACCEPT_CHARSET, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Accept-Encoding" ENUMDEF(HTTP_QUERY_ACCEPT_ENCODING, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Accept-Language" ENUMDEF(HTTP_QUERY_ACCEPT_LANGUAGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Accept-Ranges" ENUMDEF(HTTP_QUERY_ACCEPT_RANGES, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Age" ENUMDEF(HTTP_QUERY_AGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Allow" ENUMDEF(HTTP_QUERY_ALLOW, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Authorization" ENUMDEF(HTTP_QUERY_AUTHORIZATION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Cache-Control" ENUMDEF(HTTP_QUERY_CACHE_CONTROL, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Connection" ENUMDEF(HTTP_QUERY_CONNECTION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Base" ENUMDEF(HTTP_QUERY_CONTENT_BASE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Description" ENUMDEF(HTTP_QUERY_CONTENT_DESCRIPTION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Disposition" ENUMDEF(HTTP_QUERY_CONTENT_DISPOSITION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Encoding" ENUMDEF(HTTP_QUERY_CONTENT_ENCODING, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Id" ENUMDEF(HTTP_QUERY_CONTENT_ID, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Language" ENUMDEF(HTTP_QUERY_CONTENT_LANGUAGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Length" ENUMDEF(HTTP_QUERY_CONTENT_LENGTH, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_NUMBER)) }, { "Content-Location" ENUMDEF(HTTP_QUERY_CONTENT_LOCATION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Md5" ENUMDEF(HTTP_QUERY_CONTENT_MD5, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Range" ENUMDEF(HTTP_QUERY_CONTENT_RANGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Transfer-Encoding" ENUMDEF(HTTP_QUERY_CONTENT_TRANSFER_ENCODING, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Content-Type" ENUMDEF(HTTP_QUERY_CONTENT_TYPE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Cookie" ENUMDEF(HTTP_QUERY_COOKIE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Cost" ENUMDEF(HTTP_QUERY_COST, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Date" ENUMDEF(HTTP_QUERY_DATE, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) }, { "Derived-From" ENUMDEF(HTTP_QUERY_DERIVED_FROM, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Etag" ENUMDEF(HTTP_QUERY_ETAG, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Expect" ENUMDEF(HTTP_QUERY_EXPECT, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) }, { "Expires" ENUMDEF(HTTP_QUERY_EXPIRES, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Forwarded" ENUMDEF(HTTP_QUERY_FORWARDED, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "From" ENUMDEF(HTTP_QUERY_FROM, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Host" ENUMDEF(HTTP_QUERY_HOST, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "If-Modified-Since" ENUMDEF(HTTP_QUERY_IF_MODIFIED_SINCE, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) }, { "If-Match" ENUMDEF(HTTP_QUERY_IF_MATCH, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "If-None-Match" ENUMDEF(HTTP_QUERY_IF_NONE_MATCH, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "If-Range" ENUMDEF(HTTP_QUERY_IF_RANGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "If-Unmodified-Since" ENUMDEF(HTTP_QUERY_IF_UNMODIFIED_SINCE, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) }, { "Last-Modified" ENUMDEF(HTTP_QUERY_LAST_MODIFIED, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) }, { "Link" ENUMDEF(HTTP_QUERY_LINK, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Location" ENUMDEF(HTTP_QUERY_LOCATION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Mime-Version" ENUMDEF(HTTP_QUERY_MIME_VERSION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Max-Forwards" ENUMDEF(HTTP_QUERY_MAX_FORWARDS, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Message-id" ENUMDEF(HTTP_QUERY_MESSAGE_ID, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Ms-Echo-Request" ENUMDEF(HTTP_QUERY_ECHO_REQUEST, 0) }, { "Ms-Echo-Reply" ENUMDEF(HTTP_QUERY_ECHO_REPLY, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Orig-Uri" ENUMDEF(HTTP_QUERY_ORIG_URI, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Pragma" ENUMDEF(HTTP_QUERY_PRAGMA, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Proxy-Authenticate" ENUMDEF(HTTP_QUERY_PROXY_AUTHENTICATE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Proxy-Authorization" ENUMDEF(HTTP_QUERY_PROXY_AUTHORIZATION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Proxy-Connection" ENUMDEF(HTTP_QUERY_PROXY_CONNECTION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Proxy-Support" ENUMDEF(HTTP_QUERY_PROXY_SUPPORT, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Public" ENUMDEF(HTTP_QUERY_PUBLIC, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Range" ENUMDEF(HTTP_QUERY_RANGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Referer" ENUMDEF(HTTP_QUERY_REFERER, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Refresh" ENUMDEF(HTTP_QUERY_REFRESH, 0) }, { "Retry-After" ENUMDEF(HTTP_QUERY_RETRY_AFTER, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) }, { "Server" ENUMDEF(HTTP_QUERY_SERVER, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Set-Cookie" ENUMDEF(HTTP_QUERY_SET_COOKIE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Title" ENUMDEF(HTTP_QUERY_TITLE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Transfer-Encoding" ENUMDEF(HTTP_QUERY_TRANSFER_ENCODING, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Unless-Modified-Since" ENUMDEF(HTTP_QUERY_UNLESS_MODIFIED_SINCE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Upgrade" ENUMDEF(HTTP_QUERY_UPGRADE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Uri" ENUMDEF(HTTP_QUERY_URI, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "User-Agent" ENUMDEF(HTTP_QUERY_USER_AGENT, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Vary" ENUMDEF(HTTP_QUERY_VARY, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Via" ENUMDEF(HTTP_QUERY_VIA, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Warning" ENUMDEF(HTTP_QUERY_WARNING, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "WWW-Authenticate" ENUMDEF(HTTP_QUERY_WWW_AUTHENTICATE, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "Authentication-Info" ENUMDEF(HTTP_QUERY_AUTHENTICATION_INFO, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "PassportURLs" ENUMDEF(HTTP_QUERY_PASSPORT_URLS, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { "PassportConfig" ENUMDEF(HTTP_QUERY_PASSPORT_CONFIG, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, // NULL strs must be in end of array
{ NULL ENUMDEF(HTTP_QUERY_VERSION, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { NULL ENUMDEF(HTTP_QUERY_STATUS_CODE, HTTP_QUERY_FLAG_NUMBER) }, { NULL ENUMDEF(HTTP_QUERY_STATUS_TEXT, 0) }, { NULL ENUMDEF(HTTP_QUERY_RAW_HEADERS, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { NULL ENUMDEF(HTTP_QUERY_RAW_HEADERS_CRLF, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { NULL ENUMDEF(HTTP_QUERY_REQUEST_METHOD, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { NULL ENUMDEF(HTTP_QUERY_ECHO_HEADERS, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, { NULL ENUMDEF(HTTP_QUERY_ECHO_HEADERS_CRLF, HTTP_QUERY_FLAG_REQUEST_HEADERS) }, };
//
// Declarations of common strings used in creating output "C" file
//
char szFileHeader[] = {"/*++\n\n" "Copyright (c) 1997 Microsoft Corporation\n\n" "Module Name:\n\n" " " OUTPUT_CODE_FILE "\n\n" "Abstract:\n\n" " This file contains autogenerated table values of a perfect hash function\n" " DO NOT, DO NOT EDIT THIS FILE, TO ADD HEADERS SEE hashgen.cpp\n" " Contents:\n" " GlobalKnownHeaders\n" " GlobalHeaderHashs\n\n" "Author:\n\n" " Arthur Bierer (arthurbi) 19-Dec-1997 (AND) my code generator[hashgen.exe]\n\n" "Revision History:\n\n" "--*/\n\n\n" };
char szComment1[] = { "//\n" "// GlobalHeaderHashs - array of precalculated hashes on case-sensetive set of known headers.\n" "// This array must be used with the same hash function used to generate it.\n" "// Note, all entries in this array are biased (++'ed) by 1 from HTTP_QUERY_ manifests in wininet.h.\n" "// 0-ed entries indicate error values\n" "//\n\n" };
char szComment2[] = { "//\n" "// GlobalKnownHeaders - array of HTTP request and response headers that we understand.\n" "// This array must be in the same order as the HTTP_QUERY_ manifests in WININET.H\n" "//\n\n" "#define HEADER_ENTRY(String, Flags, HashVal) String, sizeof(String) - 1, Flags, HashVal\n\n" };
char szDef1[] = { "#ifdef HEADER_HASH_SEED\n" "#if (HEADER_HASH_SEED != %u)\n" "#error HEADER_HASH_SEED has not been updated in the header file, please copy this number to the header\n" "#endif\n" "#else\n" "#define HEADER_HASH_SEED %u\n" "#endif\n\n" };
char szDef2[] = { "#ifdef MAX_HEADER_HASH_SIZE\n" "#if (MAX_HEADER_HASH_SIZE != %u)\n" "#error MAX_HEADER_HASH_SIZE has not been updated in the header file, please copy this number to the header\n" "#endif\n" "#else\n" "#define MAX_HEADER_HASH_SIZE %u\n" "#endif\n\n" };
char szDef3[] = { "#ifdef HTTP_QUERY_MAX\n" "#if (HTTP_QUERY_MAX != %u)\n" "#error HTTP_QUERY_MAX is not the same as the value used in wininet.h, this indicates mismatched headers, see hashgen.cpp\n" "#endif\n" "#endif\n\n" };
char szIncludes[] = { "#include <wininetp.h>\n" "#include \"httpp.h\"\n\n" };
//
// Hash - function used to create table,
// THIS FUNCTION MUST BE THE SAME AS THE ONE USED in WININET
//
DWORD Hash(char *pszName, DWORD j, DWORD seed) { DWORD hash = seed;
while (*pszName) { hash += (hash << 5) + *pszName++; } return (j==0) ? hash : hash % j; }
//
// CompareItems - a util function for qsort-ing by ID for table creation
// in the output file
//
int __cdecl CompareItems (const void *elem1, const void *elem2 ) { const struct Item *pItem1, *pItem2;
pItem1 = (struct Item *) elem1; pItem2 = (struct Item *) elem2;
if ( pItem1->id < pItem2->id ) { return -1; } else if ( pItem1->id > pItem2->id ) { return 1; }
return 0; }
//
// usage() - print out our usage instructions to command line
//
void usage() { fprintf(stderr, "\n" "usage: hashgen [-m[#]] [-b[#]] [-t[#]] [-o] [-p<path>] [-f<filename>]\n" "\n" "where: -m[#] = Max hash table size to test with, default = 600\n" " -b[#] = Starting hash seed, default = 0\n" " -t[#] = Threshold of table size to halt search at, default = 200\n" " -o = Enable optimal exhaustive search mode (can take 24+ hrs)\n" " -p = Path used for output generation\n" " -f = Output filename, \"hhead.cxx\" is assumed\n" "\n" "Instructions for adding new HTTP header:\n" "\t1. Update wininet.w and rebuild wininet.h with new HTTP_QUERY_ code\n" "\t2. Add/Edit this file/program, hashgen.cpp with the new header string\n" "\t3. Compile/Execute new hashgen.exe with -o, write down a good seed\n" "\t4. Re-Execute hashgen.exe with -b# set with your seed to generate\n" "\t hhead.cxx\n" "\t5. Transfer new hhead.cxx file to wininet\\http\n" "\t6. Update const defines MAX_HEADER_HASH_SIZE and HEADER_HASH_SEED\n" "\t from new hhead.cxx to wininet\\http\\headers.h\n" "\t7. Transfer and checkin hashgen.cpp, wininet.w, headers,h, hhead.cxx\n" ); exit(1); }
//
// MakeMeLower - Makes a lower case string using a static 255 byte array
//
LPSTR MakeMeLower( IN LPSTR lpszMixedCaseStr ) { static CHAR szLowerCased[256];
if ( lstrlen(lpszMixedCaseStr) > 255 ) { fprintf(stderr, "Internal error: an HTTP header is too long\n\n"); return szLowerCased; }
lstrcpy( szLowerCased, lpszMixedCaseStr ); CharLower(szLowerCased);
return szLowerCased; }
//
// main - where it all gets done !!!!
//
void __cdecl //_CRTAPI1
main( int argc, char * argv[] ) { DWORD nMax = MAX_SIZE_HASHARRAY_TO_ATTEMPT; DWORD dwBestNumber = 0, dwBestSeed = 0 /*349160*/ /*4458*//*202521*/; DWORD dwSearchThreshold = 200; BOOL bFoundOne = FALSE; BOOL bFindOptimalSeed = FALSE; LPSTR szPath = ""; LPSTR szFileName = OUTPUT_CODE_FILE; DWORD i, j, k; DWORD dwValidStringsInArray = 0; DWORD *pHash = new DWORD[nMax];
for (--argc, ++argv; argc; --argc, ++argv) { if (IS_ARG(**argv)) { switch (*++*argv) { case '?': usage(); break;
case 'm': nMax = (DWORD)atoi(++*argv); break;
case 'b': dwBestSeed = (DWORD)atoi(++*argv); break;
case 't': dwSearchThreshold = (DWORD)atoi(++*argv); break; case 'p': szPath = ++*argv; break;
case 'f': szFileName = ++*argv; break;
case 'o': bFindOptimalSeed = TRUE; break; default: fprintf(stderr,"error: unrecognized command line flag: '%c'\n", **argv); usage(); } } else { fprintf(stderr,"error: unrecognized command line argument: \"%s\"\n", *argv); usage(); } }
//
// Let the Work begin...
//
dwBestNumber = nMax;
if (bFindOptimalSeed) { printf("This will take a while, perhaps all night(consider a Ctrl-C)...\n"); }
for (i = 0; i < DIM(Items); i++ ) { if ( Items[i].ptok ) dwValidStringsInArray++; }
for (i = dwBestSeed; i < (~0); i++) { //printf("%d,\n", i);
for (j = dwValidStringsInArray; j < nMax; j++) { memset (pHash, UNKNOWN_HASH_ENTRY, nMax * sizeof(DWORD)); for (k = 0; k < dwValidStringsInArray; k++) { DWORD HashNow = Hash(MakeMeLower(Items[k].ptok), j, i) /*% j(table_size), i(seed)*/;
if ( HashNow > j ) { fprintf(stderr, "Error, Error - exceed table size, bad hash alg\n"); break; }
if (pHash[HashNow] != UNKNOWN_HASH_ENTRY) break; else { pHash[HashNow] = Items[k].id+1; } }
if ( k == dwValidStringsInArray ) { //printf( "Found one with hash_size=%d, seed=%u...\n", j,i );
bFoundOne = TRUE; goto found_one; } } found_one:
if ( bFoundOne ) { if (j < dwBestNumber) { dwBestNumber = j; dwBestSeed = i;
printf("Found a New One, hashtable_size=%d, seed=%u...\n", j ,i); if ( !bFindOptimalSeed && dwBestNumber < dwSearchThreshold ) { goto stop_search; } }
bFoundOne = FALSE; } }
stop_search:
if ( dwBestNumber < nMax && dwBestNumber == j) { printf("Generating %s which contains, perfect hash for known headers\n", OUTPUT_CODE_FILE);
FILE *f; CHAR szOutputFileAndPath[512];
strcpy(szOutputFileAndPath, szPath); strcat(szOutputFileAndPath, szFileName);
f = fopen(szOutputFileAndPath, "w");
if ( f == NULL ) { fprintf(stderr, "Err: Could Not Open %s for writing\n", szOutputFileAndPath); exit(-1); }
fprintf(f, szFileHeader); // print header
fprintf(f, szIncludes); // includes
fprintf(f, szDef1, dwBestSeed, dwBestSeed); fprintf(f, szDef2, dwBestNumber, dwBestNumber); fprintf(f, szDef3, HTTP_QUERY_MAX);
fprintf(f, szComment1); // print comment
if ( dwBestNumber < 255 ) { fprintf(f, "const BYTE GlobalHeaderHashs[MAX_HEADER_HASH_SIZE] = {\n"); } else { fprintf(f, "const WORD GlobalHeaderHashs[MAX_HEADER_HASH_SIZE] = {\n"); } DWORD col = 0;
//
// spit our Nicely calculated perfect hash table..
//
for ( i = 0; i < dwBestNumber; i++ ) { col++; if ( col == 1 ) { fprintf(f, " "); }
fprintf(f, "%3u, ", (BYTE) pHash[i]);
if ( col == 6 ) { fprintf(f, "\n"); col = 0; } }
fprintf(f, "\n };\n\n");
//
// Now spit our KnownHeader array...
//
qsort(Items, DIM(Items), sizeof(Items[0]), CompareItems);
fprintf(f, szComment2);
if ( DIM(Items) != (HTTP_QUERY_MAX+1) ) { fprintf(stderr, "ERROR, HTTP_QUERY_MAX the wrong size,( different wininet.h's? )\n"); return; }
fprintf(f, "const struct KnownHeaderType GlobalKnownHeaders[HTTP_QUERY_MAX+1] = {\n");
for (j = 0; j < DIM(Items); j++) { char szBuffer[256]; DWORD dwHash = 0;
sprintf(szBuffer, " HEADER_ENTRY(\"%s\",", (Items[j].ptok ? Items[j].ptok : "\0")); if ( Items[j].ptok ) { dwHash = Hash(MakeMeLower(Items[j].ptok), 0, dwBestSeed); }
fprintf(f, "%-45s %s, 0x%X),\n", szBuffer, Items[j].pFlagsName, dwHash); }
fprintf(f," };\n\n\n");
fclose(f); } else { fprintf(stderr, "Error, could not find an ideal number\n"); }
}
|