⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hhp.c

📁 CHM decompiler is a program that converts the internal files of CHM files back into the HHP, HHC, an
💻 C
📖 第 1 页 / 共 2 页
字号:
				if( !exists("$FIftiMain") ){ Full_text_search = false; got_fts = true; }				else {					struct stat st;					if( stat("$FIftiMain",&st) == 0 ){						got_fts = true;						Full_text_search = (st.st_size != 0);					}				}			}			if( got_fts && (Full_text_search || print_defaults) )				fprintf( hhp, "Full-text search=%s\r\n", Full_text_search ? "Yes" : "No" );		}		/* fprintf( hhp, "IGNORE=%s\r\n", IGNORE ); */		/* Index file */		if( Index_file ) fprintf( hhp, "Index file=%s\r\n", Index_file );		/* else {			FIXME: Find out how to find files with a particular extension			fputs( ";The best guess for the Index file is one of the following\r\n", hhp );			while(f=findfile("*.hhk",case insensitive))				fprintf( hhp, ";Index file=%s\r\n", f );		}*/		{ /* Language */			bool got_lcid = got_stuff;			if(!got_lcid){				FILE* tmp = fopen( "$FIftiMain", "rb" );				if( tmp ){					fseek( tmp, 0x7E, SEEK_SET );					got_lcid = read_DWORD( tmp, &Language );					FCLOSE( tmp );				}				if( !got_lcid && (tmp = fopen( "$WWKeywordLinks/BTree", "rb" )) ){					fseek( tmp, 0x34, SEEK_SET );					got_lcid = read_DWORD( tmp, &Language );					FCLOSE( tmp );				}				if( !got_lcid && (tmp = fopen( "$WWAssociativeLinks/BTree", "rb" )) ){					fseek( tmp, 0x34, SEEK_SET );					got_lcid = read_DWORD( tmp, &Language );					FCLOSE( tmp );				}				/* FIXME: check the LCIDs in $OBJINST */				/* if( !got_lcid && (tmp = fopen( "$OBJINST", "rb" )) ){					FCLOSE( tmp );				} */			}			if(got_lcid){				char* Language_string = get_lcid_string( Language );				if( Language_string ) fprintf( hhp, "Language=0x%x %s\n", Language, Language_string );				else fprintf( hhp, "Language=0x%x\n", Language );			}		}		/* fprintf( hhp, "PREFIX=%s\r\n", PREFIX ); */		 /* Sample Staging Path, Sample list file */		if( samples_success ){			fprintf( hhp, "Sample Staging Path=%s\r\n", Sample_Staging_Path );			fprintf( hhp, "Sample list file=%s\r\n", Sample_list_file );		}		{ /* Title */			char* Title = (char*)get_system( Title_CODE );			if( Title ) fprintf( hhp, "Title=%s\n", Title );			FREE( Title );		}		/* fprintf( hhp, "TMPDIR=%s\r\n", TMPDIR ); */		{ /* Custom tab */			BYTE* Custom_tabs = get_system( Custom_tabs_CODE );			if(Custom_tabs){				char* s = (char*)Custom_tabs+4;				DWORD n = get_DWORD( Custom_tabs );				while(n){					if(!*s) break;					fprintf( hhp, "Custom tab=\"%s\", ", s ); /* This is not a typo */					s += strlen(s) + 1;					if(!*s) break;					fprintf( hhp, "%s\r\n", s );					s += strlen(s) + 1;					n --;				}				FREE(Custom_tabs);			}		}		close_system();		/* [WINDOWS] */		if( open_windows() ){			fputs( "\r\n[WINDOWS]\r\n", hhp );			while( print_windows_entry( hhp ) );			close_windows();			/* FIXME: How to do the following properly			uint i;			bool got_one = true;			for(i = 0; i < num_windows; i++){				got_one = print_windows_entry( hhp );				if(!got_one) break;			}			if(got_one){				/ * So this is only printed when num_windows is a lie * /				fputs( ";The following windows were hidden\r\n", hhp );				while( print_windows_entry( hhp ) );			} */		}		/* [FILES] */		/* This only dumps out names of all non-internal files */		no_files_yet = true;		print_files(".");		FREE(prefix);		prefix_len = prefix_size = 0;		/* [ALIAS], [MAP] */		if( alias_map_success ){			fprintf( hhp,				"\r\n[ALIAS]\r\n"				"#include %s\r\n"				"\r\n[MAP]\r\n"				"#include %s\r\n",				ALIAS_FILE_NAME,				MAP_FILE_NAME			);		}		/* [TEXT POPUPS] */		/*		FIXME: For this we need to grep -l '^[[:space:]]*\.topic[[:space:]]\+[0-9]\+' *.txt | fileno(hhp)		grep or glob()+regcomp() would be ideal, but, dunno if these can be relied on these for example on Win32		the best would be if there were a grep to C script that made optimisations for constant regexps		fputs( "\r\n[TEXT POPUPS]\r\n", hhp );		*/		{ /* [MERGE FILES] */			FILE* idxhdr = fopen("#IDXHDR","rb");			if( idxhdr ){				DWORD num_merge_files;				fseek( idxhdr, 0x48, SEEK_SET );				if( read_DWORD( idxhdr, &num_merge_files ) && num_merge_files ){					DWORD merge_file;					fseek( idxhdr, 4, SEEK_CUR );					fputs( "\r\n[MERGE FILES]\r\n", hhp );					while( read_DWORD( idxhdr, &merge_file ) && merge_file ){						print_string( hhp, merge_file );						fputs( "\r\n", hhp );					}					if( merge_file ){						fputs( ";The following chms were in the internal string list, but not the merge files list\r\n", hhp );						/* stream the rest of the strings file through a \0 to \r\n converter */						print_strings( hhp );					}				}				FCLOSE( idxhdr );			}		}		/* Output this or not? May as well, since HHW does */		fputs( "\r\n[INFOTYPES]\r\n", hhp );		{ /* [SUBSETS] */			struct stat st;			if( stat("#SUBSETS",&st) == 0 ){				uint i, num_subsets = (st.st_size-4)/12;				fputs( "\r\n[SUBSETS]\r\n", hhp );				/* Here we want to print some string out once for each #SUBSETS entry */				 /* FIXME: Rethink the strings below */				if( num_subsets == 1 ) fprintf( hhp, "There was one entry in this section, but only garbage was produced\r\n" );				else if( num_subsets )					for( i = 0; i < num_subsets; i++ )						fprintf( hhp, "There were %u entries in this section, but only garbage was produced\r\n", num_subsets );				if( (st.st_size-4)%12 )					fprintf( stderr, "%s: warning: %s/%s: %s\n", PROGNAME, input, "#SUBSETS", "partial entry found" );			}		}		if( !ferror(hhp) ) hhp_success = true;		else fprintf( stderr, "%s: %s/%s/%s: %s\n", PROGNAME, input, "#recreated", pf, strerror(errno) );		FCLOSE( hhp );	} else fprintf( stderr, "%s: %s/%s/%s: %s\n", PROGNAME, input, "#recreated", pf, strerror(errno) );}/* Returns true if the argument is the name of an internal file */bool isinternal( char* f ){	return		!strcmp( f, "#BSSC" ) ||		!strcmp( f, "#GRPINF" ) ||		!strcmp( f, "#IDXHDR" ) ||		!strcmp( f, "#INFOTYPES" ) ||		!strcmp( f, "#ITBITS" ) ||		!strcmp( f, "#IVB" ) ||		!strcmp( f, "#KEY_DATA" ) ||		!strcmp( f, "#KEY_DELETED" ) ||		!strcmp( f, "#STRINGS" ) ||		!strcmp( f, "#SUBSETS" ) ||		!strcmp( f, "#SYSTEM" ) ||		!strcmp( f, "#TOCIDX" ) ||		!strcmp( f, "#TOPICS" ) ||		!strcmp( f, "#URLS" ) ||		!strcmp( f, "#URLSTR" ) ||		!strcmp( f, "#URLTBL" ) ||		!strcmp( f, "#WINDOWS" ) ||		!strcmp( f, "$FIftiMain" ) ||		!strcmp( f, "$HHTitleMap" ) ||		!strcmp( f, "$OBJINST" ) ||		!strcmp( f, "$TitleMap" ) ||		!strcmp( f, "$WWAssociativeLinks" ) ||		!strcmp( f, "$WWKeywordLinks" ) ||		/* The following may go away when "<input>-rec" in the current dir is where we recreate stuff */		!strcmp( f, "#recreated" ); /* Bit of a kludge, spose i should use the inode (which is not very portable) */}/* Recurse through a dir, printing out the names of files found */void print_files( char* d ){	DIR* dir = opendir( d );	if( dir ){		struct stat st;		struct dirent* de;		/* On cygwin we need to enter the dir first */		chdir( d );		while( (de = readdir( dir )) ){			/* Most systems define these as the current & parent dirs */			if( !strcmp( de->d_name, "." ) || !strcmp( de->d_name, ".." ) )				continue;			/* Ignore internal files, except when not in root */			if( (!prefix || !*prefix) && isinternal(de->d_name) )				continue;			/* Check if it is a subdir */			if( !stat( de->d_name, &st ) && S_ISDIR( st.st_mode ) ){				/* Add the directory name */				size_t old_prefix_len = prefix_len;				size_t new_prefix_len = prefix_len + strlen( de->d_name ) + 1;				size_t new_prefix_size = ((new_prefix_len+1)/PREFIX_GROW+1)*PREFIX_GROW;				if( new_prefix_size > prefix_size ){					char* new_prefix = (char*)realloc( prefix, new_prefix_size );					if( !new_prefix ){						fprintf( stderr, "%s: %s %s: %s\n", PROGNAME, input, "prefix buffer", strerror(errno) );						continue;					}					prefix = new_prefix;					prefix_size = new_prefix_size;				}				strcpy( prefix+prefix_len, de->d_name );				prefix[new_prefix_len-1] = '\\';				prefix[new_prefix_len] = '\0';				prefix_len = new_prefix_len;				/* Print any files in the subdir */				print_files( de->d_name );				/* Strip away the last path */				prefix_len = old_prefix_len;				prefix[prefix_len] = '\0';			} else {				/* FIXME: what is the best way to speed this up? */				if( no_files_yet ){					fputs( "\r\n[FILES]\r\n", hhp );					no_files_yet = false;				}				/* Print the filename */				fprintf( hhp, "%s%s\r\n", prefix?prefix:"", de->d_name );			}		}		/* Back out */		if( !!strcmp( d, "." ) ) chdir( ".." );		closedir( dir );	} else		fprintf( stderr, "%s: %s/%s/%s: %s\n", PROGNAME, input, prefix?prefix:"", d, strerror(errno) );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -