pvpgn-1.8.5/0000755000175000017500000000000011151347031011635 5ustar aaronaaronpvpgn-1.8.5/bin/0000755000175000017500000000000011151345372012413 5ustar aaronaaronpvpgn-1.8.5/NEWS0000644000175000017500000001125311151345317012343 0ustar aaronaaron PvPGN 1.7.x Major Changes And New Features ============================================== o Westwood Online (WOL) support This is a historic moment in the life of the PvPGN project. For the first time a different gaming network than Battle.net is supported with PvPGN. Current support works with Tiberian Sun (TS), Red Alert 2 (RA2) and Yuri's Revenge (YR). o WIN32 GUI for d2cs and d2dbs d2cs and d2bs now feature a new slick GUI if build under WIN32. o Instant startup (partial) PvPGN now can startup in a lot lesser time than before, this is due to code changes which make it not load all accounts at startup. This improvement should be mostly noticed on very high number of accounts servers. Note that currently this happens only to SQL storage types (the file based storage types still load all accounts at startup). o Optimized account loading/saving codes Account loading/saving codes have been rewritten allowing PvPGN to scale a lot better with a high number of online users (ie lower CPU usage). o Better game result calculation Game result decision has been completly changed to use a democratic ellection scheme (ie it bases the decision on the oppinions of the most results). This should solve problems with game results beeing wrong under some situations (like team games). o New WIN32 compiler/enviroment support Now you can compile PvPGN under WIN32 using complete GPL/free build tools by using Dev-C++ project and additional tools (mingw, etc). o Optimized handling of D2 clients Replaced a O(n) search algorithm through the client connection list used mostly by D2 handling functions with a O(1) algorithm. o Optimized timers codes Timers codes have been rewritten so the most used functions complete a lot faster than before. This improves PvPGN CPU usage a lot because some timers functions are used very often inside PvPGN. o Memory management changes and optimizations There has been added some memory management wrappers functions which never fail and thus the calling codes were simplified a lot by removing checks to memory allocation failures. If memory allocation fails PvPGN tries to recover by programming an immediate shutdown and cleaning up some safe memory. o Changed codes to use logged in username instead of account username This change makes PvPGN use the username introduced at login (with the exact case as in login) instead of the account name. This solves some bugs (like could not edit profile in D2 if logged in with different case) and also gets us more close to Battle.Net. o Switched from string based tags to integer based tags Codes have been dramatically changed to use integers for storing of tags (client tags, architecture tags, etc) and thus when comparing tags we use plain integer comparation instead of string comparation. This should reduce CPU usage a lot. o Optimized list handling codes The list API has been changed and the codes have been optimized so it will remove elements from the list upon request and not later, thus eliminating a O(n) search and thus making PvPGN a lot faster. o Unified and extended address translation system We have unified all address translation files and codes to use a single address_translation.conf file for this job. Also the file syntax has been completly changed to be more flexible and allow configuration of almost any thinkable NAT setup. o IRC support reworked IRC client support has been bugfixed, optimized and made to work with a lot more IRC clients. o Unified file based storage File based storage (plain and cdb) have been unified into a single storage backend (called "file") and the mode (plain/cdb) is just a parameter. o Rewritten low level socket multiplexing codes (fdwatch2) The codes which deal with how PvPGN knows which sockets are available for reading/writing have been rewritten with a new interface which does not presume (like the old codes) that the underlying OS allocates socket values "close" (ex. WIN32 systems do not while most Unix based systems do so). The new codes eliminates this presumtion and thus allows WIN32 hosts to support a large number of connections as PvPGN supported Unix based platforms. o Added more storage types: SQLite3 and ODBC With 1.7.x PvPGN now supports besides the MySQL/PostgreSQL SQL backends also SQLite3 (www.sqlite.org) and ... ODBC SQL engine !! This means that theoretically now you should be able to use PvPGN with almost any SQL engine as long as an ODBC driver exists for it. pvpgn-1.8.5/Win32-Projects/0000755000175000017500000000000011151345372014334 5ustar aaronaaronpvpgn-1.8.5/Win32-Projects/bncdb.dev0000644000175000017500000001145511151345317016111 0ustar aaronaaron[Project] FileName=bncdb.dev Name=bncdb UnitCount=26 Type=1 Ver=1 ObjFiles= Includes=..\src Libs= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=_@@_ IsCpp=0 Icon= ExeOutput=..\bin ObjectOutput= OverrideOutput=0 OverrideOutputName=bncdb.exe HostApplication= Folders=bncdb,"bncdb/Header Files","bncdb/Source Files",common,"common/Header Files","common/Source Files",compat,"compat/Header Files","compat/Source Files" CommandLine= UseCustomMakefile=0 IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 CustomMakefile= PrivateResource= [Unit1] FileName=..\src\tinycdb\cdb_unpack.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\src\tinycdb\cdb.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\src\tinycdb\cdb.h CompileCpp=0 Folder=bncdb/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\src\tinycdb\cdb_find.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\src\tinycdb\cdb_findnext.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\src\tinycdb\cdb_hash.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\src\tinycdb\cdb_init.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\src\tinycdb\cdb_int.h CompileCpp=0 Folder=bncdb/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\src\tinycdb\cdb_make.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\src\tinycdb\cdb_make_add.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\src\tinycdb\cdb_make_find.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\src\tinycdb\cdb_make_put.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\src\tinycdb\cdb_seek.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\src\tinycdb\cdb_seq.c CompileCpp=0 Folder=bncdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\src\common\xalloc.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\src\common\eventlog.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\src\common\hexdump.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\src\compat\mmap.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\src\compat\getopt.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\src\common\xalloc.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\src\common\eventlog.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\src\common\hexdump.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\src\compat\mmap.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\src\compat\getopt.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion=0.1 FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=bncdb.exe ProductName=bncdb ProductVersion=0.1 AutoIncBuildNr=0 [Unit25] FileName=..\src\compat\strerror.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\src\compat\strerror.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= pvpgn-1.8.5/Win32-Projects/d2dbs.dev0000644000175000017500000002165311151345317016040 0ustar aaronaaron[Project] FileName=d2dbs.dev Name=d2dbs UnitCount=57 Type=0 Ver=1 ObjFiles= Includes=..\src Libs= ResourceIncludes=..\src MakeIncludes= Compiler=-DWIN32_GUI_@@_ CppCompiler= Linker=-lws2_32_@@_ IsCpp=0 Icon=d2dbs.ico ExeOutput=..\bin ObjectOutput= OverrideOutput=0 OverrideOutputName=d2dbs.exe HostApplication= Folders=common,"common/Header Files","common/Source Files",compat,"compat/Header Files","compat/Source Files",d2dbs,"d2dbs/Header Files","d2dbs/Source Files",win32,"win32/Header Files","win32/Resource Files","win32/Source Files" CommandLine= UseCustomMakefile=0 IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 CustomMakefile= PrivateResource=d2dbs_private.rc [Unit1] FileName=..\src\win32\service.h CompileCpp=0 Folder=win32/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\src\win32\service.c CompileCpp=0 Folder=win32/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\src\d2dbs\version.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\src\d2dbs\charlock.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\src\d2dbs\d2ladder.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\src\d2dbs\dbsdupecheck.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\src\d2dbs\dbserver.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\src\d2dbs\dbspacket.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\src\d2dbs\handle_signal.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\src\d2dbs\prefs.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\src\d2dbs\setup.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\src\d2dbs\prefs.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\src\d2dbs\charlock.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\src\d2dbs\d2ladder.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\src\d2dbs\dbsdupecheck.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\src\d2dbs\dbserver.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\src\d2dbs\dbspacket.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\src\d2dbs\handle_signal.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\src\d2dbs\main.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\src\common\xalloc.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\src\common\addr.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\src\common\bn_type.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\src\common\d2char_checksum.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\src\common\eventlog.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=..\src\common\hexdump.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\src\common\list.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=..\src\common\util.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=..\src\compat\strsep.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=..\src\compat\inet_aton.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit30] FileName=..\src\compat\psock.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit31] FileName=..\src\compat\strerror.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=..\src\common\util.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit33] FileName=..\src\common\addr.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit34] FileName=..\src\common\bn_type.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit35] FileName=..\src\common\d2char_checksum.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit36] FileName=..\src\common\eventlog.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit37] FileName=..\src\common\hexdump.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit38] FileName=..\src\common\list.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit39] FileName=..\src\compat\strsep.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit40] FileName=..\src\compat\inet_aton.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit41] FileName=..\src\compat\psock.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit42] FileName=..\src\compat\strerror.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit43] FileName=..\src\common\xalloc.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit44] FileName=..\src\win32\d2dbs_winmain.c CompileCpp=0 Folder=win32/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit45] FileName=..\src\win32\winmain.h CompileCpp=0 Folder=win32/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion=0.1 FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=d2dbs.exe ProductName=d2dbs ProductVersion=0.1 AutoIncBuildNr=0 [Unit46] FileName=..\src\win32\d2dbs_resource.rc CompileCpp=0 Folder=win32/Resource Files Compile=1 Link=0 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit47] FileName=..\src\win32\d2dbs_resource.h CompileCpp=0 Folder=win32/Resource Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit48] FileName=..\src\common\packet.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit49] FileName=..\src\common\network.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit50] FileName=..\src\common\packet.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit51] FileName=..\src\common\network.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit52] FileName=..\src\common\conf.h Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= CompileCpp=0 [Unit53] FileName=..\src\common\conf.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit54] FileName=..\src\d2dbs\cmdline.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit55] FileName=..\src\d2dbs\cmdline.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit56] FileName=..\src\common\xstring.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit57] FileName=..\src\common\xstring.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= pvpgn-1.8.5/Win32-Projects/PvPGN.sln0000644000175000017500000000646211151345317016013 0ustar aaronaaronMicrosoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bncdb", "bncdb.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F0}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bnchat", "bnchat.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F4}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bnftp", "bnftp.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F5}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d2cs", "d2cs.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F1}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d2dbs", "d2dbs.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F2}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PvPGN", "PvPGN.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F3}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Release = Release EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {300F80E0-1A0E-4639-AEB9-18A692FF35F0}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F0}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F0}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F0}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F4}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F4}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F4}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F4}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F5}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F5}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F5}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F5}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F1}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F1}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F1}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F1}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F2}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F2}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F2}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F2}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F3}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F3}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F3}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F3}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal pvpgn-1.8.5/Win32-Projects/PvPGN.vcproj0000644000175000017500000006377411151345317016533 0ustar aaronaaron pvpgn-1.8.5/Win32-Projects/PvPGNConsole.sln0000644000175000017500000000653011151345317017332 0ustar aaronaaronMicrosoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PvPGNConsole", "PvPGNConsole.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F3}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d2csConsole", "d2csConsole.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F1}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d2dbsConsole", "d2dbsConsole.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F2}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bncdb", "bncdb.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F0}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bnchat", "bnchat.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F4}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bnftp", "bnftp.vcproj", "{300F80E0-1A0E-4639-AEB9-18A692FF35F5}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Release = Release EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {300F80E0-1A0E-4639-AEB9-18A692FF35F3}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F3}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F3}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F3}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F1}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F1}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F1}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F1}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F2}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F2}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F2}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F2}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F0}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F0}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F0}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F0}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F4}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F4}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F4}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F4}.Release.Build.0 = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F5}.Debug.ActiveCfg = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F5}.Debug.Build.0 = Debug|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F5}.Release.ActiveCfg = Release|Win32 {300F80E0-1A0E-4639-AEB9-18A692FF35F5}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal pvpgn-1.8.5/Win32-Projects/bnchat.vcproj0000644000175000017500000001746011151345317017027 0ustar aaronaaron pvpgn-1.8.5/Win32-Projects/bnftp.vcproj0000644000175000017500000001655511151345317016705 0ustar aaronaaron pvpgn-1.8.5/Win32-Projects/d2cs.vcproj0000644000175000017500000003142711151345317016422 0ustar aaronaaron pvpgn-1.8.5/Win32-Projects/PvPGNConsole.dev0000644000175000017500000012445311151345317017321 0ustar aaronaaron[Project] FileName=PvPGNConsole.dev Name=PvPGNConsole UnitCount=293 Type=1 Ver=1 ObjFiles= Includes=..\src Libs= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=-lws2_32_@@_ IsCpp=0 Icon=PvPGNConsole.ico ExeOutput=..\bin ObjectOutput= OverrideOutput=0 OverrideOutputName=PvPGNConsole.exe HostApplication= Folders=bnetd,"bnetd/Header Files","bnetd/Source Files",common,"common/Header Files","common/Source Files",compat,"compat/Header Files","compat/Source Files",tinycdb,"tinycdb/Header Files","tinycdb/Source Files",win32,"win32/Header Files","win32/Source Files",zlib,"zlib/Header Files","zlib/Source Files" CommandLine= UseCustomMakefile=0 IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 CustomMakefile= PrivateResource=PvPGNConsole_private.rc [Unit1] FileName=..\src\bnetd\watch.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\src\bnetd\account.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\src\bnetd\account_wrap.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\src\bnetd\adbanner.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\src\bnetd\alias_command.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\src\bnetd\anongame.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\src\bnetd\anongame_gameresult.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\src\bnetd\anongame_infos.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\src\bnetd\anongame_maplists.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\src\bnetd\autoupdate.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\src\bnetd\channel.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\src\bnetd\channel_conv.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\src\bnetd\character.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\src\bnetd\clan.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\src\bnetd\command.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\src\bnetd\command_groups.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\src\bnetd\connection.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\src\bnetd\file.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\src\bnetd\file_cdb.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\src\bnetd\file_plain.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\src\bnetd\friends.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\src\bnetd\game.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\src\bnetd\game_conv.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\src\bnetd\handle_anongame.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=..\src\bnetd\handle_bnet.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\src\bnetd\handle_bot.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=..\src\bnetd\handle_d2cs.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=..\src\bnetd\handle_file.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=..\src\bnetd\handle_init.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit30] FileName=..\src\bnetd\handle_irc.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit31] FileName=..\src\bnetd\handle_telnet.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=..\src\bnetd\handle_udp.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit33] FileName=..\src\bnetd\helpfile.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit34] FileName=..\src\bnetd\ipban.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit35] FileName=..\src\bnetd\irc.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit36] FileName=..\src\bnetd\ladder.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit37] FileName=..\src\bnetd\ladder_binary.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit38] FileName=..\src\bnetd\ladder_calc.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit39] FileName=..\src\bnetd\mail.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit40] FileName=..\src\bnetd\main.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit41] FileName=..\src\bnetd\message.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit42] FileName=..\src\bnetd\news.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit43] FileName=..\src\bnetd\output.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit44] FileName=..\src\bnetd\prefs.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit45] FileName=..\src\bnetd\realm.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit46] FileName=..\src\bnetd\runprog.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit47] FileName=..\src\bnetd\server.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit48] FileName=..\src\bnetd\sql_dbcreator.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit49] FileName=..\src\bnetd\sql_mysql.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit50] FileName=..\src\bnetd\sql_pgsql.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit51] FileName=..\src\bnetd\storage.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit52] FileName=..\src\bnetd\storage_file.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit53] FileName=..\src\bnetd\storage_sql.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit54] FileName=..\src\bnetd\support.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit55] FileName=..\src\bnetd\tick.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit56] FileName=..\src\bnetd\timer.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit57] FileName=..\src\bnetd\topic.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit58] FileName=..\src\bnetd\tournament.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit59] FileName=..\src\bnetd\tracker.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit60] FileName=..\src\bnetd\udptest_send.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit61] FileName=..\src\bnetd\versioncheck.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit62] FileName=..\src\bnetd\account.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit63] FileName=..\src\bnetd\account_wrap.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit64] FileName=..\src\bnetd\adbanner.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit65] FileName=..\src\bnetd\alias_command.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit66] FileName=..\src\bnetd\anongame.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit67] FileName=..\src\bnetd\anongame_gameresult.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit68] FileName=..\src\bnetd\anongame_infos.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit69] FileName=..\src\bnetd\anongame_maplists.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit70] FileName=..\src\bnetd\autoupdate.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit71] FileName=..\src\bnetd\channel.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit72] FileName=..\src\bnetd\channel_conv.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit73] FileName=..\src\bnetd\character.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit74] FileName=..\src\bnetd\clan.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit75] FileName=..\src\bnetd\command.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit76] FileName=..\src\bnetd\command_groups.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit77] FileName=..\src\bnetd\connection.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit78] FileName=..\src\bnetd\file.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit79] FileName=..\src\bnetd\file_cdb.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit80] FileName=..\src\bnetd\file_plain.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit81] FileName=..\src\bnetd\friends.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit82] FileName=..\src\bnetd\game.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit83] FileName=..\src\bnetd\game_conv.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit84] FileName=..\src\bnetd\handle_anongame.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit85] FileName=..\src\bnetd\handle_bnet.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit86] FileName=..\src\bnetd\handle_bot.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit87] FileName=..\src\bnetd\handle_d2cs.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit88] FileName=..\src\bnetd\handle_file.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit89] FileName=..\src\bnetd\handle_init.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit90] FileName=..\src\bnetd\handle_irc.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit91] FileName=..\src\bnetd\handle_telnet.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit92] FileName=..\src\bnetd\handle_udp.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit93] FileName=..\src\bnetd\handlers.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit94] FileName=..\src\bnetd\helpfile.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit95] FileName=..\src\bnetd\ipban.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit96] FileName=..\src\bnetd\irc.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit97] FileName=..\src\bnetd\ladder.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit98] FileName=..\src\bnetd\ladder_binary.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit99] FileName=..\src\bnetd\ladder_calc.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit100] FileName=..\src\bnetd\mail.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit101] FileName=..\src\bnetd\message.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit102] FileName=..\src\bnetd\news.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit103] FileName=..\src\bnetd\output.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit104] FileName=..\src\bnetd\prefs.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit105] FileName=..\src\bnetd\quota.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit106] FileName=..\src\bnetd\realm.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit107] FileName=..\src\bnetd\runprog.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit108] FileName=..\src\bnetd\server.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit109] FileName=..\src\bnetd\sql_dbcreator.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit110] FileName=..\src\bnetd\sql_mysql.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit111] FileName=..\src\bnetd\sql_pgsql.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit112] FileName=..\src\bnetd\storage.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit113] FileName=..\src\bnetd\storage_file.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit114] FileName=..\src\bnetd\storage_sql.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit115] FileName=..\src\bnetd\support.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit116] FileName=..\src\bnetd\tick.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit117] FileName=..\src\bnetd\timer.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit118] FileName=..\src\bnetd\topic.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit119] FileName=..\src\bnetd\tournament.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit120] FileName=..\src\bnetd\udptest_send.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit121] FileName=..\src\bnetd\versioncheck.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit122] FileName=..\src\bnetd\watch.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit123] FileName=..\src\common\xalloc.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit124] FileName=..\src\common\addr.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit125] FileName=..\src\common\anongame_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=..\ ProductName= ProductVersion= AutoIncBuildNr=0 [Unit126] FileName=..\src\common\bn_type.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit127] FileName=..\src\common\bnet_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit128] FileName=..\src\common\bnethash.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit129] FileName=..\src\common\bnethashconv.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit130] FileName=..\src\common\bnettime.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit131] FileName=..\src\common\bot_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit132] FileName=..\src\common\d2char_checksum.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit133] FileName=..\src\common\d2char_file.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit134] FileName=..\src\common\d2game_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit135] FileName=..\src\common\elist.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit136] FileName=..\src\common\eventlog.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit137] FileName=..\src\common\fdwatch.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit138] FileName=..\src\common\fdwatch_epoll.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit139] FileName=..\src\common\fdwatch_kqueue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit140] FileName=..\src\common\fdwatch_poll.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit141] FileName=..\src\common\fdwatch_select.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit142] FileName=..\src\common\field_sizes.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit143] FileName=..\src\common\file_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit144] FileName=..\src\common\flags.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit145] FileName=..\src\common\give_up_root_privileges.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit146] FileName=..\src\common\hashtable.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit147] FileName=..\src\common\hexdump.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit148] FileName=..\src\common\init_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit149] FileName=..\src\common\introtate.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit150] FileName=..\src\common\irc_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit151] FileName=..\src\common\list.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit152] FileName=..\src\common\network.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit153] FileName=..\src\common\packet.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit154] FileName=..\src\common\proginfo.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit155] FileName=..\src\common\queue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit156] FileName=..\src\common\rlimit.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit157] FileName=..\src\common\setup_after.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit158] FileName=..\src\common\setup_before.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit159] FileName=..\src\common\tag.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit160] FileName=..\src\common\token.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit161] FileName=..\src\common\tracker.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit162] FileName=..\src\common\trans.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit163] FileName=..\src\common\udp_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit164] FileName=..\src\common\util.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit165] FileName=..\src\common\version.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit166] FileName=..\src\common\xalloc.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit167] FileName=..\src\common\addr.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit168] FileName=..\src\common\bn_type.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit169] FileName=..\src\common\bnethash.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit170] FileName=..\src\common\bnethashconv.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit171] FileName=..\src\common\bnettime.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit172] FileName=..\src\common\d2char_checksum.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit173] FileName=..\src\common\eventlog.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit174] FileName=..\src\common\fdwatch.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit175] FileName=..\src\common\fdwatch_epoll.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit176] FileName=..\src\common\fdwatch_kqueue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit177] FileName=..\src\common\fdwatch_poll.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit178] FileName=..\src\common\fdwatch_select.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit179] FileName=..\src\common\give_up_root_privileges.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit180] FileName=..\src\common\hashtable.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit181] FileName=..\src\common\hexdump.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit182] FileName=..\src\common\list.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit183] FileName=..\src\common\network.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit184] FileName=..\src\common\packet.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit185] FileName=..\src\common\proginfo.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit186] FileName=..\src\common\queue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit187] FileName=..\src\common\rlimit.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit188] FileName=..\src\common\tag.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit189] FileName=..\src\common\token.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit190] FileName=..\src\common\trans.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit191] FileName=..\src\common\util.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit192] FileName=..\src\compat\uname.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit193] FileName=..\src\compat\access.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit194] FileName=..\src\compat\char_bit.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit195] FileName=..\src\compat\difftime.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit196] FileName=..\src\compat\exitstatus.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit197] FileName=..\src\compat\gethostname.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit198] FileName=..\src\compat\getopt.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit199] FileName=..\src\compat\gettimeofday.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit200] FileName=..\src\compat\inet_aton.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit201] FileName=..\src\compat\inet_ntoa.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit202] FileName=..\src\compat\memcpy.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit203] FileName=..\src\compat\memmove.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit204] FileName=..\src\compat\memset.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit205] FileName=..\src\compat\mkdir.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit206] FileName=..\src\compat\mmap.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit207] FileName=..\src\compat\netinet_in.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit208] FileName=..\src\compat\pdir.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit209] FileName=..\src\compat\psock.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit210] FileName=..\src\compat\read.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit211] FileName=..\src\compat\recv.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit212] FileName=..\src\compat\seek.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit213] FileName=..\src\compat\send.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit214] FileName=..\src\compat\signal.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit215] FileName=..\src\compat\socket.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit216] FileName=..\src\compat\statmacros.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit217] FileName=..\src\compat\stdfileno.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit218] FileName=..\src\compat\strcasecmp.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit219] FileName=..\src\compat\strchr.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit220] FileName=..\src\compat\strdup.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit221] FileName=..\src\compat\strerror.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit222] FileName=..\src\compat\strftime.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit223] FileName=..\src\compat\strncasecmp.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit224] FileName=..\src\compat\strrchr.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit225] FileName=..\src\compat\strsep.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit226] FileName=..\src\compat\strtoul.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit227] FileName=..\src\compat\termios.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit228] FileName=..\src\compat\uint.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit229] FileName=..\src\compat\uname.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit230] FileName=..\src\compat\difftime.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit231] FileName=..\src\compat\getopt.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit232] FileName=..\src\compat\gettimeofday.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit233] FileName=..\src\compat\inet_aton.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit234] FileName=..\src\compat\inet_ntoa.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit235] FileName=..\src\compat\memcpy.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit236] FileName=..\src\compat\memmove.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit237] FileName=..\src\compat\memset.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit238] FileName=..\src\compat\mmap.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit239] FileName=..\src\compat\pdir.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit240] FileName=..\src\compat\psock.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit241] FileName=..\src\compat\strcasecmp.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit242] FileName=..\src\compat\strdup.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit243] FileName=..\src\compat\strerror.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit244] FileName=..\src\compat\strftime.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit245] FileName=..\src\compat\strncasecmp.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit246] FileName=..\src\compat\strsep.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit247] FileName=..\src\compat\strtoul.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit248] FileName=..\src\zlib\pvpgn_zutil.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit249] FileName=..\src\zlib\pvpgn_deflate.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit250] FileName=..\src\zlib\pvpgn_trees.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit251] FileName=..\src\zlib\pvpgn_zconf.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit252] FileName=..\src\zlib\pvpgn_zlib.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit253] FileName=..\src\zlib\pvpgn_zutil.c CompileCpp=0 Folder=zlib/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit254] FileName=..\src\zlib\pvpgn_adler32.c CompileCpp=0 Folder=zlib/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit255] FileName=..\src\zlib\pvpgn_deflate.c CompileCpp=0 Folder=zlib/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit256] FileName=..\src\zlib\pvpgn_trees.c CompileCpp=0 Folder=zlib/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit257] FileName=..\src\tinycdb\cdb_int.h CompileCpp=0 Folder=tinycdb/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit258] FileName=..\src\tinycdb\cdb_unpack.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit259] FileName=..\src\tinycdb\cdb_find.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit260] FileName=..\src\tinycdb\cdb_findnext.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit261] FileName=..\src\tinycdb\cdb_hash.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit262] FileName=..\src\tinycdb\cdb_init.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit263] FileName=..\src\tinycdb\cdb_make.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit264] FileName=..\src\tinycdb\cdb_make_add.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit265] FileName=..\src\tinycdb\cdb_make_find.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit266] FileName=..\src\tinycdb\cdb_make_put.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit267] FileName=..\src\tinycdb\cdb_seek.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit268] FileName=..\src\tinycdb\cdb_seq.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit269] FileName=..\src\win32\service.h CompileCpp=0 Folder=win32/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit270] FileName=..\src\win32\service.c CompileCpp=0 Folder=win32/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit271] FileName=..\src\bnetd\team.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit272] FileName=..\src\bnetd\team.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit273] FileName=..\src\common\rcm.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit274] FileName=..\src\common\rcm.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit275] FileName=..\src\bnetd\attr.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit276] FileName=..\src\bnetd\attrlayer.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit277] FileName=..\src\bnetd\attrgroup.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit278] FileName=..\src\bnetd\attrlayer.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit279] FileName=..\src\bnetd\attrgroup.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit280] FileName=..\src\bnetd\cmdline.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit281] FileName=..\src\bnetd\cmdline.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit282] FileName=..\src\common\conf.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit283] FileName=..\src\common\conf.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit284] FileName=..\src\bnetd\sql_common.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit285] FileName=..\src\bnetd\sql_sqlite3.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit286] FileName=..\src\bnetd\sql_odbc.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit287] FileName=..\src\bnetd\sql_sqlite3.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit288] FileName=..\src\bnetd\sql_common.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit289] FileName=..\src\bnetd\sql_odbc.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit290] FileName=..\src\common\xstr.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit291] FileName=..\src\common\xstr.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit292] FileName=..\src\bnetd\storage_sql2.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit293] FileName=..\src\bnetd\storage_sql2.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= pvpgn-1.8.5/Win32-Projects/d2cs.dev0000644000175000017500000004441111151345317015672 0ustar aaronaaron[Project] FileName=d2cs.dev Name=d2cs UnitCount=124 Type=0 Ver=1 ObjFiles= Includes=..\src Libs= ResourceIncludes=..\src MakeIncludes= Compiler=-DWIN32_GUI_@@_ CppCompiler= Linker=-lws2_32_@@_ IsCpp=0 Icon=d2cs.ico ExeOutput=..\bin ObjectOutput= OverrideOutput=0 OverrideOutputName=d2cs.exe HostApplication= Folders=common,"common/Header Files","common/Source Files",compat,"compat/Header Files","compat/Source Files",d2cs,"d2cs/Header Files","d2cs/Source Files",win32,"win32/Header Files","win32/Resource Files","win32/Source Files" CommandLine= UseCustomMakefile=0 IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 CustomMakefile= PrivateResource=d2cs_private.rc [Unit1] FileName=..\src\d2cs\bit.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\src\d2cs\bnetd.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\src\d2cs\connection.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\src\d2cs\d2charfile.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\src\d2cs\d2charlist.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\src\d2cs\d2cs_bnetd_protocol.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\src\d2cs\d2cs_d2dbs_ladder.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\src\d2cs\d2cs_d2gs_character.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\src\d2cs\d2cs_d2gs_protocol.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\src\d2cs\d2cs_protocol.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\src\d2cs\d2gs.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\src\d2cs\d2ladder.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\src\d2cs\game.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\src\d2cs\gamequeue.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\src\d2cs\handle_bnetd.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\src\d2cs\handle_d2cs.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\src\d2cs\handle_d2gs.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\src\d2cs\handle_init.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\src\d2cs\handle_signal.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\src\d2cs\net.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\src\d2cs\prefs.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\src\d2cs\s2s.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\src\d2cs\server.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\src\d2cs\serverqueue.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=..\src\d2cs\setup.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\src\d2cs\version.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=..\src\d2cs\bnetd.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=..\src\d2cs\connection.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=..\src\d2cs\d2charfile.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit30] FileName=..\src\d2cs\d2charlist.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit31] FileName=..\src\d2cs\d2gs.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=..\src\d2cs\d2ladder.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit33] FileName=..\src\d2cs\game.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit34] FileName=..\src\d2cs\gamequeue.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit35] FileName=..\src\d2cs\handle_bnetd.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit36] FileName=..\src\d2cs\handle_d2cs.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit37] FileName=..\src\d2cs\handle_d2gs.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit38] FileName=..\src\d2cs\handle_init.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit39] FileName=..\src\d2cs\handle_signal.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit40] FileName=..\src\d2cs\main.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit41] FileName=..\src\d2cs\net.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit42] FileName=..\src\d2cs\prefs.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit43] FileName=..\src\d2cs\s2s.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit44] FileName=..\src\d2cs\server.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit45] FileName=..\src\d2cs\serverqueue.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit46] FileName=..\src\common\xalloc.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit47] FileName=..\src\common\addr.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit48] FileName=..\src\common\bn_type.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit49] FileName=..\src\common\d2char_checksum.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit50] FileName=..\src\common\eventlog.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit51] FileName=..\src\common\fdwatch.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit52] FileName=..\src\common\fdwatch_epoll.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit53] FileName=..\src\common\fdwatch_kqueue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit54] FileName=..\src\common\fdwatch_poll.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit55] FileName=..\src\common\fdwatch_select.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit56] FileName=..\src\common\hashtable.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit57] FileName=..\src\common\hexdump.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit58] FileName=..\src\common\list.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit59] FileName=..\src\common\network.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit60] FileName=..\src\common\packet.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit61] FileName=..\src\common\queue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit62] FileName=..\src\common\rlimit.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit63] FileName=..\src\common\trans.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit64] FileName=..\src\common\util.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit65] FileName=..\src\common\xalloc.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit66] FileName=..\src\common\addr.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit67] FileName=..\src\common\bn_type.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit68] FileName=..\src\common\d2char_checksum.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit69] FileName=..\src\common\eventlog.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit70] FileName=..\src\common\fdwatch.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit71] FileName=..\src\common\fdwatch_epoll.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit72] FileName=..\src\common\fdwatch_kqueue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit73] FileName=..\src\common\fdwatch_poll.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit74] FileName=..\src\common\fdwatch_select.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit75] FileName=..\src\common\hashtable.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit76] FileName=..\src\common\hexdump.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit77] FileName=..\src\common\list.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit78] FileName=..\src\common\network.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit79] FileName=..\src\common\packet.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit80] FileName=..\src\common\queue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit81] FileName=..\src\common\rlimit.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit82] FileName=..\src\common\trans.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit83] FileName=..\src\common\util.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit84] FileName=..\src\compat\uname.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit85] FileName=..\src\compat\difftime.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit86] FileName=..\src\compat\gettimeofday.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit87] FileName=..\src\compat\inet_aton.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit88] FileName=..\src\compat\inet_ntoa.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit89] FileName=..\src\compat\pdir.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit90] FileName=..\src\compat\psock.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit91] FileName=..\src\compat\strcasecmp.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit92] FileName=..\src\compat\strdup.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit93] FileName=..\src\compat\strerror.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit94] FileName=..\src\compat\strftime.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit95] FileName=..\src\compat\strncasecmp.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit96] FileName=..\src\compat\strsep.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit97] FileName=..\src\compat\strtoul.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit98] FileName=..\src\compat\strsep.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit99] FileName=..\src\compat\strtoul.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit100] FileName=..\src\compat\uname.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit101] FileName=..\src\compat\access.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit102] FileName=..\src\compat\difftime.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit103] FileName=..\src\compat\gettimeofday.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit104] FileName=..\src\compat\inet_aton.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit105] FileName=..\src\compat\inet_ntoa.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit106] FileName=..\src\compat\pdir.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit107] FileName=..\src\compat\psock.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit108] FileName=..\src\compat\strcasecmp.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit109] FileName=..\src\compat\strdup.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit110] FileName=..\src\compat\strerror.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit111] FileName=..\src\compat\strftime.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit112] FileName=..\src\compat\strncasecmp.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit113] FileName=..\src\win32\service.h CompileCpp=0 Folder=win32/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit114] FileName=..\src\win32\service.c CompileCpp=0 Folder=win32/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit115] FileName=..\src\win32\d2cs_resource.h CompileCpp=0 Folder=win32/Resource Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit116] FileName=..\src\win32\d2cs_resource.rc CompileCpp=0 Folder=win32/Resource Files Compile=1 Link=0 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit117] FileName=..\src\win32\winmain.h CompileCpp=0 Folder=win32/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit118] FileName=..\src\win32\d2cs_winmain.c CompileCpp=0 Folder=win32/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion=0.1 FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=d2cs.exe ProductName=d2cs ProductVersion=0.1 AutoIncBuildNr=0 [Unit119] FileName=..\src\common\conf.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit120] FileName=..\src\common\conf.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit121] FileName=..\src\d2cs\cmdline.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit122] FileName=..\src\d2cs\cmdline.c Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= CompileCpp=0 [Unit123] FileName=..\src\common\xstring.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit124] FileName=..\src\common\xstring.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= pvpgn-1.8.5/Win32-Projects/d2csConsole.dev0000644000175000017500000004326211151345317017220 0ustar aaronaaron[Project] FileName=d2csConsole.dev Name=d2csConsole UnitCount=120 Type=1 Ver=1 ObjFiles= Includes=..\src Libs= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=-lws2_32_@@_ IsCpp=0 Icon=d2csConsole.ico ExeOutput=..\bin ObjectOutput= OverrideOutput=0 OverrideOutputName=d2csConsole.exe HostApplication= Folders=common,"common/Header Files","common/Source Files",compat,"compat/Header Files","compat/Source Files",d2cs,"d2cs/Header Files","d2cs/Source Files",win32,"win32/Header Files","win32/Source Files" CommandLine= UseCustomMakefile=0 IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 CustomMakefile= PrivateResource=d2csConsole_private.rc [Unit1] FileName=..\src\d2cs\bit.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\src\d2cs\bnetd.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\src\d2cs\connection.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\src\d2cs\d2charfile.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\src\d2cs\d2charlist.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\src\d2cs\d2cs_bnetd_protocol.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\src\d2cs\d2cs_d2dbs_ladder.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\src\d2cs\d2cs_d2gs_character.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\src\d2cs\d2cs_d2gs_protocol.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\src\d2cs\d2cs_protocol.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\src\d2cs\d2gs.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\src\d2cs\d2ladder.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\src\d2cs\game.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\src\d2cs\gamequeue.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\src\d2cs\handle_bnetd.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\src\d2cs\handle_d2cs.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\src\d2cs\handle_d2gs.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\src\d2cs\handle_init.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\src\d2cs\handle_signal.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\src\d2cs\net.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\src\d2cs\prefs.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\src\d2cs\s2s.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\src\d2cs\server.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\src\d2cs\serverqueue.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=..\src\d2cs\setup.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\src\d2cs\version.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=..\src\d2cs\bnetd.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=..\src\d2cs\connection.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=..\src\d2cs\d2charfile.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit30] FileName=..\src\d2cs\d2charlist.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit31] FileName=..\src\d2cs\d2gs.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=..\src\d2cs\d2ladder.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit33] FileName=..\src\d2cs\game.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit34] FileName=..\src\d2cs\gamequeue.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit35] FileName=..\src\d2cs\handle_bnetd.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit36] FileName=..\src\d2cs\handle_d2cs.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit37] FileName=..\src\d2cs\handle_d2gs.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit38] FileName=..\src\d2cs\handle_init.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit39] FileName=..\src\d2cs\handle_signal.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit40] FileName=..\src\d2cs\main.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit41] FileName=..\src\d2cs\net.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit42] FileName=..\src\d2cs\prefs.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit43] FileName=..\src\d2cs\s2s.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit44] FileName=..\src\d2cs\server.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit45] FileName=..\src\d2cs\serverqueue.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit46] FileName=..\src\common\xalloc.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit47] FileName=..\src\common\addr.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit48] FileName=..\src\common\bn_type.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit49] FileName=..\src\common\d2char_checksum.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit50] FileName=..\src\common\eventlog.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit51] FileName=..\src\common\fdwatch.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit52] FileName=..\src\common\fdwatch_epoll.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit53] FileName=..\src\common\fdwatch_kqueue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit54] FileName=..\src\common\fdwatch_poll.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit55] FileName=..\src\common\fdwatch_select.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit56] FileName=..\src\common\hashtable.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit57] FileName=..\src\common\hexdump.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit58] FileName=..\src\common\list.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit59] FileName=..\src\common\network.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit60] FileName=..\src\common\packet.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit61] FileName=..\src\common\queue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit62] FileName=..\src\common\rlimit.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit63] FileName=..\src\common\trans.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit64] FileName=..\src\common\util.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit65] FileName=..\src\common\xalloc.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit66] FileName=..\src\common\addr.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit67] FileName=..\src\common\bn_type.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit68] FileName=..\src\common\d2char_checksum.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit69] FileName=..\src\common\eventlog.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit70] FileName=..\src\common\fdwatch.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit71] FileName=..\src\common\fdwatch_epoll.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit72] FileName=..\src\common\fdwatch_kqueue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit73] FileName=..\src\common\fdwatch_poll.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit74] FileName=..\src\common\fdwatch_select.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit75] FileName=..\src\common\hashtable.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit76] FileName=..\src\common\hexdump.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit77] FileName=..\src\common\list.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit78] FileName=..\src\common\network.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit79] FileName=..\src\common\packet.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit80] FileName=..\src\common\queue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit81] FileName=..\src\common\rlimit.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit82] FileName=..\src\common\trans.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit83] FileName=..\src\common\util.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit84] FileName=..\src\compat\uname.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit85] FileName=..\src\compat\difftime.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit86] FileName=..\src\compat\gettimeofday.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit87] FileName=..\src\compat\inet_aton.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit88] FileName=..\src\compat\inet_ntoa.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit89] FileName=..\src\compat\pdir.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit90] FileName=..\src\compat\psock.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit91] FileName=..\src\compat\strcasecmp.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit92] FileName=..\src\compat\strdup.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit93] FileName=..\src\compat\strerror.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit94] FileName=..\src\compat\strftime.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit95] FileName=..\src\compat\strncasecmp.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit96] FileName=..\src\compat\strsep.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit97] FileName=..\src\compat\strtoul.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit98] FileName=..\src\compat\strsep.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit99] FileName=..\src\compat\strtoul.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit100] FileName=..\src\compat\uname.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit101] FileName=..\src\compat\access.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit102] FileName=..\src\compat\difftime.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit103] FileName=..\src\compat\gettimeofday.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit104] FileName=..\src\compat\inet_aton.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit105] FileName=..\src\compat\inet_ntoa.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit106] FileName=..\src\compat\pdir.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit107] FileName=..\src\compat\psock.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit108] FileName=..\src\compat\strcasecmp.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit109] FileName=..\src\compat\strdup.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit110] FileName=..\src\compat\strerror.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit111] FileName=..\src\compat\strftime.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit112] FileName=..\src\compat\strncasecmp.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit113] FileName=..\src\win32\service.h CompileCpp=0 Folder=win32/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit114] FileName=..\src\win32\service.c CompileCpp=0 Folder=win32/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit115] FileName=..\src\d2cs\cmdline.h CompileCpp=0 Folder=d2cs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit116] FileName=..\src\d2cs\cmdline.c CompileCpp=0 Folder=d2cs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit117] FileName=..\src\common\conf.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit118] FileName=..\src\common\conf.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion=0.1 FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=d2cs.exe ProductName=d2cs ProductVersion=0.1 AutoIncBuildNr=0 [Unit119] FileName=..\src\common\xstring.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit120] FileName=..\src\common\xstring.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= pvpgn-1.8.5/Win32-Projects/d2dbs.vcproj0000644000175000017500000002157011151345317016563 0ustar aaronaaron pvpgn-1.8.5/Win32-Projects/PvPGNConsole.vcproj0000644000175000017500000006357711151345317020057 0ustar aaronaaron pvpgn-1.8.5/Win32-Projects/d2dbsConsole.vcproj0000644000175000017500000002043211151345317020102 0ustar aaronaaron pvpgn-1.8.5/Win32-Projects/Makefile.BORLAND0000644000175000017500000006412611151345317017064 0ustar aaronaaron# # Copyright (C) 2002 Erik Latoshek [forester] (laterk@inbox.lv) # Copyright (C) 2001 _type_in_ # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # Makefile.BORLAND - # Makefile for Borland's/Inprise's free command-line win32 tools # Tested with Version 5.5 # attention! # on some win95 systems even if there are valid ilink32.cfg file, # ilink32 does not find objects in lib dir! notice, that on NT all works fine # so if you get a error that c0x32.obj cannot be found uncomment this macro #LINK_LIBS_PATH = "c:\program files\bcc55\lib" # -> ofcourse set path to your path # -> this was detected in 5.5 srcdir = . # prefix is the directory where the bnetd binary # distribution will be installed prefix = . exec_prefix = .\bnetd bindir = ${exec_prefix}\bin sbindir = ${exec_prefix}\sbin mandir = ${prefix}\man confdir = ${prefix}\conf sharedir = ${prefix}\var filesdir = ${sharedir}\files usersdir = ${sharedir}\users clandir = ${sharedir}\clans teamdir = ${sharedir}\teams reportsdir = ${sharedir}\reports chanlogsdir = ${sharedir}\chanlogs TOPDIR = ${srcdir}\.. INSTALLDIR = ${prefix} OBJDIR = ${srcdir}\..\obj\bcc\ SRC_SRCDIR = ${srcdir} SRC_BINDIR = ${srcdir}\..\bin SRC_SBINDIR = ${srcdir}\..\sbin SRC_MANDIR = ${srcdir}\..\man SRC_CONFDIR = ${SRCDIR}\..\conf SRC_SHAREDIR = ${SRCDIR}\..\files SRC_ACDIR = ${SRC_SRCDIR}\autoconf SRC_BNETDDIR = ${SRC_SRCDIR}\bnetd SRC_D2CSDIR = ${SRC_SRCDIR}\d2cs SRC_D2DBSDIR = ${SRC_SRCDIR}\d2dbs SRC_BNIUTILSDIR = ${SRC_SRCDIR}\bniutils SRC_BNPASSDIR = ${SRC_SRCDIR}\bnpass SRC_BNPROXYDIR = ${SRC_SRCDIR}\bnproxy SRC_BNTRACKDDIR = ${SRC_SRCDIR}\bntrackd SRC_CLIENTDIR = ${SRC_SRCDIR}\client SRC_COMMONDIR = ${SRC_SRCDIR}\common SRC_COMPATDIR = ${SRC_SRCDIR}\compat SRC_DEBUGDIR = ${SRC_SRCDIR}\debug SRC_WIN32DIR = ${SRC_SRCDIR}\win32 SRC_CDBDIR = ${SRC_SRCDIR}\tinycdb SRC_ZLIBDIR = ${SRC_SRCDIR}\zlib MKDIR = md RMF = del #del /q is better if available, as it works on a non-english OS !if ${OS}==Windows_NT RMFALL = del /Q !else RMFALL = echo y|del !endif RMDIR = rmdir ECHO = echo SED = notavailable INSTALL = notavailable INSTALL_PROGRAM = notavailable INSTALL_DATA = notavailable INSTALL_SCRIPT = notavailable INSTALL_DIRS = mkdir CC = bcc32 RC = brc32 # Grr... warning 8060 complains about if (!(var = create())) and the compiler stops # working correctly after 20 or 30 warnings so we have to disable it. # Warning 8057 is that a function parameter is unused... this is probably intentional so # this only makes the compile noisy. #Note on MYSQL support: #libmySQL.lib has to be converted to work with borland, use this borland tool: #COFF2OMF libmySQL.lib libmySQL_bc.lib #Or create it from the dll file: #IMPLIB libmysql_bc.lib libmysql.dll #However the data alignment has to be set to "quad word", thus the -a8 in SQLFLAGS #This might not work flawless, MYSQL suggests to use their static libs from http://www.mysql.com/downloads/os-win32.html !ifdef WITH_GUI bnetd_RESOURCES = ${SRC_WIN32DIR}\resource.res d2cs_RESOURCES = ${SRC_WIN32DIR}\d2cs_resource.res d2dbs_RESOURCES = ${SRC_WIN32DIR}\d2dbs_resource.res GUIBCCFLAGS = -tWM -DWIN32_GUI LINKPREFIX = /aa c0w32 LINKPOSTFIX = cw32mt import32 , , !else LINKPREFIX = /ap c0x32 LINKPOSTFIX = cw32 import32 !endif !ifdef WITH_SQL_MYSQL SQLFLAGS = -DWITH_SQL_MYSQL -a8 !endif !ifdef WITH_SQL_ODBC SQLFLAGS = -DWITH_SQL_ODBC !endif !ifdef WITH_CDB CDBFLAGS = -DWITH_CDB !endif CFLAGS = -v -y -O2 -d -j2 -w-8060 -w-8057 CPPFLAGS = -DWIN32 -I${SRC_SRCDIR} \ -DBNETD_DEFAULT_CONF_FILE=\"${bnetd_DEFCONFFILE:\=\\}\" \ -DD2CS_DEFAULT_CONF_FILE=\"${d2cs_DEFCONFFILE:\=\\}\" \ -DD2DBS_DEFAULT_CONF_FILE=\"${d2dbs_DEFCONFFILE:\=\\}\" \ ${SQLFLAGS} ${CDBFLAGS} ${GUIBCCFLAGS} COMPILE = ${CC} ${CFLAGS} ${CPPFLAGS} -c LINK = ilink32 -v -L${LINK_LIBS_PATH} -I${OBJDIR} !ifdef WITH_SQL_MYSQL !ifdef WITH_SQL_ODBC LINK_LIBS = libmySQL_bc.lib odbc32.lib !else LINK_LIBS = libmySQL_bc.lib !endif !else !ifdef WITH_SQL_ODBC LINK_LIBS = odbc32.lib !else LINK_LIBS = !endif !endif bnetd_DEFCONFFILE = ${confdir}\bnetd.conf bnetd_SBIN = ${SRC_SBINDIR}\bnetd.exe bnetd_OBJECTS = \ ${SRC_BNETDDIR}\main.obj \ ${SRC_BNETDDIR}\server.obj \ ${SRC_BNETDDIR}\connection.obj \ ${SRC_BNETDDIR}\message.obj \ ${SRC_BNETDDIR}\handle_init.obj \ ${SRC_BNETDDIR}\handle_bnet.obj \ ${SRC_BNETDDIR}\handle_file.obj \ ${SRC_BNETDDIR}\handle_bot.obj \ ${SRC_BNETDDIR}\handle_telnet.obj \ ${SRC_BNETDDIR}\handle_irc.obj \ ${SRC_BNETDDIR}\handle_udp.obj \ ${SRC_BNETDDIR}\handle_anongame.obj \ ${SRC_BNETDDIR}\channel.obj \ ${SRC_BNETDDIR}\channel_conv.obj \ ${SRC_BNETDDIR}\game.obj \ ${SRC_BNETDDIR}\anongame.obj \ ${SRC_BNETDDIR}\friends.obj \ ${SRC_BNETDDIR}\command.obj \ ${SRC_BNETDDIR}\account.obj \ ${SRC_BNETDDIR}\account_wrap.obj \ ${SRC_BNETDDIR}\prefs.obj \ ${SRC_BNETDDIR}\tick.obj \ ${SRC_BNETDDIR}\file.obj \ ${SRC_BNETDDIR}\watch.obj \ ${SRC_BNETDDIR}\ladder.obj \ ${SRC_BNETDDIR}\ladder_calc.obj \ ${SRC_BNETDDIR}\adbanner.obj \ ${SRC_BNETDDIR}\timer.obj \ ${SRC_BNETDDIR}\tracker.obj \ ${SRC_BNETDDIR}\ipban.obj \ ${SRC_BNETDDIR}\game_conv.obj \ ${SRC_BNETDDIR}\autoupdate.obj \ ${SRC_BNETDDIR}\helpfile.obj \ ${SRC_BNETDDIR}\mail.obj \ ${SRC_BNETDDIR}\anongame_infos.obj \ ${SRC_BNETDDIR}\anongame_gameresult.obj \ ${SRC_BNETDDIR}\storage.obj \ ${SRC_BNETDDIR}\runprog.obj \ ${SRC_BNETDDIR}\realm.obj \ ${SRC_BNETDDIR}\character.obj \ ${SRC_BNETDDIR}\udptest_send.obj \ ${SRC_BNETDDIR}\versioncheck.obj \ ${SRC_BNETDDIR}\handle_d2cs.obj \ ${SRC_BNETDDIR}\news.obj \ ${SRC_BNETDDIR}\irc.obj \ ${SRC_BNETDDIR}\alias_command.obj \ ${SRC_BNETDDIR}\storage_file.obj \ ${SRC_BNETDDIR}\file_plain.obj \ ${SRC_BNETDDIR}\file_cdb.obj \ ${SRC_BNETDDIR}\storage_sql.obj \ ${SRC_BNETDDIR}\sql_mysql.obj \ ${SRC_BNETDDIR}\sql_odbc.obj \ ${SRC_BNETDDIR}\sql_dbcreator.obj \ ${SRC_BNETDDIR}\command_groups.obj \ ${SRC_BNETDDIR}\output.obj \ ${SRC_BNETDDIR}\tournament.obj \ ${SRC_BNETDDIR}\anongame_maplists.obj \ ${SRC_BNETDDIR}\clan.obj \ ${SRC_BNETDDIR}\topic.obj \ ${SRC_BNETDDIR}\ladder_binary.obj \ ${SRC_BNETDDIR}\support.obj \ ${SRC_BNETDDIR}\team.obj \ ${SRC_BNETDDIR}\attrgroup.obj \ ${SRC_BNETDDIR}\attrlayer.obj \ ${SRC_BNETDDIR}\cmdline.obj \ ${SRC_WIN32DIR}\service.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\bn_type.obj \ ${SRC_COMMONDIR}\packet.obj \ ${SRC_COMMONDIR}\queue.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\network.obj \ ${SRC_COMMONDIR}\list.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\bnettime.obj \ ${SRC_COMMONDIR}\bnethash.obj \ ${SRC_COMMONDIR}\bnethashconv.obj \ ${SRC_COMMONDIR}\addr.obj \ ${SRC_COMMONDIR}\hashtable.obj \ ${SRC_COMMONDIR}\give_up_root_privileges.obj \ ${SRC_COMMONDIR}\token.obj \ ${SRC_COMMONDIR}\proginfo.obj \ ${SRC_COMMONDIR}\rlimit.obj \ ${SRC_COMMONDIR}\tag.obj \ ${SRC_COMMONDIR}\trans.obj \ ${SRC_COMMONDIR}\fdwatch.obj \ ${SRC_COMMONDIR}\fdwatch_poll.obj \ ${SRC_COMMONDIR}\fdwatch_select.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMMONDIR}\rcm.obj \ ${SRC_COMMONDIR}\conf.obj \ ${SRC_COMPATDIR}\pdir.obj \ ${SRC_COMPATDIR}\inet_aton.obj \ ${SRC_COMPATDIR}\inet_ntoa.obj \ ${SRC_COMPATDIR}\strdup.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\strtoul.obj \ ${SRC_COMPATDIR}\strftime.obj \ ${SRC_COMPATDIR}\strcasecmp.obj \ ${SRC_COMPATDIR}\strncasecmp.obj \ ${SRC_COMPATDIR}\strsep.obj \ ${SRC_COMPATDIR}\psock.obj \ ${SRC_COMPATDIR}\uname.obj \ ${SRC_COMPATDIR}\gettimeofday.obj \ ${SRC_COMPATDIR}\difftime.obj \ ${SRC_COMPATDIR}\memset.obj \ ${SRC_COMPATDIR}\memcpy.obj \ ${SRC_COMPATDIR}\mmap.obj \ ${SRC_COMPATDIR}\getopt.obj \ ${SRC_CDBDIR}\cdb_init.obj \ ${SRC_CDBDIR}\cdb_find.obj \ ${SRC_CDBDIR}\cdb_findnext.obj \ ${SRC_CDBDIR}\cdb_seek.obj \ ${SRC_CDBDIR}\cdb_seq.obj \ ${SRC_CDBDIR}\cdb_unpack.obj \ ${SRC_CDBDIR}\cdb_make_add.obj \ ${SRC_CDBDIR}\cdb_make_put.obj \ ${SRC_CDBDIR}\cdb_make_find.obj \ ${SRC_CDBDIR}\cdb_make.obj \ ${SRC_CDBDIR}\cdb_hash.obj \ $(SRC_ZLIBDIR)\pvpgn_adler32.obj \ $(SRC_ZLIBDIR)\pvpgn_deflate.obj \ $(SRC_ZLIBDIR)\pvpgn_trees.obj \ $(SRC_ZLIBDIR)\pvpgn_zutil.obj \ ${SRC_WIN32DIR}\winmain.obj sbnetd_SBIN = ${SRC_SBINDIR}\sbnetd.exe sbnetd_OBJECTS = ${SRC_DEBUGDIR}\sbnetd.obj \ ${SRC_COMPATDIR}\strerror.obj d2cs_DEFCONFFILE = ${confdir}\d2cs.conf d2cs_SBIN = ${SRC_SBINDIR}\d2cs.exe d2cs_OBJECTS = \ ${SRC_D2CSDIR}\main.obj \ ${SRC_D2CSDIR}\d2gs.obj \ ${SRC_D2CSDIR}\handle_d2gs.obj \ ${SRC_D2CSDIR}\serverqueue.obj \ ${SRC_D2CSDIR}\connection.obj \ ${SRC_D2CSDIR}\game.obj \ ${SRC_D2CSDIR}\server.obj \ ${SRC_D2CSDIR}\handle_init.obj \ ${SRC_D2CSDIR}\handle_d2cs.obj \ ${SRC_D2CSDIR}\d2charfile.obj \ ${SRC_D2CSDIR}\d2charlist.obj \ ${SRC_D2CSDIR}\gamequeue.obj \ ${SRC_D2CSDIR}\prefs.obj \ ${SRC_D2CSDIR}\cmdline.obj \ ${SRC_D2CSDIR}\bnetd.obj \ ${SRC_D2CSDIR}\handle_bnetd.obj \ ${SRC_D2CSDIR}\handle_signal.obj \ ${SRC_D2CSDIR}\s2s.obj \ ${SRC_D2CSDIR}\net.obj \ ${SRC_D2CSDIR}\d2ladder.obj \ ${SRC_COMMONDIR}\conf.obj \ ${SRC_COMMONDIR}\hashtable.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\fdwatch.obj \ ${SRC_COMMONDIR}\fdwatch_poll.obj \ ${SRC_COMMONDIR}\fdwatch_select.obj \ ${SRC_COMMONDIR}\list.obj \ ${SRC_COMMONDIR}\packet.obj \ ${SRC_COMMONDIR}\bn_type.obj \ ${SRC_COMMONDIR}\addr.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\queue.obj \ ${SRC_COMMONDIR}\network.obj \ ${SRC_COMMONDIR}\rlimit.obj \ ${SRC_COMMONDIR}\trans.obj \ ${SRC_COMMONDIR}\d2char_checksum.obj \ ${SRC_COMMONDIR}\fdwatch_select.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMMONDIR}\xstring.obj \ ${SRC_COMPATDIR}\inet_aton.obj \ ${SRC_COMPATDIR}\inet_ntoa.obj \ ${SRC_COMPATDIR}\strdup.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\strtoul.obj \ ${SRC_COMPATDIR}\strftime.obj \ ${SRC_COMPATDIR}\strcasecmp.obj \ ${SRC_COMPATDIR}\strncasecmp.obj \ ${SRC_COMPATDIR}\psock.obj \ ${SRC_COMPATDIR}\uname.obj \ ${SRC_COMPATDIR}\gettimeofday.obj \ ${SRC_COMPATDIR}\difftime.obj \ ${SRC_COMPATDIR}\pdir.obj \ ${SRC_COMPATDIR}\strsep.obj \ ${SRC_WIN32DIR}\service.obj \ ${SRC_WIN32DIR}\d2cs_winmain.obj d2dbs_DEFCONFFILE = ${confdir}\d2dbs.conf d2dbs_SBIN = ${SRC_SBINDIR}\d2dbs.exe d2dbs_OBJECTS = \ ${SRC_D2DBSDIR}\main.obj \ ${SRC_D2DBSDIR}\charlock.obj \ ${SRC_D2DBSDIR}\d2ladder.obj \ ${SRC_D2DBSDIR}\dbserver.obj \ ${SRC_D2DBSDIR}\dbspacket.obj \ ${SRC_D2DBSDIR}\cmdline.obj \ ${SRC_D2DBSDIR}\prefs.obj \ ${SRC_D2DBSDIR}\dbsdupecheck.obj \ ${SRC_D2DBSDIR}\handle_signal.obj \ ${SRC_COMMONDIR}\conf.obj \ ${SRC_COMMONDIR}\list.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\bn_type.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\addr.obj \ ${SRC_COMMONDIR}\d2char_checksum.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMMONDIR}\packet.obj \ ${SRC_COMMONDIR}\network.obj \ ${SRC_COMMONDIR}\xstring.obj \ ${SRC_COMPATDIR}\inet_aton.obj \ ${SRC_COMPATDIR}\psock.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\strsep.obj \ ${SRC_WIN32DIR}\service.obj \ ${SRC_WIN32DIR}\d2dbs_winmain.obj bnproxy_SBIN = ${SRC_SBINDIR}\bnproxy.exe bnproxy_OBJECTS = ${SRC_BNPROXYDIR}\bnproxy.obj \ ${SRC_BNPROXYDIR}\virtconn.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\packet.obj \ ${SRC_COMMONDIR}\queue.obj \ ${SRC_COMMONDIR}\list.obj \ ${SRC_COMMONDIR}\bn_type.obj \ ${SRC_COMMONDIR}\network.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMPATDIR}\inet_ntoa.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\psock.obj bntrackd_SBIN = ${SRC_SBINDIR}\bntrackd.exe bntrackd_OBJECTS= ${SRC_BNTRACKDDIR}\bntrackd.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\list.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMPATDIR}\inet_ntoa.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\psock.obj bnchat_BIN = ${SRC_BINDIR}\bnchat.exe bnchat_OBJECTS = ${SRC_CLIENTDIR}\bnchat.obj \ ${SRC_CLIENTDIR}\client.obj \ ${SRC_CLIENTDIR}\client_connect.obj \ ${SRC_CLIENTDIR}\udptest.obj \ ${SRC_COMMONDIR}\packet.obj \ ${SRC_COMMONDIR}\queue.obj \ ${SRC_COMMONDIR}\bn_type.obj \ ${SRC_COMMONDIR}\network.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\bnethash.obj \ ${SRC_COMMONDIR}\bnethashconv.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\bnettime.obj \ ${SRC_COMMONDIR}\proginfo.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMPATDIR}\inet_ntoa.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\psock.obj \ ${SRC_COMPATDIR}\vsnprintf.obj \ ${SRC_COMPATDIR}\gettimeofday.obj bnpass_BIN = ${SRC_BINDIR}\bnpass.exe bnpass_OBJECTS = ${SRC_BNPASSDIR}\bnpass.obj \ ${SRC_COMMONDIR}\bnethash.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMPATDIR}\strerror.obj bnftp_BIN = ${SRC_BINDIR}\bnftp.exe bnftp_OBJECTS = ${SRC_CLIENTDIR}\bnftp.obj \ ${SRC_CLIENTDIR}\client.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\packet.obj \ ${SRC_COMMONDIR}\queue.obj \ ${SRC_COMMONDIR}\bn_type.obj \ ${SRC_COMMONDIR}\network.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\bnettime.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMPATDIR}\inet_ntoa.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\strftime.obj \ ${SRC_COMPATDIR}\psock.obj \ ${SRC_COMPATDIR}\gettimeofday.obj bnbot_BIN = ${SRC_BINDIR}\bnbot.exe bnbot_OBJECTS = ${SRC_CLIENTDIR}\bnbot.obj \ ${SRC_CLIENTDIR}\client.obj \ ${SRC_COMMONDIR}\packet.obj \ ${SRC_COMMONDIR}\bn_type.obj \ ${SRC_COMMONDIR}\network.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMPATDIR}\inet_ntoa.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\psock.obj bnstat_BIN = ${SRC_BINDIR}\bnstat.exe bnstat_OBJECTS = ${SRC_CLIENTDIR}\bnstat.obj \ ${SRC_CLIENTDIR}\client.obj \ ${SRC_CLIENTDIR}\client_connect.obj \ ${SRC_CLIENTDIR}\udptest.obj \ ${SRC_COMMONDIR}\packet.obj \ ${SRC_COMMONDIR}\queue.obj \ ${SRC_COMMONDIR}\bn_type.obj \ ${SRC_COMMONDIR}\network.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\bnethash.obj \ ${SRC_COMMONDIR}\bnethashconv.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\bnettime.obj \ ${SRC_COMMONDIR}\proginfo.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMPATDIR}\inet_ntoa.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\strftime.obj \ ${SRC_COMPATDIR}\psock.obj \ ${SRC_COMPATDIR}\gettimeofday.obj bnilist_BIN = ${SRC_BINDIR}\bnilist.exe bnilist_OBJECTS = ${SRC_BNIUTILSDIR}\bnilist.obj \ ${SRC_BNIUTILSDIR}\fileio.obj \ ${SRC_BNIUTILSDIR}\tga.obj \ ${SRC_COMPATDIR}\strerror.obj bni2tga_BIN = ${SRC_BINDIR}\bni2tga.exe bni2tga_OBJECTS = ${SRC_BNIUTILSDIR}\bni2tga.obj \ ${SRC_BNIUTILSDIR}\fileio.obj \ ${SRC_COMPATDIR}\strerror.obj bniextract_BIN = ${SRC_BINDIR}\bniextract.exe bniextract_OBJECTS= ${SRC_BNIUTILSDIR}\bniextract.obj \ ${SRC_BNIUTILSDIR}\fileio.obj \ ${SRC_BNIUTILSDIR}\tga.obj \ ${SRC_BNIUTILSDIR}\bni.obj \ ${SRC_COMPATDIR}\strerror.obj bnibuild_BIN = ${SRC_BINDIR}\bnibuild.exe bnibuild_OBJECTS= ${SRC_BNIUTILSDIR}\bnibuild.obj \ ${SRC_BNIUTILSDIR}\fileio.obj \ ${SRC_BNIUTILSDIR}\tga.obj \ ${SRC_BNIUTILSDIR}\bni.obj \ ${SRC_COMPATDIR}\strerror.obj tgainfo_BIN = ${SRC_BINDIR}\tgainfo.exe tgainfo_OBJECTS = ${SRC_BNIUTILSDIR}\tgainfo.obj \ ${SRC_BNIUTILSDIR}\fileio.obj \ ${SRC_BNIUTILSDIR}\tga.obj \ ${SRC_COMPATDIR}\strerror.obj timetest_BIN = ${SRC_BINDIR}\timetest.exe timetest_OBJECTS = ${SRC_DEBUGDIR}\timetest.obj \ ${SRC_COMMONDIR}\bn_type.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\bnettime.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\gettimeofday.obj listtest_BIN = ${SRC_BINDIR}\listtest.exe listtest_OBJECTS = ${SRC_DEBUGDIR}\listtest.obj \ ${SRC_COMMONDIR}\list.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\strdup.obj hashtabletest_BIN = ${SRC_BINDIR}\hashtabletest.exe hashtabletest_OBJECTS = ${SRC_DEBUGDIR}\hashtabletest.obj \ ${SRC_COMMONDIR}\hashtable.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\strdup.obj addrtest_BIN = ${SRC_BINDIR}\addrtest.exe addrtest_OBJECTS = ${SRC_DEBUGDIR}\addrtest.obj \ ${SRC_COMMONDIR}\addr.obj \ ${SRC_COMMONDIR}\util.obj \ ${SRC_COMMONDIR}\list.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMPATDIR}\inet_aton.obj \ ${SRC_COMPATDIR}\inet_ntoa.obj \ ${SRC_COMPATDIR}\strerror.obj \ ${SRC_COMPATDIR}\psock.obj \ ${SRC_COMPATDIR}\memset.obj \ ${SRC_COMPATDIR}\memcpy.obj \ ${SRC_COMPATDIR}\strdup.obj cdb_BIN = ${SRC_BINDIR}\bncdb.exe cdb_OBJECTS = ${SRC_CDBDIR}\cdb.obj \ ${SRC_CDBDIR}\cdb_init.obj \ ${SRC_CDBDIR}\cdb_seek.obj \ ${SRC_CDBDIR}\cdb_seq.obj \ ${SRC_CDBDIR}\cdb_find.obj \ ${SRC_CDBDIR}\cdb_findnext.obj \ ${SRC_CDBDIR}\cdb_unpack.obj \ ${SRC_CDBDIR}\cdb_make_add.obj \ ${SRC_CDBDIR}\cdb_make_put.obj \ ${SRC_CDBDIR}\cdb_make_find.obj \ ${SRC_CDBDIR}\cdb_make.obj \ ${SRC_CDBDIR}\cdb_hash.obj \ ${SRC_COMMONDIR}\eventlog.obj \ ${SRC_COMMONDIR}\hexdump.obj \ ${SRC_COMMONDIR}\xalloc.obj \ ${SRC_COMPATDIR}\mmap.obj \ ${SRC_COMPATDIR}\getopt.obj \ ${SRC_COMPATDIR}\strerror.obj OBJECTS = ${bnetd_OBJECTS} ${d2cs_OBJECTS} ${d2dbs_OBJECTS} ${bntrackd_OBJECTS} ${bnchat_OBJECTS} ${bnpass_OBJECTS} ${bnbot_OBJECTS} ${bnftp_OBJECTS} ${bnstat_OBJECTS} ${bnilist_OBJECTS} ${bni2tga_OBJECTS} ${bniextract_OBJECTS} ${bnibuild_OBJECTS} ${tgainfo_OBJECTS} ${timetest_OBJECTS} ${listtest_OBJECTS} ${hashtabletest_OBJECTS} ${addrtest_OBJECTS} ${cdb_OBJECTS} GUISBINS = ${bnetd_SBIN} ${d2cs_SBIN} ${d2dbs_SBIN} SBINS = ${bnproxy_SBIN} ${bntrackd_SBIN} BINS = ${bnchat_BIN} ${bnpass_BIN} ${bnftp_BIN} ${bnbot_BIN} ${bnstat_BIN} ${bnilist_BIN} ${bni2tga_BIN} ${bniextract_BIN} ${bnibuild_BIN} ${tgainfo_BIN} ${cdb_BIN} CONFS = ad.conf bnetd.conf bnetd_default_user.plain bnetd_default_user.cdb bnmotd.txt channel.conf news.txt bnban.conf bnhelp.conf autoupdate.conf realm.conf bnmaps.conf bnxplevel.conf bnxpcalc.conf news.txt command_groups.conf bnban.conf bnhelp.conf bnalias.conf anongame_infos.conf tournament.conf topics.conf sql_DB_layout.conf address_translation.conf supportfile.conf SHARES = ad000001.smk tos.txt OTHERBINS = ${sbnetd_OBJECTS} ${sbnetd_SBIN} DIRS = ${SRC_BINDIR} ${SRC_SBINDIR} !ifdef WITH_GUI all: config objdir ${GUISBINS} @echo =================================================================== @echo Build GUI versions of bnetd, d2cs and d2dbs. @echo Now building non GUI stuff. @-${RMF} ${SRC_COMMONDIR}\eventlog.obj @make_borland console !else all: config objdir ${GUISBINS} ${SBINS} ${BINS} -${RMF} ${SRC_COMMONDIR}\eventlog.obj @echo =================================================================== @echo All applications build. @echo =================================================================== !endif !ifndef WITH_GUI console: config objdir ${SBINS} ${BINS} -${RMF} ${SRC_COMMONDIR}\eventlog.obj @echo =================================================================== @echo remaining sbin and bin applications build. @echo =================================================================== !endif objdir: if not exist ${OBJDIR} ${INSTALL_DIRS} ${OBJDIR} clean: # win95 supports only 1 parameter to 'del' & 'rmdir' # and wants 'y' for *.* -${RMF} ${SRC_BNTRACKDDIR}\*.obj -${RMF} ${SRC_CLIENTDIR}\*.obj -${RMF} ${SRC_BNIUTILSDIR}\*.obj -${RMF} ${SRC_BNPASSDIR}\*.obj -${RMF} ${SRC_BNPROXYDIR}\*.obj -${RMF} ${SRC_COMPATDIR}\*.obj -${RMF} ${SRC_COMMONDIR}\*.obj -${RMF} ${SRC_WIN32DIR}\*.obj -${RMF} ${SRC_BNETDDIR}\*.obj -${RMF} ${SRC_D2DBSDIR}\*.obj -${RMF} ${SRC_D2CSDIR}\*.obj -${RMF} ${SRC_CDBDIR}\*.obj -${RMF} ${SRC_ZLIBDIR}\*.obj -${RMF} ${SRC_BNETDDIR}\*.res -${RMF} ${SRC_COMPATDIR}\*.g_obj -${RMF} ${SRC_COMMONDIR}\*.g_obj -${RMF} ${SRC_WIN32DIR}\*.g_obj -${RMF} ${SRC_BNETDDIR}\*.g_obj -${RMF} ${SRC_CDBDIR}\*.g_obj -${RMF} ${SRC_ZLIBDIR}\*.g_obj -${RMFALL} ${SRC_BINDIR}\*.* -${RMFALL} ${SRC_SBINDIR}\*.* -${RMFALL} ${OBJDIR}\*.* -${RMDIR} ${SRC_BINDIR} -${RMDIR} ${SRC_SBINDIR} -${RMDIR} ${OBJDIR} distclean: clean -${RMF} ${SRC_CONFDIR}\bnetd.conf -${RMF} ${SRC_CONFDIR}\d2dbs.conf -${RMF} ${SRC_SRCDIR}\config.cache -${RMF} ${SRC_SRCDIR}\config.log -${RMF} ${SRC_SRCDIR}\config.status -${RMF} ${SRC_SRCDIR}\Makefile -${RMF} ${SRC_SRCDIR}\config.h -${RMDIR} ${SRC_BINDIR} -${RMDIR} ${SRC_SBINDIR} clean-compile: clean all config: ${SRC_SRCDIR}\Makefile ${SRC_SRCDIR}\Makefile: Makefile.BORLAND copy Makefile.BORLAND ${SRC_SRCDIR}\Makefile ${SRC_BINDIR}: if not exist $@ ${INSTALL_DIRS} $@ ${SRC_SBINDIR}: if not exist $@ ${INSTALL_DIRS} $@ install: config all -${INSTALL_DIRS} ${INSTALLDIR} -${INSTALL_DIRS} ${INSTALLDIR}\bin -${INSTALL_DIRS} ${INSTALLDIR}\sbin -${INSTALL_DIRS} ${INSTALLDIR}\var -${INSTALL_DIRS} ${INSTALLDIR}\var\files -${INSTALL_DIRS} ${INSTALLDIR}\var\users -${INSTALL_DIRS} ${INSTALLDIR}\var\reports -${INSTALL_DIRS} ${INSTALLDIR}\var\chanlogs -${INSTALL_DIRS} ${INSTALLDIR}\etc copy ${TOPDIR}\files\*.* ${INSTALLDIR}\var\files copy ${TOPDIR}\conf\*.* ${INSTALLDIR}\etc copy ${INSTALLDIR}\etc\bnetd.conf.win32 ${INSTALLDIR}\etc\bnetd.conf copy ${INSTALLDIR}\etc\d2cs.conf.win32 ${INSTALLDIR}\etc\d2cs.conf copy ${INSTALLDIR}\etc\d2dbs.conf.win32 ${INSTALLDIR}\etc\d2dbs.conf copy ${TOPDIR}\sbin\*.exe ${INSTALLDIR}\sbin copy ${TOPDIR}\bin\*.exe ${INSTALLDIR}\bin copy ${TOPDIR}\*.* ${INSTALLDIR} echo @cd ${INSTALLDIR} > ${INSTALLDIR}\bnetd.bat echo @.\sbin\bnetd.exe -c .\etc\bnetd.conf >> ${INSTALLDIR}\bnetd.bat # The Borland compiler silently ignores -ofilename if it is after the source file # The Borland compiler silently ignores -efilename if it is after the object file .rc.res: ${RC} -r -i${srcdir} -fo$@ $< .c.obj: ${COMPILE} -o$@ $< ${bnetd_SBIN}: ${bnetd_OBJECTS} ${bnetd_RESOURCES} ${SRC_SBINDIR} ${LINK} ${LINKPREFIX} ${bnetd_OBJECTS}, $@, , ${LINK_LIBS} ${LINKPOSTFIX} ${bnetd_RESOURCES} ${d2cs_SBIN}: ${d2cs_OBJECTS} ${d2cs_RESOURCES} ${SRC_SBINDIR} ${LINK} ${LINKPREFIX} ${d2cs_OBJECTS}, $@, , ${LINK_LIBS} ${LINKPOSTFIX} ${d2cs_RESOURCES} ${d2dbs_SBIN}: ${d2dbs_OBJECTS} ${d2dbs_RESOURCES} ${SRC_SBINDIR} ${LINK} ${LINKPREFIX} ${d2dbs_OBJECTS}, $@, , ${LINK_LIBS} ${LINKPOSTFIX} ${d2dbs_RESOURCES} ${bnproxy_SBIN}: ${bnproxy_OBJECTS} ${SRC_SBINDIR} ${LINK} /ap c0x32 ${bnproxy_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bntrackd_SBIN}: ${bntrackd_OBJECTS} ${SRC_SBINDIR} ${LINK} /ap c0x32 ${bntrackd_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bnchat_BIN}: ${bnchat_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${bnchat_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bnpass_BIN}: ${bnpass_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${bnpass_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bnftp_BIN}: ${bnftp_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${bnftp_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bnbot_BIN}: ${bnbot_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${bnbot_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bnstat_BIN}: ${bnstat_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${bnstat_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bnilist_BIN}: ${bnilist_OBJECTS} ${LINK} /ap c0x32 ${bnilist_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bni2tga_BIN}: ${bni2tga_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${bni2tga_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bniextract_BIN}: ${bniextract_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${bniextract_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${bnibuild_BIN}: ${bnibuild_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${bnibuild_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${tgainfo_BIN}: ${tgainfo_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${tgainfo_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${timetest_BIN}: ${timetest_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${timetest_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${listtest_BIN}: ${listtest_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${listtest_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${hashtabletest_BIN}: ${hashtabletest_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${hashtabletest_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${addrtest_BIN}: ${addrtest_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${addrtest_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 ${cdb_BIN}: ${cdb_OBJECTS} ${SRC_BINDIR} ${LINK} /ap c0x32 ${cdb_OBJECTS}, $@, , ${LINK_LIBS} cw32 import32 pvpgn-1.8.5/Win32-Projects/d2dbsConsole.dev0000644000175000017500000002052511151345317017360 0ustar aaronaaron[Project] FileName=d2dbsConsole.dev Name=d2dbsConsole UnitCount=53 Type=1 Ver=1 ObjFiles= Includes=..\src Libs= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=-lws2_32_@@_ IsCpp=0 Icon=d2dbsConsole.ico ExeOutput=..\bin ObjectOutput= OverrideOutput=0 OverrideOutputName=d2dbsConsole.exe HostApplication= Folders=common,"common/Header Files","common/Source Files",compat,"compat/Header Files","compat/Source Files",d2dbs,"d2dbs/Header Files","d2dbs/Source Files",win32,"win32/Header Files","win32/Source Files" CommandLine= UseCustomMakefile=0 IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 CustomMakefile= PrivateResource=d2dbsConsole_private.rc [Unit1] FileName=..\src\win32\service.h CompileCpp=0 Folder=win32/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\src\win32\service.c CompileCpp=0 Folder=win32/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\src\d2dbs\version.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\src\d2dbs\charlock.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\src\d2dbs\d2ladder.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\src\d2dbs\dbsdupecheck.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\src\d2dbs\dbserver.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\src\d2dbs\dbspacket.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\src\d2dbs\handle_signal.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\src\d2dbs\prefs.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\src\d2dbs\setup.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\src\d2dbs\prefs.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\src\d2dbs\charlock.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\src\d2dbs\d2ladder.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\src\d2dbs\dbsdupecheck.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\src\d2dbs\dbserver.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\src\d2dbs\dbspacket.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\src\d2dbs\handle_signal.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\src\d2dbs\main.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\src\common\xalloc.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\src\common\addr.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\src\common\bn_type.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\src\common\d2char_checksum.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\src\common\eventlog.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=..\src\common\hexdump.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\src\common\list.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=..\src\common\util.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=..\src\compat\strsep.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=..\src\compat\inet_aton.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit30] FileName=..\src\compat\psock.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit31] FileName=..\src\compat\strerror.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=..\src\common\util.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit33] FileName=..\src\common\addr.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit34] FileName=..\src\common\bn_type.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit35] FileName=..\src\common\d2char_checksum.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit36] FileName=..\src\common\eventlog.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit37] FileName=..\src\common\hexdump.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit38] FileName=..\src\common\list.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit39] FileName=..\src\compat\strsep.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit40] FileName=..\src\compat\inet_aton.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit41] FileName=..\src\compat\psock.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit42] FileName=..\src\compat\strerror.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit43] FileName=..\src\common\xalloc.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit44] FileName=..\src\common\packet.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit45] FileName=..\src\common\network.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion=0.1 FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=d2dbs.exe ProductName=d2dbs ProductVersion=0.1 AutoIncBuildNr=0 [Unit46] FileName=..\src\common\packet.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit47] FileName=..\src\common\network.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit48] FileName=..\src\d2dbs\cmdline.h CompileCpp=0 Folder=d2dbs/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit49] FileName=..\src\d2dbs\cmdline.c CompileCpp=0 Folder=d2dbs/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit50] FileName=..\src\common\conf.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit51] FileName=..\src\common\conf.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit52] FileName=..\src\common\xstring.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit53] FileName=..\src\common\xstring.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= pvpgn-1.8.5/Win32-Projects/PvPGN.dev0000644000175000017500000013016311151345317015771 0ustar aaronaaron[Project] FileName=PvPGN.dev Name=PvPGN UnitCount=297 Type=0 Ver=1 ObjFiles= Includes=..\src Libs= ResourceIncludes=..\src MakeIncludes= Compiler=-DWIN32_GUI_@@_ CppCompiler= Linker=-lws2_32_@@__@@_ IsCpp=0 Icon= ExeOutput=..\bin ObjectOutput= OverrideOutput=0 OverrideOutputName=PvPGN.exe HostApplication= Folders=bnetd,"bnetd/Header Files","bnetd/Source Files",common,"common/Header Files","common/Source Files",compat,"compat/Header Files","compat/Source Files",tinycdb,"tinycdb/Header Files","tinycdb/Source Files",win32,"win32/Header Files","win32/Resource Files","win32/Source Files",zlib,"zlib/Header Files","zlib/Source Files" CommandLine= UseCustomMakefile=0 IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 CustomMakefile= PrivateResource=PvPGN_private.rc [Unit1] FileName=..\src\bnetd\watch.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\src\bnetd\account.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\src\bnetd\account_wrap.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\src\bnetd\adbanner.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\src\bnetd\alias_command.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\src\bnetd\anongame.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\src\bnetd\anongame_gameresult.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\src\bnetd\anongame_infos.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\src\bnetd\anongame_maplists.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\src\bnetd\autoupdate.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\src\bnetd\channel.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\src\bnetd\channel_conv.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\src\bnetd\character.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\src\bnetd\clan.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\src\bnetd\command.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\src\bnetd\command_groups.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\src\bnetd\connection.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\src\bnetd\file.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\src\bnetd\file_cdb.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\src\bnetd\file_plain.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\src\bnetd\friends.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\src\bnetd\game.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\src\bnetd\game_conv.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\src\bnetd\handle_anongame.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=..\src\bnetd\handle_bnet.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\src\bnetd\handle_bot.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=..\src\bnetd\handle_d2cs.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=..\src\bnetd\handle_file.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=..\src\bnetd\handle_init.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit30] FileName=..\src\bnetd\handle_irc.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit31] FileName=..\src\bnetd\handle_telnet.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=..\src\bnetd\handle_udp.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit33] FileName=..\src\bnetd\helpfile.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit34] FileName=..\src\bnetd\ipban.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit35] FileName=..\src\bnetd\irc.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit36] FileName=..\src\bnetd\ladder.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit37] FileName=..\src\bnetd\ladder_binary.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit38] FileName=..\src\bnetd\ladder_calc.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit39] FileName=..\src\bnetd\mail.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit40] FileName=..\src\bnetd\main.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit41] FileName=..\src\bnetd\message.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit42] FileName=..\src\bnetd\news.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit43] FileName=..\src\bnetd\output.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit44] FileName=..\src\bnetd\prefs.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit45] FileName=..\src\bnetd\realm.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit46] FileName=..\src\bnetd\runprog.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit47] FileName=..\src\bnetd\server.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit48] FileName=..\src\bnetd\sql_dbcreator.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit49] FileName=..\src\bnetd\sql_mysql.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit50] FileName=..\src\bnetd\sql_pgsql.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit51] FileName=..\src\bnetd\storage.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit52] FileName=..\src\bnetd\storage_file.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit53] FileName=..\src\bnetd\storage_sql.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit54] FileName=..\src\bnetd\support.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit55] FileName=..\src\bnetd\tick.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit56] FileName=..\src\bnetd\timer.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit57] FileName=..\src\bnetd\topic.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit58] FileName=..\src\bnetd\tournament.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit59] FileName=..\src\bnetd\tracker.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit60] FileName=..\src\bnetd\udptest_send.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit61] FileName=..\src\bnetd\versioncheck.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit62] FileName=..\src\bnetd\account.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit63] FileName=..\src\bnetd\account_wrap.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit64] FileName=..\src\bnetd\adbanner.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit65] FileName=..\src\bnetd\alias_command.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit66] FileName=..\src\bnetd\anongame.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit67] FileName=..\src\bnetd\anongame_gameresult.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit68] FileName=..\src\bnetd\anongame_infos.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit69] FileName=..\src\bnetd\anongame_maplists.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit70] FileName=..\src\bnetd\autoupdate.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit71] FileName=..\src\bnetd\channel.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit72] FileName=..\src\bnetd\channel_conv.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit73] FileName=..\src\bnetd\character.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit74] FileName=..\src\bnetd\clan.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit75] FileName=..\src\bnetd\command.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit76] FileName=..\src\bnetd\command_groups.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit77] FileName=..\src\bnetd\connection.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit78] FileName=..\src\bnetd\file.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit79] FileName=..\src\bnetd\file_cdb.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit80] FileName=..\src\bnetd\file_plain.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit81] FileName=..\src\bnetd\friends.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit82] FileName=..\src\bnetd\game.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit83] FileName=..\src\bnetd\game_conv.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit84] FileName=..\src\bnetd\handle_anongame.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit85] FileName=..\src\bnetd\handle_bnet.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit86] FileName=..\src\bnetd\handle_bot.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit87] FileName=..\src\bnetd\handle_d2cs.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit88] FileName=..\src\bnetd\handle_file.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit89] FileName=..\src\bnetd\handle_init.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit90] FileName=..\src\bnetd\handle_irc.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit91] FileName=..\src\bnetd\handle_telnet.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit92] FileName=..\src\bnetd\handle_udp.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit93] FileName=..\src\bnetd\handlers.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit94] FileName=..\src\bnetd\helpfile.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit95] FileName=..\src\bnetd\ipban.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit96] FileName=..\src\bnetd\irc.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit97] FileName=..\src\bnetd\ladder.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit98] FileName=..\src\bnetd\ladder_binary.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit99] FileName=..\src\bnetd\ladder_calc.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit100] FileName=..\src\bnetd\mail.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit101] FileName=..\src\bnetd\message.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit102] FileName=..\src\bnetd\news.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit103] FileName=..\src\bnetd\output.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit104] FileName=..\src\bnetd\prefs.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit105] FileName=..\src\bnetd\quota.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit106] FileName=..\src\bnetd\realm.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit107] FileName=..\src\bnetd\runprog.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit108] FileName=..\src\bnetd\server.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit109] FileName=..\src\bnetd\sql_dbcreator.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit110] FileName=..\src\bnetd\sql_mysql.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit111] FileName=..\src\bnetd\sql_pgsql.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit112] FileName=..\src\bnetd\storage.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit113] FileName=..\src\bnetd\storage_file.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit114] FileName=..\src\bnetd\storage_sql.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit115] FileName=..\src\bnetd\support.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit116] FileName=..\src\bnetd\tick.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit117] FileName=..\src\bnetd\timer.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit118] FileName=..\src\bnetd\topic.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit119] FileName=..\src\bnetd\tournament.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit120] FileName=..\src\bnetd\udptest_send.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit121] FileName=..\src\bnetd\versioncheck.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit122] FileName=..\src\bnetd\watch.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit123] FileName=..\src\common\xalloc.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit124] FileName=..\src\common\addr.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit125] FileName=..\src\common\anongame_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=..\ ProductName= ProductVersion= AutoIncBuildNr=0 [Unit126] FileName=..\src\common\bn_type.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit127] FileName=..\src\common\bnet_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit128] FileName=..\src\common\bnethash.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit129] FileName=..\src\common\bnethashconv.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit130] FileName=..\src\common\bnettime.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit131] FileName=..\src\common\bot_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit132] FileName=..\src\common\d2char_checksum.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit133] FileName=..\src\common\d2char_file.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit134] FileName=..\src\common\d2game_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit135] FileName=..\src\common\elist.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit136] FileName=..\src\common\eventlog.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit137] FileName=..\src\common\fdwatch.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit138] FileName=..\src\common\fdwatch_epoll.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit139] FileName=..\src\common\fdwatch_kqueue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit140] FileName=..\src\common\fdwatch_poll.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit141] FileName=..\src\common\fdwatch_select.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit142] FileName=..\src\common\field_sizes.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit143] FileName=..\src\common\file_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit144] FileName=..\src\common\flags.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit145] FileName=..\src\common\give_up_root_privileges.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit146] FileName=..\src\common\hashtable.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit147] FileName=..\src\common\hexdump.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit148] FileName=..\src\common\init_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit149] FileName=..\src\common\introtate.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit150] FileName=..\src\common\irc_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit151] FileName=..\src\common\list.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit152] FileName=..\src\common\network.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit153] FileName=..\src\common\packet.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit154] FileName=..\src\common\proginfo.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit155] FileName=..\src\common\queue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit156] FileName=..\src\common\rlimit.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit157] FileName=..\src\common\setup_after.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit158] FileName=..\src\common\setup_before.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit159] FileName=..\src\common\tag.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit160] FileName=..\src\common\token.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit161] FileName=..\src\common\tracker.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit162] FileName=..\src\common\trans.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit163] FileName=..\src\common\udp_protocol.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit164] FileName=..\src\common\util.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit165] FileName=..\src\common\version.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit166] FileName=..\src\common\xalloc.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit167] FileName=..\src\common\addr.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit168] FileName=..\src\common\bn_type.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit169] FileName=..\src\common\bnethash.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit170] FileName=..\src\common\bnethashconv.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit171] FileName=..\src\common\bnettime.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit172] FileName=..\src\common\d2char_checksum.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit173] FileName=..\src\common\eventlog.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit174] FileName=..\src\common\fdwatch.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit175] FileName=..\src\common\fdwatch_epoll.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit176] FileName=..\src\common\fdwatch_kqueue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit177] FileName=..\src\common\fdwatch_poll.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit178] FileName=..\src\common\fdwatch_select.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit179] FileName=..\src\common\give_up_root_privileges.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit180] FileName=..\src\common\hashtable.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit181] FileName=..\src\common\hexdump.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit182] FileName=..\src\common\list.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit183] FileName=..\src\common\network.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit184] FileName=..\src\common\packet.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit185] FileName=..\src\common\proginfo.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit186] FileName=..\src\common\queue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit187] FileName=..\src\common\rlimit.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit188] FileName=..\src\common\tag.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit189] FileName=..\src\common\token.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit190] FileName=..\src\common\trans.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit191] FileName=..\src\common\util.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit192] FileName=..\src\compat\uname.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit193] FileName=..\src\compat\access.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit194] FileName=..\src\compat\char_bit.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit195] FileName=..\src\compat\difftime.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit196] FileName=..\src\compat\exitstatus.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit197] FileName=..\src\compat\gethostname.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit198] FileName=..\src\compat\getopt.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit199] FileName=..\src\compat\gettimeofday.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit200] FileName=..\src\compat\inet_aton.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit201] FileName=..\src\compat\inet_ntoa.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit202] FileName=..\src\compat\memcpy.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit203] FileName=..\src\compat\memmove.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit204] FileName=..\src\compat\memset.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit205] FileName=..\src\compat\mkdir.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit206] FileName=..\src\compat\mmap.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit207] FileName=..\src\compat\netinet_in.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit208] FileName=..\src\compat\pdir.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit209] FileName=..\src\compat\psock.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit210] FileName=..\src\compat\read.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit211] FileName=..\src\compat\recv.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit212] FileName=..\src\compat\seek.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit213] FileName=..\src\compat\send.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit214] FileName=..\src\compat\signal.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit215] FileName=..\src\compat\socket.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit216] FileName=..\src\compat\statmacros.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit217] FileName=..\src\compat\stdfileno.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit218] FileName=..\src\compat\strcasecmp.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit219] FileName=..\src\compat\strchr.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit220] FileName=..\src\compat\strdup.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit221] FileName=..\src\compat\strerror.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit222] FileName=..\src\compat\strftime.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit223] FileName=..\src\compat\strncasecmp.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit224] FileName=..\src\compat\strrchr.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit225] FileName=..\src\compat\strsep.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit226] FileName=..\src\compat\strtoul.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit227] FileName=..\src\compat\termios.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit228] FileName=..\src\compat\uint.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit229] FileName=..\src\compat\uname.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit230] FileName=..\src\compat\difftime.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit231] FileName=..\src\compat\getopt.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit232] FileName=..\src\compat\gettimeofday.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit233] FileName=..\src\compat\inet_aton.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit234] FileName=..\src\compat\inet_ntoa.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit235] FileName=..\src\compat\memcpy.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit236] FileName=..\src\compat\memmove.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit237] FileName=..\src\compat\memset.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit238] FileName=..\src\compat\mmap.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit239] FileName=..\src\compat\pdir.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit240] FileName=..\src\compat\psock.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit241] FileName=..\src\compat\strcasecmp.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit242] FileName=..\src\compat\strdup.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit243] FileName=..\src\compat\strerror.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit244] FileName=..\src\compat\strftime.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit245] FileName=..\src\compat\strncasecmp.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit246] FileName=..\src\compat\strsep.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit247] FileName=..\src\compat\strtoul.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit248] FileName=..\src\zlib\pvpgn_zutil.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit249] FileName=..\src\zlib\pvpgn_deflate.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit250] FileName=..\src\zlib\pvpgn_trees.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit251] FileName=..\src\zlib\pvpgn_zconf.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit252] FileName=..\src\zlib\pvpgn_zlib.h CompileCpp=0 Folder=zlib/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit253] FileName=..\src\zlib\pvpgn_zutil.c CompileCpp=0 Folder=zlib/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit254] FileName=..\src\zlib\pvpgn_adler32.c CompileCpp=0 Folder=zlib/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit255] FileName=..\src\zlib\pvpgn_deflate.c CompileCpp=0 Folder=zlib/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit256] FileName=..\src\zlib\pvpgn_trees.c CompileCpp=0 Folder=zlib/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit257] FileName=..\src\tinycdb\cdb_int.h CompileCpp=0 Folder=tinycdb/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit258] FileName=..\src\tinycdb\cdb_unpack.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit259] FileName=..\src\tinycdb\cdb_find.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit260] FileName=..\src\tinycdb\cdb_findnext.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit261] FileName=..\src\tinycdb\cdb_hash.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit262] FileName=..\src\tinycdb\cdb_init.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit263] FileName=..\src\tinycdb\cdb_make.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit264] FileName=..\src\tinycdb\cdb_make_add.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit265] FileName=..\src\tinycdb\cdb_make_find.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit266] FileName=..\src\tinycdb\cdb_make_put.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit267] FileName=..\src\tinycdb\cdb_seek.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit268] FileName=..\src\tinycdb\cdb_seq.c CompileCpp=0 Folder=tinycdb/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit269] FileName=..\src\win32\service.h CompileCpp=0 Folder=win32/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit270] FileName=..\src\win32\service.c CompileCpp=0 Folder=win32/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit271] FileName=..\src\bnetd\team.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit272] FileName=..\src\bnetd\team.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit273] FileName=..\src\win32\winmain.h CompileCpp=0 Folder=win32/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit274] FileName=..\src\win32\winmain.c CompileCpp=0 Folder=win32/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit275] FileName=..\src\win32\resource.rc CompileCpp=0 Folder=win32/Resource Files Compile=1 Link=0 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit276] FileName=..\src\win32\resource.h CompileCpp=0 Folder=win32/Resource Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit277] FileName=..\src\common\rcm.h Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= CompileCpp=0 [Unit278] FileName=..\src\common\rcm.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit279] FileName=..\src\bnetd\attr.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit280] FileName=..\src\bnetd\attrlayer.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit281] FileName=..\src\bnetd\attrgroup.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit282] FileName=..\src\bnetd\attrlayer.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit283] FileName=..\src\bnetd\attrgroup.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit284] FileName=..\src\bnetd\cmdline.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit285] FileName=..\src\bnetd\cmdline.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit286] FileName=..\src\common\conf.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit287] FileName=..\src\common\conf.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit290] FileName=..\src\bnetd\sql_odbc.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit288] FileName=..\src\bnetd\sql_odbc.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit289] FileName=..\src\bnetd\sql_sqlite3.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit291] FileName=..\src\bnetd\sql_sqlite3.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit293] FileName=..\src\common\xstr.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit294] FileName=..\src\bnetd\storage_sql2.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit296] FileName=..\src\bnetd\sql_common.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit297] FileName=..\src\bnetd\sql_common.h CompileCpp=0 Folder=bnetd/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit298] FileName=C:\Programme\Dev-Cpp\include\odbc++\preparedstatement.h CompileCpp=0 Folder=dependencies Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit299] FileName=C:\Programme\Dev-Cpp\include\odbc++\resultset.h CompileCpp=0 Folder=dependencies Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit300] FileName=C:\Programme\Dev-Cpp\include\odbc++\resultsetmetadata.h CompileCpp=0 Folder=dependencies Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit301] FileName=C:\Programme\Dev-Cpp\include\odbc++\setup.h CompileCpp=0 Folder=dependencies Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit302] FileName=C:\Programme\Dev-Cpp\include\odbc++\statement.h CompileCpp=0 Folder=dependencies Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit303] FileName=C:\Programme\Dev-Cpp\include\odbc++\threads.h CompileCpp=0 Folder=dependencies Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit304] FileName=C:\Programme\Dev-Cpp\include\odbc++\types.h CompileCpp=0 Folder=dependencies Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit305] FileName=C:\Programme\Dev-Cpp\include\sqlite3.h CompileCpp=0 Folder=dependencies Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit292] FileName=..\src\common\xstr.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit295] FileName=..\src\bnetd\storage_sql2.c CompileCpp=0 Folder=bnetd/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= pvpgn-1.8.5/Win32-Projects/bnftp.dev0000644000175000017500000001327611151345317016155 0ustar aaronaaron[Project] FileName=bnftp.dev Name=bnftp UnitCount=32 Type=1 Ver=1 ObjFiles= Includes=..\src Libs= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=-lws2_32_@@_ IsCpp=0 Icon= ExeOutput=..\bin ObjectOutput= OverrideOutput=0 OverrideOutputName=bnftp.exe HostApplication= Folders=bnftp,"bnftp/Header Files","bnftp/Source Files",common,"common/Header Files","common/Source Files",compat,"compat/Header Files","compat/Source Files" CommandLine= UseCustomMakefile=0 IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 CustomMakefile= PrivateResource= [Unit1] FileName=..\src\client\client.c CompileCpp=0 Folder=bnftp/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\src\client\bnftp.c CompileCpp=0 Folder=bnftp/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\src\common\xalloc.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\src\common\bn_type.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\src\common\bnettime.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\src\common\eventlog.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\src\common\hexdump.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\src\common\network.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\src\common\packet.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\src\common\queue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\src\common\util.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\src\compat\strftime.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\src\compat\gettimeofday.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\src\compat\inet_ntoa.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\src\compat\psock.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\src\compat\strerror.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\src\common\xalloc.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\src\common\bn_type.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\src\common\bnettime.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\src\common\eventlog.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\src\common\hexdump.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\src\common\network.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\src\common\packet.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\src\common\queue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=..\src\common\setup_before.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\src\common\util.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=..\src\compat\strftime.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=..\src\compat\gettimeofday.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=..\src\compat\inet_ntoa.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit30] FileName=..\src\compat\psock.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit31] FileName=..\src\compat\strerror.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=..\src\client\client.h CompileCpp=0 Folder=bnftp/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion=0.1 FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=bnftp.exe ProductName=bnftp ProductVersion=0.1 AutoIncBuildNr=0 pvpgn-1.8.5/Win32-Projects/d2csConsole.vcproj0000644000175000017500000003121711151345317017742 0ustar aaronaaron pvpgn-1.8.5/Win32-Projects/bncdb.vcproj0000644000175000017500000001517411151345317016640 0ustar aaronaaron pvpgn-1.8.5/Win32-Projects/make_borland.bat0000644000175000017500000000125511151345317017444 0ustar aaronaaron@echo off echo =================================================================== echo Parameter -DWITH_SQL_MYSQL enables MySQL SQL storage support echo Parameter -DWITH_SQL_ODBC enables ODBC SQL storage support echo Parameter -DWITH_CDB enables CDB file storage support echo Parameter -DWITH_GUI to build GUI versions of bnetd, d2cs and d2dbs echo =================================================================== echo Parameter clean deletes object files echo =================================================================== copy Makefile.BORLAND ..\src\Makefile.BORLAND copy make_borland.bat ..\src\make_borland.bat cd ..\src make -fMakefile.BORLAND %1 %2 cd ..\Win32-Projectspvpgn-1.8.5/Win32-Projects/bnchat.dev0000644000175000017500000001634411151345317016302 0ustar aaronaaron[Project] FileName=bnchat.dev Name=bnchat UnitCount=42 Type=1 Ver=1 ObjFiles= Includes=..\src Libs= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=-lws2_32_@@_ IsCpp=0 Icon= ExeOutput=..\bin ObjectOutput= OverrideOutput=0 OverrideOutputName=bnchat.exe HostApplication= Folders=bnchat,"bnchat/Header Files","bnchat/Source Files",common,"common/Header Files","common/Source Files",compat,"compat/Header Files","compat/Source Files" CommandLine= UseCustomMakefile=0 IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 CustomMakefile= PrivateResource= [Unit1] FileName=..\src\client\udptest.c CompileCpp=0 Folder=bnchat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\src\client\bnchat.c CompileCpp=0 Folder=bnchat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\src\client\client.c CompileCpp=0 Folder=bnchat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\src\client\client_connect.c CompileCpp=0 Folder=bnchat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\src\common\xalloc.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\src\common\bn_type.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\src\common\bnethash.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\src\common\bnethashconv.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\src\common\bnettime.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\src\common\eventlog.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\src\common\hexdump.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\src\common\network.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\src\common\packet.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\src\common\proginfo.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\src\common\queue.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\src\common\util.c CompileCpp=0 Folder=common/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\src\compat\strerror.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\src\compat\gettimeofday.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\src\compat\inet_ntoa.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\src\compat\psock.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\src\common\xalloc.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\src\common\bn_type.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\src\common\bnethash.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\src\common\bnethashconv.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=..\src\common\bnettime.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\src\common\eventlog.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=..\src\common\hashtable.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=..\src\common\network.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=..\src\common\packet.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit30] FileName=..\src\common\proginfo.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit31] FileName=..\src\common\queue.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=..\src\common\setup_before.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit33] FileName=..\src\common\util.h CompileCpp=0 Folder=common/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit34] FileName=..\src\compat\strerror.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit35] FileName=..\src\compat\gettimeofday.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit36] FileName=..\src\compat\inet_ntoa.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit37] FileName=..\src\compat\psock.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit38] FileName=..\src\client\udptest.h CompileCpp=0 Folder=bnchat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit39] FileName=..\src\client\client.h CompileCpp=0 Folder=bnchat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit40] FileName=..\src\client\client_connect.h CompileCpp=0 Folder=bnchat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion=0.1 FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=bnchat.exe ProductName=bnchat ProductVersion=0.1 AutoIncBuildNr=0 [Unit41] FileName=..\src\compat\vsnprintf.h CompileCpp=0 Folder=compat/Header Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit42] FileName=..\src\compat\vsnprintf.c CompileCpp=0 Folder=compat/Source Files Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= pvpgn-1.8.5/BUGS0000644000175000017500000000355111151345317012331 0ustar aaronaaron You think you have found a bug ? Good, now read the list below and check if its already known. If you dont find it in the list then follow the bug report instructions. Known Bugs: - tournament support has only first round and it doesnt show the map after 25 minutes nor it stops the game after 30 minutes - there are some reported issues with PG/quickgame (network errors plus people getting lost game results when they shouldnt be, unfortunetly we havent been able to reproduce those) Bug report instructions: - first read this webpage and only after you have read it come back: http://www.chiark.greenend.org.uk/~sgtatham/bugs.html - logon to forums.pvpgn.org (create an account if necesarry) - search the support forums (official support or open tech support) if your problem was already reported, if it was reported then just add some comments to the already opened forum thread if you feel its necesary - if you got a new/unknown problem, open a new thread in the open tech support forum - give a usefull title to the thread, not like "it doesnt work" or "pvpgn sucks" couse this messages will just get ignored; you need to describe your problem in the tile in few words like "client disconnects in profile view" or "players get loss in playgame disconnects" or something like that - in the body of the post start with first saying which pvpgn version, on which OS (operating system) you run pvpgn, configure command line you used if you compiled your source on Unix/Linux - after that describe in detail your problem; what exactly did you tried to do, what did you expected from PvPGN and what happened wrong; also try before reporting the problem to find a way to reproduce the problem, that is to find the steps which if someone from the PvPGN team will do then they will get the problem too, and describe exactly the reproduction steps - thank you for the bug report! pvpgn-1.8.5/scripts/0000755000175000017500000000000011151345372013332 5ustar aaronaaronpvpgn-1.8.5/scripts/bnetd.init0000644000175000017500000000146011151345317015313 0ustar aaronaaron# -*- sh -*- # # bnetd Script to control the Unix Battle.net Daemon # # Author: Hakan Tandogan # # chkconfig: 2345 21 79 # description: bnetd is a Unix clone of the Battle.net Daemon # # Source function library. . /etc/rc.d/init.d/functions # See how we were called. case "$1" in start) # Start daemons. echo -n "Starting bnetd: " daemon bnetd echo touch /var/lock/subsys/bnetd ;; stop) # Stop daemons. echo -n "Shutting down bnetd: " killproc bnetd echo rm -f /var/lock/subsys/bnetd ;; reload) $0 stop $0 start ;; restart) $0 stop $0 start ;; status) status bnetd ;; *) echo "Usage: bnetd {start|stop|restart|reload|status}" exit 1 esac exit 0 pvpgn-1.8.5/scripts/cvs2cl.pl0000644000175000017500000016212111151345317015065 0ustar aaronaaron#!/bin/sh exec perl -w -x $0 ${1+"$@"} # -*- mode: perl; perl-indent-level: 2; -*- #!perl -w ############################################################## ### ### ### cvs2cl.pl: produce ChangeLog(s) from `cvs log` output. ### ### ### ############################################################## ## ## (C) 1999 Karl Fogel , under the GNU GPL. ## ## (Extensively hacked on by Melissa O'Neill .) ## ## cvs2cl.pl is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2, or (at your option) ## any later version. ## ## cvs2cl.pl is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You may have received a copy of the GNU General Public License ## along with cvs2cl.pl; see the file COPYING. If not, write to the ## Free Software Foundation, Inc., 59 Temple Place - Suite 330, ## Boston, MA 02111-1307, USA. use strict; use Text::Wrap; use Time::Local; use File::Basename; # The Plan: # # Read in the logs for multiple files, spit out a nice ChangeLog that # mirrors the information entered during `cvs commit'. # # The problem presents some challenges. In an ideal world, we could # detect files with the same author, log message, and checkin time -- # each would be a changelog entry. # We'd sort them; and spit them out. Unfortunately, CVS is *not atomic* # so checkins can span a range of times. Also, the directory structure # could be hierarchical. # # Another question is whether we really want to have the ChangeLog # exactly reflect commits. An author could issue two related commits, # with different log entries, reflecting a single logical change to the # source. GNU style ChangeLogs group these under a single author/date. # We try to do the same. # # So, we parse the output of `cvs log', storing log messages in a # multilevel hash that stores the mapping: # directory => author => time => message => filelist # As we go, we notice "nearby" commit times and store them together # (i.e., under the same timestamp), so they appear in the same log # entry. # # When we've read all the logs, we twist this mapping into # a time => author => message => filelist mapping for each directory. # # If we're not using the `--distributed' flag, the directory is always # considered to be `./', even as descend into subdirectories. ############### Globals ################ # What we run to generate it: my $Log_Source_Command = "cvs log"; # In case we have to print it out: my $VERSION = '$Revision: 1.1.1.1 $'; $VERSION =~ s/\S+\s+(\S+)\s+\S+/$1/; ## Vars set by options: # Print debugging messages? my $Debug = 0; # Just show version and exit? my $Print_Version = 0; # Just print usage message and exit? my $Print_Usage = 0; # Single top-level ChangeLog, or one per subdirectory? my $Distributed = 0; # What file should we generate (defaults to "ChangeLog")? my $Log_File_Name = "ChangeLog"; # Grab most recent entry date from existing ChangeLog file, just add # to that ChangeLog. my $Cumulative = 0; # Expand usernames to email addresses based on a map file? my $User_Map_File = ""; # Output to a file or to stdout? my $Output_To_Stdout = 0; # Eliminate empty log messages? my $Prune_Empty_Msgs = 0; # Don't call Text::Wrap on the body of the message my $No_Wrap = 0; # Separates header from log message. Code assumes it is either " " or # "\n\n", so if there's ever an option to set it to something else, # make sure to go through all conditionals that use this var. my $After_Header = " "; # Format more for programs than for humans. my $XML_Output = 0; # Do some special tweaks for log data that was written in FSF # ChangeLog style. my $FSF_Style = 0; # Show times in UTC instead of local time my $UTC_Times = 0; # Show day of week in output? my $Show_Day_Of_Week = 0; # Show revision numbers in output? my $Show_Revisions = 0; # Show tags (symbolic names) in output? my $Show_Tags = 0; # Show branches by symbolic name in output? my $Show_Branches = 0; # Show only revisions on these branches or their ancestors. my @Follow_Branches; # Don't bother with files matching this regexp. my @Ignore_Files; # How exactly we match entries. We definitely want "o", # and user might add "i" by using --case-insensitive option. my $Case_Insensitive = 0; # Maybe only show log messages matching a certain regular expression. my $Regexp_Gate = ""; # Pass this global option string along to cvs, to the left of `log': my $Global_Opts = ""; # Pass this option string along to the cvs log subcommand: my $Command_Opts = ""; # Read log output from stdin instead of invoking cvs log? my $Input_From_Stdin = 0; # Don't show filenames in output. my $Hide_Filenames = 0; # Max checkin duration. CVS checkin is not atomic, so we may have checkin # times that span a range of time. We assume that checkins will last no # longer than $Max_Checkin_Duration seconds, and that similarly, no # checkins will happen from the same users with the same message less # than $Max_Checkin_Duration seconds apart. my $Max_Checkin_Duration = 180; # What to put at the front of [each] ChangeLog. my $ChangeLog_Header = ""; ## end vars set by options. # In 'cvs log' output, one long unbroken line of equal signs separates # files: my $file_separator = "=======================================" . "======================================"; # In 'cvs log' output, a shorter line of dashes separates log messages # within a file: my $logmsg_separator = "----------------------------"; ############### End globals ############ &parse_options (); &derive_change_log (); ### Everything below is subroutine definitions. ### # If accumulating, grab the boundary date from pre-existing ChangeLog. sub maybe_grab_accumulation_date () { if (! $Cumulative) { return ""; } # else open (LOG, "$Log_File_Name") or die ("trouble opening $Log_File_Name for reading ($!)"); my $boundary_date; while () { if (/^(\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)/) { $boundary_date = "$1"; last; } } close (LOG); return $boundary_date; } # Fills up a ChangeLog structure in the current directory. sub derive_change_log () { # See "The Plan" above for a full explanation. my %grand_poobah; my $file_full_path; my $time; my $revision; my $author; my $msg_txt; my $detected_file_separator; # Might be adding to an existing ChangeLog my $accumulation_date = &maybe_grab_accumulation_date (); if ($accumulation_date) { $Log_Source_Command .= " -d\'>${accumulation_date}\'"; } # We might be expanding usernames my %usermap; # In general, it's probably not very maintainable to use state # variables like this to tell the loop what it's doing at any given # moment, but this is only the first one, and if we never have more # than a few of these, it's okay. my $collecting_symbolic_names = 0; my %symbolic_names; # Where tag names get stored. my %branch_names; # We'll grab branch names while we're at it. my %branch_numbers; # Save some revisions for @Follow_Branches my @branch_roots; # For showing which files are branch ancestors. # Bleargh. Compensate for a deficiency of custom wrapping. if (($After_Header ne " ") and $FSF_Style) { $After_Header .= "\t"; } if (! $Input_From_Stdin) { open (LOG_SOURCE, "$Log_Source_Command |") or die "unable to run \"${Log_Source_Command}\""; } else { open (LOG_SOURCE, "-") or die "unable to open stdin for reading"; } %usermap = &maybe_read_user_map_file (); while () { # If on a new file and don't see filename, skip until we find it, and # when we find it, grab it. if ((! (defined $file_full_path)) and /^Working file: (.*)/) { $file_full_path = $1; if (@Ignore_Files) { my $base; ($base, undef, undef) = fileparse ($file_full_path); # Ouch, I wish trailing operators in regexps could be # evaluated on the fly! if ($Case_Insensitive) { if (grep ($file_full_path =~ m|$_|i, @Ignore_Files)) { undef $file_full_path; } } elsif (grep ($file_full_path =~ m|$_|, @Ignore_Files)) { undef $file_full_path; } } next; } # Just spin wheels if no file defined yet. next if (! $file_full_path); # Collect tag names in case we're asked to print them in the output. if (/^symbolic names:$/) { $collecting_symbolic_names = 1; next; # There's no more info on this line, so skip to next } if ($collecting_symbolic_names) { # All tag names are listed with whitespace in front in cvs log # output; so if see non-whitespace, then we're done collecting. if (/^\S/) { $collecting_symbolic_names = 0; } else # we're looking at a tag name, so parse & store it { # According to the Cederqvist manual, in node "Tags", tag # names must start with an uppercase or lowercase letter and # can contain uppercase and lowercase letters, digits, `-', # and `_'. However, it's not our place to enforce that, so # we'll allow anything CVS hands us to be a tag: /^\s+([^:]+): ([\d.]+)$/; my $tag_name = $1; my $tag_rev = $2; # A branch number either has an odd number of digit sections # (and hence an even number of dots), or has ".0." as the # second-to-last digit section. Test for these conditions. my $real_branch_rev = ""; if (($tag_rev =~ /^(\d+\.\d+\.)+\d+$/) # Even number of dots... and (! ($tag_rev =~ /^(1\.)+1$/))) # ...but not "1.[1.]1" { $real_branch_rev = $tag_rev; } elsif ($tag_rev =~ /(\d+\.(\d+\.)+)0.(\d+)/) # Has ".0." { $real_branch_rev = $1 . $3; } # If we got a branch, record its number. if ($real_branch_rev) { $branch_names{$real_branch_rev} = $tag_name; if (@Follow_Branches) { if (grep ($_ eq $tag_name, @Follow_Branches)) { $branch_numbers{$tag_name} = $real_branch_rev; } } } else { # Else it's just a regular (non-branch) tag. push (@{$symbolic_names{$tag_rev}}, $tag_name); } } } # End of code for collecting tag names. # If have file name, but not revision, and see revision, then grab # it. (We collect unconditionally, even though we may or may not # ever use it.) if ((! (defined $revision)) and (/^revision (\d+\.[\d.]+)/)) { $revision = $1; if (@Follow_Branches) { foreach my $branch (@Follow_Branches) { # Special case for following trunk revisions if (($branch =~ /^trunk$/i) and ($revision =~ /^[0-9]+\.[0-9]+$/)) { goto dengo; } my $branch_number = $branch_numbers{$branch}; if ($branch_number) { # Are we on one of the follow branches or an ancestor of # same? # # If this revision is a prefix of the branch number, or # possibly is less in the minormost number, OR if this # branch number is a prefix of the revision, then yes. # Otherwise, no. # # So below, we determine if any of those conditions are # met. # Trivial case: is this revision on the branch? # (Compare this way to avoid regexps that screw up Emacs # indentation, argh.) if ((substr ($revision, 0, ((length ($branch_number)) + 1))) eq ($branch_number . ".")) { goto dengo; } # Non-trivial case: check if rev is ancestral to branch elsif ((length ($branch_number)) > (length ($revision))) { $revision =~ /^((?:\d+\.)+)(\d+)$/; my $r_left = $1; # still has the trailing "." my $r_end = $2; $branch_number =~ /^((?:\d+\.)+)(\d+)\.\d+$/; my $b_left = $1; # still has trailing "." my $b_mid = $2; # has no trailing "." if (($r_left eq $b_left) && ($r_end <= $b_mid)) { goto dengo; } } } } } else # (! @Follow_Branches) { next; } # Else we are following branches, but this revision isn't on the # path. So skip it. undef $revision; dengo: next; } # If we don't have a revision right now, we couldn't possibly # be looking at anything useful. if (! (defined ($revision))) { $detected_file_separator = /^$file_separator$/o; if ($detected_file_separator) { # No revisions for this file; can happen, e.g. "cvs log -d DATE" goto CLEAR; } else { next; } } # If have file name but not date and author, and see date or # author, then grab them: unless (defined $time) { if (/^date: .*/) { ($time, $author) = &parse_date_and_author ($_); if (defined ($usermap{$author}) and $usermap{$author}) { $author = $usermap{$author}; } } else { $detected_file_separator = /^$file_separator$/o; if ($detected_file_separator) { # No revisions for this file; can happen, e.g. "cvs log -d DATE" goto CLEAR; } } # If the date/time/author hasn't been found yet, we couldn't # possibly care about anything we see. So skip: next; } # A "branches: ..." line here indicates that one or more branches # are rooted at this revision. If we're showing branches, then we # want to show that fact as well, so we collect all the branches # that this is the latest ancestor of and store them in # @branch_roots. Just for reference, the format of the line we're # seeing at this point is: # # branches: 1.5.2; 1.5.4; ...; # # Okay, here goes: if (/^branches:\s+(.*);$/) { if ($Show_Branches) { my $lst = $1; $lst =~ s/(1\.)+1;|(1\.)+1$//; # ignore the trivial branch 1.1.1 if ($lst) { @branch_roots = split (/;\s+/, $lst); } else { undef @branch_roots; } next; } else { # Ugh. This really bothers me. Suppose we see a log entry # like this: # # ---------------------------- # revision 1.1 # date: 1999/10/17 03:07:38; author: jrandom; state: Exp; # branches: 1.1.2; # Intended first line of log message begins here. # ---------------------------- # # The question is, how we can tell the difference between that # log message and a *two*-line log message whose first line is # # "branches: 1.1.2;" # # See the problem? The output of "cvs log" is inherently # ambiguous. # # For now, we punt: we liberally assume that people don't # write log messages like that, and just toss a "branches:" # line if we see it but are not showing branches. I hope no # one ever loses real log data because of this. next; } } # If have file name, time, and author, then we're just grabbing # log message texts: $detected_file_separator = /^$file_separator$/o; if ($detected_file_separator && ! (defined $revision)) { # No revisions for this file; can happen, e.g. "cvs log -d DATE" goto CLEAR; } unless ($detected_file_separator || /^$logmsg_separator$/o) { $msg_txt .= $_; # Normally, just accumulate the message... next; } # ... until a msg separator is encountered: # Ensure the message contains something: if ((! $msg_txt) || ($msg_txt =~ /^\s*\.\s*$|^\s*$/) || ($msg_txt =~ /\*\*\* empty log message \*\*\*/)) { if ($Prune_Empty_Msgs) { goto CLEAR; } # else $msg_txt = "[no log message]\n"; } ### Store it all in the Grand Poobah: { my $dir_key; # key into %grand_poobah my %qunk; # complicated little jobbie, see below # Each revision of a file has a little data structure (a `qunk') # associated with it. That data structure holds not only the # file's name, but any additional information about the file # that might be needed in the output, such as the revision # number, tags, branches, etc. The reason to have these things # arranged in a data structure, instead of just appending them # textually to the file's name, is that we may want to do a # little rearranging later as we write the output. For example, # all the files on a given tag/branch will go together, followed # by the tag in parentheses (so trunk or otherwise non-tagged # files would go at the end of the file list for a given log # message). This rearrangement is a lot easier to do if we # don't have to reparse the text. # # A qunk looks like this: # # { # filename => "hello.c", # revision => "1.4.3.2", # time => a timegm() return value (moment of commit) # tags => [ "tag1", "tag2", ... ], # branch => "branchname" # There should be only one, right? # branchroots => [ "branchtag1", "branchtag2", ... ] # } if ($Distributed) { # Just the basename, don't include the path. ($qunk{'filename'}, $dir_key, undef) = fileparse ($file_full_path); } else { $dir_key = "./"; $qunk{'filename'} = $file_full_path; } # This may someday be used in a more sophisticated calculation # of what other files are involved in this commit. For now, we # don't use it, because the common-commit-detection algorithm is # hypothesized to be "good enough" as it stands. $qunk{'time'} = $time; # We might be including revision numbers and/or tags and/or # branch names in the output. Most of the code from here to # loop-end deals with organizing these in qunk. $qunk{'revision'} = $revision; # Grab the branch, even though we may or may not need it: $qunk{'revision'} =~ /((?:\d+\.)+)\d+/; my $branch_prefix = $1; $branch_prefix =~ s/\.$//; # strip off final dot if ($branch_names{$branch_prefix}) { $qunk{'branch'} = $branch_names{$branch_prefix}; } # If there's anything in the @branch_roots array, then this # revision is the root of at least one branch. We'll display # them as branch names instead of revision numbers, the # substitution for which is done directly in the array: if (@branch_roots) { my @roots = map { $branch_names{$_} } @branch_roots; $qunk{'branchroots'} = \@roots; } # Save tags too. if (defined ($symbolic_names{$revision})) { $qunk{'tags'} = $symbolic_names{$revision}; delete $symbolic_names{$revision}; } # Add this file to the list # (We use many spoonfuls of autovivication magic. Hashes and arrays # will spring into existence if they aren't there already.) &debug ("(pushing log msg for ${dir_key}$qunk{'filename'})\n"); # Store with the files in this commit. Later we'll loop through # again, making sure that revisions with the same log message # and nearby commit times are grouped together as one commit. push (@{$grand_poobah{$dir_key}{$author}{$time}{$msg_txt}}, \%qunk); } CLEAR: # Make way for the next message undef $msg_txt; undef $time; undef $revision; undef $author; undef @branch_roots; # Maybe even make way for the next file: if ($detected_file_separator) { undef $file_full_path; undef %branch_names; undef %branch_numbers; undef %symbolic_names; } } close (LOG_SOURCE); ### Process each ChangeLog while (my ($dir,$authorhash) = each %grand_poobah) { &debug ("DOING DIR: $dir\n"); # Here we twist our hash around, from being # author => time => message => filelist # in %$authorhash to # time => author => message => filelist # in %changelog. # # This is also where we merge entries. The algorithm proceeds # through the timeline of the changelog with a sliding window of # $Max_Checkin_Duration seconds; within that window, entries that # have the same log message are merged. # # (To save space, we zap %$authorhash after we've copied # everything out of it.) my %changelog; while (my ($author,$timehash) = each %$authorhash) { my $lasttime; my %stamptime; foreach my $time (sort {$main::a <=> $main::b} (keys %$timehash)) { my $msghash = $timehash->{$time}; while (my ($msg,$qunklist) = each %$msghash) { my $stamptime = $stamptime{$msg}; if ((defined $stamptime) and (($time - $stamptime) < $Max_Checkin_Duration) and (defined $changelog{$stamptime}{$author}{$msg})) { push(@{$changelog{$stamptime}{$author}{$msg}}, @$qunklist); } else { $changelog{$time}{$author}{$msg} = $qunklist; $stamptime{$msg} = $time; } } } } undef (%$authorhash); ### Now we can write out the ChangeLog! my ($logfile_here, $logfile_bak, $tmpfile); if (! $Output_To_Stdout) { $logfile_here = $dir . $Log_File_Name; $logfile_here =~ s/^\.\/\//\//; # fix any leading ".//" problem $tmpfile = "${logfile_here}.cvs2cl$$.tmp"; $logfile_bak = "${logfile_here}.bak"; open (LOG_OUT, ">$tmpfile") or die "Unable to open \"$tmpfile\""; } else { open (LOG_OUT, ">-") or die "Unable to open stdout for writing"; } print LOG_OUT $ChangeLog_Header; if ($XML_Output) { print LOG_OUT "\n\n" . "\n\n"; } foreach my $time (sort {$main::b <=> $main::a} (keys %changelog)) { my $authorhash = $changelog{$time}; while (my ($author,$mesghash) = each %$authorhash) { # If XML, escape in outer loop to avoid compound quoting: if ($XML_Output) { $author = &xml_escape ($author); } while (my ($msg,$qunklist) = each %$mesghash) { my $files = &pretty_file_list ($qunklist); my $header_line; # date and author my $body; # see below my $wholething; # $header_line + $body # Set up the date/author line. # kff todo: do some more XML munging here, on the header # part of the entry: my ($ignore,$min,$hour,$mday,$mon,$year,$wday) = $UTC_Times ? gmtime($time) : localtime($time); # XML output includes everything else, we might as well make # it always include Day Of Week too, for consistency. if ($Show_Day_Of_Week or $XML_Output) { $wday = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")[$wday]; $wday = ($XML_Output) ? "${wday}\n" : " $wday"; } else { $wday = ""; } if ($XML_Output) { $header_line = sprintf ("%4u-%02u-%02u\n" . "${wday}" . "\n" . "%s\n", $year+1900, $mon+1, $mday, $hour, $min, $author); } else { $header_line = sprintf ("%4u-%02u-%02u${wday} %02u:%02u %s\n\n", $year+1900, $mon+1, $mday, $hour, $min, $author); } # Reshape the body according to user preferences. if ($XML_Output) { $msg = &preprocess_msg_text ($msg); $body = $files . $msg; } elsif ($No_Wrap) { $msg = &preprocess_msg_text ($msg); $files = wrap ("\t", " ", "$files"); $msg =~ s/\n(.*)/\n\t$1/g; unless ($After_Header eq " ") { $msg =~ s/^(.*)/\t$1/g; } $body = $files . $After_Header . $msg; } else # do wrapping, either FSF-style or regular { if ($FSF_Style) { $files = wrap ("\t", " ", "$files"); my $files_last_line_len = 0; if ($After_Header eq " ") { $files_last_line_len = &last_line_len ($files); $files_last_line_len += 1; # for $After_Header } $msg = &wrap_log_entry ($msg, "\t", 69 - $files_last_line_len, 69); $body = $files . $After_Header . $msg; } else # not FSF-style { $msg = &preprocess_msg_text ($msg); $body = $files . $After_Header . $msg; $body = wrap ("\t", " ", "$body"); } } $wholething = $header_line . $body; if ($XML_Output) { $wholething = "\n${wholething}\n"; } # One last check: make sure it passes the regexp test, if the # user asked for that. We have to do it here, so that the # test can match against information in the header as well # as in the text of the log message. # How annoying to duplicate so much code just because I # can't figure out a way to evaluate scalars on the trailing # operator portion of a regular expression. Grrr. if ($Case_Insensitive) { unless ($Regexp_Gate && ($wholething =~ /$Regexp_Gate/oi)) { print LOG_OUT "${wholething}\n"; } } else { unless ($Regexp_Gate && ($wholething =~ /$Regexp_Gate/o)) { print LOG_OUT "${wholething}\n"; } } } } } if ($XML_Output) { print LOG_OUT "\n"; } close (LOG_OUT); if (! $Output_To_Stdout) { # If accumulating, append old data to new before renaming. But # don't append the most recent entry, since it's already in the # new log due to CVS's idiosyncratic interpretation of "log -d". if ($Cumulative && -f $logfile_here) { open (NEW_LOG, ">>$tmpfile") or die "trouble appending to $tmpfile ($!)"; open (OLD_LOG, "<$logfile_here") or die "trouble reading from $logfile_here ($!)"; my $started_first_entry = 0; my $passed_first_entry = 0; while () { if (! $passed_first_entry) { if ((! $started_first_entry) && /^(\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)/) { $started_first_entry = 1; } elsif (/^(\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)/) { $passed_first_entry = 1; print NEW_LOG $_; } } else { print NEW_LOG $_; } } close (NEW_LOG); close (OLD_LOG); } if (-f $logfile_here) { rename ($logfile_here, $logfile_bak); } rename ($tmpfile, $logfile_here); } } } sub parse_date_and_author () { # Parses the date/time and author out of a line like: # # date: 1999/02/19 23:29:05; author: apharris; state: Exp; my $line = shift; my ($year, $mon, $mday, $hours, $min, $secs, $author) = $line =~ m#(\d+)/(\d+)/(\d+)\s+(\d+):(\d+):(\d+);\s+author:\s+([^;]+);# or die "Couldn't parse date ``$line''"; die "Bad date or Y2K issues" unless ($year > 1969 and $year < 2258); # Kinda arbitrary, but useful as a sanity check my $time = timegm($secs,$min,$hours,$mday,$mon-1,$year-1900); return ($time, $author); } # Here we take a bunch of qunks and convert them into printed # summary that will include all the information the user asked for. sub pretty_file_list () { if ($Hide_Filenames and (! $XML_Output)) { return ""; } my $qunksref = shift; my @qunkrefs = @$qunksref; my @filenames; my $beauty = ""; # The accumulating header string for this entry. my %non_unanimous_tags; # Tags found in a proper subset of qunks my %unanimous_tags; # Tags found in all qunks my %all_branches; # Branches found in any qunk my $common_dir = undef; # Dir prefix common to all files ("" if none) my $fbegun = 0; # Did we begin printing filenames yet? # First, loop over the qunks gathering all the tag/branch names. # We'll put them all in non_unanimous_tags, and take out the # unanimous ones later. foreach my $qunkref (@qunkrefs) { # Keep track of whether all the files in this commit were in the # same directory, and memorize it if so. We can make the output a # little more compact by mentioning the directory only once. if ((scalar (@qunkrefs)) > 1) { if (! (defined ($common_dir))) { my ($base, $dir); ($base, $dir, undef) = fileparse ($$qunkref{'filename'}); if ((! (defined ($dir))) # this first case is sheer paranoia or ($dir eq "") or ($dir eq "./") or ($dir eq ".\\")) { $common_dir = ""; } else { $common_dir = $dir; } } elsif ($common_dir ne "") { # Already have a common dir prefix, so how much of it can we preserve? $common_dir = &common_path_prefix ($$qunkref{'filename'}, $common_dir); } } else # only one file in this entry anyway, so common dir not an issue { $common_dir = ""; } if (defined ($$qunkref{'branch'})) { $all_branches{$$qunkref{'branch'}} = 1; } if (defined ($$qunkref{'tags'})) { foreach my $tag (@{$$qunkref{'tags'}}) { $non_unanimous_tags{$tag} = 1; } } } # Any tag held by all qunks will be printed specially... but only if # there are multiple qunks in the first place! if ((scalar (@qunkrefs)) > 1) { foreach my $tag (keys (%non_unanimous_tags)) { my $everyone_has_this_tag = 1; foreach my $qunkref (@qunkrefs) { if ((! (defined ($$qunkref{'tags'}))) or (! (grep ($_ eq $tag, @{$$qunkref{'tags'}})))) { $everyone_has_this_tag = 0; } } if ($everyone_has_this_tag) { $unanimous_tags{$tag} = 1; delete $non_unanimous_tags{$tag}; } } } if ($XML_Output) { # If outputting XML, then our task is pretty simple, because we # don't have to detect common dir, common tags, branch prefixing, # etc. We just output exactly what we have, and don't worry about # redundancy or readability. foreach my $qunkref (@qunkrefs) { my $filename = $$qunkref{'filename'}; my $revision = $$qunkref{'revision'}; my $tags = $$qunkref{'tags'}; my $branch = $$qunkref{'branch'}; my $branchroots = $$qunkref{'branchroots'}; $filename = &xml_escape ($filename); # probably paranoia $revision = &xml_escape ($revision); # definitely paranoia $beauty .= "\n"; $beauty .= "${filename}\n"; $beauty .= "${revision}\n"; if ($branch) { $branch = &xml_escape ($branch); # more paranoia $beauty .= "${branch}\n"; } foreach my $tag (@$tags) { $tag = &xml_escape ($tag); # by now you're used to the paranoia $beauty .= "${tag}\n"; } foreach my $root (@$branchroots) { $root = &xml_escape ($root); # which is good, because it will continue $beauty .= "${root}\n"; } $beauty .= "\n"; } # Theoretically, we could go home now. But as long as we're here, # let's print out the common_dir and utags, as a convenience to # the receiver (after all, earlier code calculated that stuff # anyway, so we might as well take advantage of it). if ((scalar (keys (%unanimous_tags))) > 1) { foreach my $utag ((keys (%unanimous_tags))) { $utag = &xml_escape ($utag); # the usual paranoia $beauty .= "${utag}\n"; } } if ($common_dir) { $common_dir = &xml_escape ($common_dir); $beauty .= "${common_dir}\n"; } # That's enough for XML, time to go home: return $beauty; } # Else not XML output, so complexly compactify for chordate # consumption. At this point we have enough global information # about all the qunks to organize them non-redundantly for output. if ($common_dir) { # Note that $common_dir still has its trailing slash $beauty .= "$common_dir: "; } if ($Show_Branches) { # For trailing revision numbers. my @brevisions; foreach my $branch (keys (%all_branches)) { foreach my $qunkref (@qunkrefs) { if ((defined ($$qunkref{'branch'})) and ($$qunkref{'branch'} eq $branch)) { if ($fbegun) { # kff todo: comma-delimited in XML too? Sure. $beauty .= ", "; } else { $fbegun = 1; } my $fname = substr ($$qunkref{'filename'}, length ($common_dir)); $beauty .= $fname; $$qunkref{'printed'} = 1; # Just setting a mark bit, basically if ($Show_Tags && (defined @{$$qunkref{'tags'}})) { my @tags = grep ($non_unanimous_tags{$_}, @{$$qunkref{'tags'}}); if (@tags) { $beauty .= " (tags: "; $beauty .= join (', ', @tags); $beauty .= ")"; } } if ($Show_Revisions) { # Collect the revision numbers' last components, but don't # print them -- they'll get printed with the branch name # later. $$qunkref{'revision'} =~ /.+\.([\d]+)$/; push (@brevisions, $1); # todo: we're still collecting branch roots, but we're not # showing them anywhere. If we do show them, it would be # nifty to just call them revision "0" on a the branch. # Yeah, that's the ticket. } } } $beauty .= " ($branch"; if (@brevisions) { if ((scalar (@brevisions)) > 1) { $beauty .= ".["; $beauty .= (join (',', @brevisions)); $beauty .= "]"; } else { $beauty .= ".$brevisions[0]"; } } $beauty .= ")"; } } # Okay; any qunks that were done according to branch are taken care # of, and marked as printed. Now print everyone else. foreach my $qunkref (@qunkrefs) { next if (defined ($$qunkref{'printed'})); # skip if already printed if ($fbegun) { $beauty .= ", "; } else { $fbegun = 1; } $beauty .= substr ($$qunkref{'filename'}, length ($common_dir)); # todo: Shlomo's change was this: # $beauty .= substr ($$qunkref{'filename'}, # (($common_dir eq "./") ? "" : length ($common_dir))); $$qunkref{'printed'} = 1; # Set a mark bit. if ($Show_Revisions || $Show_Tags) { my $started_addendum = 0; if ($Show_Revisions) { $started_addendum = 1; $beauty .= " ("; $beauty .= "$$qunkref{'revision'}"; } if ($Show_Tags && (defined $$qunkref{'tags'})) { my @tags = grep ($non_unanimous_tags{$_}, @{$$qunkref{'tags'}}); if ((scalar (@tags)) > 0) { if ($started_addendum) { $beauty .= ", "; } else { $beauty .= " (tags: "; } $beauty .= join (', ', @tags); $started_addendum = 1; } } if ($started_addendum) { $beauty .= ")"; } } } # Unanimous tags always come last. if ($Show_Tags && %unanimous_tags) { $beauty .= " (utags: "; $beauty .= join (', ', keys (%unanimous_tags)); $beauty .= ")"; } # todo: still have to take care of branch_roots? $beauty = "* $beauty:"; return $beauty; } sub common_path_prefix () { my $path1 = shift; my $path2 = shift; my ($dir1, $dir2); (undef, $dir1, undef) = fileparse ($path1); (undef, $dir2, undef) = fileparse ($path2); # Transmogrify Windows filenames to look like Unix. # (It is far more likely that someone is running cvs2cl.pl under # Windows than that they would genuinely have backslashes in their # filenames.) $dir1 =~ tr#\\#/#; $dir2 =~ tr#\\#/#; my $accum1 = ""; my $accum2 = ""; my $last_common_prefix = ""; while ($accum1 eq $accum2) { $last_common_prefix = $accum1; last if ($accum1 eq $dir1); my ($tmp1) = split (/\//, (substr ($dir1, length ($accum1)))); my ($tmp2) = split (/\//, (substr ($dir2, length ($accum2)))); $accum1 .= "$tmp1/" if ((defined ($tmp1)) and $tmp1); $accum2 .= "$tmp2/" if ((defined ($tmp2)) and $tmp2); } return $last_common_prefix; } sub preprocess_msg_text () { my $text = shift; # Strip out carriage returns (as they probably result from DOSsy editors). $text =~ s/\r\n/\n/g; # If it *looks* like two newlines, make it *be* two newlines: $text =~ s/\n\s*\n/\n\n/g; if ($XML_Output) { $text = &xml_escape ($text); $text = "${text}\n"; } elsif (! $No_Wrap) { # Strip off lone newlines, but only for lines that don't begin with # whitespace or a mail-quoting character, since we want to preserve # that kind of formatting. Also don't strip newlines that follow a # period; we handle those specially next. And don't strip # newlines that precede an open paren. 1 while ($text =~ s/(^|\n)([^>\s].*[^.\n])\n([^>\n])/$1$2 $3/g); # If a newline follows a period, make sure that when we bring up the # bottom sentence, it begins with two spaces. 1 while ($text =~ s/(^|\n)([^>\s].*)\n([^>\n])/$1$2 $3/g); } return $text; } sub last_line_len () { my $files_list = shift; my @lines = split (/\n/, $files_list); my $last_line = pop (@lines); return length ($last_line); } # A custom wrap function, sensitive to some common constructs used in # log entries. sub wrap_log_entry () { my $text = shift; # The text to wrap. my $left_pad_str = shift; # String to pad with on the left. # These do NOT take left_pad_str into account: my $length_remaining = shift; # Amount left on current line. my $max_line_length = shift; # Amount left for a blank line. my $wrapped_text = ""; # The accumulating wrapped entry. my $user_indent = ""; # Inherited user_indent from prev line. my $first_time = 1; # First iteration of the loop? my $suppress_line_start_match = 0; # Set to disable line start checks. my @lines = split (/\n/, $text); while (@lines) # Don't use `foreach' here, it won't work. { my $this_line = shift (@lines); chomp $this_line; if ($this_line =~ /^(\s+)/) { $user_indent = $1; } else { $user_indent = ""; } # If it matches any of the line-start regexps, print a newline now... if ($suppress_line_start_match) { $suppress_line_start_match = 0; } elsif (($this_line =~ /^(\s*)\*\s+[a-zA-Z0-9]/) || ($this_line =~ /^(\s*)\* [a-zA-Z0-9_\.\/\+-]+/) || ($this_line =~ /^(\s*)\([a-zA-Z0-9_\.\/\+-]+(\)|,\s*)/) || ($this_line =~ /^(\s+)(\S+)/) || ($this_line =~ /^(\s*)- +/) || ($this_line =~ /^()\s*$/) || ($this_line =~ /^(\s*)\*\) +/) || ($this_line =~ /^(\s*)[a-zA-Z0-9](\)|\.|\:) +/)) { # Make a line break immediately, unless header separator is set # and this line is the first line in the entry, in which case # we're getting the blank line for free already and shouldn't # add an extra one. unless (($After_Header ne " ") and ($first_time)) { if ($this_line =~ /^()\s*$/) { $suppress_line_start_match = 1; $wrapped_text .= "\n${left_pad_str}"; } $wrapped_text .= "\n${left_pad_str}"; } $length_remaining = $max_line_length - (length ($user_indent)); } # Now that any user_indent has been preserved, strip off leading # whitespace, so up-folding has no ugly side-effects. $this_line =~ s/^\s*//; # Accumulate the line, and adjust parameters for next line. my $this_len = length ($this_line); if ($this_len == 0) { # Blank lines should cancel any user_indent level. $user_indent = ""; $length_remaining = $max_line_length; } elsif ($this_len >= $length_remaining) # Line too long, try breaking it. { # Walk backwards from the end. At first acceptable spot, break # a new line. my $idx = $length_remaining - 1; if ($idx < 0) { $idx = 0 }; while ($idx > 0) { if (substr ($this_line, $idx, 1) =~ /\s/) { my $line_now = substr ($this_line, 0, $idx); my $next_line = substr ($this_line, $idx); $this_line = $line_now; # Clean whitespace off the end. chomp $this_line; # The current line is ready to be printed. $this_line .= "\n${left_pad_str}"; # Make sure the next line is allowed full room. $length_remaining = $max_line_length - (length ($user_indent)); # Strip next_line, but then preserve any user_indent. $next_line =~ s/^\s*//; # Sneak a peek at the user_indent of the upcoming line, so # $next_line (which will now precede it) can inherit that # indent level. Otherwise, use whatever user_indent level # we currently have, which might be none. my $next_next_line = shift (@lines); if ((defined ($next_next_line)) && ($next_next_line =~ /^(\s+)/)) { $next_line = $1 . $next_line if (defined ($1)); # $length_remaining = $max_line_length - (length ($1)); $next_next_line =~ s/^\s*//; } else { $next_line = $user_indent . $next_line; } if (defined ($next_next_line)) { unshift (@lines, $next_next_line); } unshift (@lines, $next_line); # Our new next line might, coincidentally, begin with one of # the line-start regexps, so we temporarily turn off # sensitivity to that until we're past the line. $suppress_line_start_match = 1; last; } else { $idx--; } } if ($idx == 0) { # We bottomed out because the line is longer than the # available space. But that could be because the space is # small, or because the line is longer than even the maximum # possible space. Handle both cases below. if ($length_remaining == ($max_line_length - (length ($user_indent)))) { # The line is simply too long -- there is no hope of ever # breaking it nicely, so just insert it verbatim, with # appropriate padding. $this_line = "\n${left_pad_str}${this_line}"; } else { # Can't break it here, but may be able to on the next round... unshift (@lines, $this_line); $length_remaining = $max_line_length - (length ($user_indent)); $this_line = "\n${left_pad_str}"; } } } else # $this_len < $length_remaining, so tack on what we can. { # Leave a note for the next iteration. $length_remaining = $length_remaining - $this_len; if ($this_line =~ /\.$/) { $this_line .= " "; $length_remaining -= 2; } else # not a sentence end { $this_line .= " "; $length_remaining -= 1; } } # Unconditionally indicate that loop has run at least once. $first_time = 0; $wrapped_text .= "${user_indent}${this_line}"; } # One last bit of padding. $wrapped_text .= "\n"; return $wrapped_text; } sub xml_escape () { my $txt = shift; $txt =~ s/&/&/g; $txt =~ s//>/g; return $txt; } sub maybe_read_user_map_file () { my %expansions; if ($User_Map_File) { open (MAPFILE, "<$User_Map_File") or die ("Unable to open $User_Map_File ($!)"); while () { next if /^\s*#/; # Skip comment lines. next if not /:/; # Skip lines without colons. # It is now safe to split on ':'. my ($username, $expansion) = split ':'; chomp $expansion; $expansion =~ s/^'(.*)'$/$1/; $expansion =~ s/^"(.*)"$/$1/; # If it looks like the expansion has a real name already, then # we toss the username we got from CVS log. Otherwise, keep # it to use in combination with the email address. if ($expansion =~ /^\s*<{0,1}\S+@.*/) { # Also, add angle brackets if none present if (! ($expansion =~ /<\S+@\S+>/)) { $expansions{$username} = "$username <$expansion>"; } else { $expansions{$username} = "$username $expansion"; } } else { $expansions{$username} = $expansion; } } close (MAPFILE); } return %expansions; } sub parse_options () { # Check this internally before setting the global variable. my $output_file; # If this gets set, we encountered unknown options and will exit at # the end of this subroutine. my $exit_with_admonishment = 0; while (my $arg = shift (@ARGV)) { if ($arg =~ /^-h$|^-help$|^--help$|^--usage$|^-?$/) { $Print_Usage = 1; } elsif ($arg =~ /^--debug$/) { # unadvertised option, heh $Debug = 1; } elsif ($arg =~ /^--version$/) { $Print_Version = 1; } elsif ($arg =~ /^-g$|^--global-opts$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; # Don't assume CVS is called "cvs" on the user's system: $Log_Source_Command =~ s/(^\S*)/$1 $narg/; } elsif ($arg =~ /^-l$|^--log-opts$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $Log_Source_Command .= " $narg"; } elsif ($arg =~ /^-f$|^--file$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $output_file = $narg; } elsif ($arg =~ /^--accum$/) { $Cumulative = 1; } elsif ($arg =~ /^--fsf$/) { $FSF_Style = 1; } elsif ($arg =~ /^-U$|^--usermap$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $User_Map_File = $narg; } elsif ($arg =~ /^-W$|^--window$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $Max_Checkin_Duration = $narg; } elsif ($arg =~ /^-I$|^--ignore$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; push (@Ignore_Files, $narg); } elsif ($arg =~ /^-C$|^--case-insensitive$/) { $Case_Insensitive = 1; } elsif ($arg =~ /^-R$|^--regexp$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $Regexp_Gate = $narg; } elsif ($arg =~ /^--stdout$/) { $Output_To_Stdout = 1; } elsif ($arg =~ /^--version$/) { $Print_Version = 1; } elsif ($arg =~ /^-d$|^--distributed$/) { $Distributed = 1; } elsif ($arg =~ /^-P$|^--prune$/) { $Prune_Empty_Msgs = 1; } elsif ($arg =~ /^-S$|^--separate-header$/) { $After_Header = "\n\n"; } elsif ($arg =~ /^--no-wrap$/) { $No_Wrap = 1; } elsif ($arg =~ /^--gmt$|^--utc$/) { $UTC_Times = 1; } elsif ($arg =~ /^-w$|^--day-of-week$/) { $Show_Day_Of_Week = 1; } elsif ($arg =~ /^-r$|^--revisions$/) { $Show_Revisions = 1; } elsif ($arg =~ /^-t$|^--tags$/) { $Show_Tags = 1; } elsif ($arg =~ /^-b$|^--branches$/) { $Show_Branches = 1; } elsif ($arg =~ /^-F$|^--follow$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; push (@Follow_Branches, $narg); } elsif ($arg =~ /^--stdin$/) { $Input_From_Stdin = 1; } elsif ($arg =~ /^--header$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $ChangeLog_Header = &slurp_file ($narg); if (! defined ($ChangeLog_Header)) { $ChangeLog_Header = ""; } } elsif ($arg =~ /^--xml$/) { $XML_Output = 1; } elsif ($arg =~ /^--hide-filenames$/) { $Hide_Filenames = 1; $After_Header = ""; } else { # Just add a filename as argument to the log command $Log_Source_Command .= " $arg"; } } ## Check for contradictions... if ($Output_To_Stdout && $Distributed) { print STDERR "cannot pass both --stdout and --distributed\n"; $exit_with_admonishment = 1; } if ($Output_To_Stdout && $output_file) { print STDERR "cannot pass both --stdout and --file\n"; $exit_with_admonishment = 1; } if ($XML_Output && $Cumulative) { print STDERR "cannot pass both --xml and --accum\n"; $exit_with_admonishment = 1; } # Or if any other error message has already been printed out, we # just leave now: if ($exit_with_admonishment) { &usage (); exit (1); } elsif ($Print_Usage) { &usage (); exit (0); } elsif ($Print_Version) { &version (); exit (0); } ## Else no problems, so proceed. if ($output_file) { $Log_File_Name = $output_file; } } sub slurp_file () { my $filename = shift || die ("no filename passed to slurp_file()"); my $retstr; open (SLURPEE, "<${filename}") or die ("unable to open $filename ($!)"); my $saved_sep = $/; undef $/; $retstr = ; $/ = $saved_sep; close (SLURPEE); return $retstr; } sub debug () { if ($Debug) { my $msg = shift; print STDERR $msg; } } sub version () { print "cvs2cl.pl version ${VERSION}; distributed under the GNU GPL.\n"; } sub usage () { &version (); print <<'END_OF_INFO'; Generate GNU-style ChangeLogs in CVS working copies. Notes about the output format(s): The default output of cvs2cl.pl is designed to be compact, formally unambiguous, but still easy for humans to read. It is largely self-explanatory, I hope; the one abbreviation that might not be obvious is "utags". That stands for "universal tags" -- a universal tag is one held by all the files in a given change entry. If you need output that's easy for a program to parse, use the --xml option. Note that with XML output, just about all available information is included with each change entry, whether you asked for it or not, on the theory that your parser can ignore anything it's not looking for. Notes about the options and arguments (the actual options are listed last in this usage message): * The -I and -F options may appear multiple times. * To follow trunk revisions, use "-F trunk" ("-F TRUNK" also works). This is okay because no would ever, ever be crazy enough to name a branch "trunk", right? Right. * For the -U option, the UFILE should be formatted like CVSROOT/users. That is, each line of UFILE looks like this jrandom:jrandom@red-bean.com or maybe even like this jrandom:'Jesse Q. Random ' Don't forget to quote the portion after the colon if necessary. * Many people want to filter by date. To do so, invoke cvs2cl.pl like this: cvs2cl.pl -l "-d'DATESPEC'" where DATESPEC is any date specification valid for "cvs log -d". (Note that CVS 1.10.7 and below requires there be no space between -d and its argument). Options/Arguments: -h, -help, --help, or -? Show this usage and exit --version Show version and exit -r, --revisions Show revision numbers in output -b, --branches Show branch names in revisions when possible -t, --tags Show tags (symbolic names) in output --stdin Read from stdin, don't run cvs log --stdout Output to stdout not to ChangeLog -d, --distributed Put ChangeLogs in subdirs -f FILE, --file FILE Write to FILE instead of "ChangeLog" --fsf Use this if log data is in FSF ChangeLog style -W SECS, --window SECS Window of time within which log entries unify -U UFILE, --usermap UFILE Expand usernames to email addresses from UFILE -R REGEXP, --regexp REGEXP Include only entries that match REGEXP -I REGEXP, --ignore REGEXP Ignore files whose names match REGEXP -C, --case-insensitive Any regexp matching is done case-insensitively -F BRANCH, --follow BRANCH Show only revisions on or ancestral to BRANCH -S, --separate-header Blank line between each header and log message --no-wrap Don't auto-wrap log message (recommend -S also) --gmt, --utc Show times in GMT/UTC instead of local time --accum Add to an existing ChangeLog (incompat w/ --xml) -w, --day-of-week Show day of week --header FILE Get ChangeLog header from FILE ("-" means stdin) --xml Output XML instead of ChangeLog format --hide-filenames Don't show filenames (ignored for XML output) -P, --prune Don't show empty log messages -g OPTS, --global-opts OPTS Invoke like this "cvs OPTS log ..." -l OPTS, --log-opts OPTS Invoke like this "cvs ... log OPTS" FILE1 [FILE2 ...] Show only log information for the named FILE(s) See http://www.red-bean.com/cvs2cl for maintenance and bug info. END_OF_INFO } __END__ =head1 NAME cvs2cl.pl - produces GNU-style ChangeLogs in CVS working copies, by running "cvs log" and parsing the output. Shared log entries are unified in an intuitive way. =head1 DESCRIPTION This script generates GNU-style ChangeLog files from CVS log information. Basic usage: just run it inside a working copy and a ChangeLog will appear. It requires repository access (i.e., 'cvs log' must work). Run "cvs2cl.pl --help" to see more advanced options. See http://www.red-bean.com/cvs2cl for updates, and for instructions on getting anonymous CVS access to this script. Maintainer: Karl Fogel Please report bugs to . =head1 README This script generates GNU-style ChangeLog files from CVS log information. Basic usage: just run it inside a working copy and a ChangeLog will appear. It requires repository access (i.e., 'cvs log' must work). Run "cvs2cl.pl --help" to see more advanced options. See http://www.red-bean.com/cvs2cl for updates, and for instructions on getting anonymous CVS access to this script. Maintainer: Karl Fogel Please report bugs to . =head1 PREREQUISITES This script requires C, C, and C. It also seems to require C or higher. =pod OSNAMES any =pod SCRIPT CATEGORIES Version_Control/CVS =cut -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- Note about a bug-slash-opportunity: ----------------------------------- There's a bug in Text::Wrap, which affects cvs2cl. This script reveals it: #!/usr/bin/perl -w use Text::Wrap; my $test_text = "This script demonstrates a bug in Text::Wrap. The very long line following this paragraph will be relocated relative to the surrounding text: ==================================================================== See? When the bug happens, we'll get the line of equal signs below this paragraph, even though it should be above."; # Print out the test text with no wrapping: print "$test_text"; print "\n"; print "\n"; # Now print it out wrapped, and see the bug: print wrap ("\t", " ", "$test_text"); print "\n"; print "\n"; If the line of equal signs were one shorter, then the bug doesn't happen. Interesting. Anyway, rather than fix this in Text::Wrap, we might as well write a new wrap() which has the following much-needed features: * initial indentation, like current Text::Wrap() * subsequent line indentation, like current Text::Wrap() * user chooses among: force-break long words, leave them alone, or die()? * preserve existing indentation: chopped chunks from an indented line are indented by same (like this line, not counting the asterisk!) * optional list of things to preserve on line starts, default ">" Note that the last two are essentially the same concept, so unify in implementation and give a good interface to controlling them. And how about: Optionally, when encounter a line pre-indented by same as previous line, then strip the newline and refill, but indent by the same. Yeah... pvpgn-1.8.5/scripts/ladder.py0000644000175000017500000003023711151345317015143 0ustar aaronaaron#!/usr/bin/env python # -*- Mode: Python; tab-width: 4 -*- # # Copyright (C) 2001 Gianluigi Tiesi # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # Ranking patch by 20020503 # Small "unsigned int" fix by 20020818 # # ========================================================================== __version__ = "0.9" ### Only if CGI_MODE = 1 CGI_MODE=0 FILE="/opt/bnetd/var/ladders/ladder.D2DV" MAX=100 from struct import unpack,calcsize from string import find,split,join from os import stat from sys import argv,exit,stdout from getopt import getopt #### Templates modes = [ 'html', 'ansi', 'ascii', 'python' ] templates = {} for m in modes: templates[m] = {} ### html ### # templates['html']['header']=""" D2 Closed Realm Ladder

D2 Closed Realm Ladder

""" # templates['html']['footer']="""

Generated by ladder.py v %s - © 2001 Sherpya

""" % __version__ # %s for description of ladder type templates['html']['summary'] = """ Ladder for %s """ # templates['html']['tbheader'] = """#Charnamelevelclassexp """ # %s for charname templates['html']['normal'] = """%s""" templates['html']['hardcore'] = { 0 : """%s""", 1 : """%s""" } # %s charname - %d level - %s class - %d experience templates['html']['entry'] = """%d%s%d%s%d """ # templates['html']['separator'] = """  """ #### html #### ascii / ansi line = '-' * 59 + '\n' s10 = ' ' * 10 s14 = ' ' * 14 s5 = ' ' * 5 text = 'D2 Closed Ladder' esc = '\033' off = esc + '[0m' colors = { 'grey': esc + '[1;30m', 'red': esc + '[1;31m', 'green': esc + '[1;32m', 'yellow': esc + '[1;33m', 'blue': esc + '[1;34m', 'purple': esc + '[1;35m', 'magenta': esc + '[1;36m', 'white': esc + '[1;37m', 'green': esc + '[1;32m' } templates['ascii']['header'] = line + (int((len(line) - len(text))/ 2)) * ' ' + text + '\n' + line templates['ascii']['footer'] = 'generated by ladder.py (c) Sherpya [sherpya@netfarm.it]\n' templates['ascii']['summary'] = 'Ladder for %s\n\n' templates['ascii']['tbheader'] = ' # charname' + s14 + 'level' + s10 + 'class' + s10 + 'exp' + '\n\n' templates['ascii']['normal'] = '%s' templates['ascii']['hardcore'] = { 0 : '*%s', 1: '^%s' } templates['ascii']['entry'] = '%3d %-23s %2d %16s %10d\n' templates['ascii']['separator'] = line + '\n' line = colors['blue'] + ( '-' * 59) + off + '\n' templates['ansi']['header'] = line + (int((len(line) - len(text) - 10)/ 2)) * ' ' + colors['green'] + text + off + '\n' + line templates['ansi']['footer'] = colors['green'] + 'generated by ' + colors['blue'] + 'ladder.py' + colors['green'] + ' (c) Sherpya [sherpya@netfarm.it]' + off + '\n' templates['ansi']['summary'] = colors['white'] + 'Ladder for %s' + off + '\n\n' templates['ansi']['tbheader'] = colors['green'] + ' # charname' + s14 + 'level' + s10 + 'class' + s10 + 'exp' + off + '\n\n' templates['ansi']['normal'] = colors['yellow'] + '%s' templates['ansi']['hardcore'] = { 0 : colors['red'] + '%s', 1: colors['grey'] + '%s' } templates['ansi']['entry'] = colors['yellow'] + '%3d %-30s %2d %16s %10d' + off + '\n' templates['ansi']['separator'] = line + '\n' del text #### ascii / ansi ### Some struct from d2cs/d2dbs source # # ladder header (4 + 4 = 8): # bn_int maxtype # bn_int checksum LD_HEAD="<2i" szLD_HEAD = calcsize(LD_HEAD) # # ladder info (4 + 2 + 1 + 1 + 16 = 24): # bn_int experience # bn_short status # bn_byte level # bn_byte class; # char charname[16]; LD_INFO=" 0: try: experience, status, level, _class, charname = unpack(LD_INFO, data.read(szLD_INFO)) except: ### Bad data size = size - szLD_INFO continue size = size - szLD_INFO ## Avoid null chars if not experience: continue charname = remove_null(charname) died = 0 if status & S_EXP: _type = 'exp' difficulty = ((status >> 0x08) & 0x0f) / 5 else: _type = 'nor' difficulty = ((status >> 0x08) & 0x0f) / 5 if status & S_HC: hc = 1 if status & S_DEAD: died = 1 else: hc = 0 c_class = classes[_class] if difficulty and diff[_type].has_key(difficulty): prefix = diff[_type][difficulty][hc][c_class[1]] else: prefix = None char = (experience, { 'charname' : charname, 'prefix' : prefix, 'experience' : experience, 'class' : c_class[0], 'sex' : c_class[0], 'level' : level, 'type' : _type, 'difficulty' : difficulty, 'hc' : hc, 'died' : died }) ## Dupe char? why? if char not in temp[_type]: temp[_type].append(char) data.close() ## Sorting by exp temp['nor'].sort() temp['nor'].reverse() temp['exp'].sort() temp['exp'].reverse() for _type in temp.keys(): for ch in temp[_type]: ladder[_type].append(ch[1]) del temp return ladder def generate(ladder, mode, output, max): output.write(templates[mode]['header']) for _type in ladder.keys(): count = 1 output.write(templates[mode]['summary'] % desc[_type]) output.write(templates[mode]['tbheader']) for ch in ladder[_type]: if ch['prefix']: charname = "%s %s" % (ch['prefix'], ch['charname']) else: charname = ch['charname'] if ch['hc']: charname = templates[mode]['hardcore'][ch['died']] % charname else: charname = templates[mode]['normal'] % charname output.write(templates[mode]['entry'] % (count, charname, ch['level'], ch['class'], ch['experience'])) count = count + 1 if count > max: break output.write(templates[mode]['separator']) output.write(templates[mode]['footer']) def pickle_to(ladder, output): try: from cPickle import dump except: from pickle import dump try: out = open(output, "wb") except: print "Cannot open %s for pickle dump" % output exit() dump(ladder, out) out.close() ### Main ### CGI MODE if CGI_MODE: print "Content-Type: text/html" print ladder = get_ladder(FILE) generate(ladder, 'html', stdout, MAX) exit() args = argv[1:] optlist, args = getopt(args, "hi:o:m:n:") if len(args): for bad in args: print "%s: Unrecognized option %s" % (argv[0], bad) exit() ### defaults file = None output = None # stdout mode = modes[0] real_max = 1000 max = 100 def show_help(): print print "ladder.py v%s - (c) 2001 Sherpya " % __version__ print "Usage: ladder.py -i ladder_file [-o outputfile] [-m mode] [-n max ladder chars]" print print " -i ladder_file, is the ladder file like ladder.D2DV" print " -o output file, if omitted defaults to stdout" print " -m mode, avaiables mode are: %s, defaults to %s" % (join(modes,', '), modes[0]) print " -n max_char, max char to display in each ladder, defaults to %d" % max print print " note: python output mode creates a python object usable by pickle module" print for opt in optlist: # Help if opt[0] == '-h': show_help() exit() # Input file if opt[0] == '-i': file = opt[1] continue # Output file if opt[0] == '-o': output = opt[1] continue # Output mode (html, ansi, ascii, python) if opt[0] == '-m': if opt[1] in modes: mode = opt[1] continue else: print "Invalid mode %s, valid modes are %s" % (opt[1], join(modes, ', ')) exit() # Max chars in ladder if opt[0] == '-n': try: max = int(opt[1]) except: max = 0 if (max < 2) or max > real_max: print "Invalid value for max char in ladder must be > 1 and < %d" % real_max exit() continue if not file: show_help() exit() ladder = get_ladder(file) if mode == 'python': if output: pickle_to(ladder, output) else: print "Cannot dump python object to stdout" exit() if output: try: output = open(output, "wb") except: print "Cannot open %s for writing" % output exit() else: output = stdout generate(ladder, mode, output, max) pvpgn-1.8.5/scripts/make_testusers.sh0000644000175000017500000000135211151345317016724 0ustar aaronaaron#!/bin/sh # creates massive numbers of dummy "test" accounts # number of accounts to connect with numaccts=400 # "prefix" of account names name="bob" # account password pass="bob" # number of zero-padded columns in suffix padding=6 # "users" directory users=/usr/local/bnetd/var/users # bnpass command bnpass=/usr/local/bnetd/bin/bnpass hash="`echo \"${pass}\" | \"${bnpass}\" | sed -e 's/^.*"\([0-9a-f]*\)"/\1/'`" num=0 while [ "${num}" -lt 400 ]; do num="`expr \"${num}\" '+' '1'`" form="`printf \"%06d\" \"${num}\"`" ( echo '"BNET\\acct\\username"="'"${name}${form}"'"' echo '"BNET\\acct\\passhash1"="'"${hash}"'"' echo '"BNET\\acct\\userid"="'"${num}"'"' ) > "${users}/${form}" done exit 0 pvpgn-1.8.5/scripts/tos.bat0000644000175000017500000000165711151345317014637 0ustar aaronaaron@echo off cd ../files copy tos.txt tos_RUS.txt copy tos.txt tos_POL.txt copy tos.txt tos_CHI.txt copy tos.txt tos_SIN.txt copy tos.txt tos_HAN.txt copy tos.txt tos_KOR.txt copy tos.txt tos_JPN.txt copy tos.txt tos_ITA.txt copy tos.txt tos_BRA.txt copy tos.txt tos_POR.txt copy tos.txt tos_FRA.txt copy tos.txt tos_DEU.txt copy tos.txt tos_ESP.txt copy tos.txt tos_USA.txt copy tos.txt tos_ENU.txt copy tos.txt tos-unicode_RUS.txt copy tos.txt tos-unicode_POL.txt copy tos.txt tos-unicode_CHI.txt copy tos.txt tos-unicode_SIN.txt copy tos.txt tos-unicode_HAN.txt copy tos.txt tos-unicode_KOR.txt copy tos.txt tos-unicode_JPN.txt copy tos.txt tos-unicode_ITA.txt copy tos.txt tos-unicode_BRA.txt copy tos.txt tos-unicode_POR.txt copy tos.txt tos-unicode_FRA.txt copy tos.txt tos-unicode_DEU.txt copy tos.txt tos-unicode_ESP.txt copy tos.txt tos-unicode_USA.txt copy tos.txt tos-unicode_ENU.txt cd ../scriptspvpgn-1.8.5/scripts/S98bnetd0000644000175000017500000000252411151345317014657 0ustar aaronaaron#!/bin/sh # A semi-RedHat style init script for staring bnetd . /etc/rc.d/init.d/functions bnetduser="bnetd" bnetdhome="/home/bnetd" bnetdpid="${bnetdhome}/bnetd.pid" bnetdexe="${bnetdhome}/sbin/bnetd" case "$1" in start) echo -n "Starting bnetd: " if [ -r "${bnetdpid}" ] && kill -0 `cat "${bnetdpid}"`; then echo "${bnetdpid} exists and the pid is still valid." else if [ -d "${bnetdhome}" ]; then if [ -x "${bnetdexe}" ]; then # su -c "cd ${bnetdhome}; ${bnetdexe} -f &" - "${bnetduser}" 2>&1 > /dev/null su -c "${bnetdexe}" - "${bnetduser}" 2>&1 > /dev/null # "${bnetdexe}" echo bnetd else echo "${bnetdexe} is not an executable." fi else echo "${bnetdhome} is not a directory." fi fi ;; restart) echo -n "Restarting bnetd: " if [ -f "${bnetdpid}" ] && kill -0 `cat "${bnetdpid}"`; then kill -HUP `cat "${bnetdpid}"` echo "bnetd" else echo "bnetd is not running." fi ;; stop) echo -n "Stopping bnetd: " if [ -f "${bnetdpid}" ]; then kill -TERM `cat "${bnetdpid}"` sleep 1 if [ -f "${bnetdpid}" ] && kill -0 `cat "${bnetdpid}"` 2>&1 > /dev/null; then echo "waiting for users to log out." else rm -f "${bnetdpid}" echo "bnetd" fi else echo "bnetd is not running." fi ;; status) status bnetd ;; *) echo "Usage: $0 {start|stop|restart|status}" exit 1 esac exit 0 pvpgn-1.8.5/scripts/bnetmasq.sh0000644000175000017500000000765111151345317015510 0ustar aaronaaron#!/bin/sh # Author: Marco Ziech (mmz@gmx.net) # Date: Jan-24-2000 # # Bnetd UDP masquerade for Linux # # NOTE: # This script is not needed if you have "loose UDP" turned # on. It was a patch around the 2.2 series. It automates # all of this for any "well behaved" peer-to-peer games, # not just for Battle.net clients. # # Kernel: # This script should work fine with 2.2 kernels but I don't # know if it works with older kernels too. # # Installation: # Copy this file into your local init.d directory. # The position of this directory may vary with diffrent # linux distributions. # On Debian/GNU Linux it's /etc/init.d # On S.u.S.E. Linux it's /sbin/init.d (I guess) # To start the script on system startup you have to # make a symlink to this file from a filename like # "S99bnetmasq.sh" in the rc2.d directory. To stop it # on system shutdown do the same with "K01bnetmasq.sh" # in the rc0.d, rc1.d and rc6.d directories. These # directories are usually in the same as the init.d # directory. # If you have a dial-up connection and want to start the # script on dial-in you have to put a script which starts # or stops this script in /etc/ppp/ip-up.d and # /etc/ppp/ip-down.d . # # Using on original Bnet: # This script should also work with the original Battle.net. # # Using on servers not running on your masquerading gateway: # Outside servers like the real Battle.net will not # know your correct address, only your internal IP:port. # to fix it, either bnproxy needs to be improved to # be used instead of ipmasq or this need to do some # content altering like with the ftp script. # --- Thanks to Ross Combs for these corrections. # This is the destination port on the clients. It is usually 6112. BNET_PORT=6112 # This is the list of the destination hosts with their ports on # the firewall. The list should look like this: # client1IP:GW1port client2IP:GW2port ... clientNIP:GWNport # Remember that each port can only be allocated by one client. # Some ports may already be reserved by some programs. # I recomment using ports between 5000 and 7000. See # /etc/services on information about assigned ports. REDIR_LIST="192.168.1.1:5000 192.168.1.2:5001" # This is the external interface i.e. the interface which is # connected to the Internet. On dial-up links this is usually # ppp0 or ippp0 (for ISDN). EXTERNAL_IF=eth0 # ------------------- END OF CONFIG SECTION ----------------- # This determines the ip of the external interface EXTERNAL_IP=`LANGUAGE="C" LC_ALL="C" ifconfig $EXTERNAL_IF | grep 'inet addr:' | sed 's/.*inet addr:\([0-9.]*\).*/\1/g'` case "$1" in start) echo -n "Starting bnet masquerading: " for i in $REDIR_LIST; do echo -n "$i " D_HOST="`echo $i | sed -e 's/:/ /g' | awk '{ print $1 }'`" D_PORT="`echo $i | sed -e 's/:/ /g' | awk '{ print $2 }'`" ipmasqadm portfw -a -P udp -L $EXTERNAL_IP $D_PORT -R $D_HOST $BNET_PORT # FIXME: according to: http://www.mail-archive.com/masq@tori.indyramp.com/msg01538.html #> setting up a single machine would look like: #> # ipmasqadm portfw -a -P tcp -L $1 6112 -R $2 6112 #> # ipmasqadm portfw -a -P tcp -L $3 6112 -R $2 6112 #> # ipmasqadm portfw -a -P udp -L $1 6112 -R $2 6112 #> # ipmasqadm portfw -a -P udp -L $3 6112 -R $2 6112 #> Replace $1 with the internal IP address of your gateway machine, $2 #> with the address (internal again, but it should be the only) of the #> machine you're playing starcraft on and $3 with the external IP ad- #> dress of the gateway machine. # This implies that # inside_gw --> client # outside_gw --> inside_gw # this script doesn't do the gw --> gw setup.... does it need to?! done echo "." ;; stop) echo -n "Stopping bnet masquerading: " for i in $REDIR_LIST; do echo -n "$i " D_PORT="`echo $i | sed -e 's/:/ /g' | awk '{ print $2 }'`" ipmasqadm portfw -d -P udp -L $EXTERNAL_IP $D_PORT done echo "." ;; *) echo "Usage: $0 {start|stop}" exit 1 ;; esac pvpgn-1.8.5/scripts/sql/0000755000175000017500000000000011151345372014131 5ustar aaronaaronpvpgn-1.8.5/scripts/sql/repairlevels.pl0000644000175000017500000000453511151345317017171 0ustar aaronaaron#!/usr/bin/perl $| = 1; use DBI; &header; if (scalar(@ARGV) < 5) { &usage; exit; } $levelxpfile = shift; $dbhost = shift; $dbname = shift; $dbuser = shift; $dbpass = shift; open LEVELFD, $levelxpfile or die "Could not open XP level file ($levelxpfile)"; print "Reading from XP file ...\n"; while($line = ) { $line =~ s/#.*//; if ($line !~ m/^\s*$/) { ($level, $startxp, $neededxp, $lossfactor, $mingames) = split(/\s+/,$line); print "level: $level startxp: $startxp neededxp: $neededxp lossfactor: $lossfactor mingames: $mingames\n"; $xplevel[$level]->{startxp} = $startxp; $xplevel[$level]->{neededxp} = $neededxp; $xplevel[$level]->{lossfactor} = $lossfactor; $xplevel[$level]->{mingames} = $mingames; } } close LEVELFD; print "...done\n\nConnecting to db..."; $dbh = DBI->connect("dbi:mysql:$dbname;host=$dbhost", $dbuser, $dbpass) or die "Could not connect to db (mysql, db: $dbname, host: $dbhost, user: $dbuser, pass: $dbpass)"; $sth = $dbh->prepare("SELECT uid, solo_xp, solo_level FROM Record WHERE uid > 0") or die "Error preparing query!"; $sth->execute() or die "Error executing query!"; while($row = $sth->fetchrow_hashref) { $level = $row->{solo_level}; $xp = $row->{solo_xp}; if ($level eq "" or $xp eq "" or $level < 1) { next; } for($i = $level; $i < 50 ; $i++) { if ($xplevel[$i]->{startxp} > $xp) { $i--; last; } } $level = $i; for($i = $level; $i > 1; $i++) { if ($xplevel[$i]->{needed_xp} <= $xp) { last; } } $level = $i; if ($level < 1) {$level = 1;} if ($level != $row->{solo_level}) { print "Repaired $uid from (level: " , $row->{solo_level}, " xp: $xp) to (level: $level xp: $xp)\n"; $dbh->do("UPDATE profile SET solo_level = '$level' WHERE uid = '".$row->{uid}."'"); } } $sth->finish(); $dbh->disconnect(); sub header { print "Account db accounts XP levels repair tool.\n"; print " Copyright (C) 2002 Dizzy (dizzy\@roedu.net)\n"; print " People Versus People Gaming Network (www.pvpgn.org)\n\n"; } sub usage { print "Usage:\n\nrepairlevels.pl \n\n"; print " \t: path/name of the file with the XP level data (ex. bnxplevel.txt)\n"; print " \t: the database host\n"; print " \t: the database name\n"; print " \t: the database user\n"; print " \t: the database password\n"; } pvpgn-1.8.5/scripts/fsgs2bnetd.pl0000644000175000017500000000352611151345317015735 0ustar aaronaaron#!/usr/bin/perl #Usage: fsgs2bnetd "source directory" "destination directory" #source directory: directory contains fsgs account files #destnation directory: directory to save newly created bnetd # accounts,should exist before run this # #there is another change made to bnetd account in this script #i think fsgs account filename format is better #than using bnetd's , so i kept it in fsgs format. #you may change it by edit the script yourself $ARGV[1] eq "" && die "error arguments"; $s_dir=$ARGV[0]; $d_dir=$ARGV[1]; opendir(DIR,$s_dir) || die "error open dir"; @files= grep { /^[^.]/ && -f "$s_dir/$_" } readdir(DIR); closedir DIR; $userid=1; $fsgs{'name'}="\"BNET\\\\acct\\\\username\""; $fsgs{'password'}="\"BNET\\\\acct\\\\passhash1\""; foreach (@files) { open(S_FILE,"$s_dir/$_") || die "error open s_file: $_\n"; $dest_file=lc("$d_dir/$_"); open(D_FILE,">$dest_file") || die "error open d_file: $_\n"; while () { chop($_); ($name,$value)=split(/:/,$_); foreach (keys %fsgs) { if ($_ eq $name) { if ( $_ eq "password" ) { $value=&passconv($value); } print D_FILE "$fsgs{$_}=\"$value\"\n"; break; } } } print D_FILE "\"BNET\\\\acct\\\\userid\"=\"$userid\"\n"; $userid++; close(S_FILE); close(D_FILE); } sub passconv { ($f_pass)=@_; my ($d_pass)=""; $f_pass=lc($f_pass); $length=length($f_pass); for ($i=0;$i<=$length;$i=$i+2) { $a=2*(int(($i/2)/4)*8+3-$i/2); $d_pass .= substr($f_pass,$a,2); } return $d_pass; } pvpgn-1.8.5/scripts/tos.sh0000644000175000017500000000041111151345317014466 0ustar aaronaaron#!/bin/sh if [ X"$1" != X"" ]; then cd "$1" fi LNG="RUS POL CHI SIN HAN KOR JPN ITA BRA POR FRA DEU ESP USA ENU" for i in $LNG do echo "Generating Term Of Service for language \"$i\"" cp -f tos.txt tos_"$i".txt cp -f tos.txt tos-unicode_"$i".txt done pvpgn-1.8.5/scripts/pvpgn_hash.inc.php0000644000175000017500000000625611151345317016760 0ustar aaronaaron> 6) + 1; for($i=0; $i < $nblk * 16; $i++) $blks[$i] = 0; for($i=0; $i < strlen($str); $i++) { $blks[$i >> 2] |= ord(substr($str, $i, 1)) << ( ($i % 4) * 8); } return $blks; } function safe_add($x, $y) { $lsw = ($x & 0xFFFF) + ($y & 0xFFFF); $msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16); return ($msw << 16) | ($lsw & 0xFFFF); } function safe_not( $num ) { $lsw = (~($num & 0xFFFF)) & 0xFFFF; $msw = (~($num >> 16)) & 0xFFFF; return ($msw << 16) | $lsw; } function safe_rol( $num, $amt ) { $leftmask = 0xffff | (0xffff << 16); $leftmask <<= 32 - $amt; $rightmask = 0xffff | (0xffff << 16); $rightmask <<= $amt; $rightmask = safe_not($rightmask); $remains = $num & $leftmask; $remains >>= 32 - $amt; $remains &= $rightmask; $res = ($num << $amt) | $remains; return $res; } function ft($t, $b, $c, $d) { if($t < 20) return ($b & $c) | ((safe_not($b)) & $d); if($t < 40) return $d ^ $c ^ $b; if($t < 60) return ($c & $b) | ($d & $c) | ($d & $b); return $d ^ $c ^ $b; } function kt($t) { if ($t < 20) { return 0x5a82 << 16 | 0x7999; } else if ($t < 40) { return 0x6ed9 << 16 | 0xeba1; } else if ($t < 60) { return 0x8f1b << 16 | 0xbcdc; } else { return 0xca62 << 16 | 0xc1d6; } } function pvpgn_hash($str) { $x = str2blks_pvpgn($str); $a = 0x6745 << 16 | 0x2301; $b = 0xefcd << 16 | 0xab89; $c = 0x98ba << 16 | 0xdcfe; $d = 0x1032 << 16 | 0x5476; $e = 0xc3d2 << 16 | 0xe1f0; for($i = 0; $i < sizeof($x); $i += 16) { $olda = $a; $oldb = $b; $oldc = $c; $oldd = $d; $olde = $e; for($j = 0; $j < 16; $j++) { $w[$j] = $x[$i+$j]; } for($j = 0; $j < 64; $j++) { $ww = $w[$j] ^ $w[$j+8] ^ $w[$j+2] ^ $w[$j+13]; $w[$j+16] = 1 << ($ww%32); } for($j = 0; $j < 80; $j++) { if ($j<20) { $t = safe_add(safe_add(safe_rol($a, 5), ft($j, $b, $c, $d)), safe_add(safe_add($e, $w[$j]), kt($j))); } else { $t = safe_add(safe_add(safe_rol($t, 5), ft($j, $b, $c, $d)), safe_add(safe_add($e, $w[$j]), kt($j))); } $e = $d; $d = $c; $c = safe_rol($b, 30); $b = $a; $a = $t; } $a = safe_add($t, $olda); $b = safe_add($b, $oldb); $c = safe_add($c, $oldc); $d = safe_add($d, $oldd); $e = safe_add($e, $olde); } return sprintf("%08x%08x%08x%08x%08x",$a,$b,$c,$d,$e); } ?>pvpgn-1.8.5/scripts/process.pl0000644000175000017500000001766411151345317015362 0ustar aaronaaron#!/usr/bin/perl -w #!/usr/local/bin/perl -w #!/opt/perl/bin/perl -w # # Copyright (C) 1999 Mark Baysinger (mbaysing@ucsd.edu) # Copyright (C) 1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) # Copyright (C) 2001 Roland Haeder (webmaster@ai-project-now.de) # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Version of this script $version = "v1.05"; # modify to use correct locations $infile = "./bnetdlist.txt"; #$infile = "/var/tmp/bnetdlist.txt"; $outfile = "./bnetdlist.html"; #$outfile = "/home/httpd/html/bnetdlist.html"; $tmpfile = $outfile . ".temp"; # document look $page_bg_color = "#202020"; $link_color = "#5070FF"; $alink_color = "#FF3030"; $vlink_color = "#8090FF"; $tbl_border_color = "#404040"; $tbl_border_ramp = "0"; $tbl_border_width = "2"; $tbl_padding = "1"; $tbl_head_bg_color = "$tbl_border_color"; $tbl_bg_color = "#000000"; $tbl_text_color = "#80A0FF"; $title_bg_color = "$page_bg_color"; $title_text_color = "#FFFFFF"; $sum_bg_color = "$page_bg_color"; $sum_text_color = "$title_text_color"; # header strings $title = "BNETD Server Status"; $header = "
$title
"; open(INFILE, "<$infile") || die("Can't open \"$infile\" for reading: $!\n"); $/ = "\#\#\#\n"; @servers = ; chomp @servers; close INFILE; open(OUTFILE, ">$tmpfile") || die("Can't open \"$tmpfile\" for writing: $!\n"); print OUTFILE "\n"; print OUTFILE "\n"; print OUTFILE " \n"; print OUTFILE " $title\n"; print OUTFILE "\n"; print OUTFILE "\n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE "
$header
\n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE "
\n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; $allservers = 0; $allusers = 0; $allgames = 0; foreach $server (@servers) { print OUTFILE " \n"; $/ = "\#\#\n"; # Fix-up for special characters $server =~ s/&/&/g; $server =~ s//>/g; @serverinfo = split /^\#\#\n/m, $server; chomp @serverinfo; chop @serverinfo; # put fields into descriptive variable names $addr = $serverinfo[0]; $loc = $serverinfo[2]; if (length($loc)<1) { $loc = " "; } $desc = $serverinfo[8]; if (length($desc)<1) { $desc = " "; } $soft = $serverinfo[3] . " " . $serverinfo[4]; $osys = $serverinfo[9]; if (length($osys)<1) { $osys = "unknown"; } $url = $serverinfo[10]; $contact = $serverinfo[11]; if (length($contact)<1) { $contact = " "; } $email = $serverinfo[12]; $currusers = $serverinfo[5]; $totusers = $serverinfo[15]; $currchans = $serverinfo[6]; $currgames = $serverinfo[7]; $totgames = $serverinfo[14]; $uptime = sprintf("%02d:%02d:%02d",int $serverinfo[13]/3600, int ($serverinfo[13]%3600)/60, int $serverinfo[13]%60); # print it out print OUTFILE " \n"; # IP print OUTFILE " \n"; print OUTFILE " \n"; if (length($url)<1) { print OUTFILE " \n"; } else { print OUTFILE " \n"; } print OUTFILE " \n"; if (length($email)<1) { print OUTFILE " \n"; } else { print OUTFILE " \n"; } print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; $allservers++; $allusers+=${currusers}; $allgames+=${currgames}; } print OUTFILE "
AddressLocationDescriptionURLUptimeContactSoftwareUCG
$addr$loc$desc $url$uptime$contact$contact ($email)$soft
$osys
${currusers}c
${totusers}t
${currchans}${currgames}c
${totgames}t
\n"; print OUTFILE "
\n"; print OUTFILE "

\n"; print OUTFILE "
\n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE " \n"; print OUTFILE "
\n"; print OUTFILE " \n"; print OUTFILE " servers: " . $allservers . "
\n"; print OUTFILE " users: " . $allusers . "
\n"; print OUTFILE " games: " . $allgames . "
\n"; print OUTFILE "
\n"; print OUTFILE " Last updated " . gmtime(time) . " GMT
\n"; print OUTFILE "

\n"; print OUTFILE "
\n"; print OUTFILE "
\n"; print OUTFILE "\n"; close(OUTFILE); unlink($outfile); rename($tmpfile, $outfile); exit(0); pvpgn-1.8.5/scripts/login_testusers.sh0000644000175000017500000000162411151345317017121 0ustar aaronaaron#!/bin/sh # tries to login with a massive number of test accounts # See make_testusers.sh for a way to create these accounts. # number of accounts to connect with numaccts=400 # "prefix" of account names name="bob" # account password pass="bob" # delay between printing messages delay=30 # where to connect server=localhost # number of zero-padded columns in suffix padding=6 # how many seconds until logout total=600 num=0 while [ "${num}" -lt "${numaccts}" ]; do num="`expr \"${num}\" '+' '1'`" form="`printf \"%0${padding}d\" \"${num}\"`" ( echo '' echo "${name}${form}" echo "${pass}" total=0; while [ "${total}" -lt "${maxtime}" ]; do sleep "${delay}" echo "My name is ${name}${form}" total="`expr \"${total}\" '+' \"${delay}\"`" done echo "/quit" ) | telnet "${server}" 6112 & done exit 0 pvpgn-1.8.5/scripts/storage/0000755000175000017500000000000011151345372014776 5ustar aaronaaronpvpgn-1.8.5/scripts/storage/plain2sql.pl0000644000175000017500000000565511151345317017252 0ustar aaronaaron#!/usr/bin/perl if (scalar(@ARGV) != 1) { &usage; exit; } &header; # remove a trailing / $dirpath = $ARGV[0]; $dirpath =~ s!(.*)/$!$1!; opendir FILEDIR, $dirpath or die "Error opening filedir!\n"; while ($filename = readdir FILEDIR) { if ($filename =~ m/^\./) { next; } #ignore . and .. if ( ! (($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat "$dirpath/$filename" )) { print STDERR "Error stat-ing the file $pathdir/$filename!\n" ; next; } $type = ($mode & 070000) >> 12; if ($type != 0) { print STDERR "File $dirpath/$filename its not regular\n"; next; } convertplain2db("$dirpath/$filename"); } closedir FILEDIR; sub convertplain2db { my $filen = shift; my ($userid, $count, $alist); open FILE, $filen or die "Error opening file $filen\n"; print STDERR "Converting file $filen ... "; $count = 0; $userid = ""; undef @alist; while($line = ) { if ($line =~ m/".*"=".*"/) { $line =~ m/^"([A-Za-z0-9]+)\\\\(.*)"="(.*)"/; $tab = $1; # skip Team as we now have another team structure if ($tab =~ m/^team$/i) { print STDERR "WARNING: skipping Team information!\n"; next; } elsif ($tab =~ m/^\s*$/) { print STDERR "WARNING: skipping empty tab!\n"; next; } $alist[$count]{tab} = $tab; $alist[$count]{col} = &escape_key($2); $alist[$count]{val} = $3; $alist[$count]{col} =~ s!\\\\!_!g; if ($alist[$count]{col} =~ m!userid$!) { $userid = $alist[$count]{val}; } $count++; } } if ($userid ne "") { &db_set($dbh, $userid, $alist); } close FILE; print STDERR "done\n"; } sub header { print STDERR "Account files to db accounts converting tool.\n"; print STDERR " Copyright (C) 2002,2005 Dizzy (dizzy\@roedu.net)\n"; print STDERR " Player Versus Player Gaming Network (www.pvpgn.org)\n\n"; } sub usage { &header; print STDERR "Usage:\n\n\tfiles2db.pl \n\n"; print STDERR "\t \t: directory with the account files\n"; } sub db_set { my $dbh = shift; my $userid = shift; my $alist = shift; my ($i); print("INSERT INTO BNET (uid) VALUES ($userid);\n"); print("INSERT INTO profile (uid) VALUES ($userid);\n"); print("INSERT INTO Record (uid) VALUES ($userid);\n"); print("INSERT INTO friend (uid) VALUES ($userid);\n"); for($i=0; $i> 12; if ($type != 0) { print STDERR "File $dirpath/$filename its not regular\n"; next; } convert_cdb2sql("$dirpath/$filename"); } closedir FILEDIR; sub convert_cdb2sql { my $filen = shift; my ($userid, $count, $alist); $pid = open(FILE, "$bncdb -d \"".$filen."\" |"); print STDERR "Converting file $filen ... "; $count = 0; $userid = ""; undef @alist; while($line = ) { if ($line =~ m/:.*->.*/) { $line =~ m/^\+([0-9]+),([0-9]+):([A-Za-z0-9]+)\\(.*)$/; # key length and value length $keylen = $1; $vallen = $2; $tab = $3; $tab =~ tr/A-Z/a-z/; $str = $4; # skip Team as we now have another team structure if ($tab =~ m/^team$/i) { print STDERR "WARNING: skipping Team information!\n"; next; } elsif ($tab =~ m/^\s*$/) { print STDERR "WARNING: skipping empty tab!\n"; next; } $alist[$count]{tab} = $tab; $alist[$count]{col} = &escape_key(substr($str, 0, $keylen - length($tab) - 1)); $alist[$count]{val} = substr($str, $keylen - length($tab) + 1); if ($alist[$count]{col} =~ m!userid$!) { $userid = $alist[$count]{val}; } $count++; } } if ($userid ne "") { &db_set($dbh, $userid, $alist); } close FILE; waitpid $pid, 0; print STDERR "done\n"; } sub header { print STDERR "Account files to db accounts converting tool.\n"; print STDERR " Copyright (C) 2002,2005 Dizzy (dizzy\@roedu.net)\n"; print STDERR " Player Versus Player Gaming Network (www.pvpgn.org)\n\n"; } sub usage { &header; print STDERR "Usage:\n\n\tcdb2sql.pl \n\n"; print STDERR "\t \t: directory with the account files\n"; } sub db_set { my $dbh = shift; my $userid = shift; my $alist = shift; my ($i); print("INSERT INTO BNET (uid) VALUES ($userid);\n"); print("INSERT INTO profile (uid) VALUES ($userid);\n"); print("INSERT INTO Record (uid) VALUES ($userid);\n"); print("INSERT INTO friend (uid) VALUES ($userid);\n"); for($i=0; $i] | reform.awk # To save a dump: # tcpdump -s 2000 -w dumpfile # To replay it: # tcpdump -x -s 2000 -r dumpfile | reform.awk function hexvalue(nybble) { if (nybble=="0") { return 0; } if (nybble=="1") { return 1; } if (nybble=="2") { return 2; } if (nybble=="3") { return 3; } if (nybble=="4") { return 4; } if (nybble=="5") { return 5; } if (nybble=="6") { return 6; } if (nybble=="7") { return 7; } if (nybble=="8") { return 8; } if (nybble=="9") { return 9; } if (nybble=="a") { return 10; } if (nybble=="b") { return 11; } if (nybble=="c") { return 12; } if (nybble=="d") { return 13; } if (nybble=="e") { return 14; } if (nybble=="f") { return 15; } } # ab67 483d cac9 08ca 3efb 35f8 9406 36e8 { if (substr($0,1,1)=="\t") { printf(" "); str = ""; for (i=1; i<=NF; i++) { nybble1 = substr($(i),1,1); nybble2 = substr($(i),2,1); byte1 = 16*hexvalue(nybble1)+hexvalue(nybble2); if (headerleft) { headerleft--; printf("** "); str = str " "; } else { printf("%02X ",byte1); if (byte1<32 || byte1>126) { str = str "."; } else { str = str sprintf("%c",0+byte1); } } nybble3 = substr($(i),3,1); nybble4 = substr($(i),4,1); if (nybble3=="" && nybble4=="") { printf(" "); } else { byte2 = 16*hexvalue(nybble3)+hexvalue(nybble4); if (headerleft) { headerleft--; printf("** "); str = str " "; } else { printf("%02X ",byte2); if (byte2<32 || byte2>126) { str = str "."; } else { str = str sprintf("%c",0+byte2); } } } if (i==4) { printf(" "); } } for (; i<=8; i++) { if (i==4) { printf(" "); } printf(" "); } printf(" %s\n",str); } else { printf("%s\n",$0); headerleft = 40; } } pvpgn-1.8.5/scripts/bnetd.logrotate0000644000175000017500000000020111151345317016340 0ustar aaronaaron/var/log/bnetd/bnetd.log { rotate 9 missingok notifempty postrotate /usr/bin/killall -HUP bnetd endscript } pvpgn-1.8.5/scripts/lastlogin.pl0000644000175000017500000000161511151345317015665 0ustar aaronaaron#!/usr/bin/perl #Usage: lastlogins.pl $ARGV[1] eq "" && die "error arguments"; $userdir=$ARGV[0]; opendir(DIR,$userdir) || die "error open dir $userdir"; @files= grep { /^[^.]/ && -f "$userdir/$_" } readdir(DIR); closedir DIR; $tbl{'name'}='"BNET\\acct\\lastlogin_time"'; foreach (@files) { open(S_FILE,"$s_dir/$_") || die "error open s_file"; $dest_file=lc("$d_dir/$_"); while () { chop($_); ($name,$value)=split(/:/,$_); foreach (keys %tbl) { if ($_ eq $name) { if ( $_ eq "password" ) { $value=&passconv($value); } break; } } } $userid++; close(S_FILE); } pvpgn-1.8.5/scripts/convert_w3.pl0000644000175000017500000000456211151345317015766 0ustar aaronaaron#!/usr/bin/perl if (scalar(@ARGV) != 2) { &usage; exit; } &header; # remove a trailing / $dirpath = $ARGV[0]; $dirpath =~ s!(.*)/$!$1!; $dirpath2 = $ARGV[1]; $dirpath2 =~ s!(.*)/$!$1!; $max_uid = -1; opendir FILEDIR, $dirpath or die "Error opening filedir!\n"; while ($filename = readdir FILEDIR) { if ($filename =~ m/^\./) { next; } #ignore . and .. if ( ! (($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat $dirpath ."/". $filename )) { print "Error stat-ing the file $pathdir/$filename!\n" ; next; } $type = ($mode & 070000) >> 12; if ($type != 0) { print "File ". $dirpath ."/". $filename ." its not regular\n"; next; } convertfile($filename); } closedir FILEDIR; sub convertfile { my $filen = shift; my ($tab, $col, $val); open FILE, $dirpath ."/". $filen or die "Error opening file ". $dirpath ."/". $filen ."\n"; if (open FILEOUT, $dirpath2 ."/". $filen) { die "Found existent file : ". $dirpath2 ."/". $filen ."!! Plese provide an empty output directory !!"; } open FILEOUT, ">". $dirpath2 ."/". $filen or die "Error opening output file ". $dirpath2 ."/". $filen ."\n"; print "Converting file ". $filen ."... "; while($line = ) { if ($line =~ m/".*"=".*"/) { $line =~ m/^"([A-Za-z0-9]+)\\\\(.*)"="(.*)"\n$/; $tab = $1; $col = $2; $val = $3; if ($tab =~ m/^team$/i) { print FILEOUT "\"". $tab . "\\\\WAR3\\\\" . $col . "\"=\"" . $val ."\"\n"; next; } if ($tab =~ m/^record$/i) { if ($col =~ m/^solo/i or $col =~ m/^team/i or $col =~ m/^ffa/i or $col =~ m/^orcs/i or $col =~ m/^humans/i or $col =~ m/^nightelves/i or $col =~ m/^undead/i or $col =~ m/^random/i) { print FILEOUT "\"". $tab . "\\\\WAR3\\\\" . $col . "\"=\"" . $val ."\"\n"; next; } } print FILEOUT $line; } } close FILEOUT; close FILE; print "done\n"; } sub header { print "Account files WAR3 converting tool.\n"; print " Copyright (C) 2003 Dizzy (dizzy\@roedu.net)\n"; print " People Versus People Gaming Network (www.pvpgn.org)\n\n"; } sub usage { &header; print "Usage:\n\n\tconvert_w3.pl \n\n"; print "\t \t: directory with the input account files\n"; print "\t \t: directory where the output account files will reside\n"; } pvpgn-1.8.5/scripts/rc.bnetd0000644000175000017500000000252511151345317014757 0ustar aaronaaron#!/bin/sh # # /etc/rc.d/rc.bnetd # # Copyright (C) 2003 rakware@go.ro # BSD style RC startup script # start/stop/restart the pvpgn Battle.net emulator. # # to make bnetd start automatically at boot, make this # file executable: chmod +x /etc/rc.d/rc.bnetd # also make sure that your rc.local script executes it # # 30.10.2003 # added sleep 3 to bnetd_up(down) so pidof can do # the work right bnetd_up() { sleep 3; if `echo `pidof bnetd`` >>/dev/null; then echo "OK" else echo "FAILED" fi } bnetd_down() { sleep 3; if `echo `pidof bnetd`` >>/dev/null; then echo "FAILED" else echo "OK" fi } bnetd_start() { if [ -x /usr/local/sbin/bnetd -a -r /usr/local/bnetd/etc/bnetd.conf ]; then /usr/local/sbin/bnetd echo -n "starting pvpgn... : "; bnetd_up fi } bnetd_stop() { killall -9 bnetd echo -n "killing pvpgn... : "; bnetd_down } bnetd_restart() { bnetd_stop sleep 3 bnetd_start } bnetd_status() { if `echo `pidof bnetd`` >>/dev/null; then echo "pvpgn is UP and running" else echo "pvpgn is NOT running" fi } case "$1" in 'start') bnetd_start ;; 'stop') bnetd_stop ;; 'restart') bnetd_restart ;; 'status') bnetd_status ;; *) # Default is "start", for backwards compatibility with previous # Slackware versions. This may change to a 'usage' error someday. bnetd_start esac pvpgn-1.8.5/scripts/announce.sh0000644000175000017500000000340711151345317015477 0ustar aaronaaron#!/bin/sh # This script is to announce a message on a server automatically # and repeatedly. It is intended for server admin use. # Here is an example: # # announce.sh localhost account password 30 "Attention: Here is an # announcement\nAnd here is another announcement" # # The bnchat program can be obtained from the bnetd package. BNCHAT=bnchat PIPE="/tmp/pipe-bnannounce-$$" cleanup () { kill -9 "${pid}" 2> /dev/null rm -f "${PIPE}" 2> /dev/null exit 0 } if [ -z "$4" ]; then echo -e "Usage: $0 server account password interval [msgs] ..." echo -e " server server ip or hostname" echo -e " account your server account" echo -e " password password for your account" echo -e " interval time intervals between announce in seconds" echo -e " [msgs] messages you want to announce" echo echo -e "Notes: Your account should have announce or admin permissions" echo -e " If interval is zero then bnannounce will only print" echo -e " one copy of the announcement." echo exit fi rm -f "${PIPE}" mknod "${PIPE}" p > /dev/null if [ $? -ne 0 ] ; then echo "$0: failed to make pipe file ${PIPE}, check your permissions." >&2 exit 1 fi server="$1" user="$2" pass="$3" interval="$4" shift 4 msg="`echo -e "$*" | sed -e 's/^/\/announce /g'`" "${BNCHAT}" < "${PIPE}" > /dev/null 2>&1 & pid="$!" trap "eval cleanup" SIGINT SIGQUIT SIGTERM EXIT echo -e "${user}" > "${PIPE}" echo -e "${pass}" > "${PIPE}" echo "/join Support" > "${PIPE}" while kill -0 "${pid}" 2> /dev/null; do echo "/announce ${msg}" > "${PIPE}" if [ "${interval}" -lt "1" ]; then exit fi sleep "${interval}" done exit pvpgn-1.8.5/scripts/flat2cdb.pl0000644000175000017500000000410511151345317015347 0ustar aaronaaron#!/usr/bin/perl $cdb_command = "/usr/local/bin/cdb"; if (scalar(@ARGV) != 2) { &usage; exit; } &header; # remove a trailing / $dirpath = $ARGV[0]; $dirpath =~ s!(.*)/$!$1!; $dirpath2 = $ARGV[1]; $dirpath2 =~ s!(.*)/$!$1!; $max_uid = -1; opendir FILEDIR, $dirpath or die "Error opening filedir!\n"; while ($filename = readdir FILEDIR) { if ($filename =~ m/^\./) { next; } #ignore . and .. if ( ! (($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat $dirpath ."/". $filename )) { print "Error stat-ing the file $pathdir/$filename!\n" ; next; } $type = ($mode & 070000) >> 12; if ($type != 0) { print "File ". $dirpath ."/". $filename ." its not regular\n"; next; } convertfile($filename); } closedir FILEDIR; sub convertfile { my $filen = shift; my ($key, $val, $outpath); open FILE, $dirpath ."/". $filen or die "Error opening file ". $dirpath ."/". $filen ."\n"; $outpath = $dirpath2 ."/". $filen; if (open FILEOUT, $outpath) { die "Found existent file : ". $outpath ."!! Plese provide an empty output directory !!"; } close FILEOUT; open CDB, "| $cdb_command -c -t '". $outpath . ".tmp' '". $outpath ."'" || die "Error running $cdb_command\n"; print "Converting file ". $filen ."... "; while($line = ) { if ($line =~ m/^#/) { next; } if ($line =~ m/^"(.*)"="(.*)"\s*$/) { $key = $1; $val = $2; $key =~ s/\\\\/\\/g; print CDB "+". length($key) .",". length($val) .":". $key ."->". $val ."\n"; } } print CDB "\n"; close CDB; close FILE; print "done\n"; } sub header { print "Account files flat2cdb converting tool.\n"; print " Copyright (C) 2003 Dizzy (dizzy\@roedu.net)\n"; print " People Versus People Gaming Network (www.pvpgn.org)\n\n"; } sub usage { &header; print "Usage:\n\n\tflat2cdb.pl \n\n"; print "\t \t: directory with the input flat account files\n"; print "\t \t: directory where the output cdb account files will reside\n"; } pvpgn-1.8.5/UPDATE0000644000175000017500000001455711151345317012563 0ustar aaronaaron========================== PVPGN UPDATE INFORMATION ========================== This file contains a summary of all changes from previous version you need to take care of when updating your server to the current version. It should contain: -- info's about all new/changed parameters in bnetd.conf -- all new/changed config files in the conf/ subfolder The path's specified are those of the default unix installation NOTE: If updating through several versions (example if updating from 1.7.1 to 1.7.5) you HAVE to go through ALL the update information listed for every version in between and including the last one (ex. you have to go through 1.7.1 to 1.7.2 update info, then 1.7.2 to 1.7.3, and so on until 1.7.4 to 1.7.5) Updating from 1.8.4 to 1.8.5 =================================== Configuration files changed: - conf/versioncheck.conf : added STAR/SEXP IX86 vcheck entries - conf/autoupdate.conf : STAR/SEXP related updates - conf/sql_DB_layout.conf : changed field sizes in clan table - conf/sql_DB_layout2.conf : changed field sizes in clan table Updating from 1.8.3 to 1.8.4 =================================== Configuration files changed: - conf/versioncheck.conf : added STAR/SEXP IX86 vcheck entries - conf/autoupdate.conf : STAR/SEXP related updates Updating from 1.8.2 to 1.8.3 =================================== Configuration files changed: - conf/channels.conf : added channels needed by DUNE 2000 clients - conf/versioncheck.conf : added WAR3/W3XP/D2DV/D2XP IX86 entries and rewritten all STAR/SEXP/W2BN/DRTL IX86 vcheck entries - conf/supportfile.conf : added needed ver-ix86-1.mpq support file - conf/bnmaps.conf : updated ladder map lineup to be equal to battle.net - conf/autoupdate.conf : WAR3/W3XP/D2DV/D2XP/STAR/SEXP related updates Updating from 1.8.1 to 1.8.2 =================================== Configuration files changed: - conf/versioncheck.conf : added SC/BW entries Updating from 1.8.0 to 1.8.1 =================================== Configuration files changed: - conf/versioncheck.conf : added W3/SC entries entries - conf/bnetd.conf : added account_force_username option - conf/supportfile.conf : removed unused support files from the list - conf/sql_DB_layout.conf : added WOL table - conf/sql_DB_layout2.conf : added WOL table - conf/address_translation.conf : added support for WOL servserv address translation Updating from 1.8.0rc2 to 1.8.0 ==================================== Configuration files changed: - conf/versioncheck.conf : added W3/SC entries entries Updating from 1.8.0rc1 to 1.8.0rc2 ==================================== Configuration files changed: - conf/versioncheck.conf : added W3 entries - conf/autoupdate.conf : W3 related updates Updating from 1.7.9 to 1.8.0rc1 ================================= Configuration files changed: - conf/sql_DB_layout2.conf : added creation of two additional indices - conf/versioncheck.conf : added D2 / W3 entries + cleanups - conf/autoupdate.conf : general cleanup/update Updating from 1.7.8 to 1.7.9 ============================== Configuration files changed: - conf/d2cs.conf : added pid entry - conf/d2dbs.conf : added pid entry - conf/bnetd.conf : added examples for sql2 usage - conf/versioncheck.conf : added many SC/BW vchecks (yeah seems they have been busy lately) and W3 vchecks - conf/command_groups.conf : added entry for the new "/tos" command Configuration files added: - conf/sql_DB_layout2.conf : contains database structure initialization SQL statements for sql2 mode Updating from 1.7.7 to 1.7.8 ============================== Configuration files changed: - conf/sql_DB_layout.conf : includes changes needed for the new "username" SQL field used to fix a MAJOR bug that shows up with case sensitive SQL engines (almost ALL non-MySQL engines); if you update to 1.7.8 YOU MUST update this file too if you have your accounts on SQL - conf/bnetd.conf : added Westwood Online (WOL) configuration options; woladdr to specify the address to listen for WOL clients, woltimezone for the server timezone to send to clients, wollong for the server longitute, wollat for the server latitude - conf/bnetd.conf : changed "servaddrs" directive to not be totally commented and be as ":" by default in bnetd.conf (if "servaddrs" is commented this means "bnetd" will not listen for b.net services at all) - conf/channels.conf : added channels needed by WOL clients - conf/versioncheck.conf : updated with latest client versions (War3 1.18a, SC/BW 1.13 and 1.13b) - conf/bnmaps.conf : updated with the maps used now on b.net Updating from 1.7.5 to 1.7.6 ============================== Configuration files changed: - conf/bnetd.conf : moved the old "servername" parameter to "hostname" - conf/bnetd.conf : introduced "servername" parameter for server identification Updating from 1.7.3 to 1.7.4 ============================== Configuration files changed: - conf/bnetd.conf : added "ladder_prefix" parameter to allow only games with matching gamename to be counted as ladder (applies only to alternative ladder game types as specified by "ladder_games" directive) Updating from 1.7.1 to 1.7.2 ============================== Configuration files changed: - conf/bnetd.conf : added "sync_on_logoff" parameter to have account data saved to disk on user's logoff - conf/d2cs.conf : added "bak_charsavedir" & "bak_charinfodir" parameter so d2cs can delete the backup copy of charactars deleted by the client. these settings need to be set the same as the d2dbs.conf parameters of the same name Updating from 1.7.0 to 1.7.1 ============================== Configuration files changed: - conf/bnetd.conf : added "max_connections" parameter to set up the max allowed number of connections to the bnetd daemon - conf/d2cs.conf : added "max_connections" parameter to set up the max allowed number of connections to the d2cs daemon - conf/d2dbs.conf : added "difficulty_hack" parameter to activate the Diablo II level 100 workaround Updating from 1.6.x to 1.7.0 ============================== Because of the many changes in 1.7.0 we recommend to use a clean install and update the configuration files as necesarry. Things to note: 1. you now need GNU make to build PvPGN on POSIX systems (on Linux this is just "make" but on *BSD is "gmake") 2. d2trans,gametrans,w3trans have been unified under address_translation.conf file which has a complete new syntax so take care with that pvpgn-1.8.5/README.DEV0000644000175000017500000004060611151345317013145 0ustar aaronaaron PVPGN (wannabe) DEVELOPERS GUIDE Please read this file before asking any questions ! 0. About this document ======================= This document is intended to be read by all of you out there wanting to do development or testing for/on PvPGN. ChangeLog: 29-07-2003: dizzy : Initial version 28-08-2004: dizzy : Run-time debugging : Appendix A 30-08-2004: dizzy : Updated (fdwatch, xalloc, goto, gdb) 1. Why ? ========= You want to start coding for PvPGN ? Why ? What do you expect to get from it ? Answer yourself this questions and then go to the next paragraph. 2. History =========== PvPGN has started as a game server emulation project, taking the excelent's bnetd project source and working on it. While initially it has started as a War3 emulation patch over bnetd it become a lot more than that (lots of new features, lots of code changes organizing). Because of the code roots you will notice a lot of things still carrying the "bnetd" word (most notable examples are the main servers program file called "bnetd" or the main server configuration file called bnetd.conf). We considered that as a sign of respect from us to the bnetd coders we keep their names on the code they written (but on the new code of course we may name them different). 3. Objective ============= PvPGN's main objective is to support all Battle.Net clients (games) but are considering in the near future to extend it to support other game protocols as well. 4. Layout of files =================== Note: Starting here on you may find lots of terms and wors which may sound "strange" to you and for this reason we have included a glossary of terms in the end of this file. The PvPGN project consists of a main server (called "bnetd") and various other programs and (little) servers (ex. bnchat, d2cs, d2dbs etc...). PvPGN follows the bnetd's layout of files: ./bin -> used to store binaries (after compilation) ./conf -> configuration files (many of them templates) ./files -> various files needed for clients connecting ./man -> outdated man pages :( ./sbin -> same as ./bin ./scripts -> various scripts for testing/managing pvpgn ./src -> the source main directory ./src/bnetd -> source files used only by the main server ./src/common -> source files used in common by different programs ./src/compat -> source files concerning portability of code ... The build process takes place in the "src" dir. 5. Coding Style ================ a. General PvPGN is mainly developed on and for UNIX/Linux. The reasons are because we as coders work on this systems and because our users (at least the big ones) use UNIX/Linux more than ex. Windows. But, even so we try to code in a portable fashion and any release PvPGN had we made sure it compiles on win32 too (we even release win32 binaries). We will never refuse a good win32 coder but we prefer UNIX ones ;) One thing which is overlooked by newbie coders is the "esthetical" side of the code. It may not be so important to many people (which code on the idea "if it works then its good") but for us, coding on PvPGN is VERY important. When you are coding for PvPGN PLEASE try to make your code look similar to already written code (this includes identing, identificator names, etc...). Keeping the code look "the same" makes its reading a lot more easier so, finding bugs easier so coding better. One way to make sure your code sticks with the PvPGN coding style is to use "indent" code indenting formating tool (http://www.gnu.org/software/indent/). To use indent to get your code acording to PvPGN coding style use something like this (it will format properly the file clan.c and save the new file to clan.c.new): $ indent -kr -bl -bli0 -l0 -br -ce -cli4 clan.c -o clan.c.new Other overlooked aspect for newbie coders is code replication. Please DONT copy and paste code arround !!! If you need to copy common functionality from some place, think about making some API of that functionalilty, put it in some functions and use it from both places. I repeat, DONT replicate code. When allocating memory inside a function always free it in the same function before its exit (exceptions: the function returns the allocated memory in which case the calling function should take care of the allocated memory; or the allocated memory is cached/stored somewhere to be used later, in which case you must make sure it will be free()d when not needed anymore). In the startup code of any "external" function (function which may be called from other modules then the one containing it) please check ALL the input parameters (you will notice how PvPGN already does that in such functions). Traditionally this has been done with contructs like: if (var==NULL) { eventlog(error); return ; } We have recently changed our policy because of increasing code size and lots of redundant checks, we now usually prefer using assert() for this type of checks (check the manual page for assert). A new addition is the xalloc memory allocation wrappers (for malloc, calloc, realloc, strdup and free). We now do NOT allow memory allocation to take place without this wrappers. They make the code smaller and easier to read because they never fail so they eliminate the need for failure checks and eventlogs in such cases. Another thing recently adopted in the team is the usage of "goto" keyword. Many people have argued (and continue to) that goto are inherently _evil_ and they produce "spaghetti code". But that is true for pointers and lots of other powerfull C features. We consider the programmer to be the cause of bad written codes and not some keywords. So we are moving into using "goto" mainly in the "error exit paths" cases. Let's say you have a function which needs to allocate some stuff (in 3 variables), checks for each allocation, exits with error for each specific failure (also free()ing the already allocated space). You can do it the PvPGN traditional way like: ------- CODE ---------- a = malloc(X); if (!a) { eventlog(bla); return -1; } b = malloc(Y); if (!b) { eventlog(bla); free(a); return -1; } c = malloc(Z); if (!c) { eventlog(bla); free(b); free(a); return -1; } return 0; ------ CODE ----------- Or you can do it the new, "goto" way: --------- CODE -------------- a = malloc(X); if (!a) { eventlog(bla); goto err_a; } b = malloc(Y); if (!b) { eventlog(bla); goto err_b; } c = malloc(Z); if (!c) { eventlog(bla); goto err_c; } return 0; err_c: free(c); err_b: free(b); err_a: return -1; -------- CODE ------------ The last version is a lot easier to read/debug. Because the reader is usually interested by the main (non-error) code path not about the error code path. Also the traditional way replicates codes (those replicated free()) which is error prone (more badly, its prone to memory leaks, and believe me, I did fixed a lot of this forgotten free() in error exit paths). NOTE: however, with the xalloc wrappers that never fail the above examples are obsolete, still there are many other similar situations where you need a complex error exit path and goto comes in handy. When developing code you should compile always with "all warnings" enabled and try to fix them (some warnings uncover real bugs), like for gcc use "-Wall". When running/testing the codes you should use a memory debugger like valgrind and/or bounds checking compiler patches like bounds-checking-gcc. For more details about how to run pvpgn check Appendix B. b. Code Organizing PvPGN (inhireted from bnetd) trys to group functions based on their data on which they work on. Thus it somewhat resembles the principle of data encapsulation used in OOP. For example connection.h defines structs necesarry to work with connections (the main one beeing t_connection) and functions which work with this structs and which do actions related to this connections. Also notice that all this functions are named like conn_(). In general if you have a set of functions working on a set of structs, you define the structs and the functions in a .h file (thus defining the API) then write the function implementations in .c file. And the function names should be something like _(). Separating and grouping functions in their own modules, working on their own data structures helps isolating functionality in the server and thus hunting bugs a lot easier. c. Code Flow Note: this chapter is more or less correct. Is intended to give a general ideea about the code flow, it may contain flows and things which are not in sync with the actual code, for a better understanding I recommend reading the actual code The server starts in main() found in bnetd/main.c file. There it parses command line arguments then tries to initilize the modules by calling their initilizing function (many of them called like _init()). Some of this modules depend on the initilizing of others so the order there may be important. Also some of the modules if fail on initilizing may represent a general fail thus PvPGN bails out. But should print out a explaining message (or write it to the log configured file). From there the server calls the main server loop function found in server.c. Here the loop may be simplified to something like: 1. fdwatch() on the set of opened sockets 2. call fdwatch_handle() which reads (if any) network data and "handle" them (by calling the handle function coresponding to the class of the connection receiving the data) 3. write (if any) to the network from the output queue 4. do any periodic or time based events 5. go to 1 As seen on step 2. above we call the handling functions coresponding to the class of the connection. The handle functions usualy are a big switch/case or a for/if (which is equivalent) and they check for the packet type received, then they act acordingly to the data received (many of them responing with packets by adding them to the output packet queue of the connection). Appendix A. Glossary of terms =============================== * autoupdate: the feature of Battle.Net servers to send a (MPQ, see MPQ) file to the client which after downloading it, it is used to update the client * connection class: when a connection is established to a bnet listening address the client sends an initial byte which tells the server of what class of connection the following packets will be; classes of connections determine what packets can go through that connection. * MPQ: a format archive which is used by Blizzard clients and Battle.Net servers. This files are used for containing verious files (sound/graphics in clients, AI scripts, update patches etc...) * versioncheck: also know as vcheck and sometimes just vc ; a client verification system used by Battle.Net servers to identify client version and "purity". Based on this the server may accept/refuse connection or ask for upgrade (see autoupdate). Appendix B. How to run PvPGN for debugging =========================================== It is very helpfull in finding out memory coruption bugs as soon as possible so while developing codes or just when running a server it is good that you use some memory coruption run-time debuggers. I dont know about Win32 users but on Unix/Linux there are some good options. 1. valgrind (http://valgrind.kde.org) Valgrind is not very portable (only x86, Linux and very recently FreeBSD), also it slows down the debugged codes (it acts like a CPU emulator so it has to do that) but I have yet to find out a better debugging tool for what he does. Valgrind is so cool that recently many OSS projects use it for finding out bugs in their codes. For more information you can check out their web page. I will focus on valgrind with PvPGN. After you have compiled and installed valgrind (it's easy, ./configure, make, make install) you will use it by running PvPGN like this: $ valgrind --tool=memcheck --num-callers=10 /path/to/bnetd -f 2> valg.out "num-callers" makes valgrind record backtraces with 10 entries and is usually needed with PvPGN which has not very small backtrace path :) Another option you might want to use is "--leak-check=yes" and probably "--leak-resolution=high". This options make valgrind even slower but they will give memory leak information when PvPGN exits. I encourage EVERYONE to use it if available (that is if you run PvPGN on a supported platform). Only very big servers won't be able to do it because there is no hardware powerfull enough to run a big server with valgrind (but big means over 500 users online). You should test it with your server and if it does not make your bnetd go over 90% CPU then you should be fine. If you cannot run valgrind for any reason or if you are hunting for some bugs valgrind cannot find (yes, valgrind is superb but there is a class of bugs, especially overflows which valgrind can't help you with) you should then try the next debugging tool. 2. bounds-checking GCC (http://sourceforge.net/projects/boundschecking/) This has the drawback of beeing just for GCC (as far as I know of) but has the advantage over valgrind that is : more portable (virtually it should be possible to use it anywhere you can use a recent GCC), a lot faster and can detect bugs that valgrind cannot find. However it has the disadvantage that it's error reports do not contain backtraces so they might be lesser usefull. To use it basically it cuts down to: - download a recent compiler (ex GCC 3.4.1) - download the coresponding patch from the project's sf.net page - apply the patch while beeing in the gcc source dir you unpacked with a command like bunzip2 -c /path/to/patch.bz2 | patch -p1 - compile gcc and install gcc - to make pvpgn compile with your new gcc do something like: $ CC=/path/to/new/gcc CFLAGS="-O0 -Wall -fbounds-checking -g" ./configure - then the usual make, make install - to run PvPGN you will probably need to redirect stderr like: $ /path/to/bnetd -f 2> debug.out You will probably encounter some problems when configuring, building gcc, so you should read the text in the beginning of the bounds-checking patch file. Also the gcc install docs are usefull. When starting up your new bounds checking enabled binary you will see some usefull messages. By default the patch makes the debugged program exit on the first error it encounters. For a production server this is not very nice so you will want to set GCC_BOUNDS_OPTS shell variable to "-never-fatal" like: $ GCC_BOUNDS_OPTS="-never-fatal" /path/to/bnetd -f 2> debug.out Appendix C. How to generate and use "core" files ================================================= This appendix is for Unix users. I dont know if other platforms have similar features, that when the program crashes unexpectedly the OS would dump the contents of the memory of the crashing process into a disk file for later inspection. First make sure that PvPGN has been compiled with debugging ("-g" parameter to gcc) and with no optimizations ("-O0" parameter to gcc). PvPGN default build process puts "-g -O2" so you need to edit Makefile file before compile and change it to "-g -O0". Then something like "make clean; make". On Unix/Linux to be able to get core dumps you first need to make sure your core file size limit is set acordingly. Use "ulimit -c" for querying and setting this limit (I recommend setting it to "unlimited"). After that when you start PvPGN make sure you are in a directory where you have write access (so the OS when it wants to do the core dump it will be allowed to do so). The last thing to do is when starting PvPGN make sure it starts in FOREGROUND, example : /path/to/bnetd -f . If you did all this then when PvPGN will crash you will get a core dump. On linux this is a file called "core", on *BSD it's called .core (for bnetd that means it's called bnetd.core). Now that you got a core file it is time to use it to identify what happened wrong in the crashing process. We use gdb (the GNU debugger, should be available on all Unices) to do this. Run gdb like this: $ gdb /path/to/bnetd /path/to/corefile Then gdb should startup, print out a lot of messages and stop after printing a file and line number and quoting some C code where the crash has happened. You can find out a lot more information than this. Run gdb's command "bt full" and it will display a full backtrace of the moment of the crash. The backtrace will contain how the functions were called along the way (their parameters), and also any local variables. If you do not know what to do next from here contact a PvPGN developer and give him exactly that backtrace dump, he should know more. pvpgn-1.8.5/README.ALPHA0000644000175000017500000000033211151345317013344 0ustar aaronaaron ALPHA releases ONLY README This release is only intended for profesionals and PvPGN team members. This release has not beeing had any testing (it may not even compile). You are on your own with this release. pvpgn-1.8.5/src/0000755000175000017500000000000011151346340012426 5ustar aaronaaronpvpgn-1.8.5/src/autoconf/0000755000175000017500000000000011151345372014250 5ustar aaronaaronpvpgn-1.8.5/src/autoconf/ansi2knr.c0000644000175000017500000004746211151345317016157 0ustar aaronaaron/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. */ /*$Id: ansi2knr.c,v 1.2 2005/02/10 08:31:08 pandaemonium Exp $*/ /* Convert ANSI C function definitions to K&R ("traditional C") syntax */ /* ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU General Public License (the "GPL") for full details. Everyone is granted permission to copy, modify and redistribute ansi2knr, but only under the conditions described in the GPL. A copy of this license is supposed to have been given to you along with ansi2knr so you can know your rights and responsibilities. It should be in a file named COPYLEFT, or, if there is no file named COPYLEFT, a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. We explicitly state here what we believe is already implied by the GPL: if the ansi2knr program is distributed as a separate set of sources and a separate executable file which are aggregated on a storage medium together with another program, this in itself does not bring the other program under the GPL, nor does the mere fact that such a program or the procedures for constructing it invoke the ansi2knr executable bring any other part of the program under the GPL. */ /* * Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]] * --filename provides the file name for the #line directive in the output, * overriding input_file (if present). * If no input_file is supplied, input is read from stdin. * If no output_file is supplied, output goes to stdout. * There are no error messages. * * ansi2knr recognizes function definitions by seeing a non-keyword * identifier at the left margin, followed by a left parenthesis, with a * right parenthesis as the last character on the line, and with a left * brace as the first token on the following line (ignoring possible * intervening comments and/or preprocessor directives), except that a line * consisting of only * identifier1(identifier2) * will not be considered a function definition unless identifier2 is * the word "void", and a line consisting of * identifier1(identifier2, <>) * will not be considered a function definition. * ansi2knr will recognize a multi-line header provided that no intervening * line ends with a left or right brace or a semicolon. These algorithms * ignore whitespace, comments, and preprocessor directives, except that * the function name must be the first thing on the line. The following * constructs will confuse it: * - Any other construct that starts at the left margin and * follows the above syntax (such as a macro or function call). * - Some macros that tinker with the syntax of function headers. */ /* * The original and principal author of ansi2knr is L. Peter Deutsch * . Other authors are noted in the change history * that follows (in reverse chronological order): lpd 2000-04-12 backs out Eggert's changes because of bugs: - concatlits didn't declare the type of its bufend argument; - concatlits didn't recognize when it was inside a comment; - scanstring could scan backward past the beginning of the string; when - the check for \ + newline in scanstring was unnecessary. 2000-03-05 Paul Eggert Add support for concatenated string literals. * ansi2knr.c (concatlits): New decl. (main): Invoke concatlits to concatenate string literals. (scanstring): Handle backslash-newline correctly. Work with character constants. Fix bug when scanning backwards through backslash-quote. Check for unterminated strings. (convert1): Parse character constants, too. (appendline, concatlits): New functions. * ansi2knr.1: Document this. lpd 1999-08-17 added code to allow preprocessor directives wherever comments are allowed lpd 1999-04-12 added minor fixes from Pavel Roskin for clean compilation with gcc -W -Wall lpd 1999-03-22 added hack to recognize lines consisting of identifier1(identifier2, xxx) as *not* being procedures lpd 1999-02-03 made indentation of preprocessor commands consistent lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an endless loop; quoted strings within an argument list confused the parser lpd 1999-01-24 added a check for write errors on the output, suggested by Jim Meyering lpd 1998-11-09 added further hack to recognize identifier(void) as being a procedure lpd 1998-10-23 added hack to recognize lines consisting of identifier1(identifier2) as *not* being procedures lpd 1997-12-08 made input_file optional; only closes input and/or output file if not stdin or stdout respectively; prints usage message on stderr rather than stdout; adds --filename switch (changes suggested by ) lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with compilers that don't understand void, as suggested by Tom Lane lpd 1996-01-15 changed to require that the first non-comment token on the line following a function header be a left brace, to reduce sensitivity to macros, as suggested by Tom Lane lpd 1995-06-22 removed #ifndefs whose sole purpose was to define undefined preprocessor symbols as 0; changed all #ifdefs for configuration symbols to #ifs lpd 1995-04-05 changed copyright notice to make it clear that including ansi2knr in a program does not bring the entire program under the GPL lpd 1994-12-18 added conditionals for systems where ctype macros don't handle 8-bit characters properly, suggested by Francois Pinard ; removed --varargs switch (this is now the default) lpd 1994-10-10 removed CONFIG_BROKETS conditional lpd 1994-07-16 added some conditionals to help GNU `configure', suggested by Francois Pinard ; properly erase prototype args in function parameters, contributed by Jim Avera ; correct error in writeblanks (it shouldn't erase EOLs) lpd 1989-xx-xx original version */ /* Most of the conditionals here are to make ansi2knr work with */ /* or without the GNU configure machinery. */ #if HAVE_CONFIG_H # include #endif #include #include #if HAVE_CONFIG_H /* For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h). This will define HAVE_CONFIG_H and so, activate the following lines. */ # if STDC_HEADERS || HAVE_STRING_H # include # else # include # endif #else /* not HAVE_CONFIG_H */ /* Otherwise do it the hard way */ # ifdef BSD # include # else # ifdef VMS extern int strlen(), strncmp(); # else # include # endif # endif #endif /* not HAVE_CONFIG_H */ #if STDC_HEADERS # include #else /* malloc and free should be declared in stdlib.h, but if you've got a K&R compiler, they probably aren't. */ # ifdef MSDOS # include # else # ifdef VMS extern char *malloc(); extern void free(); # else extern char *malloc(); extern int free(); # endif # endif #endif /* Define NULL (for *very* old compilers). */ #ifndef NULL # define NULL (0) #endif /* * The ctype macros don't always handle 8-bit characters correctly. * Compensate for this here. */ #ifdef isascii # undef HAVE_ISASCII /* just in case */ # define HAVE_ISASCII 1 #else #endif #if STDC_HEADERS || !HAVE_ISASCII # define is_ascii(c) 1 #else # define is_ascii(c) isascii(c) #endif #define is_space(c) (is_ascii(c) && isspace(c)) #define is_alpha(c) (is_ascii(c) && isalpha(c)) #define is_alnum(c) (is_ascii(c) && isalnum(c)) /* Scanning macros */ #define isidchar(ch) (is_alnum(ch) || (ch) == '_') #define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_') /* Forward references */ char *ppdirforward(); char *ppdirbackward(); char *skipspace(); char *scanstring(); int writeblanks(); int test1(); int convert1(); /* The main program */ int main(argc, argv) int argc; char *argv[]; { FILE *in = stdin; FILE *out = stdout; char *filename = 0; char *program_name = argv[0]; char *output_name = 0; #define bufsize 5000 /* arbitrary size */ char *buf; char *line; char *more; char *usage = "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n"; /* * In previous versions, ansi2knr recognized a --varargs switch. * If this switch was supplied, ansi2knr would attempt to convert * a ... argument to va_alist and va_dcl; if this switch was not * supplied, ansi2knr would simply drop any such arguments. * Now, ansi2knr always does this conversion, and we only * check for this switch for backward compatibility. */ int convert_varargs = 1; int output_error; while ( argc > 1 && argv[1][0] == '-' ) { if ( !strcmp(argv[1], "--varargs") ) { convert_varargs = 1; argc--; argv++; continue; } if ( !strcmp(argv[1], "--filename") && argc > 2 ) { filename = argv[2]; argc -= 2; argv += 2; continue; } fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name, argv[1]); fprintf(stderr, usage); exit(1); } switch ( argc ) { default: fprintf(stderr, usage); exit(0); case 3: output_name = argv[2]; out = fopen(output_name, "w"); if ( out == NULL ) { fprintf(stderr, "%s: Cannot open output file %s\n", program_name, output_name); exit(1); } /* falls through */ case 2: in = fopen(argv[1], "r"); if ( in == NULL ) { fprintf(stderr, "%s: Cannot open input file %s\n", program_name, argv[1]); exit(1); } if ( filename == 0 ) filename = argv[1]; /* falls through */ case 1: break; } if ( filename ) fprintf(out, "#line 1 \"%s\"\n", filename); buf = malloc(bufsize); if ( buf == NULL ) { fprintf(stderr, "Unable to allocate read buffer!\n"); exit(1); } line = buf; while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) { test: line += strlen(line); switch ( test1(buf) ) { case 2: /* a function header */ convert1(buf, out, 1, convert_varargs); break; case 1: /* a function */ /* Check for a { at the start of the next line. */ more = ++line; f: if ( line >= buf + (bufsize - 1) ) /* overflow check */ goto wl; if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL ) goto wl; switch ( *skipspace(ppdirforward(more), 1) ) { case '{': /* Definitely a function header. */ convert1(buf, out, 0, convert_varargs); fputs(more, out); break; case 0: /* The next line was blank or a comment: */ /* keep scanning for a non-comment. */ line += strlen(line); goto f; default: /* buf isn't a function header, but */ /* more might be. */ fputs(buf, out); strcpy(buf, more); line = buf; goto test; } break; case -1: /* maybe the start of a function */ if ( line != buf + (bufsize - 1) ) /* overflow check */ continue; /* falls through */ default: /* not a function */ wl: fputs(buf, out); break; } line = buf; } if ( line != buf ) fputs(buf, out); free(buf); if ( output_name ) { output_error = ferror(out); output_error |= fclose(out); } else { /* out == stdout */ fflush(out); output_error = ferror(out); } if ( output_error ) { fprintf(stderr, "%s: error writing to %s\n", program_name, (output_name ? output_name : "stdout")); exit(1); } if ( in != stdin ) fclose(in); return 0; } /* * Skip forward or backward over one or more preprocessor directives. */ char * ppdirforward(p) char *p; { for (; *p == '#'; ++p) { for (; *p != '\r' && *p != '\n'; ++p) if (*p == 0) return p; if (*p == '\r' && p[1] == '\n') ++p; } return p; } char * ppdirbackward(p, limit) char *p; char *limit; { char *np = p; for (;; p = --np) { if (*np == '\n' && np[-1] == '\r') --np; for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np) if (np[-1] == 0) return np; if (*np != '#') return p; } } /* * Skip over whitespace, comments, and preprocessor directives, * in either direction. */ char * skipspace(p, dir) char *p; int dir; /* 1 for forward, -1 for backward */ { for ( ; ; ) { while ( is_space(*p) ) p += dir; if ( !(*p == '/' && p[dir] == '*') ) break; p += dir; p += dir; while ( !(*p == '*' && p[dir] == '/') ) { if ( *p == 0 ) return p; /* multi-line comment?? */ p += dir; } p += dir; p += dir; } return p; } /* Scan over a quoted string, in either direction. */ char * scanstring(p, dir) char *p; int dir; { for (p += dir; ; p += dir) if (*p == '"' && p[-dir] != '\\') return p + dir; } /* * Write blanks over part of a string. * Don't overwrite end-of-line characters. */ int writeblanks(start, end) char *start; char *end; { char *p; for ( p = start; p < end; p++ ) if ( *p != '\r' && *p != '\n' ) *p = ' '; return 0; } /* * Test whether the string in buf is a function definition. * The string may contain and/or end with a newline. * Return as follows: * 0 - definitely not a function definition; * 1 - definitely a function definition; * 2 - definitely a function prototype (NOT USED); * -1 - may be the beginning of a function definition, * append another line and look again. * The reason we don't attempt to convert function prototypes is that * Ghostscript's declaration-generating macros look too much like * prototypes, and confuse the algorithms. */ int test1(buf) char *buf; { char *p = buf; char *bend; char *endfn; int contin; if ( !isidfirstchar(*p) ) return 0; /* no name at left margin */ bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1); switch ( *bend ) { case ';': contin = 0 /*2*/; break; case ')': contin = 1; break; case '{': return 0; /* not a function */ case '}': return 0; /* not a function */ default: contin = -1; } while ( isidchar(*p) ) p++; endfn = p; p = skipspace(p, 1); if ( *p++ != '(' ) return 0; /* not a function */ p = skipspace(p, 1); if ( *p == ')' ) return 0; /* no parameters */ /* Check that the apparent function name isn't a keyword. */ /* We only need to check for keywords that could be followed */ /* by a left parenthesis (which, unfortunately, is most of them). */ { static char *words[] = { "asm", "auto", "case", "char", "const", "double", "extern", "float", "for", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "switch", "typedef", "unsigned", "void", "volatile", "while", 0 }; char **key = words; char *kp; unsigned len = endfn - buf; while ( (kp = *key) != 0 ) { if ( strlen(kp) == len && !strncmp(kp, buf, len) ) return 0; /* name is a keyword */ key++; } } { char *id = p; int len; /* * Check for identifier1(identifier2) and not * identifier1(void), or identifier1(identifier2, xxxx). */ while ( isidchar(*p) ) p++; len = p - id; p = skipspace(p, 1); if (*p == ',' || (*p == ')' && (len != 4 || strncmp(id, "void", 4))) ) return 0; /* not a function */ } /* * If the last significant character was a ), we need to count * parentheses, because it might be part of a formal parameter * that is a procedure. */ if (contin > 0) { int level = 0; for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1)) level += (*p == '(' ? 1 : *p == ')' ? -1 : 0); if (level > 0) contin = -1; } return contin; } /* Convert a recognized function definition or header to K&R syntax. */ int convert1(buf, out, header, convert_varargs) char *buf; FILE *out; int header; /* Boolean */ int convert_varargs; /* Boolean */ { char *endfn; char *p; /* * The breaks table contains pointers to the beginning and end * of each argument. */ char **breaks; unsigned num_breaks = 2; /* for testing */ char **btop; char **bp; char **ap; char *vararg = 0; /* Pre-ANSI implementations don't agree on whether strchr */ /* is called strchr or index, so we open-code it here. */ for ( endfn = buf; *(endfn++) != '('; ) ; top: p = endfn; breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); if ( breaks == NULL ) { /* Couldn't allocate break table, give up */ fprintf(stderr, "Unable to allocate break table!\n"); fputs(buf, out); return -1; } btop = breaks + num_breaks * 2 - 2; bp = breaks; /* Parse the argument list */ do { int level = 0; char *lp = NULL; char *rp = NULL; char *end = NULL; if ( bp >= btop ) { /* Filled up break table. */ /* Allocate a bigger one and start over. */ free((char *)breaks); num_breaks <<= 1; goto top; } *bp++ = p; /* Find the end of the argument */ for ( ; end == NULL; p++ ) { switch(*p) { case ',': if ( !level ) end = p; break; case '(': if ( !level ) lp = p; level++; break; case ')': if ( --level < 0 ) end = p; else rp = p; break; case '/': if (p[1] == '*') p = skipspace(p, 1) - 1; break; case '"': p = scanstring(p, 1) - 1; break; default: ; } } /* Erase any embedded prototype parameters. */ if ( lp && rp ) writeblanks(lp + 1, rp); p--; /* back up over terminator */ /* Find the name being declared. */ /* This is complicated because of procedure and */ /* array modifiers. */ for ( ; ; ) { p = skipspace(p - 1, -1); switch ( *p ) { case ']': /* skip array dimension(s) */ case ')': /* skip procedure args OR name */ { int level = 1; while ( level ) switch ( *--p ) { case ']': case ')': level++; break; case '[': case '(': level--; break; case '/': if (p > buf && p[-1] == '*') p = skipspace(p, -1) + 1; break; case '"': p = scanstring(p, -1) + 1; break; default: ; } } if ( *p == '(' && *skipspace(p + 1, 1) == '*' ) { /* We found the name being declared */ while ( !isidfirstchar(*p) ) p = skipspace(p, 1) + 1; goto found; } break; default: goto found; } } found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' ) { if ( convert_varargs ) { *bp++ = "va_alist"; vararg = p-2; } else { p++; if ( bp == breaks + 1 ) /* sole argument */ writeblanks(breaks[0], p); else writeblanks(bp[-1] - 1, p); bp--; } } else { while ( isidchar(*p) ) p--; *bp++ = p+1; } p = end; } while ( *p++ == ',' ); *bp = p; /* Make a special check for 'void' arglist */ if ( bp == breaks+2 ) { p = skipspace(breaks[0], 1); if ( !strncmp(p, "void", 4) ) { p = skipspace(p+4, 1); if ( p == breaks[2] - 1 ) { bp = breaks; /* yup, pretend arglist is empty */ writeblanks(breaks[0], p + 1); } } } /* Put out the function name and left parenthesis. */ p = buf; while ( p != endfn ) putc(*p, out), p++; /* Put out the declaration. */ if ( header ) { fputs(");", out); for ( p = breaks[0]; *p; p++ ) if ( *p == '\r' || *p == '\n' ) putc(*p, out); } else { for ( ap = breaks+1; ap < bp; ap += 2 ) { p = *ap; while ( isidchar(*p) ) putc(*p, out), p++; if ( ap < bp - 1 ) fputs(", ", out); } fputs(") ", out); /* Put out the argument declarations */ for ( ap = breaks+2; ap <= bp; ap += 2 ) (*ap)[-1] = ';'; if ( vararg != 0 ) { *vararg = 0; fputs(breaks[0], out); /* any prior args */ fputs("va_dcl", out); /* the final arg */ fputs(bp[0], out); } else fputs(breaks[0], out); } free((char *)breaks); return 0; } pvpgn-1.8.5/src/autoconf/termios.m40000644000175000017500000000215211151345317016173 0ustar aaronaaron# AM_SYS_POSIX_TERMIOS # Copyright 1996, 2000, 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # From Jim Meyering. # serial 1 AC_DEFUN([AM_SYS_POSIX_TERMIOS], [AC_CACHE_CHECK([POSIX termios], am_cv_sys_posix_termios, [AC_TRY_LINK([#include #include #include ], [/* SunOS 4.0.3 has termios.h but not the library calls. */ tcgetattr(0, 0);], am_cv_sys_posix_termios=yes, am_cv_sys_posix_termios=no)]) ]) pvpgn-1.8.5/src/autoconf/winsz.m40000644000175000017500000000325111151345317015664 0ustar aaronaaron# AM_HEADER_TIOCGWINSZ_NEEDS_SYS_IOCTL # Copyright 1996, 1998, 2000, 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # From Jim Meyering. # serial 1 AC_DEFUN([AM_HEADER_TIOCGWINSZ_NEEDS_SYS_IOCTL], [AC_REQUIRE([AM_SYS_POSIX_TERMIOS]) AC_CACHE_CHECK([whether use of TIOCGWINSZ requires sys/ioctl.h], am_cv_sys_tiocgwinsz_needs_sys_ioctl_h, [am_cv_sys_tiocgwinsz_needs_sys_ioctl_h=no gwinsz_in_termios_h=no if test $am_cv_sys_posix_termios = yes; then AC_EGREP_CPP([yes], [#include # include # ifdef TIOCGWINSZ yes # endif ], gwinsz_in_termios_h=yes) fi if test $gwinsz_in_termios_h = no; then AC_EGREP_CPP([yes], [#include # include # ifdef TIOCGWINSZ yes # endif ], am_cv_sys_tiocgwinsz_needs_sys_ioctl_h=yes) fi ]) if test $am_cv_sys_tiocgwinsz_needs_sys_ioctl_h = yes; then AC_DEFINE(GWINSZ_IN_SYS_IOCTL,1, [Define if TIOCGWINSZ requires sys/ioctl.h]) fi ]) pvpgn-1.8.5/src/autoconf/install-sh0000644000175000017500000001272111151345317016253 0ustar aaronaaron#! /bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 pvpgn-1.8.5/src/autoconf/mkdir-p0000644000175000017500000000313211151345317015534 0ustar aaronaaron#! /bin/sh # $XConsortium: mkdirhier.sh,v 1.7 94/03/24 15:46:34 gildea Exp $ # Courtesy of Paul Eggert # # Modified by QingLong for portability. 24-02-97. # newline=' ' IFS=$newline # # WARNING! Some ancient shells do not understand `:=' and `:-' expansion. # Use just `=' instead of `:=' if you have lame one. #: ${MKDIR:=mkdir} ${TR:=tr} # if test -z "${MKDIR-}" ; then MKDIR=mkdir fi if test -z "${TR-}" ; then TR=tr fi case ${1--} in -*) echo >&2 "mkdir-p: usage: mkdir-p directory ..." exit 1 esac status="" for directory do case $directory in '') echo >&2 "mkdir-p: empty directory name" status="1" continue ;; *"$newline"*) echo >&2 "mkdir-p: directory name contains a newline: \`\`$directory''" status="1" continue ;; ///*) prefix="/" # See POSIX 2.3 "path". ;; //*) prefix="//" ;; /*) prefix="/" ;; -*) prefix="./" ;; *) prefix="" esac # IFS=/ set x $directory # case $2 in */*) # IFS parsing is broken IFS=' ' set x `echo $directory | ${TR} / ' '` ;; esac # IFS=$newline shift # for filename do path="$prefix$filename" prefix="$path/" shift # test -d "$path" || \ { paths=$path for filename do if test "$filename" != "." ; then path="$path/$filename" paths="$paths$newline$path" fi done # ${MKDIR} $paths || status=$? # break } done done exit $status pvpgn-1.8.5/src/autoconf/mkdir.m40000644000175000017500000000150411151345317015617 0ustar aaronaarondnl AC_FUNC_MKDIR dnl Check mkdir arguments. dnl Defines MKDIR_TAKES_ONE_ARG. dnl dnl Based on code written by Alexandre Duret-Lutz . AC_DEFUN([AC_FUNC_MKDIR_ARGS], [AC_CHECK_FUNCS([mkdir _mkdir]) AC_CACHE_CHECK([whether mkdir takes one argument], [ac_cv_mkdir_takes_one_arg], [AC_TRY_COMPILE([ #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_DIR_H # include #endif #ifdef HAVE_DIRECT_H # include #endif #ifndef HAVE_MKDIR # ifdef HAVE__MKDIR # define mkdir _mkdir # endif #endif ],[mkdir(".");], [ac_cv_mkdir_takes_one_arg=yes],[ac_cv_mkdir_takes_one_arg=no])]) if test x"$ac_cv_mkdir_takes_one_arg" = xyes; then AC_DEFINE([MKDIR_TAKES_ONE_ARG],1, [Define if mkdir takes only one argument.]) fi ]) pvpgn-1.8.5/src/autoconf/ccstdc.m40000644000175000017500000000701411151345317015756 0ustar aaronaaron## ----------------------------------------- ## ## ANSIfy the C compiler whenever possible. ## ## From Franc,ois Pinard ## ## ----------------------------------------- ## # Copyright 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 1 # @defmac AC_PROG_CC_STDC # @maindex PROG_CC_STDC # @ovindex CC # If the C compiler in not in ANSI C mode by default, try to add an option # to output variable @code{CC} to make it so. This macro tries various # options that select ANSI C on some system or another. It considers the # compiler to be in ANSI C mode if it handles function prototypes correctly. # # If you use this macro, you should check after calling it whether the C # compiler has been set to accept ANSI C; if not, the shell variable # @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source # code in ANSI C, you can make an un-ANSIfied copy of it by using the # program @code{ansi2knr}, which comes with Ghostscript. # @end defmac AC_DEFUN([AM_PROG_CC_STDC], [AC_REQUIRE([AC_PROG_CC]) AC_BEFORE([$0], [AC_C_INLINE]) AC_BEFORE([$0], [AC_C_CONST]) dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require dnl a magic option to avoid problems with ANSI preprocessor commands dnl like #elif. dnl FIXME: can't do this because then AC_AIX won't work due to a dnl circular dependency. dnl AC_BEFORE([$0], [AC_PROG_CPP]) AC_MSG_CHECKING([for ${CC-cc} option to accept ANSI C]) AC_CACHE_VAL(am_cv_prog_cc_stdc, [am_cv_prog_cc_stdc=no ac_save_CC="$CC" # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" AC_TRY_COMPILE( [#include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; ], [ return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ], [am_cv_prog_cc_stdc="$ac_arg"; break]) done CC="$ac_save_CC" ]) if test -z "$am_cv_prog_cc_stdc"; then AC_MSG_RESULT([none needed]) else AC_MSG_RESULT([$am_cv_prog_cc_stdc]) fi case "x$am_cv_prog_cc_stdc" in x|xno) ;; *) CC="$CC $am_cv_prog_cc_stdc" ;; esac ]) pvpgn-1.8.5/src/autoconf/config.sub0000644000175000017500000007467011151345317016245 0ustar aaronaaron#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. timestamp='2004-03-12' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32r | m32rle | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | msp430-* \ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; cr16c) basic_machine=cr16c-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nv1) basic_machine=nv1-cray os=-unicosmp ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: pvpgn-1.8.5/src/autoconf/config.guess0000644000175000017500000012513111151345317016567 0ustar aaronaaron#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. timestamp='2004-03-12' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amd64:OpenBSD:*:*) echo x86_64-unknown-openbsd${UNAME_RELEASE} exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; cats:OpenBSD:*:*) echo arm-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pegasos:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit 0 ;; macppc:MirBSD:*:*) echo powerppc-unknown-mirbsd${UNAME_RELEASE} exit 0 ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha*:OpenVMS:*:*) echo alpha-hp-vms exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; *:OS400:*:*) echo powerpc-ibm-os400 exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then # avoid double evaluation of $set_cc_for_build test -n "$CC_FOR_BUILD" || eval $set_cc_for_build if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; *:UNICOS/mp:*:*) echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) # Determine whether the default compiler uses glibc. eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #if __GLIBC__ >= 2 LIBC=gnu #else LIBC= #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` # GNU/KFreeBSD systems have a "k" prefix to indicate we are using # FreeBSD's kernel, but not the complete OS. case ${LIBC} in gnu) kernel_only='k' ;; esac echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:[34]*) echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' exit 0 ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) case `uname -p` in *86) UNAME_PROCESSOR=i686 ;; powerpc) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit 0 ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: pvpgn-1.8.5/src/bniutils/0000755000175000017500000000000011151345372014263 5ustar aaronaaronpvpgn-1.8.5/src/bniutils/bnibuild.c0000644000175000017500000002377111151345317016230 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "compat/strerror.h" #ifdef HAVE_SYS_STAT_H # include #endif #include "compat/statmacros.h" #include "fileio.h" #include "tga.h" #include "bni.h" #include "common/version.h" #include "common/setup_after.h" #define BUFSIZE 1024 static int read_list(char const * progname, t_bnifile * bnifile, char const * name) { FILE * f; char line[BUFSIZE]; f = fopen(name,"r"); if (f == NULL) { fprintf(stderr,"%s: could not open index file \"%s\" for reading (fopen: %s)\n",progname,name,pstrerror(errno)); return -1; } bnifile->unknown1 = 0x00000010; /* in case they are not set */ bnifile->unknown2 = 0x00000001; bnifile->numicons = 0; bnifile->dataoffset = 16; /* size of header */ bnifile->icons = malloc(1); /* some realloc()s are broken */ while (fgets(line,sizeof(line),f)) { char cmd[BUFSIZE]; sscanf(line,"%s",cmd); if (strcmp(cmd,"unknown1") == 0) { sscanf(line,"unknown1 %08x",&bnifile->unknown1); } else if (strcmp(cmd,"unknown2") == 0) { sscanf(line,"unknown2 %08x",&bnifile->unknown2); } else if (strcmp(cmd,"icon") == 0) { char c; sscanf(line,"icon %c",&c); if (c == '!') { unsigned char tg[4]; int tag; unsigned int x,y,unknown; sscanf(line,"icon !%c%c%c%c %u %u %08x",&tg[0],&tg[1],&tg[2],&tg[3],&x,&y,&unknown); tag = tg[3] + (tg[2] << 8) + (tg[1] << 16) + (tg[0] << 24); fprintf(stderr,"Icon[%d]: id=0x%x x=%u y=%u unknown=0x%x tag=\"%c%c%c%c\"\n",bnifile->numicons,0,x,y,unknown,((tag >> 24) & 0xff),((tag >> 16) & 0xff),((tag >> 8) & 0xff),((tag >> 0) & 0xff)); bnifile->icons = realloc(bnifile->icons,((bnifile->numicons+1)*sizeof(t_bniicon))); bnifile->icons->icon[bnifile->numicons].id = 0; bnifile->icons->icon[bnifile->numicons].x = x; bnifile->icons->icon[bnifile->numicons].y = y; bnifile->icons->icon[bnifile->numicons].tag = tag; bnifile->icons->icon[bnifile->numicons].unknown = unknown; bnifile->numicons++; bnifile->dataoffset += 20; } else if (c == '#') { unsigned int id,x,y,unknown; sscanf(line,"icon #%08x %u %u %08x",&id,&x,&y,&unknown); fprintf(stderr,"Icon[%d]: id=0x%x x=%u y=%u unknown=0x%x tag=0x00000000\n",bnifile->numicons,id,x,y,unknown); bnifile->icons = realloc(bnifile->icons,((bnifile->numicons+1)*sizeof(t_bniicon))); bnifile->icons->icon[bnifile->numicons].id=id; bnifile->icons->icon[bnifile->numicons].x = x; bnifile->icons->icon[bnifile->numicons].y = y; bnifile->icons->icon[bnifile->numicons].tag=0; bnifile->icons->icon[bnifile->numicons].unknown = unknown; bnifile->numicons++; bnifile->dataoffset += 16; } else fprintf(stderr,"Bad character '%c' in icon specifier for icon %u in index file \"%s\"\n",c,bnifile->numicons+1,name); } else fprintf(stderr,"Unknown command \"%s\" in index file \"%s\"\n",cmd,name); } if (fclose(f)<0) fprintf(stderr,"%s: could not close index file \"%s\" after reading (fclose: %s)\n",progname,name,pstrerror(errno)); return 0; } static char * geticonfilename(t_bnifile *bnifile, char const * indir, int i) { char * name; if (bnifile->icons->icon[i].id == 0) { unsigned int tag = bnifile->icons->icon[i].tag; name = malloc(strlen(indir)+10); sprintf(name,"%s/%c%c%c%c.tga",indir,((tag >> 24) & 0xff),((tag >> 16) & 0xff),((tag >> 8) & 0xff),((tag >> 0) & 0xff)); } else { name = malloc(strlen(indir)+16); sprintf(name,"%s/%08x.tga",indir,bnifile->icons->icon[i].id); } return name; } static int img2area(t_tgaimg *dst, t_tgaimg *src, int x, int y) { unsigned char *sdp; unsigned char *ddp; int pixelsize; int i; pixelsize = getpixelsize(dst); if (getpixelsize(src) != pixelsize) { fprintf(stderr,"Error: source pixelsize is %d should be %d!\n",getpixelsize(src),pixelsize); return -1; } if (src->width+x > dst->width) return -1; if (src->height+y > dst->height) return -1; sdp = src->data; ddp = dst->data + (y * dst->width * pixelsize); for (i = 0; i < src->height; i++) { ddp += x*pixelsize; memcpy(ddp,sdp,src->width*pixelsize); sdp += src->width*pixelsize; ddp += (dst->width-x)*pixelsize; } return 0; } static void usage(char const * progname) { fprintf(stderr, "usage: %s [] [--] []\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n",progname); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { char const * indir=NULL; char const * bnifile=NULL; FILE * fbni; struct stat s; int a; int forcefile=0; char dash[]="-"; /* unique address used as flag */ if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a\n",argv[0]); return STATUS_FAILURE; } if (stat(indir,&s)<0) { fprintf(stderr,"%s: could not stat input directory \"%s\" (stat: %s)\n",argv[0],indir,pstrerror(errno)); return STATUS_FAILURE; } if (!S_ISDIR(s.st_mode)) { fprintf(stderr,"%s: \"%s\" is not a directory\n",argv[0],indir); return -1; } if (bnifile==dash) fbni = stdout; else if (!(fbni = fopen(bnifile,"w"))) { fprintf(stderr,"%s: could not open BNI file \"%s\" for writing (fopen: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_FAILURE; } { unsigned int i; unsigned int yline; t_tgaimg * img; t_bnifile bni; char * listfilename; listfilename = malloc(strlen(indir)+14); sprintf(listfilename,"%s/bniindex.lst",indir); fprintf(stderr,"Info: Reading index from file \"%s\"...\n",listfilename); if (read_list(argv[0],&bni,listfilename)<0) return STATUS_FAILURE; fprintf(stderr,"BNIHeader: unknown1=%u unknown2=%u numicons=%u dataoffset=%u\n",bni.unknown1,bni.unknown2,bni.numicons,bni.dataoffset); if (write_bni(fbni,&bni)<0) { fprintf(stderr,"Error: Failed to write BNI header.\n"); return STATUS_FAILURE; } img = new_tgaimg(0,0,24,tgaimgtype_rlecompressed_truecolor); for (i = 0; i < bni.numicons; i++) { if (bni.icons->icon[i].x > img->width) img->width = bni.icons->icon[i].x; img->height += bni.icons->icon[i].y; } fprintf(stderr,"Info: Creating TGA with %ux%ux%ubpp.\n",img->width,img->height,img->bpp); img->data = malloc(img->width*img->height*getpixelsize(img)); yline = 0; for (i = 0; i < bni.numicons; i++) { t_tgaimg *icon; FILE *f; char *name; name = geticonfilename(&bni,indir,i); f = fopen(name,"r"); if (f==NULL) { perror("fopen"); free(name); return STATUS_FAILURE; } free(name); icon = load_tga(f); if (fclose(f)<0) fprintf(stderr,"Error: could not close TGA file \"%s\" after reading (fclose: %s)\n",name,pstrerror(errno)); if (icon == NULL) { fprintf(stderr,"Error: load_tga failed with data from TGA file \"%s\"\n",name); return STATUS_FAILURE; } if (img2area(img,icon,0,yline)<0) { fprintf(stderr,"Error: inserting icon from TGA file \"%s\" into big TGA failed\n",name); return STATUS_FAILURE; } yline += icon->height; destroy_img(icon); } if (write_tga(fbni,img)<0) { fprintf(stderr,"Error: Failed to write TGA to BNI file.\n"); return STATUS_FAILURE; } if (bnifile!=dash && fclose(fbni)<0) { fprintf(stderr,"%s: could not close BNI file \"%s\" after writing (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_FAILURE; } } fprintf(stderr,"Info: Writing to \"%s\" finished.\n",bnifile); return STATUS_SUCCESS; } pvpgn-1.8.5/src/bniutils/bni.c0000644000175000017500000000654511151345317015210 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech (mmz@gmx.net) Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common/setup_before.h" #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "fileio.h" #include "bni.h" #include "common/setup_after.h" extern t_bnifile * load_bni(FILE *f) { t_bnifile *b; unsigned int i; if (f == NULL) return NULL; b = malloc(sizeof(t_bnifile)); file_rpush(f); b->unknown1 = file_readd_le(); if (b->unknown1 != 0x00000010) fprintf(stderr,"load_bni: field 1 is not 0x00000010. Data may be invalid!\n"); b->unknown2 = file_readd_le(); if (b->unknown2 != 0x00000001) fprintf(stderr,"load_bni: field 2 is not 0x00000001. Data may be invalid!\n"); b->numicons = file_readd_le(); if (b->numicons > BNI_MAXICONS) { fprintf(stderr,"load_bni: more than %d (BNI_MAXICONS) icons. Increase maximum number of icons in \"bni.h\".\n",BNI_MAXICONS); b->numicons = BNI_MAXICONS; } b->dataoffset = file_readd_le(); if (b->numicons<1) { fprintf(stderr,"load_bni: strange, no icons present in BNI file\n"); b->icons = NULL; } else { b->icons = malloc(b->numicons*sizeof(t_bniicon)); } for (i = 0; i < b->numicons; i++) { b->icons->icon[i].id = file_readd_le(); b->icons->icon[i].x = file_readd_le(); b->icons->icon[i].y = file_readd_le(); if (b->icons->icon[i].id == 0) { b->icons->icon[i].tag = file_readd_le(); } else { b->icons->icon[i].tag = 0; } b->icons->icon[i].unknown = file_readd_le(); } if (ftell(f)!=(long)b->dataoffset) fprintf(stderr,"load_bni: Warning, %lu bytes of garbage after BNI header\n",(unsigned long)(b->dataoffset-ftell(f))); file_rpop(); return b; } extern int write_bni(FILE *f,t_bnifile *b) { unsigned int i; if (f == NULL) return -1; if (b == NULL) return -1; file_wpush(f); file_writed_le(b->unknown1); if (b->unknown1 != 0x00000010) fprintf(stderr,"write_bni: field 1 is not 0x00000010. Data may be invalid!\n"); file_writed_le(b->unknown2); if (b->unknown2 != 0x00000001) fprintf(stderr,"write_bni: field 2 is not 0x00000001. Data may be invalid!\n"); file_writed_le(b->numicons); file_writed_le(b->dataoffset); for (i = 0; i < b->numicons; i++) { file_writed_le(b->icons->icon[i].id); file_writed_le(b->icons->icon[i].x); file_writed_le(b->icons->icon[i].y); if (b->icons->icon[i].id == 0) { file_writed_le(b->icons->icon[i].tag); } file_writed_le(b->icons->icon[i].unknown); } if (ftell(f)!=(long)b->dataoffset) fprintf(stderr,"Warning: dataoffset is incorrect! (=0x%lx should be 0x%lx)\n",(unsigned long)b->dataoffset,(unsigned long)ftell(f)); file_wpop(); return 0; } pvpgn-1.8.5/src/bniutils/bnilist.c0000644000175000017500000001207611151345317016100 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech (mmz@gmx.net) Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef STDC_HEADERS # include #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "compat/strerror.h" #include "tga.h" #include "fileio.h" #include "common/version.h" #include "common/setup_after.h" static void usage(char const * progname) { fprintf(stderr, "usage: %s [] [--] []\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n",progname); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { char const * bnifile=NULL; FILE * fp; int a; int forcefile=0; char dash[]="-"; /* unique address used as flag */ if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a> 24) & 0xff)), ((unsigned char)((tag >> 16) & 0xff)), ((unsigned char)((tag >> 8) & 0xff)), ((unsigned char)((tag) & 0xff)),flags); if (x > expected_width) expected_width = x; expected_height += y; } if (ftell(fp)!=datastart) { fprintf(stderr,"Warning: garbage after header (pos=0x%lx-datastart=0x%lx) = %ld bytes of garbage! \n",(unsigned long)ftell(fp),(unsigned long)datastart,(long)(ftell(fp)-datastart)); } tgaimg = load_tgaheader(); print_tga_info(tgaimg,stdout); fprintf(stderr,"\n"); fprintf(stderr,"Check: Expected %dx%d TGA, got %ux%u. %s\n",expected_width,expected_height,tgaimg->width,tgaimg->height,((tgaimg->width == expected_width)&&(tgaimg->height == expected_height)) ? "OK." : "FAIL."); fprintf(stderr,"Check: Expected 24bit color depth TGA, got %dbit. %s\n",tgaimg->bpp,(tgaimg->bpp == 24) ? "OK." : "FAIL."); fprintf(stderr,"Check: Expected ImageType 10, got %d. %s\n",tgaimg->imgtype,(tgaimg->imgtype == 10) ? "OK." : "FAIL."); file_rpop(); } if (bnifile!=dash && fclose(fp)<0) fprintf(stderr,"%s: could not close BNI file \"%s\" after reading (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_SUCCESS; } pvpgn-1.8.5/src/bniutils/bni.h0000644000175000017500000000272611151345317015212 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef INCLUDED_BNI_H #define INCLUDED_BNI_H #ifndef BNI_MAXICONS #define BNI_MAXICONS 4096 #endif typedef struct { unsigned int id; /* Icon ID */ unsigned int x,y; /* width and height */ unsigned int tag; /* if ID == 0 */ unsigned int unknown; /* 0x00000000 */ } t_bniicon; typedef struct { unsigned int unknown1; /* 0x00000010 */ unsigned int unknown2; /* 0x00000001 */ unsigned int numicons; /* Number of icons */ unsigned int dataoffset; /* Start of TGA-File */ struct { t_bniicon icon[BNI_MAXICONS]; } *icons; /* The icons */ } t_bnifile; #include extern t_bnifile * load_bni(FILE *f); extern int write_bni(FILE *f, t_bnifile *b); #endif pvpgn-1.8.5/src/bniutils/fileio.c0000644000175000017500000001112711151345317015677 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech (mmz@gmx.net) Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common/setup_before.h" #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/uint.h" #include "fileio.h" #include "common/setup_after.h" typedef struct t_file { FILE *f; struct t_file *next; } t_file; static t_file *r_file = NULL; static t_file *w_file = NULL; /* ----------------------------------------------------------------- */ extern void file_rpush(FILE *f) { t_file *tf = malloc(sizeof(t_file)); tf->next = r_file; tf->f = f; r_file = tf; return; } extern void file_rpop(void) { t_file *tf; tf = r_file; r_file = tf->next; free(tf); return; } /* ----------------------------------------------------------------- */ extern void file_wpush(FILE *f) { t_file *tf = malloc(sizeof(t_file)); tf->next = w_file; tf->f = f; w_file = tf; return; } extern void file_wpop(void) { t_file *tf; tf = w_file; w_file = tf->next; free(tf); return; } /* ----------------------------------------------------------------- */ extern t_uint8 file_readb(void) { unsigned char buff[1]; if (fread(buff,1,sizeof(buff),r_file->f) < sizeof(buff)) { if (ferror(r_file->f)) perror("file_readb: fread"); return 0; } return (((t_uint8)buff[0]) ); } extern t_uint16 file_readw_le(void) { unsigned char buff[2]; if (fread(buff,1,sizeof(buff),r_file->f) < sizeof(buff)) { if (ferror(r_file->f)) perror("file_readw_le: fread"); return 0; } return (((t_uint16)buff[0]) )| (((t_uint16)buff[1])<< 8); } extern t_uint16 file_readw_be(void) { unsigned char buff[2]; if (fread(buff,1,sizeof(buff),r_file->f) < sizeof(buff)) { if (ferror(r_file->f)) perror("file_readw_be: fread"); return 0; } return (((t_uint16)buff[0])<< 8)| (((t_uint16)buff[1]) ); } extern t_uint32 file_readd_le(void) { unsigned char buff[4]; if (fread(buff,1,sizeof(buff),r_file->f) < sizeof(buff)) { if (ferror(r_file->f)) perror("file_readd_le: fread"); return 0; } return (((t_uint32)buff[0]) )| (((t_uint32)buff[1])<< 8)| (((t_uint32)buff[2])<<16)| (((t_uint32)buff[3])<<24); } extern t_uint32 file_readd_be(void) { unsigned char buff[4]; if (fread(buff,1,sizeof(buff),r_file->f) < sizeof(buff)) { if (ferror(r_file->f)) perror("file_readd_be: fread"); return 0; } return (((t_uint32)buff[0])<<24)| (((t_uint32)buff[1])<<16)| (((t_uint32)buff[2])<< 8)| (((t_uint32)buff[3]) ); } extern int file_writeb(t_uint8 u) { unsigned char buff[1]; buff[0] = (u ); if (fwrite(buff,1,sizeof(buff),w_file->f) < sizeof(buff)) { if (ferror(w_file->f)) perror("file_writeb: fwrite"); return -1; } return 0; } extern int file_writew_le(t_uint16 u) { unsigned char buff[2]; buff[0] = (u ); buff[1] = (u>> 8); if (fwrite(buff,1,sizeof(buff),w_file->f) < sizeof(buff)) { if (ferror(w_file->f)) perror("file_writew_le: fwrite"); return -1; } return 0; } extern int file_writew_be(t_uint16 u) { unsigned char buff[2]; buff[0] = (u>> 8); buff[1] = (u ); if (fwrite(buff,1,sizeof(buff),w_file->f) < sizeof(buff)) { if (ferror(w_file->f)) perror("file_writew_be: fwrite"); return -1; } return 0; } extern int file_writed_le(t_uint32 u) { unsigned char buff[4]; buff[0] = (u ); buff[1] = (u>> 8); buff[2] = (u>>16); buff[3] = (u>>24); if (fwrite(buff,1,sizeof(buff),w_file->f) < sizeof(buff)) { if (ferror(w_file->f)) perror("file_writed_le: fwrite"); return -1; } return 0; } extern int file_writed_be(t_uint32 u) { unsigned char buff[4]; buff[0] = (u>>24); buff[1] = (u>>16); buff[2] = (u>> 8); buff[3] = (u ); if (fwrite(buff,1,sizeof(buff),w_file->f) < sizeof(buff)) { if (ferror(w_file->f)) perror("file_writed_be: fwrite"); return -1; } return 0; } pvpgn-1.8.5/src/bniutils/tga.h0000644000175000017500000000710511151345317015211 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef INCLUDED_TGA_H #define INCLUDED_TGA_H #ifdef JUST_NEED_TYPES # include "compat/uint.h" #else # define JUST_NEED_TYPES # include "compat/uint.h" # undef JUST_NEED_TYPES #endif typedef struct { t_uint8 idlen; /* number of bytes in Field 6: 0==no id */ t_uint8 cmaptype; /* colormap: 0==none, 1==included, <128==TrueVision, >=128==developer */ t_uint8 imgtype; /* pixel format: <128==TrueVision, >=128==developer */ t_uint16 cmapfirst; /* first entry offset */ t_uint16 cmaplen; /* number of colormap entries */ t_uint8 cmapes; /* size of a single colormap entry in bits, 15 forces 1 attribute bit, 32 forces 8 */ t_uint16 xorigin; /* x coordinate of lower left hand corner with origin at left of screen */ t_uint16 yorigin; /* y coordinate of lower left hand corner with origin at bottom of screen */ t_uint16 width; /* width in pixels */ t_uint16 height; /* height in pixels */ t_uint8 bpp; /* bits per pixel, including attributes and alpha channel */ t_uint8 desc; /* image descriptor: bits 0,1,2,3==num attribute bits per pixel, bit 4==horizontal order, bit 5==vertical order, bits 6,7==interleaving */ /* field 6, optional */ /* field 7, colormap data in ARGB, optional, entries are (min(cmapes/3,8)*3+7)/8 bits wide */ t_uint8 *data; /* field 9, developer area, optional */ /* field 10, extension area, optional */ t_uint32 extareaoff; /* extension area offset, 0==none */ t_uint32 devareaoff; /* developer area offset, 0==none */ /* magic, null terminated */ } t_tgaimg; typedef enum { tgaimgtype_empty=0, tgaimgtype_uncompressed_mapped=1, tgaimgtype_uncompressed_truecolor=2, tgaimgtype_uncompressed_monochrome=3, tgaimgtype_rlecompressed_mapped=9, tgaimgtype_rlecompressed_truecolor=10, tgaimgtype_rlecompressed_monochrome=11, tgaimgtype_huffman_mapped=32, tgaimgtype_huffman_4pass_mapped=33 } t_tgaimgtype; typedef enum { tgadesc_attrbits0=1, tgadesc_attrbits1=2, tgadesc_attrbits2=4, tgadesc_attrbits3=8, tgadesc_horz=16, tgadesc_vert=32, tgadesc_interleave1=64, tgadesc_interleave2=128 } t_tgadesc; typedef enum { tgacmap_none=0, tgacmap_included=1 } t_tgacmap; typedef enum { RLE, RAW } t_tgapkttype; /* "new" style TGA allowing for developer and extension areas must have this magic at the end of the file */ #define TGAMAGIC "TRUEVISION-XFILE." #include extern t_tgaimg * new_tgaimg(unsigned int width, unsigned int height, unsigned int bpp, t_tgaimgtype imgtype); extern int getpixelsize(t_tgaimg const *img); extern t_tgaimg * load_tgaheader(void); extern t_tgaimg * load_tga(FILE *f); extern int write_tga(FILE *f, t_tgaimg *img); extern void destroy_img(t_tgaimg * img); extern void print_tga_info(t_tgaimg const * img, FILE * fp); #endif pvpgn-1.8.5/src/bniutils/tga.c0000644000175000017500000003651311151345317015211 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech (mmz@gmx.net) Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common/setup_before.h" #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "compat/strerror.h" #include "fileio.h" #include "tga.h" #include "common/setup_after.h" static int rotate_updown(t_tgaimg *img); static int rotate_leftright(t_tgaimg *img); static int RLE_decompress(FILE *f, void *buf, int bufsize, int pixelsize); static void RLE_write_pkt(FILE *f, t_tgapkttype pkttype, int len, void *data, int pixelsize); static int RLE_compress(FILE *f, t_tgaimg const *img); static int rotate_updown(t_tgaimg *img) { unsigned char *ndata; int pixelsize; int y; if (img == NULL) return -1; if (img->data == NULL) return -1; pixelsize = getpixelsize(img); if (pixelsize == 0) return -1; ndata = malloc(img->width*img->height*pixelsize); for (y = 0; y < img->height; y++) { memcpy(ndata + (y*img->width*pixelsize), img->data + ((img->width*img->height*pixelsize)-((y+1)*img->width*pixelsize)), img->width*pixelsize); } free(img->data); img->data = ndata; return 0; } static int rotate_leftright(t_tgaimg *img) { unsigned char *ndata, *datap; int pixelsize; int y,x; fprintf(stderr,"WARNING: rotate_leftright: this function is untested!\n"); if (img == NULL) return -1; if (img->data == NULL) return -1; pixelsize = getpixelsize(img); if (pixelsize == 0) return -1; ndata = malloc(img->width*img->height*pixelsize); datap = img->data; for (y = 0; y < img->height; y++) { unsigned char *linep = (ndata + (((y+1)*img->width*pixelsize)-pixelsize)); for (x = 0; x < img->width; x++) { memcpy(linep,datap,pixelsize); linep -= pixelsize; datap += pixelsize; } } free(img->data); img->data = ndata; return 0; } extern int getpixelsize(t_tgaimg const *img) { switch (img->bpp) { case 8: return 1; case 15: case 16: return 2; case 24: return 3; case 32: return 4; default: fprintf(stderr,"load_tga: color depth %u is not supported!\n",img->bpp); return 0; } } extern t_tgaimg * new_tgaimg(unsigned int width, unsigned int height, unsigned int bpp, t_tgaimgtype imgtype) { t_tgaimg *img; img = malloc(sizeof(t_tgaimg)); img->idlen = 0; img->cmaptype = tgacmap_none; img->imgtype = imgtype; img->cmapfirst = 0; img->cmaplen = 0; img->cmapes = 0; img->xorigin = 0; img->yorigin = 0; img->width = width; img->height = height; img->bpp = bpp; img->desc = 0; /* no attribute bits, top, left, and zero reserved */ img->data = NULL; img->extareaoff = 0; img->devareaoff = 0; return img; } extern t_tgaimg * load_tgaheader(void) { t_tgaimg *img; img = malloc(sizeof(t_tgaimg)); img->idlen = file_readb(); img->cmaptype = file_readb(); img->imgtype = file_readb(); img->cmapfirst = file_readw_le(); img->cmaplen = file_readw_le(); img->cmapes = file_readb(); img->xorigin = file_readw_le(); img->yorigin = file_readw_le(); img->width = file_readw_le(); img->height = file_readw_le(); img->bpp = file_readb(); img->desc = file_readb(); img->data = NULL; img->extareaoff = 0; /* ignored when reading */ img->devareaoff = 0; /* ignored when reading */ return img; } extern t_tgaimg * load_tga(FILE *f) { t_tgaimg *img; int pixelsize; file_rpush(f); img = load_tgaheader(); /* make sure we understand the header fields */ if (img->cmaptype != tgacmap_none) { fprintf(stderr,"load_tga: Color-mapped images are not (yet?) supported!\n"); free(img); return NULL; } if (img->imgtype!=tgaimgtype_uncompressed_truecolor && img->imgtype!=tgaimgtype_rlecompressed_truecolor) { fprintf(stderr,"load_tga: imagetype %u is not supported. (only 2 and 10 are supported)\n",img->imgtype); free(img); return NULL; } pixelsize = getpixelsize(img); if (pixelsize == 0) { free(img); return NULL; } /* Skip the ID if there is one */ if (img->idlen > 0) { fprintf(stderr,"load_tga: ID present, skipping %d bytes\n",img->idlen); if (fseek(f,img->idlen,SEEK_CUR)<0) fprintf(stderr,"load_tga: could not seek %u bytes forward (fseek: %s)\n",img->idlen,pstrerror(errno)); } /* Now, we can alloc img->data */ img->data = malloc(img->width*img->height*pixelsize); if (img->imgtype == tgaimgtype_uncompressed_truecolor) { if (fread(img->data,pixelsize,img->width*img->height,f)<(unsigned)(img->width*img->height)) { fprintf(stderr,"load_tga: error while reading data!\n"); free(img->data); free(img); return NULL; } } else { /* == tgaimgtype_rlecompressed_truecolor */ if (RLE_decompress(f,img->data,img->width*img->height*pixelsize,pixelsize) < 0) { fprintf(stderr,"load_tga: error while decompressing data!\n"); free(img->data); free(img); return NULL; } } file_rpop(); if ((img->desc & tgadesc_horz) == 1) { /* right, want left */ if (rotate_leftright(img)<0) { fprintf(stderr,"ERROR: rotate_leftright failed!\n"); } } if ((img->desc & tgadesc_vert) == 0) { /* bottom, want top */ if (rotate_updown(img)<0) { fprintf(stderr,"ERROR: rotate_updown failed!\n"); } } return img; } extern int write_tga(FILE *f, t_tgaimg *img) { if (f == NULL) return -1; if (img == NULL) return -1; if (img->data == NULL) return -1; if (img->idlen!=0) return -1; if (img->cmaptype!=tgacmap_none) return -1; if (img->imgtype!=tgaimgtype_uncompressed_truecolor && img->imgtype!=tgaimgtype_rlecompressed_truecolor) return -1; file_wpush(f); file_writeb(img->idlen); file_writeb(img->cmaptype); file_writeb(img->imgtype); file_writew_le(img->cmapfirst); file_writew_le(img->cmaplen); file_writeb(img->cmapes); file_writew_le(img->xorigin); file_writew_le(img->yorigin); file_writew_le(img->width); file_writew_le(img->height); file_writeb(img->bpp); file_writeb(img->desc); if ((img->desc&tgadesc_horz)==1) { /* right, want left */ fprintf(stderr,"write_tga: flipping horizontally\n"); if (rotate_leftright(img)<0) { fprintf(stderr,"ERROR: rotate_updown failed!\n"); } } if ((img->desc&tgadesc_vert)==0) { /* bottom, want top */ fprintf(stderr,"write_tga: flipping vertically\n"); if (rotate_updown(img)<0) { fprintf(stderr,"ERROR: rotate_updown failed!\n"); } } if (img->imgtype==tgaimgtype_uncompressed_truecolor) { int pixelsize; pixelsize = getpixelsize(img); if (pixelsize == 0) return -1; if (fwrite(img->data,pixelsize,img->width*img->height,f)<(unsigned)(img->width*img->height)) { fprintf(stderr,"write_tga: could not write %d pixels (fwrite: %s)\n",img->width*img->height,pstrerror(errno)); file_wpop(); return -1; } } else if (img->imgtype==tgaimgtype_rlecompressed_truecolor) { fprintf(stderr,"write_tga: using RLE compression\n"); if (RLE_compress(f,img)<0) { fprintf(stderr,"write_tga: RLE compression failed.\n"); } } /* Write the file-footer */ file_writed_le(img->extareaoff); file_writed_le(img->devareaoff); if (fwrite(TGAMAGIC,strlen(TGAMAGIC)+1,1,f)<1) fprintf(stderr,"write_tga: could not write TGA footer magic (fwrite: %s)\n",pstrerror(errno)); /* Ready */ file_wpop(); return 0; } static int RLE_decompress(FILE *f, void *buf, int bufsize, int pixelsize) { unsigned char pt; unsigned char *bufp; unsigned char temp[8]; /* MAXPIXELSIZE */ int bufi; int count; file_rpush(f); bufp = buf; for (bufi=0; bufibufsize) { fprintf(stderr,"RLE_decompress: buffer too short for next packet (need %d bytes, have %d)\n",bufi+count*pixelsize,bufsize); file_rpop(); return -1; } if ((pt & 0x80) == 0) { /* RAW PACKET */ if (fread(bufp,pixelsize,count,f)<(unsigned)count) { if (feof(f)) fprintf(stderr,"RLE_decompress: short RAW packet (expected %d bytes) (EOF)\n",pixelsize*count); else fprintf(stderr,"RLE_decompress: short RAW packet (expected %d bytes) (fread: %s)\n",pixelsize*count,pstrerror(errno)); #if 0 file_rpop(); return -1; #endif } bufp += count*pixelsize; bufi += count*pixelsize; } else { /* RLE PACKET */ if (fread(temp,pixelsize,1,f) < 1) { if (feof(f)) fprintf(stderr,"RLE_decompress: short RLE packet (expected %d bytes) (EOF)\n",pixelsize); else fprintf(stderr,"RLE_decompress: short RLE packet (expected %d bytes) (fread: %s)\n",pixelsize,pstrerror(errno)); #if 0 file_rpop(); return -1; #endif } if (count<2) { fprintf(stderr,"RLE_decompress: suspicious RLE repetition count %d\n",count); } for (;count > 0; count--) { memcpy(bufp,temp,pixelsize); bufp += pixelsize; bufi += pixelsize; } } } file_rpop(); return 0; } static void RLE_write_pkt(FILE *f, t_tgapkttype pkttype, int len, void *data, int pixelsize) { unsigned char count; if (len<1 || len>128) { fprintf(stderr,"RLE_write_pkt: packet has bad length (%d bytes)\n",len); return; } if (pkttype==RLE) { if (len<2) { fprintf(stderr,"RLE_write_pkt: RLE packet has bad length (%d bytes)\n",len); return; } count = (unsigned char)(0x80 | (len-1)); if (fwrite(&count, 1, 1, f)<1) fprintf(stderr,"RLE_write_pkt: could not write RLE pixel count (fwrite: %s)\n",pstrerror(errno)); if (fwrite(data, pixelsize, 1, f)<1) fprintf(stderr,"RLE_write_pkt: could not write RLE pixel value (fwrite: %s)\n",pstrerror(errno)); } else { count = (unsigned char) (len-1); if (fwrite(&count, 1, 1, f)<1) fprintf(stderr,"RLE_write_pkt: could not write RAW pixel count (fwrite: %s)\n",pstrerror(errno)); if (fwrite(data,pixelsize,len,f)<(unsigned)len) fprintf(stderr,"RLE_write_pkt: could not write %d RAW pixels (fwrite: %s)\n",len,pstrerror(errno)); } } static int RLE_compress(FILE *f, t_tgaimg const *img) { int pixelsize; unsigned char const *datap; unsigned char *pktdata; unsigned int pktlen; t_tgapkttype pkttype; unsigned char *pktdatap; unsigned int actual=0,perceived=0; int i; pkttype = RAW; pktdatap = NULL; if (img == NULL) return -1; if (img->data == NULL) return -1; pixelsize = getpixelsize(img); if (pixelsize == 0) return -1; datap = img->data; pktdata = malloc(img->width*img->height*pixelsize); pktlen = 0; for (i=0; iwidth*img->height; ) { if (pktlen == 0) { pktdatap = pktdata; memcpy(pktdatap,datap,pixelsize); pktlen++; i++; pktdatap += pixelsize; datap += pixelsize; pkttype = RAW; continue; } if (pktlen == 1) { if (memcmp(datap-pixelsize,datap,pixelsize)==0) { pkttype = RLE; } } if (pkttype == RLE) { if (memcmp(datap-pixelsize,datap,pixelsize)!=0 || pktlen>=128) { RLE_write_pkt(f,pkttype,pktlen,pktdata,pixelsize); actual += 1+pixelsize; perceived += pixelsize*pktlen; pktlen = 0; } else { pktlen++; i++; datap += pixelsize; } } else { if (memcmp(datap-pixelsize,datap,pixelsize)==0 || pktlen>=129) { datap -= pixelsize; /* push back last pixel */ i--; if (i<0) fprintf(stderr,"BUG!\n"); pktlen--; RLE_write_pkt(f,pkttype,pktlen,pktdata,pixelsize); actual += 1+pixelsize*pktlen; perceived += pixelsize*pktlen; pktlen = 0; } else { memcpy(pktdatap,datap,pixelsize); pktlen++; i++; pktdatap += pixelsize; datap += pixelsize; } } } if (pktlen) { RLE_write_pkt(f,pkttype,pktlen,pktdata,pixelsize); if (pkttype==RLE) { actual += 1+pixelsize; perceived += pixelsize*pktlen; } else { actual += 1+pixelsize*pktlen; perceived += pixelsize*pktlen; } pktlen = 0; } fprintf(stderr,"RLE_compress: wrote %u bytes (%u uncompressed)\n",actual,perceived); return 0; } extern void destroy_img(t_tgaimg * img) { if (img == NULL) return; if (img->data) free(img->data); free(img); } extern void print_tga_info(t_tgaimg const * img, FILE * fp) { unsigned int interleave; unsigned int attrbits; char const * typestr; char const * cmapstr; char const * horzstr; char const * vertstr; char const * intlstr; if (!img || !fp) return; interleave = ((img->desc&tgadesc_interleave1)!=0)*2+((img->desc&tgadesc_interleave2)!=0); attrbits = img->desc&(tgadesc_attrbits0|tgadesc_attrbits1|tgadesc_attrbits2|tgadesc_attrbits3); switch (img->imgtype) { case tgaimgtype_empty: typestr = "No Image Data Included"; break; case tgaimgtype_uncompressed_mapped: typestr = "Uncompressed, Color-mapped Image"; break; case tgaimgtype_uncompressed_truecolor: typestr = "Uncompressed, True-color Image"; break; case tgaimgtype_uncompressed_monochrome: typestr = "Uncompressed, Black-and-white image"; break; case tgaimgtype_rlecompressed_mapped: typestr = "Run-length encoded, Color-mapped Image"; break; case tgaimgtype_rlecompressed_truecolor: typestr = "Run-length encoded, True-color Image"; break; case tgaimgtype_rlecompressed_monochrome: typestr = "Run-length encoded, Black-and-white image"; break; case tgaimgtype_huffman_mapped: typestr = "Huffman encoded, Color-mapped image"; break; case tgaimgtype_huffman_4pass_mapped: typestr = "Four-pass Huffman encoded, Color-mapped image"; break; default: typestr = "unknown"; } switch (img->cmaptype) { case tgacmap_none: cmapstr = "None"; break; case tgacmap_included: cmapstr = "Included"; break; default: cmapstr = "Unknown"; } if ((img->desc&tgadesc_horz)==0) { horzstr = "left"; } else { horzstr = "right"; } if ((img->desc&tgadesc_vert)==0) { vertstr = "bottom"; } else { vertstr = "top"; } switch (interleave) { case 0: intlstr = "none"; break; case 2: intlstr = "two way"; break; case 3: intlstr = "four way"; break; case 4: default: intlstr = "unknown"; break; } fprintf(fp,"TGAHeader: IDLength=%u ColorMapType=%u(%s)\n",img->idlen,img->cmaptype,cmapstr); fprintf(fp,"TGAHeader: ImageType=%u(%s)\n",img->imgtype,typestr); fprintf(fp,"TGAHeader: ColorMap: FirstEntryIndex=%u ColorMapLength=%u\n",img->cmapfirst,img->cmaplen); fprintf(fp,"TGAHeader: ColorMap: ColorMapEntrySize=%ubits\n",img->cmapes); fprintf(fp,"TGAHeader: X-origin=%u Y-origin=%u Width=%u(0x%x) Height=%u(0x%x)\n",img->xorigin,img->yorigin,img->width,img->width,img->height,img->height); fprintf(fp,"TGAHeader: PixelDepth=%ubits ImageDescriptor=0x%02x(%u attribute bits, origin is %s %s, interleave=%s)\n",img->bpp,img->desc,attrbits,vertstr,horzstr,intlstr); } pvpgn-1.8.5/src/bniutils/bniextract.c0000644000175000017500000002316111151345317016574 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech (mmz@gmx.net) Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "compat/strerror.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include "compat/statmacros.h" #include "compat/mkdir.h" #include "common/version.h" #include "fileio.h" #include "tga.h" #include "bni.h" #include "common/setup_after.h" /* extract a portion of an image creating a new image */ static t_tgaimg * area2img(t_tgaimg *src, int x, int y, int width, int height, t_tgaimgtype type) { t_tgaimg *dst; int pixelsize; unsigned char *datap; unsigned char *destp; int i; if (src == NULL) return NULL; if ((x+width)>src->width) return NULL; if ((y+height)>src->height) return NULL; pixelsize = getpixelsize(src); if (pixelsize == 0) return NULL; dst = new_tgaimg(width,height,src->bpp,type); dst->data = malloc(width*height*pixelsize); datap = src->data; datap += y*src->width*pixelsize; destp = dst->data; for (i = 0; i < height; i++) { datap += x*pixelsize; memcpy(destp,datap,width*pixelsize); destp += width*pixelsize; datap += (src->width-x)*pixelsize; } return dst; } static void usage(char const * progname) { fprintf(stderr, "usage: %s [] [--] \n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n",progname); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { char const * outdir=NULL; char const * bnifile=NULL; FILE * fbni; struct stat s; int a; int forcefile=0; char dash[]="-"; /* unique address used as flag */ if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a\n",argv[0]); if (bnifile!=dash && fclose(fbni)<0) fprintf(stderr,"%s: could not close BNI file \"%s\" after reading (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_FAILURE; } if (stat(outdir,&s)<0) { if (errno == ENOENT) { fprintf(stderr,"Info: Creating directory \"%s\" ...\n",outdir); if (p_mkdir(outdir,S_IRWXU+S_IRWXG+S_IRWXO)<0) { fprintf(stderr,"%s: could not create output directory \"%s\" (mkdir: %s)",argv[0],outdir,pstrerror(errno)); if (bnifile!=dash && fclose(fbni)<0) fprintf(stderr,"%s: could not close BNI file \"%s\" after reading (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_FAILURE; } } else { fprintf(stderr,"%s: could not stat output directory \"%s\" (stat: %s)\n",argv[0],outdir,pstrerror(errno)); if (bnifile!=dash && fclose(fbni)<0) fprintf(stderr,"%s: could not close BNI file \"%s\" after reading (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_FAILURE; } } else if (S_ISDIR(s.st_mode) == 0) { fprintf(stderr,"%s: \"%s\" is not a directory\n",argv[0],outdir); if (bnifile!=dash && fclose(fbni)<0) fprintf(stderr,"%s: could not close BNI file \"%s\" after reading (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_FAILURE; } { unsigned int i; int curry; t_tgaimg * iconimg; t_bnifile * bni; FILE * indexfile; char * indexfilename; fprintf(stderr,"Info: Loading \"%s\" ...\n",bnifile); bni = load_bni(fbni); if (bni == NULL) return STATUS_FAILURE; if (fseek(fbni,bni->dataoffset,SEEK_SET)<0) { fprintf(stderr,"%s: could not seek to TGA data offset %lu (fseek: %s)\n",argv[0],(unsigned long int)bni->dataoffset,pstrerror(errno)); if (bnifile!=dash && fclose(fbni)<0) fprintf(stderr,"%s: could not close BNI file \"%s\" after reading (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_FAILURE; } fprintf(stderr,"Info: Loading image ...\n"); iconimg = load_tga(fbni); if (iconimg == NULL) return STATUS_FAILURE; fprintf(stderr,"Info: Extracting icons ...\n"); indexfilename = malloc(strlen(outdir)+14); sprintf(indexfilename,"%s/bniindex.lst",outdir); fprintf(stderr,"Info: Writing Index to \"%s\" ... \n",indexfilename); indexfile = fopen(indexfilename , "w"); if (indexfile == NULL) { fprintf(stderr,"%s: could not open index file \"%s\" for writing (fopen: %s)\n",argv[0],indexfilename,pstrerror(errno)); if (bnifile!=dash && fclose(fbni)<0) fprintf(stderr,"%s: could not close BNI file \"%s\" after reading (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_FAILURE; } fprintf(indexfile,"unknown1 %08x\n",bni->unknown1); fprintf(indexfile,"unknown2 %08x\n",bni->unknown2); curry = 0; for (i=0; i < bni->numicons; i++) { FILE *dsttga; char *name; t_tgaimg *icn; icn = area2img(iconimg,0,curry,bni->icons->icon[i].x,bni->icons->icon[i].y,tgaimgtype_uncompressed_truecolor); if (icn == NULL) { fprintf(stderr,"Error: area2img failed!\n"); return STATUS_FAILURE; } if (bni->icons->icon[i].id == 0) { int tag = bni->icons->icon[i].tag; name = malloc(strlen(outdir)+10); sprintf(name,"%s/%c%c%c%c.tga",outdir,((tag >> 24) & 0xff),((tag >> 16) & 0xff),((tag >> 8) & 0xff),((tag >> 0) & 0xff)); } else { name = malloc(strlen(outdir)+16); sprintf(name,"%s/%08x.tga",outdir,bni->icons->icon[i].id); } fprintf(stderr,"Info: Writing icon %u(%ux%u) to file \"%s\" ... \n",i+1,icn->width,icn->height,name); curry += icn->height; dsttga = fopen(name,"w"); if (dsttga == NULL) { fprintf(stderr,"%s: could not open ouptut TGA file \"%s\" for writing (fopen: %s)\n",argv[0],name,pstrerror(errno)); } else { if (write_tga(dsttga,icn) < 0) { fprintf(stderr,"Error: Writing to TGA failed.\n"); } else { int tag = bni->icons->icon[i].tag; if (bni->icons->icon[i].id == 0) { fprintf(indexfile,"icon !%c%c%c%c %d %d %08x\n",((tag >> 24) & 0xff),((tag >> 16) & 0xff),((tag >> 8) & 0xff),((tag >> 0) & 0xff),bni->icons->icon[i].x,bni->icons->icon[i].y,bni->icons->icon[i].unknown); } else { fprintf(indexfile,"icon #%08x %d %d %08x\n",bni->icons->icon[i].id,bni->icons->icon[i].x,bni->icons->icon[i].y,bni->icons->icon[i].unknown); } } if (fclose(dsttga)<0) fprintf(stderr,"%s: could not close TGA file \"%s\" after writing (fclose: %s)\n",argv[0],name,pstrerror(errno)); } free(name); destroy_img(icn); } destroy_img(iconimg); if (fclose(indexfile)<0) { fprintf(stderr,"%s: could not close index file \"%s\" after writing (fclose: %s)\n",argv[0],indexfilename,pstrerror(errno)); return STATUS_FAILURE; } free(indexfilename); } if (bnifile!=dash && fclose(fbni)<0) fprintf(stderr,"%s: could not close BNI file \"%s\" after reading (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_SUCCESS; } pvpgn-1.8.5/src/bniutils/tgainfo.c0000644000175000017500000000732511151345317016064 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech (mmz@gmx.net) Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef STDC_HEADERS # include #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "compat/strerror.h" #include "tga.h" #include "fileio.h" #include "common/version.h" #include "common/setup_after.h" static void usage(char const * progname) { fprintf(stderr, "usage: %s [] [--] []\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n",progname); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { char const * tgafile=NULL; FILE * fp; int a; int forcefile=0; char dash[]="-"; /* unique address used as flag */ if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef STDC_HEADERS # include #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "compat/strerror.h" #include "fileio.h" #include "bni.h" #include "common/version.h" #include "common/setup_after.h" #define BUFSIZE 1024 static void usage(char const * progname) { fprintf(stderr, "usage: %s [] [--] [ []]\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n",progname); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { char const * bnifile=NULL; char const * tgafile=NULL; FILE * fbni; FILE * ftga; int a; int forcefile=0; char dash[]="-"; /* unique address used as flag */ if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a0) { if (fwrite(buf,rc,1,ftga) < 1) { fprintf(stderr,"%s: could not write data to TGA file \"%s\" (fwrite: %s)\n",argv[0],tgafile,pstrerror(errno)); return STATUS_FAILURE; } } file_rpop(); } if (tgafile!=dash && fclose(ftga)<0) fprintf(stderr,"%s: could not close TGA file \"%s\" after writing (fclose: %s)\n",argv[0],tgafile,pstrerror(errno)); if (bnifile!=dash && fclose(fbni)<0) fprintf(stderr,"%s: could not close BNI file \"%s\" after reading (fclose: %s)\n",argv[0],bnifile,pstrerror(errno)); return STATUS_SUCCESS; } pvpgn-1.8.5/src/bniutils/fileio.h0000644000175000017500000000274711151345317015714 0ustar aaronaaron/* Copyright (C) 2000 Marco Ziech Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_FILEIO_PROTOS #define INCLUDED_FILEIO_PROTOS #define JUST_NEED_TYPES #include #include "compat/uint.h" #undef JUST_NEED_TYPES extern void file_rpush(FILE *f); extern void file_rpop(void); extern void file_wpush(FILE *f); extern void file_wpop(void); extern t_uint8 file_readb(void); extern t_uint16 file_readw_le(void); extern t_uint16 file_readw_be(void); extern t_uint32 file_readd_le(void); extern t_uint32 file_readd_be(void); extern int file_writeb(t_uint8 u); extern int file_writew_le(t_uint16 u); extern int file_writew_be(t_uint16 u); extern int file_writed_le(t_uint32 u); extern int file_writed_be(t_uint32 u); #endif #endif pvpgn-1.8.5/src/configure0000755000175000017500000040471711151346334014355 0ustar aaronaaron#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf version 2.13 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # Defaults: ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help --with-warn enable compiler warnings" ac_help="$ac_help --with-ansi use ANSI C mode" ac_help="$ac_help --with-includes=DIR search include DIR for header files" ac_help="$ac_help --with-libraries=DIR search library DIR for libraries" ac_help="$ac_help --with-efence link with Electric Fence to find memory problems" ac_help="$ac_help --with-mysql include MySQL user accounts support" ac_help="$ac_help --with-pgsql include PostgreSQL user accounts support" ac_help="$ac_help --with-mssql include MSSQL user accounts support (requires FreeTDS includes/libs)" ac_help="$ac_help --with-sqlite3 include SQLite3 user accounts support " ac_help="$ac_help --with-odbc include ODBC user accounts support " ac_help="$ac_help --enable-poll Enable poll() instead of select(). Normally poll is preferred over select, but configure knows poll is broken on some platforms. If you think you are smarter than the configure script, you may enable poll with this option. --disable-poll Disable the use of poll()." ac_help="$ac_help --enable-bnetd Enable building of bnetd server (default) --disable-bnetd Disable building of bnetd server" ac_help="$ac_help --enable-d2cs Enable building of d2cs server (default) --disable-d2cs Disable building of d2cs server" ac_help="$ac_help --enable-d2dbs Enable building of d2dbs server (default) --disable-d2dbs Disable building of d2dbs server" # Initialize some variables set by options. # The variables have the same names as the options, with # dashes changed to underlines. build=NONE cache_file=./config.cache exec_prefix=NONE host=NONE no_create= nonopt=NONE no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= target=NONE verbose= x_includes=NONE x_libraries=NONE bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. ac_max_here_lines=12 ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi case "$ac_option" in -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case "$ac_option" in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir="$ac_optarg" ;; -build | --build | --buil | --bui | --bu) ac_prev=build ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file="$ac_optarg" ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir="$ac_optarg" ;; -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` eval "enable_${ac_feature}=no" ;; -enable-* | --enable-*) ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "enable_${ac_feature}='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he) # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat << EOF Usage: configure [options] [host] Options: [defaults in brackets after descriptions] Configuration: --cache-file=FILE cache test results in FILE --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix] --bindir=DIR user executables in DIR [EPREFIX/bin] --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] --libexecdir=DIR program executables in DIR [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data in DIR [PREFIX/share] --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data in DIR [PREFIX/com] --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] --libdir=DIR object code libraries in DIR [EPREFIX/lib] --includedir=DIR C header files in DIR [PREFIX/include] --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] --infodir=DIR info documentation in DIR [PREFIX/info] --mandir=DIR man documentation in DIR [PREFIX/man] --srcdir=DIR find the sources in DIR [configure dir or ..] --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names EOF cat << EOF Host type: --build=BUILD configure for building on BUILD [BUILD=HOST] --host=HOST configure for HOST [guessed] --target=TARGET configure for TARGET [TARGET=HOST] Features and packages: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR EOF if test -n "$ac_help"; then echo "--enable and --with options recognized:$ac_help" fi exit 0 ;; -host | --host | --hos | --ho) ac_prev=host ;; -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir="$ac_optarg" ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir="$ac_optarg" ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir="$ac_optarg" ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir="$ac_optarg" ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir="$ac_optarg" ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir="$ac_optarg" ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir="$ac_optarg" ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix="$ac_optarg" ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix="$ac_optarg" ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name="$ac_optarg" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir="$ac_optarg" ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir="$ac_optarg" ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site="$ac_optarg" ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir="$ac_optarg" ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target="$ac_optarg" ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers) echo "configure generated by autoconf version 2.13" exit 0 ;; -with-* | --with-*) ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "with_${ac_package}='$ac_optarg'" ;; -without-* | --without-*) ac_package=`echo $ac_option|sed -e 's/-*without-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` eval "with_${ac_package}=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes="$ac_optarg" ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries="$ac_optarg" ;; -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ;; *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then echo "configure: warning: $ac_option: invalid host type" 1>&2 fi if test "x$nonopt" != xNONE; then { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } fi nonopt="$ac_option" ;; esac done if test -n "$ac_prev"; then { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } fi trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 # File descriptor usage: # 0 standard input # 1 file creation # 2 errors and warnings # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 6 checking for... messages and results # 5 compiler messages saved in config.log if test "$silent" = yes; then exec 6>/dev/null else exec 6>&1 fi exec 5>./config.log echo "\ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. " 1>&5 # Strip out --no-create and --no-recursion so they do not pile up. # Also quote any args containing shell metacharacters. ac_configure_args= for ac_arg do case "$ac_arg" in -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ac_configure_args="$ac_configure_args '$ac_arg'" ;; *) ac_configure_args="$ac_configure_args $ac_arg" ;; esac done # NLS nuisances. # Only set these to C if already set. These must not be set unconditionally # because not all systems understand e.g. LANG=C (notably SCO). # Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! # Non-C LC_CTYPE values break the ctype check. if test "${LANG+set}" = set; then LANG=C; export LANG; fi if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo > confdefs.h # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. ac_unique_file=bnetd/handle_bnet.c # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_prog=$0 ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } else { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } fi fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then echo "loading site script $ac_site_file" . "$ac_site_file" fi done if test -r "$cache_file"; then echo "loading cache $cache_file" . $cache_file else echo "creating cache $cache_file" > $cache_file fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross ac_exeext= ac_objext=o if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ac_n= ac_c=' ' ac_t=' ' else ac_n=-n ac_c= ac_t= fi else ac_n= ac_c='\c' ac_t= fi AUTOCONF_CONFIG_DIR="autoconf" ac_aux_dir= for ac_dir in ${AUTOCONF_CONFIG_DIR} $srcdir/${AUTOCONF_CONFIG_DIR}; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break fi done if test -z "$ac_aux_dir"; then { echo "configure: error: can not find install-sh or install.sh in ${AUTOCONF_CONFIG_DIR} $srcdir/${AUTOCONF_CONFIG_DIR}" 1>&2; exit 1; } fi ac_config_guess=$ac_aux_dir/config.guess ac_config_sub=$ac_aux_dir/config.sub ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. ## ----------------------------------------- ## ## ANSIfy the C compiler whenever possible. ## ## From Franc,ois Pinard ## ## ----------------------------------------- ## # Copyright 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 1 # @defmac AC_PROG_CC_STDC # @maindex PROG_CC_STDC # @ovindex CC # If the C compiler in not in ANSI C mode by default, try to add an option # to output variable @code{CC} to make it so. This macro tries various # options that select ANSI C on some system or another. It considers the # compiler to be in ANSI C mode if it handles function prototypes correctly. # # If you use this macro, you should check after calling it whether the C # compiler has been set to accept ANSI C; if not, the shell variable # @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source # code in ANSI C, you can make an un-ANSIfied copy of it by using the # program @code{ansi2knr}, which comes with Ghostscript. # @end defmac # Do some error checking and defaulting for the host and target type. # The inputs are: # configure --host=HOST --target=TARGET --build=BUILD NONOPT # # The rules are: # 1. You are not allowed to specify --host, --target, and nonopt at the # same time. # 2. Host defaults to nonopt. # 3. If nonopt is not specified, then host defaults to the current host, # as determined by config.guess. # 4. Target and build default to nonopt. # 5. If nonopt is not specified, then target and build default to host. # The aliases save the names the user supplied, while $host etc. # will get canonicalized. case $host---$target---$nonopt in NONE---*---* | *---NONE---* | *---*---NONE) ;; *) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; esac # Make sure we can run config.sub. if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 echo "configure:656: checking host system type" >&5 host_alias=$host case "$host_alias" in NONE) case $nonopt in NONE) if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } fi ;; *) host_alias=$nonopt ;; esac ;; esac host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 echo "configure:677: checking target system type" >&5 target_alias=$target case "$target_alias" in NONE) case $nonopt in NONE) target_alias=$host_alias ;; *) target_alias=$nonopt ;; esac ;; esac target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 echo "configure:695: checking build system type" >&5 build_alias=$build case "$build_alias" in NONE) case $nonopt in NONE) build_alias=$host_alias ;; *) build_alias=$nonopt ;; esac ;; esac build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$build" 1>&6 test "$host_alias" != "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- # Checks for programs. # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:722: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="gcc" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:752: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_prog_rejected=no ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" break fi done IFS="$ac_save_ifs" if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# -gt 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift set dummy "$ac_dir/$ac_word" "$@" shift ac_cv_prog_CC="$@" fi fi fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then case "`uname -s`" in *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:803: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="cl" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi ;; esac fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 echo "configure:835: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF #line 846 "configure" #include "confdefs.h" main(){return(0);} EOF if { (eval echo configure:851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cc_cross=no else ac_cv_prog_cc_cross=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 ac_cv_prog_cc_works=no fi rm -fr conftest* ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 echo "configure:877: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 echo "configure:882: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes else GCC= fi ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 echo "configure:910: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ac_cv_prog_cc_g=yes else ac_cv_prog_cc_g=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 if test "$ac_test_CFLAGS" = set; then CFLAGS="$ac_save_CFLAGS" elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo "configure:953: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : else ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then INSTALL="$ac_cv_path_install" else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL="$ac_install_sh" fi fi echo "$ac_t""$INSTALL" 1>&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # Checks compiler. echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 echo "configure:1008: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get # substituted into the Makefile and "${CC-cc}" will confuse make. CPP="${CC-cc} -E" # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1029: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1046: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1063: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* ac_cv_prog_CPP="$CPP" fi CPP="$ac_cv_prog_CPP" else ac_cv_prog_CPP="$CPP" fi echo "$ac_t""$CPP" 1>&6 # Checks for systems. echo $ac_n "checking for AIX""... $ac_c" 1>&6 echo "configure:1090: checking for AIX" >&5 cat > conftest.$ac_ext <&5 | egrep "yes" >/dev/null 2>&1; then rm -rf conftest* echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF #define _ALL_SOURCE 1 EOF else rm -rf conftest* echo "$ac_t""no" 1>&6 fi rm -f conftest* echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 echo "configure:1114: checking for POSIXized ISC" >&5 if test -d /etc/conf/kconfig.d && grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 then echo "$ac_t""yes" 1>&6 ISC=yes # If later tests want to check for ISC. cat >> confdefs.h <<\EOF #define _POSIX_SOURCE 1 EOF if test "$GCC" = yes; then CC="$CC -posix" else CC="$CC -Xp" fi else echo "$ac_t""no" 1>&6 ISC= fi ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6 echo "configure:1136: checking for minix/config.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1146: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 MINIX=yes else echo "$ac_t""no" 1>&6 MINIX= fi if test "$MINIX" = yes; then cat >> confdefs.h <<\EOF #define _POSIX_SOURCE 1 EOF cat >> confdefs.h <<\EOF #define _POSIX_1_SOURCE 2 EOF cat >> confdefs.h <<\EOF #define _MINIX 1 EOF fi # Custom checks. zwarnflags="" # Check whether --with-warn or --without-warn was given. if test "${with_warn+set}" = set; then withval="$with_warn" zwarnflags="-pedantic -Wall -W -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wunreachable-code -Winline -Wpacked -Wno-sign-compare" fi zlangflags="" # Check whether --with-ansi or --without-ansi was given. if test "${with_ansi+set}" = set; then withval="$with_ansi" zlangflags="-ansi -pedantic" fi extra_include="" # Check whether --with-includes or --without-includes was given. if test "${with_includes+set}" = set; then withval="$with_includes" case "x$withval" in x/*|x.*) echo "$ac_t""adding ${withval} to include search path" 1>&6 if test ! -d ${withval}; then echo "$ac_t""Warning: directory ${withval} does not exist" 1>&6 fi extra_include="${extra_include} -I${withval}" ;; *) echo "$ac_t""not adding any includes" 1>&6 ;; esac fi extra_lib_dir="" # Check whether --with-libraries or --without-libraries was given. if test "${with_libraries+set}" = set; then withval="$with_libraries" case "x${withval}" in x/*|x.*) echo "$ac_t""adding ${withval} to library search path" 1>&6 if test ! -d ${withval}; then echo "$ac_t""Warning: directory ${withval} does not exist" 1>&6 fi extra_lib_dir="${extra_lib_dir} -L${withval}" ;; *) echo "$ac_t""not adding any libs" 1>&6 ;; esac fi extra_lib="" # Check whether --with-efence or --without-efence was given. if test "${with_efence+set}" = set; then withval="$with_efence" extra_lib="${extra_lib} -lefence" fi # Check whether --with-mysql or --without-mysql was given. if test "${with_mysql+set}" = set; then withval="$with_mysql" : fi # Check whether --with-pgsql or --without-pgsql was given. if test "${with_pgsql+set}" = set; then withval="$with_pgsql" : fi # Check whether --with-mssql or --without-mssql was given. if test "${with_mssql+set}" = set; then withval="$with_mssql" : fi # Check whether --with-sqlite3 or --without-sqlite3 was given. if test "${with_sqlite3+set}" = set; then withval="$with_sqlite3" : fi # Check whether --with-odbc or --without-odbc was given. if test "${with_odbc+set}" = set; then withval="$with_odbc" : fi extra_define="" # Check whether --enable-poll or --disable-poll was given. if test "${enable_poll+set}" = set; then enableval="$enable_poll" case "$enableval" in yes) echo "Forcing poll() to be enabled" ac_cv_func_poll='yes' ;; no) echo "Forcing poll() to be disabled" ac_cv_func_poll='no' ;; esac fi # Disable poll() on certain platforms. Override by setting ac_cv_func_poll # when running configure. if test -z "$ac_cv_func_poll"; then case "$host" in alpha-dec-osf3.*) # John Kay (jkay@nlanr.net) 19970818 echo "disabling poll for $host..." ac_cv_func_poll='no' ;; *-hp-hpux*.*) # Duane Wessels echo "disabling poll for $host..." ac_cv_func_poll='no' ;; *-linux-*) # Henrik Nordstrom (hno@hem.passagen.se) 19980817 # poll is problematic on Linux. We disable it # by default until Linux gets it right. rev=`uname -r | awk -F. '{printf "%03d%03d",$1,$2}'` if test $rev -lt 002002; then echo "disabling poll for $host < 2.2..." ac_cv_func_poll='no' fi ;; powerpc-ibm-aix4.1.*) # Mike Laster (mlaster@metavillage.com) 19981021 echo "disabling poll for $host..." ac_cv_func_poll='no' ;; *-pc-sco3.2*) # Robert Side # Mon, 18 Jan 1999 17:48:00 GMT echo "disabling poll for $host..." ac_cv_func_poll='no' ;; esac fi # disable parts of the build process # Check whether --enable-bnetd or --disable-bnetd was given. if test "${enable_bnetd+set}" = set; then enableval="$enable_bnetd" : fi # Check whether --enable-d2cs or --disable-d2cs was given. if test "${enable_d2cs+set}" = set; then enableval="$enable_d2cs" : fi # Check whether --enable-d2dbs or --disable-d2dbs was given. if test "${enable_d2dbs+set}" = set; then enableval="$enable_d2dbs" : fi LDFLAGS="${LDFLAGS} ${extra_lib_dir}" LIBS="${LIBS} ${extra_lib}" CFLAGS="${CFLAGS} ${zlangflags} ${zwarnflags}" DEFINES="${DEFINES} ${extra_define}" CPPFLAGS="${CPPFLAGS} ${extra_include}" # This is our invention so we have to substitute it ourselves # autoconf uses DEFS # Checks for compiler quirks. if test $ac_cv_prog_gcc = yes; then echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 echo "configure:1377: checking whether ${CC-cc} needs -traditional" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_pattern="Autoconf.*'x'" cat > conftest.$ac_ext < Autoconf TIOCGETP EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "$ac_pattern" >/dev/null 2>&1; then rm -rf conftest* ac_cv_prog_gcc_traditional=yes else rm -rf conftest* ac_cv_prog_gcc_traditional=no fi rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat > conftest.$ac_ext < Autoconf TCGETA EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "$ac_pattern" >/dev/null 2>&1; then rm -rf conftest* ac_cv_prog_gcc_traditional=yes fi rm -f conftest* fi fi echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 if test $ac_cv_prog_gcc_traditional = yes; then CC="$CC -traditional" fi fi echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6 echo "configure:1426: checking for ${CC-cc} option to accept ANSI C" >&5 if eval "test \"`echo '$''{'am_cv_prog_cc_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else am_cv_prog_cc_stdc=no ac_save_CC="$CC" # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" cat > conftest.$ac_ext < #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main() { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } EOF if { (eval echo configure:1480: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* am_cv_prog_cc_stdc="$ac_arg"; break else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* done CC="$ac_save_CC" fi if test -z "$am_cv_prog_cc_stdc"; then echo "$ac_t""none needed" 1>&6 else echo "$ac_t""$am_cv_prog_cc_stdc" 1>&6 fi case "x$am_cv_prog_cc_stdc" in x|xno) ;; *) CC="$CC $am_cv_prog_cc_stdc" ;; esac echo $ac_n "checking for working const""... $ac_c" 1>&6 echo "configure:1504: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } ; return 0; } EOF if { (eval echo configure:1558: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_const=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_c_const" 1>&6 if test $ac_cv_c_const = no; then cat >> confdefs.h <<\EOF #define const EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 echo "configure:1579: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* done fi echo "$ac_t""$ac_cv_c_inline" 1>&6 case "$ac_cv_c_inline" in inline | yes) ;; no) cat >> confdefs.h <<\EOF #define inline EOF ;; *) cat >> confdefs.h <&6 echo "configure:1622: checking for pow in -lm" >&5 ac_lib_var=`echo m'_'pow | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lm" else echo "$ac_t""no" 1>&6 fi echo $ac_n "checking for compress in -lz""... $ac_c" 1>&6 echo "configure:1663: checking for compress in -lz" >&5 ac_lib_var=`echo z'_'compress | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lz $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lz" else echo "$ac_t""no" 1>&6 fi mysql_include_path="" if test "$with_mysql" = "yes" ; then echo $ac_n "checking for mysql include path""... $ac_c" 1>&6 echo "configure:1706: checking for mysql include path" >&5 mysql_try_includes="/usr/include /usr/include/mysql /usr/local/include /usr/local/include/mysql /usr/local/mysql/include /usr/local/mysql/include/mysql" for i in `echo ${mysql_try_includes}`; do if test -f "${i}/mysql.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" mysql_include_path=${i} break fi done if test -n "$mysql_include_path" ; then echo "$ac_t""found in $mysql_include_path" 1>&6 else { echo "configure: error: not found, please install the MySQL headers" 1>&2; exit 1; } fi fi mysql_lib_path="" if test "$with_mysql" = "yes" ; then echo $ac_n "checking for mysql_init in -lmysqlclient""... $ac_c" 1>&6 echo "configure:1725: checking for mysql_init in -lmysqlclient" >&5 ac_lib_var=`echo mysqlclient'_'mysql_init | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lmysqlclient $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_MYSQL" ; LIBS="${LIBS} -lmysqlclient" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for mysql lib path""... $ac_c" 1>&6 echo "configure:1764: checking for mysql lib path" >&5 mysql_try_libs="/usr/lib /usr/lib/mysql /usr/local/lib /usr/local/lib/mysql /usr/local/mysql/lib /usr/local/mysql/lib/mysql" found="" for i in `echo ${mysql_try_libs}`; do if test -f "${i}/libmysqlclient.so" -o -f "${i}/libmysqlclient.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" echo $ac_n "checking for mysql_close in -lmysqlclient""... $ac_c" 1>&6 echo "configure:1772: checking for mysql_close in -lmysqlclient" >&5 ac_lib_var=`echo mysqlclient'_'mysql_close | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lmysqlclient $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_MYSQL" ; LIBS="${LIBS} -lmysqlclient" ; mysql_lib_path="${i}" else echo "$ac_t""no" 1>&6 LDFLAGS="${save_ldflags}" fi break fi done if test -n "$mysql_lib_path" ; then echo "$ac_t""found in $mysql_lib_path" 1>&6 else { echo "configure: error: not found, please install the MySQL libraries" 1>&2; exit 1; } fi fi fi pgsql_include_path="" if test "$with_pgsql" = "yes" ; then echo $ac_n "checking for pgsql include path""... $ac_c" 1>&6 echo "configure:1828: checking for pgsql include path" >&5 pgsql_try_includes="/usr/include /usr/include/pgsql /usr/local/include /usr/local/include/pgsql /usr/local/pgsql/include" for i in `echo ${pgsql_try_includes}`; do if test -f "${i}/libpq-fe.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" pgsql_include_path=${i} break fi done if test -n "$pgsql_include_path" ; then echo "$ac_t""found in $pgsql_include_path" 1>&6 else { echo "configure: error: not found, please install the PostgreSQL includes" 1>&2; exit 1; } fi fi pgsql_lib_path="" if test "$with_pgsql" = "yes" ; then echo $ac_n "checking for PQsetdbLogin in -lpq""... $ac_c" 1>&6 echo "configure:1847: checking for PQsetdbLogin in -lpq" >&5 ac_lib_var=`echo pq'_'PQsetdbLogin | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lpq $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_PGSQL" ; LIBS="${LIBS} -lpq" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pgsql lib path""... $ac_c" 1>&6 echo "configure:1886: checking for pgsql lib path" >&5 pgsql_try_libs="/usr/lib /usr/lib/pgsql /usr/local/lib /usr/local/lib/pgsql /usr/local/pgsql/lib" for i in `echo ${pgsql_try_libs}`; do if test -f "${i}/libpq.so" -o -f "${i}/libpq.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" echo $ac_n "checking for PQfinish in -lpq""... $ac_c" 1>&6 echo "configure:1893: checking for PQfinish in -lpq" >&5 ac_lib_var=`echo pq'_'PQfinish | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lpq $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_PGSQL" ; LIBS="${LIBS} -lpq" ; pgsql_lib_path="${i}" else echo "$ac_t""no" 1>&6 LDFLAGS="${save_ldflags}" fi break fi done if test -n "$pgsql_lib_path" ; then echo "$ac_t""found in $pgsql_lib_path" 1>&6 else { echo "configure: error: not found, please install the PostgreSQL libraries" 1>&2; exit 1; } fi fi fi mssql_include_path="" if test "$with_mssql" = "yes" ; then echo $ac_n "checking for mssql/FreeTDS include path""... $ac_c" 1>&6 echo "configure:1949: checking for mssql/FreeTDS include path" >&5 mssql_try_includes="/usr/include /usr/include/freetds /usr/local/include /usr/local/include/freetds /usr/local/freetds/include" for i in `echo ${mssql_try_includes}`; do if test -f "${i}/sqlfront.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" mssql_include_path=${i} break fi done if test -n "$mssql_include_path" ; then echo "$ac_t""found in $mssql_include_path" 1>&6 else { echo "configure: error: not found, please install the FreeTDS includes" 1>&2; exit 1; } fi fi mssql_lib_path="" if test "$with_mssql" = "yes" ; then echo $ac_n "checking for dbinit in -lsybdb""... $ac_c" 1>&6 echo "configure:1968: checking for dbinit in -lsybdb" >&5 ac_lib_var=`echo sybdb'_'dbinit | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsybdb $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_MSSQL" ; LIBS="${LIBS} -lsybdb" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for mssql/FreeTDS lib path""... $ac_c" 1>&6 echo "configure:2007: checking for mssql/FreeTDS lib path" >&5 mssql_try_libs="/usr/lib /usr/lib/freetds /usr/local/lib /usr/local/lib/freetds /usr/local/freetds/lib" for i in `echo ${mssql_try_libs}`; do if test -f "${i}/libsybdb.so" -o -f "${i}/libsybdb.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" echo $ac_n "checking for dbclose in -lsybdb""... $ac_c" 1>&6 echo "configure:2014: checking for dbclose in -lsybdb" >&5 ac_lib_var=`echo sybdb'_'dbclose | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsybdb $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_MSSQL" ; LIBS="${LIBS} -lsybdb" ; mssql_lib_path="${i}" else echo "$ac_t""no" 1>&6 LDFLAGS="${save_ldflags}" fi break fi done if test -n "$mssql_lib_path" ; then echo "$ac_t""found in $mssql_lib_path" 1>&6 else { echo "configure: error: not found, please install the FreeTDS libraries" 1>&2; exit 1; } fi fi fi sqlite3_include_path="" if test "$with_sqlite3" = "yes" ; then echo $ac_n "checking for SQLite3 include path""... $ac_c" 1>&6 echo "configure:2070: checking for SQLite3 include path" >&5 sqlite3_try_includes="/usr/include /usr/include/sqlite3 /usr/local/include /usr/local/include/sqlite3 /usr/local/sqlite3/include" for i in `echo ${sqlite3_try_includes}`; do if test -f "${i}/sqlite3.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" sqlite3_include_path=${i} break fi done if test -n "$sqlite3_include_path" ; then echo "$ac_t""found in $sqlite3_include_path" 1>&6 else { echo "configure: error: not found, please install the SQLite3 includes" 1>&2; exit 1; } fi fi sqlite3_lib_path="" if test "$with_sqlite3" = "yes" ; then echo $ac_n "checking for sqlite3_open in -lsqlite3""... $ac_c" 1>&6 echo "configure:2089: checking for sqlite3_open in -lsqlite3" >&5 ac_lib_var=`echo sqlite3'_'sqlite3_open | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsqlite3 $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_SQLITE3" ; LIBS="${LIBS} -lsqlite3" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for SQLite3 lib path""... $ac_c" 1>&6 echo "configure:2128: checking for SQLite3 lib path" >&5 sqlite3_try_libs="/usr/lib /usr/lib/sqlite3 /usr/local/lib /usr/local/lib/sqlite3 /usr/local/sqlite3/lib" for i in `echo ${sqlite3_try_libs}`; do if test -f "${i}/libsqlite3.so" -o -f "${i}/libsqlite3.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" echo $ac_n "checking for sqlite3_close in -lsqlite3""... $ac_c" 1>&6 echo "configure:2135: checking for sqlite3_close in -lsqlite3" >&5 ac_lib_var=`echo sqlite3'_'sqlite3_close | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsqlite3 $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_SQLITE3" ; LIBS="${LIBS} -lsqlite3" ; sqlite3_lib_path="${i}" else echo "$ac_t""no" 1>&6 LDFLAGS="${save_ldflags}" fi break fi done if test -n "$sqlite3_lib_path" ; then echo "$ac_t""found in $sqlite3_lib_path" 1>&6 else { echo "configure: error: not found, please install the SQLite3 libraries" 1>&2; exit 1; } fi fi fi odbc_include_path="" if test "$with_odbc" = "yes" ; then echo $ac_n "checking for odbc include path""... $ac_c" 1>&6 echo "configure:2191: checking for odbc include path" >&5 odbc_try_includes="/usr/include /usr/include/odbc /usr/local/include /usr/local/include/odbc /usr/local/odbc/include" for i in `echo ${odbc_try_includes}`; do if test -f "${i}/sqlext.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" odbc_include_path=${i} break fi done if test -n "$odbc_include_path" ; then echo "$ac_t""found in $odbc_include_path" 1>&6 else { echo "configure: error: not found, please install the odbc includes" 1>&2; exit 1; } fi fi odbc_lib_path="" if test "$with_odbc" = "yes" ; then echo $ac_n "checking for SQLConnect in -lodbc""... $ac_c" 1>&6 echo "configure:2210: checking for SQLConnect in -lodbc" >&5 ac_lib_var=`echo odbc'_'SQLConnect | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lodbc $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_ODBC" ; LIBS="${LIBS} -lodbc" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for odbc lib path""... $ac_c" 1>&6 echo "configure:2249: checking for odbc lib path" >&5 odbc_try_libs="/usr/lib /usr/lib/odbc /usr/local/lib /usr/local/lib/odbc /usr/local/odbc/lib" for i in `echo ${odbc_try_libs}`; do if test -f "${i}/libodbc.so" -o -f "${i}/libodbc.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" echo $ac_n "checking for SQLDisconnect in -lodbc""... $ac_c" 1>&6 echo "configure:2256: checking for SQLDisconnect in -lodbc" >&5 ac_lib_var=`echo odbc'_'SQLDisconnect | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lodbc $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 DEFINES="${DEFINES} -DWITH_SQL_ODBC" ; LIBS="${LIBS} -lodbc" ; odbc_lib_path="${i}" else echo "$ac_t""no" 1>&6 LDFLAGS="${save_ldflags}" fi break fi done if test -n "$odbc_lib_path" ; then echo "$ac_t""found in $odbc_lib_path" 1>&6 else { echo "configure: error: not found, please install the odbc libraries" 1>&2; exit 1; } fi fi fi echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 echo "configure:2310: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lnsl" else echo "$ac_t""no" 1>&6 fi echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 echo "configure:2350: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lsocket" else echo "$ac_t""no" 1>&6 fi echo $ac_n "checking for inet_aton in -lresolv""... $ac_c" 1>&6 echo "configure:2390: checking for inet_aton in -lresolv" >&5 ac_lib_var=`echo resolv'_'inet_aton | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lresolv $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lresolv" else echo "$ac_t""no" 1>&6 fi echo $ac_n "checking for __inet_aton in -lbind""... $ac_c" 1>&6 echo "configure:2430: checking for __inet_aton in -lbind" >&5 ac_lib_var=`echo bind'_'__inet_aton | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lbind $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lbind" else echo "$ac_t""no" 1>&6 fi case "$host" in *-beos*) if test "$ac_cv_lib_bind___inet_aton" = "yes"; then echo "Forcing inet_aton() and inet_ntoa() to be enabled" ac_cv_func_inet_aton='yes' ac_cv_func_inet_ntoa='yes' fi ;; esac echo $ac_n "checking for _libwsock32_a_iname in -lwsock32""... $ac_c" 1>&6 echo "configure:2479: checking for _libwsock32_a_iname in -lwsock32" >&5 ac_lib_var=`echo wsock32'_'_libwsock32_a_iname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lwsock32 $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lwsock32" else echo "$ac_t""no" 1>&6 fi # Checks for header files. ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 echo "configure:2525: checking for $ac_hdr that defines DIR" >&5 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_hdr> int main() { DIR *dirp = 0; ; return 0; } EOF if { (eval echo configure:2538: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 echo "configure:2563: checking for opendir in -ldir" >&5 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldir $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -ldir" else echo "$ac_t""no" 1>&6 fi else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 echo "configure:2604: checking for opendir in -lx" >&5 ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lx" else echo "$ac_t""no" 1>&6 fi fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 echo "configure:2646: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #include #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:2659: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* ac_cv_header_stdc=yes else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "memchr" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "free" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') #define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF if { (eval echo configure:2726: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_header_stdc=no fi rm -fr conftest* fi fi fi echo "$ac_t""$ac_cv_header_stdc" 1>&6 if test $ac_cv_header_stdc = yes; then cat >> confdefs.h <<\EOF #define STDC_HEADERS 1 EOF fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 echo "configure:2750: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #include int main() { struct tm *tp; ; return 0; } EOF if { (eval echo configure:2764: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_time=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_header_time" 1>&6 if test $ac_cv_header_time = yes; then cat >> confdefs.h <<\EOF #define TIME_WITH_SYS_TIME 1 EOF fi echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 echo "configure:2785: checking whether stat file-mode macros are broken" >&5 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #if defined(S_ISBLK) && defined(S_IFDIR) # if S_ISBLK (S_IFDIR) You lose. # endif #endif #if defined(S_ISBLK) && defined(S_IFCHR) # if S_ISBLK (S_IFCHR) You lose. # endif #endif #if defined(S_ISLNK) && defined(S_IFREG) # if S_ISLNK (S_IFREG) You lose. # endif #endif #if defined(S_ISSOCK) && defined(S_IFREG) # if S_ISSOCK (S_IFREG) You lose. # endif #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "You lose" >/dev/null 2>&1; then rm -rf conftest* ac_cv_header_stat_broken=yes else rm -rf conftest* ac_cv_header_stat_broken=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_header_stat_broken" 1>&6 if test $ac_cv_header_stat_broken = yes; then cat >> confdefs.h <<\EOF #define STAT_MACROS_BROKEN 1 EOF fi for ac_hdr in \ fcntl.h \ sys/time.h \ time.h \ sys/select.h \ string.h \ strings.h \ unistd.h \ stdarg.h \ varargs.h \ malloc.h \ sys/utsname.h \ sys/timeb.h \ sys/socket.h \ sys/param.h \ netinet/in.h \ arpa/inet.h \ netdb.h \ termios.h \ stddef.h \ memory.h \ sys/types.h \ sys/wait.h \ sys/ioctl.h \ stdint.h \ sys/file.h \ limits.h \ poll.h \ sys/poll.h \ stropts.h \ sys/stropts.h \ sys/stat.h \ pwd.h \ grp.h \ dir.h \ direct.h \ sys/mman.h \ sys/event.h \ sys/epoll.h \ sys/resource.h \ assert.h \ sqlite3.h \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:2886: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:2896: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done # Checks for typedefs and structures echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 echo "configure:2925: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF if { (eval echo configure:2938: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_struct_tm=sys/time.h fi rm -f conftest* fi echo "$ac_t""$ac_cv_struct_tm" 1>&6 if test $ac_cv_struct_tm = sys/time.h; then cat >> confdefs.h <<\EOF #define TM_IN_SYS_TIME 1 EOF fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 echo "configure:2959: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_pid_t=yes else rm -rf conftest* ac_cv_type_pid_t=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_pid_t" 1>&6 if test $ac_cv_type_pid_t = no; then cat >> confdefs.h <<\EOF #define pid_t int EOF fi echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 echo "configure:2992: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #ifdef signal #undef signal #endif #ifdef __cplusplus extern "C" void (*signal (int, void (*)(int)))(int); #else void (*signal ()) (); #endif int main() { int i; ; return 0; } EOF if { (eval echo configure:3014: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_type_signal=int fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_signal" 1>&6 cat >> confdefs.h <&6 echo "configure:3033: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_off_t=yes else rm -rf conftest* ac_cv_type_off_t=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_off_t" 1>&6 if test $ac_cv_type_off_t = no; then cat >> confdefs.h <<\EOF #define off_t long EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 echo "configure:3066: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_size_t=yes else rm -rf conftest* ac_cv_type_size_t=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_size_t" 1>&6 if test $ac_cv_type_size_t = no; then cat >> confdefs.h <<\EOF #define size_t unsigned EOF fi echo $ac_n "checking size of unsigned char""... $ac_c" 1>&6 echo "configure:3099: checking size of unsigned char" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_char'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_unsigned_char=1 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(unsigned char)); exit(0); } EOF if { (eval echo configure:3118: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_unsigned_char=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_unsigned_char=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_unsigned_char" 1>&6 cat >> confdefs.h <&6 echo "configure:3138: checking size of unsigned short" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_unsigned_short=2 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(unsigned short)); exit(0); } EOF if { (eval echo configure:3157: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_unsigned_short=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_unsigned_short=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_unsigned_short" 1>&6 cat >> confdefs.h <&6 echo "configure:3177: checking size of unsigned int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_unsigned_int=4 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(unsigned int)); exit(0); } EOF if { (eval echo configure:3196: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_unsigned_int=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_unsigned_int=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_unsigned_int" 1>&6 cat >> confdefs.h <&6 echo "configure:3216: checking size of unsigned long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_unsigned_long=4 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(unsigned long)); exit(0); } EOF if { (eval echo configure:3235: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_unsigned_long=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_unsigned_long=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_unsigned_long" 1>&6 cat >> confdefs.h <&6 echo "configure:3255: checking size of unsigned long long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_unsigned_long_long=0 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(unsigned long long)); exit(0); } EOF if { (eval echo configure:3274: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_unsigned_long_long=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_unsigned_long_long=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_unsigned_long_long" 1>&6 cat >> confdefs.h <&6 echo "configure:3294: checking size of signed char" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_signed_char'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_signed_char=1 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(signed char)); exit(0); } EOF if { (eval echo configure:3313: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_signed_char=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_signed_char=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_signed_char" 1>&6 cat >> confdefs.h <&6 echo "configure:3333: checking size of signed short" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_signed_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_signed_short=2 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(signed short)); exit(0); } EOF if { (eval echo configure:3352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_signed_short=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_signed_short=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_signed_short" 1>&6 cat >> confdefs.h <&6 echo "configure:3372: checking size of signed int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_signed_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_signed_int=4 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(signed int)); exit(0); } EOF if { (eval echo configure:3391: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_signed_int=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_signed_int=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_signed_int" 1>&6 cat >> confdefs.h <&6 echo "configure:3411: checking size of signed long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_signed_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_signed_long=4 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(signed long)); exit(0); } EOF if { (eval echo configure:3430: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_signed_long=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_signed_long=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_signed_long" 1>&6 cat >> confdefs.h <&6 echo "configure:3450: checking size of signed long long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_signed_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_signed_long_long=0 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(signed long long)); exit(0); } EOF if { (eval echo configure:3469: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_signed_long_long=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_signed_long_long=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_signed_long_long" 1>&6 cat >> confdefs.h <&6 echo "configure:3494: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:3504: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done for ac_func in getpagesize do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:3533: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:3561: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done echo $ac_n "checking for working mmap""... $ac_c" 1>&6 echo "configure:3586: checking for working mmap" >&5 if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_func_mmap_fixed_mapped=no else cat > conftest.$ac_ext < #include #include /* This mess was copied from the GNU getpagesize.h. */ #ifndef HAVE_GETPAGESIZE # ifdef HAVE_UNISTD_H # include # endif /* Assume that all systems that can run configure have sys/param.h. */ # ifndef HAVE_SYS_PARAM_H # define HAVE_SYS_PARAM_H 1 # endif # ifdef _SC_PAGESIZE # define getpagesize() sysconf(_SC_PAGESIZE) # else /* no _SC_PAGESIZE */ # ifdef HAVE_SYS_PARAM_H # include # ifdef EXEC_PAGESIZE # define getpagesize() EXEC_PAGESIZE # else /* no EXEC_PAGESIZE */ # ifdef NBPG # define getpagesize() NBPG * CLSIZE # ifndef CLSIZE # define CLSIZE 1 # endif /* no CLSIZE */ # else /* no NBPG */ # ifdef NBPC # define getpagesize() NBPC # else /* no NBPC */ # ifdef PAGESIZE # define getpagesize() PAGESIZE # endif /* PAGESIZE */ # endif /* no NBPC */ # endif /* no NBPG */ # endif /* no EXEC_PAGESIZE */ # else /* no HAVE_SYS_PARAM_H */ # define getpagesize() 8192 /* punt totally */ # endif /* no HAVE_SYS_PARAM_H */ # endif /* no _SC_PAGESIZE */ #endif /* no HAVE_GETPAGESIZE */ #ifdef __cplusplus extern "C" { void *malloc(unsigned); } #else char *malloc(); #endif int main() { char *data, *data2, *data3; int i, pagesize; int fd; pagesize = getpagesize(); /* * First, make a file with some known garbage in it. */ data = malloc(pagesize); if (!data) exit(1); for (i = 0; i < pagesize; ++i) *(data + i) = rand(); umask(0); fd = creat("conftestmmap", 0600); if (fd < 0) exit(1); if (write(fd, data, pagesize) != pagesize) exit(1); close(fd); /* * Next, try to mmap the file at a fixed address which * already has something else allocated at it. If we can, * also make sure that we see the same garbage. */ fd = open("conftestmmap", O_RDWR); if (fd < 0) exit(1); data2 = malloc(2 * pagesize); if (!data2) exit(1); data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)) exit(1); for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data2 + i)) exit(1); /* * Finally, make sure that changes to the mapped area * do not percolate back to the file as seen by read(). * (This is a bug on some variants of i386 svr4.0.) */ for (i = 0; i < pagesize; ++i) *(data2 + i) = *(data2 + i) + 1; data3 = malloc(pagesize); if (!data3) exit(1); if (read(fd, data3, pagesize) != pagesize) exit(1); for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data3 + i)) exit(1); close(fd); unlink("conftestmmap"); exit(0); } EOF if { (eval echo configure:3734: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_mmap_fixed_mapped=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_func_mmap_fixed_mapped=no fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 if test $ac_cv_func_mmap_fixed_mapped = yes; then cat >> confdefs.h <<\EOF #define HAVE_MMAP 1 EOF fi echo $ac_n "checking for strftime""... $ac_c" 1>&6 echo "configure:3757: checking for strftime" >&5 if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char strftime(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_strftime) || defined (__stub___strftime) choke me #else strftime(); #endif ; return 0; } EOF if { (eval echo configure:3785: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strftime=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_strftime=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF #define HAVE_STRFTIME 1 EOF else echo "$ac_t""no" 1>&6 # strftime is in -lintl on SCO UNIX. echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6 echo "configure:3807: checking for strftime in -lintl" >&5 ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lintl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF #define HAVE_STRFTIME 1 EOF LIBS="-lintl $LIBS" else echo "$ac_t""no" 1>&6 fi fi echo $ac_n "checking for vprintf""... $ac_c" 1>&6 echo "configure:3853: checking for vprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char vprintf(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_vprintf) || defined (__stub___vprintf) choke me #else vprintf(); #endif ; return 0; } EOF if { (eval echo configure:3881: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_vprintf=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF #define HAVE_VPRINTF 1 EOF else echo "$ac_t""no" 1>&6 fi if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 echo "configure:3905: checking for _doprnt" >&5 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char _doprnt(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub__doprnt) || defined (__stub____doprnt) choke me #else _doprnt(); #endif ; return 0; } EOF if { (eval echo configure:3933: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func__doprnt=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF #define HAVE_DOPRNT 1 EOF else echo "$ac_t""no" 1>&6 fi fi echo $ac_n "checking whether closedir returns void""... $ac_c" 1>&6 echo "configure:3958: checking whether closedir returns void" >&5 if eval "test \"`echo '$''{'ac_cv_func_closedir_void'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_func_closedir_void=yes else cat > conftest.$ac_ext < #include <$ac_header_dirent> int closedir(); main() { exit(closedir(opendir(".")) != 0); } EOF if { (eval echo configure:3972: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_closedir_void=no else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_func_closedir_void=yes fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_func_closedir_void" 1>&6 if test $ac_cv_func_closedir_void = yes; then cat >> confdefs.h <<\EOF #define CLOSEDIR_VOID 1 EOF fi for ac_func in mkdir _mkdir do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:3997: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:4025: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done echo $ac_n "checking whether mkdir takes one argument""... $ac_c" 1>&6 echo "configure:4050: checking whether mkdir takes one argument" >&5 if eval "test \"`echo '$''{'ac_cv_mkdir_takes_one_arg'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_DIR_H # include #endif #ifdef HAVE_DIRECT_H # include #endif #ifndef HAVE_MKDIR # ifdef HAVE__MKDIR # define mkdir _mkdir # endif #endif int main() { mkdir("."); ; return 0; } EOF if { (eval echo configure:4080: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_mkdir_takes_one_arg=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_mkdir_takes_one_arg=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_mkdir_takes_one_arg" 1>&6 if test x"$ac_cv_mkdir_takes_one_arg" = xyes; then cat >> confdefs.h <<\EOF #define MKDIR_TAKES_ONE_ARG 1 EOF fi for ac_func in gethostname gettimeofday select socket strdup strtoul strerror inet_aton inet_ntoa uname recv send recvfrom sendto uname fork getpid sigaction sigprocmask sigaddset setpgid setpgrp ftime strcasecmp strncasecmp stricmp strnicmp chdir difftime strchr strrchr index rindex memcpy memset memmove bcopy wait waitpid pipe getenv ioctl setsid mktime poll gethostbyname getservbyname getlogin pow getpwnam getgrnam getuid getgid setuid setgid mkdir _mkdir strsep getopt kqueue setitimer epoll_create getrlimit vsnprintf _vsnprintf snprintf _snprintf do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:4103: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:4131: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done if test X$ac_cv_func_setpgrp = X"yes"; then echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6 echo "configure:4157: checking whether setpgrp takes no argument" >&5 if eval "test \"`echo '$''{'ac_cv_func_setpgrp_void'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then { echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < #endif /* * If this system has a BSD-style setpgrp, which takes arguments, exit * successfully. */ main() { if (setpgrp(1,1) == -1) exit(0); else exit(1); } EOF if { (eval echo configure:4185: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_setpgrp_void=no else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_func_setpgrp_void=yes fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_func_setpgrp_void" 1>&6 if test $ac_cv_func_setpgrp_void = yes; then cat >> confdefs.h <<\EOF #define SETPGRP_VOID 1 EOF fi fi if test X"${am_cv_prog_cc_stdc}" = X"no"; then COMPILEANSI1='${PREPROCESS} $< | sed '"'"'s/^# *\([0-9][0-9]*\) *\([^ ]*[a-z][^ ]*\) *.*$$/#line \1 \2/'"'"' | ${SRC_ACDIR}/ansi2knr > ${SRC_SRCDIR}/.ansi2knr_tmp.c' COMPILEANSI2='${COMPILE} ${SRC_SRCDIR}/.ansi2knr_tmp.c -o $@' COMPILEANSI3='@${RMF} ${SRC_SRCDIR}/.ansi2knr_tmp.c' ANSI2KNR_TMP='${SRC_SRCDIR}/.ansi2knr_tmp.c' ANSI2KNR_DEP='${SRC_ACDIR}/ansi2knr' else COMPILEANSI1='${COMPILE} $< -o $@' COMPILEANSI2='@:' COMPILEANSI3='@:' ANSI2KNR_TMP='' ANSI2KNR_DEP='' fi trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs. It is not useful on other systems. # If it contains results you don't want to keep, you may remove or edit it. # # By default, configure uses ./config.cache as the cache file, # creating it if it does not exist already. You can give configure # the --cache-file=FILE option to use a different cache file; that is # what configure does when it calls configure scripts in # subdirectories, so they share the cache. # Giving --cache-file=/dev/null disables caching, for debugging configure. # config.status only pays attention to the cache file if you give it the # --recheck option to rerun configure. # EOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote substitution # turns \\\\ into \\, and sed turns \\ into \). sed -n \ -e "s/'/'\\\\''/g" \ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ;; esac >> confcache if cmp -s $cache_file confcache; then : else if test -w $cache_file; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Any assignment to VPATH causes Sun make to only execute # the first set of double-colon rules, so remove it if not needed. # If there is a colon in the path, we need to keep it. if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' fi trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 DEFS=-DHAVE_CONFIG_H # Without the "./", some shells look in PATH for config.status. : ${CONFIG_STATUS=./config.status} echo creating $CONFIG_STATUS rm -f $CONFIG_STATUS cat > $CONFIG_STATUS </dev/null | sed 1q`: # # $0 $ac_configure_args # # Compiler output produced by configure, useful for debugging # configure, is in ./config.log if it exists. ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" for ac_option do case "\$ac_option" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) echo "$CONFIG_STATUS generated by autoconf version 2.13" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; *) echo "\$ac_cs_usage"; exit 1 ;; esac done ac_given_srcdir=$srcdir ac_given_INSTALL="$INSTALL" trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF $ac_vpsub $extrasub s%@SHELL@%$SHELL%g s%@CFLAGS@%$CFLAGS%g s%@CPPFLAGS@%$CPPFLAGS%g s%@CXXFLAGS@%$CXXFLAGS%g s%@FFLAGS@%$FFLAGS%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%$LDFLAGS%g s%@LIBS@%$LIBS%g s%@exec_prefix@%$exec_prefix%g s%@prefix@%$prefix%g s%@program_transform_name@%$program_transform_name%g s%@bindir@%$bindir%g s%@sbindir@%$sbindir%g s%@libexecdir@%$libexecdir%g s%@datadir@%$datadir%g s%@sysconfdir@%$sysconfdir%g s%@sharedstatedir@%$sharedstatedir%g s%@localstatedir@%$localstatedir%g s%@libdir@%$libdir%g s%@includedir@%$includedir%g s%@oldincludedir@%$oldincludedir%g s%@infodir@%$infodir%g s%@mandir@%$mandir%g s%@host@%$host%g s%@host_alias@%$host_alias%g s%@host_cpu@%$host_cpu%g s%@host_vendor@%$host_vendor%g s%@host_os@%$host_os%g s%@target@%$target%g s%@target_alias@%$target_alias%g s%@target_cpu@%$target_cpu%g s%@target_vendor@%$target_vendor%g s%@target_os@%$target_os%g s%@build@%$build%g s%@build_alias@%$build_alias%g s%@build_cpu@%$build_cpu%g s%@build_vendor@%$build_vendor%g s%@build_os@%$build_os%g s%@CC@%$CC%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g s%@INSTALL_DATA@%$INSTALL_DATA%g s%@CPP@%$CPP%g s%@DEFINES@%$DEFINES%g s%@enable_bnetd@%$enable_bnetd%g s%@enable_d2cs@%$enable_d2cs%g s%@enable_d2dbs@%$enable_d2dbs%g s%@COMPILEANSI1@%$COMPILEANSI1%g s%@COMPILEANSI2@%$COMPILEANSI2%g s%@COMPILEANSI3@%$COMPILEANSI3%g s%@ANSI2KNR_TMP@%$ANSI2KNR_TMP%g s%@ANSI2KNR_DEP@%$ANSI2KNR_DEP%g CEOF EOF cat >> $CONFIG_STATUS <<\EOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. ac_file=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_cmds # Line after last line for current file. ac_more_lines=: ac_sed_cmds="" while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file else sed "${ac_end}q" conftest.subs > conftest.s$ac_file fi if test ! -s conftest.s$ac_file; then ac_more_lines=false rm -f conftest.s$ac_file else if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f conftest.s$ac_file" else ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" fi ac_file=`expr $ac_file + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_cmds` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" # A "../" for each directory in $ac_dir_suffix. ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` else ac_dir_suffix= ac_dots= fi case "$ac_given_srcdir" in .) srcdir=. if test -z "$ac_dots"; then top_srcdir=. else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; *) # Relative path. srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" top_srcdir="$ac_dots$ac_given_srcdir" ;; esac case "$ac_given_INSTALL" in [/$]*) INSTALL="$ac_given_INSTALL" ;; *) INSTALL="$ac_dots$ac_given_INSTALL" ;; esac echo creating "$ac_file" rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." case "$ac_file" in *Makefile*) ac_comsub="1i\\ # $configure_input" ;; *) ac_comsub= ;; esac ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` sed -e "$ac_comsub s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g s%@INSTALL@%$INSTALL%g " $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done rm -f conftest.s* # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' ac_dC='\3' ac_dD='%g' # ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='\([ ]\)%\1#\2define\3' ac_uC=' ' ac_uD='\4%g' # ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_eB='$%\1#\2define\3' ac_eC=' ' ac_eD='%g' if test "${CONFIG_HEADERS+set}" != set; then EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF fi for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac echo creating $ac_file rm -f conftest.frag conftest.in conftest.out ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` cat $ac_file_inputs > conftest.in EOF # Transform confdefs.h into a sed script conftest.vals that substitutes # the proper values into config.h.in to produce config.h. And first: # Protect against being on the right side of a sed subst in config.status. # Protect against being in an unquoted here document in config.status. rm -f conftest.vals cat > conftest.hdr <<\EOF s/[\\&%]/\\&/g s%[\\$`]%\\&%g s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp s%ac_d%ac_u%gp s%ac_u%ac_e%gp EOF sed -n -f conftest.hdr confdefs.h > conftest.vals rm -f conftest.hdr # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >> conftest.vals <<\EOF s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% EOF # Break up conftest.vals because some shells have a limit on # the size of here documents, and old seds have small limits too. rm -f conftest.tail while : do ac_lines=`grep -c . conftest.vals` # grep -c gives empty output for an empty file on some AIX systems. if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi # Write a limited-size here document to conftest.frag. echo ' cat > conftest.frag <> $CONFIG_STATUS sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS echo 'CEOF sed -f conftest.frag conftest.in > conftest.out rm -f conftest.in mv conftest.out conftest.in ' >> $CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail rm -f conftest.vals mv conftest.tail conftest.vals done rm -f conftest.vals cat >> $CONFIG_STATUS <<\EOF rm -f conftest.frag conftest.h echo "/* $ac_file. Generated automatically by configure. */" > conftest.h cat conftest.in >> conftest.h rm -f conftest.in if cmp -s $ac_file conftest.h 2>/dev/null; then echo "$ac_file is unchanged" rm -f conftest.h else # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" fi rm -f $ac_file mv conftest.h $ac_file fi fi; done EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF exit 0 EOF chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 pvpgn-1.8.5/src/d2dbs/0000755000175000017500000000000011151345372013430 5ustar aaronaaronpvpgn-1.8.5/src/d2dbs/dbserver.c0000644000175000017500000003510411151345317015412 0ustar aaronaaron/* * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memset.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #include "compat/psock.h" #include "common/network.h" #include "dbserver.h" #include "charlock.h" #include "d2ladder.h" #include "dbspacket.h" #include "prefs.h" #include "handle_signal.h" #include "common/list.h" #include "common/eventlog.h" #ifdef WIN32 # include /* for kbhit() and getch() */ #endif #include "common/addr.h" #include "common/xalloc.h" #include "common/setup_after.h" static int dbs_packet_gs_id = 0; static t_preset_d2gsid *preset_d2gsid_head = NULL; t_list * dbs_server_connection_list = NULL; int dbs_server_listen_socket=-1; extern int g_ServiceStatus; /* dbs_server_main * The module's driver function -- we just call other functions and * interpret their results. */ static int dbs_handle_timed_events(void); static void dbs_on_exit(void); int dbs_server_init(void); void dbs_server_loop(int ListeningSocket); int dbs_server_setup_fdsets(fd_set * pReadFDs, fd_set * pWriteFDs, fd_set * pExceptFDs, int ListeningSocket ) ; BOOL dbs_server_read_data(t_d2dbs_connection* conn) ; BOOL dbs_server_write_data(t_d2dbs_connection* conn) ; int dbs_server_list_add_socket(int sd, unsigned int ipaddr); static int setsockopt_keepalive(int sock); static unsigned int get_preset_d2gsid(unsigned int ipaddr); int dbs_server_main(void) { eventlog(eventlog_level_info,__FUNCTION__,"establishing the listener..."); dbs_server_listen_socket = dbs_server_init(); if (dbs_server_listen_socket<0) { eventlog(eventlog_level_error,__FUNCTION__,"dbs_server_init error "); return 3; } eventlog(eventlog_level_info,__FUNCTION__,"waiting for connections..."); dbs_server_loop(dbs_server_listen_socket); dbs_on_exit(); return 0; } /* dbs_server_init * Sets up a listener on the given interface and port, returning the * listening socket if successful; if not, returns -1. */ /* FIXME: No it doesn't! pcAddress is not ever referenced in this * function. * CreepLord: Fixed much better way (will accept dns hostnames) */ int dbs_server_init(void) { int sd; struct sockaddr_in sinInterface; int val; t_addr * servaddr; dbs_server_connection_list=list_create(); if (d2dbs_d2ladder_init()==-1) { eventlog(eventlog_level_error,__FUNCTION__,"d2ladder_init() failed"); return -1; } if (cl_init(DEFAULT_HASHTBL_LEN, DEFAULT_GS_MAX)==-1) { eventlog(eventlog_level_error,__FUNCTION__,"cl_init() failed"); return -1; } if (psock_init()<0) { eventlog(eventlog_level_error,__FUNCTION__,"psock_init() failed"); return -1; } sd = psock_socket(PSOCK_PF_INET, PSOCK_SOCK_STREAM, PSOCK_IPPROTO_TCP); if (sd==-1) { eventlog(eventlog_level_error,__FUNCTION__,"psock_socket() failed : %s",pstrerror(psock_errno())); return -1; } val = 1; if (psock_setsockopt(sd, PSOCK_SOL_SOCKET, PSOCK_SO_REUSEADDR, &val, sizeof(val)) < 0) { eventlog(eventlog_level_error,__FUNCTION__,"psock_setsockopt() failed : %s",pstrerror(psock_errno())); } if (!(servaddr=addr_create_str(d2dbs_prefs_get_servaddrs(),INADDR_ANY,DEFAULT_LISTEN_PORT))) { eventlog(eventlog_level_error,__FUNCTION__,"could not get servaddr"); return -1; } sinInterface.sin_family = PSOCK_AF_INET; sinInterface.sin_addr.s_addr = htonl(addr_get_ip(servaddr)); sinInterface.sin_port = htons(addr_get_port(servaddr)); if (psock_bind(sd, (struct sockaddr*)&sinInterface, (psock_t_socklen)sizeof(struct sockaddr_in)) < 0) { eventlog(eventlog_level_error,__FUNCTION__,"psock_bind() failed : %s",pstrerror(psock_errno())); return -1; } if (psock_listen(sd, LISTEN_QUEUE) < 0) { eventlog(eventlog_level_error,__FUNCTION__,"psock_listen() failed : %s",pstrerror(psock_errno())); return -1; } addr_destroy(servaddr); return sd; } /* dbs_server_setup_fdsets * Set up the three FD sets used with select() with the sockets in the * connection list. Also add one for the listener socket, if we have * one. */ int dbs_server_setup_fdsets(t_psock_fd_set * pReadFDs, t_psock_fd_set * pWriteFDs, t_psock_fd_set * pExceptFDs, int lsocket) { t_elem const * elem; t_d2dbs_connection* it; int highest_fd; PSOCK_FD_ZERO(pReadFDs); PSOCK_FD_ZERO(pWriteFDs); PSOCK_FD_ZERO(pExceptFDs); /* FIXME: don't check these... remove this code */ /* Add the listener socket to the read and except FD sets, if there is one. */ if (lsocket >= 0) { PSOCK_FD_SET(lsocket, pReadFDs); PSOCK_FD_SET(lsocket, pExceptFDs); } highest_fd=lsocket; LIST_TRAVERSE_CONST(dbs_server_connection_list,elem) { if (!(it=elem_get_data(elem))) continue; if (it->nCharsInReadBuffer < (kBufferSize-kMaxPacketLength)) { /* There's space in the read buffer, so pay attention to incoming data. */ PSOCK_FD_SET(it->sd, pReadFDs); } if (it->nCharsInWriteBuffer > 0) { PSOCK_FD_SET(it->sd, pWriteFDs); } PSOCK_FD_SET(it->sd, pExceptFDs); if (highest_fd < it->sd) highest_fd=it->sd; } return highest_fd; } /* dbs_server_read_data * Data came in on a client socket, so read it into the buffer. Returns * false on failure, or when the client closes its half of the * connection. (EAGAIN doesn't count as a failure.) */ BOOL dbs_server_read_data(t_d2dbs_connection* conn) { int nBytes; nBytes = net_recv(conn->sd, conn->ReadBuf + conn->nCharsInReadBuffer, kBufferSize - conn->nCharsInReadBuffer); if (nBytes < 0) return FALSE; conn->nCharsInReadBuffer += nBytes; return TRUE; } /* dbs_server_write_data * The connection is writable, so send any pending data. Returns * false on failure. (EAGAIN doesn't count as a failure.) */ BOOL dbs_server_write_data(t_d2dbs_connection* conn) { int nBytes ; nBytes = net_send(conn->sd, conn->WriteBuf, conn->nCharsInWriteBuffer > kMaxPacketLength ? kMaxPacketLength : conn->nCharsInWriteBuffer); if (nBytes < 0) return FALSE; conn->nCharsInWriteBuffer -= nBytes; if (conn->nCharsInWriteBuffer) memmove(conn->WriteBuf, conn->WriteBuf + nBytes, conn->nCharsInWriteBuffer); return TRUE; } int dbs_server_list_add_socket(int sd, unsigned int ipaddr) { t_d2dbs_connection *it; struct in_addr in; it=xmalloc(sizeof(t_d2dbs_connection)); memset(it, 0, sizeof(t_d2dbs_connection)); it->sd=sd; it->ipaddr=ipaddr; it->major=0; it->minor=0; it->type=0; it->stats=0; it->verified=0; it->serverid=get_preset_d2gsid(ipaddr); it->last_active=time(NULL); it->nCharsInReadBuffer=0; it->nCharsInWriteBuffer=0; list_append_data(dbs_server_connection_list,it); in.s_addr = htonl(ipaddr); strncpy(it->serverip, inet_ntoa(in), sizeof(it->serverip)-1); return 1; } static int dbs_handle_timed_events(void) { static time_t prev_ladder_save_time=0; static time_t prev_keepalive_save_time=0; static time_t prev_timeout_checktime=0; time_t now; now=time(NULL); if (now-prev_ladder_save_time>(signed)prefs_get_laddersave_interval()) { d2ladder_saveladder(); prev_ladder_save_time=now; } if (now-prev_keepalive_save_time>(signed)prefs_get_keepalive_interval()) { dbs_keepalive(); prev_keepalive_save_time=now; } if (now-prev_timeout_checktime>(signed)d2dbs_prefs_get_timeout_checkinterval()) { dbs_check_timeout(); prev_timeout_checktime=now; } return 0; } void dbs_server_loop(int lsocket) { struct sockaddr_in sinRemote; int sd ; fd_set ReadFDs, WriteFDs, ExceptFDs; t_elem * elem; t_d2dbs_connection* it; BOOL bOK ; const char* pcErrorType ; struct timeval tv; int highest_fd; psock_t_socklen nAddrSize = sizeof(sinRemote); while (1) { #ifdef WIN32 if (g_ServiceStatus<0 && kbhit() && getch()=='q') d2dbs_signal_quit_wrapper(); if (g_ServiceStatus == 0) d2dbs_signal_quit_wrapper(); while (g_ServiceStatus == 2) Sleep(1000); #endif if (d2dbs_handle_signal()<0) break; dbs_handle_timed_events(); highest_fd=dbs_server_setup_fdsets(&ReadFDs, &WriteFDs, &ExceptFDs, lsocket); tv.tv_sec = 0; tv.tv_usec = SELECT_TIME_OUT; switch (psock_select(highest_fd+1, &ReadFDs, &WriteFDs, &ExceptFDs, &tv) ) { case -1: eventlog(eventlog_level_error,__FUNCTION__,"psock_select() failed : %s",pstrerror(psock_errno())); continue; case 0: continue; default: break; } if (PSOCK_FD_ISSET(lsocket, &ReadFDs)) { sd = psock_accept(lsocket, (struct sockaddr*)&sinRemote, &nAddrSize); if (sd == -1) { eventlog(eventlog_level_error,__FUNCTION__,"psock_accept() failed : %s",pstrerror(psock_errno())); return; } eventlog(eventlog_level_info,__FUNCTION__,"accepted connection from %s:%d , socket %d .", inet_ntoa(sinRemote.sin_addr) , ntohs(sinRemote.sin_port), sd); eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"accepted connection from %s:%d , socket %d .", inet_ntoa(sinRemote.sin_addr) , ntohs(sinRemote.sin_port), sd); setsockopt_keepalive(sd); dbs_server_list_add_socket(sd, ntohl(sinRemote.sin_addr.s_addr)); if (psock_ctl(sd,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set TCP socket [%d] to non-blocking mode (closing connection) (psock_ctl: %s)", sd,pstrerror(psock_errno())); psock_close(sd); } } else if (PSOCK_FD_ISSET(lsocket, &ExceptFDs)) { eventlog(eventlog_level_error,__FUNCTION__,"exception on listening socket"); /* FIXME: exceptions are not errors with TCP, they are out-of-band data */ return; } LIST_TRAVERSE(dbs_server_connection_list,elem) { bOK = TRUE; pcErrorType = 0; if (!(it=elem_get_data(elem))) continue; if (PSOCK_FD_ISSET(it->sd, &ExceptFDs)) { bOK = FALSE; pcErrorType = "General socket error"; /* FIXME: no no no no no */ PSOCK_FD_CLR(it->sd, &ExceptFDs); } else { if (PSOCK_FD_ISSET(it->sd, &ReadFDs)) { bOK = dbs_server_read_data(it); pcErrorType = "Read error"; PSOCK_FD_CLR(it->sd, &ReadFDs); } if (PSOCK_FD_ISSET(it->sd, &WriteFDs)) { bOK = dbs_server_write_data(it); pcErrorType = "Write error"; PSOCK_FD_CLR(it->sd, &WriteFDs); } } if (!bOK) { int err, errno2; psock_t_socklen errlen; err = 0; errlen = sizeof(err); errno2 = psock_errno(); if (psock_getsockopt(it->sd, PSOCK_SOL_SOCKET, PSOCK_SO_ERROR, &err, &errlen)==0) { if (errlen && err!=0) { err = err ? err : errno2; eventlog(eventlog_level_error,__FUNCTION__,"data socket error : %s(%d)",pstrerror(err),err); } } dbs_server_shutdown_connection(it); list_remove_elem(dbs_server_connection_list,&elem); } else { if (dbs_packet_handle(it)==-1) { eventlog(eventlog_level_error,__FUNCTION__,"dbs_packet_handle() failed"); dbs_server_shutdown_connection(it); list_remove_elem(dbs_server_connection_list,&elem); } } } } } static void dbs_on_exit(void) { t_elem * elem; t_d2dbs_connection * it; if (dbs_server_listen_socket>=0) psock_close(dbs_server_listen_socket); dbs_server_listen_socket=-1; LIST_TRAVERSE(dbs_server_connection_list,elem) { if (!(it=elem_get_data(elem))) continue; dbs_server_shutdown_connection(it); list_remove_elem(dbs_server_connection_list,&elem); } cl_destroy(); d2dbs_d2ladder_destroy(); list_destroy(dbs_server_connection_list); if (preset_d2gsid_head) { t_preset_d2gsid * curr; t_preset_d2gsid * next; for (curr=preset_d2gsid_head; curr; curr=next) { next = curr->next; xfree(curr); } } eventlog(eventlog_level_info,__FUNCTION__,"dbserver stopped"); } int dbs_server_shutdown_connection(t_d2dbs_connection* conn) { psock_shutdown(conn->sd, PSOCK_SHUT_RDWR) ; psock_close(conn->sd); if (conn->verified && conn->type==CONNECT_CLASS_D2GS_TO_D2DBS) { eventlog(eventlog_level_info,__FUNCTION__,"unlock all characters on gs %s(%d)",conn->serverip,conn->serverid); eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"unlock all characters on gs %s(%d)",conn->serverip,conn->serverid); eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"close connection to gs on socket %d", conn->sd); cl_unlock_all_char_by_gsid(conn->serverid); } xfree(conn); return 1; } static int setsockopt_keepalive(int sock) { int optval; psock_t_socklen optlen; optval = 1; optlen = sizeof(optval); if (psock_setsockopt(sock, PSOCK_SOL_SOCKET, PSOCK_SO_KEEPALIVE, &optval, optlen)) { eventlog(eventlog_level_info,__FUNCTION__,"failed set KEEPALIVE for socket %d, errno=%d", sock, psock_errno()); return -1; } else { eventlog(eventlog_level_info,__FUNCTION__,"set KEEPALIVE option for socket %d", sock); return 0; } } static unsigned int get_preset_d2gsid(unsigned int ipaddr) { t_preset_d2gsid *pgsid; pgsid = preset_d2gsid_head; while (pgsid) { if (pgsid->ipaddr == ipaddr) return pgsid->d2gsid; pgsid = pgsid->next; } /* not found, build a new item */ pgsid = xmalloc(sizeof(t_preset_d2gsid)); pgsid->ipaddr = ipaddr; pgsid->d2gsid = ++dbs_packet_gs_id; /* add to list */ pgsid->next = preset_d2gsid_head; preset_d2gsid_head = pgsid; return preset_d2gsid_head->d2gsid; } pvpgn-1.8.5/src/d2dbs/version.h0000644000175000017500000000171411151345317015270 0ustar aaronaaron/* * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_VERSION_H #define INCLUDED_VERSION_H #define D2DBS_VERSION_NUMBER "1.10.1.1" #define D2DBS_VERSION "D2DBS Version " D2DBS_VERSION_NUMBER " Built " __DATE__ " " __TIME__ #endif pvpgn-1.8.5/src/d2dbs/cmdline.c0000644000175000017500000001620311151345317015210 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * Copyright (C) 2005 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memset.h" #ifdef WIN32 # include "win32/service.h" #endif #include "common/conf.h" #include "common/xalloc.h" #include "version.h" #include "cmdline.h" #include "compat/strcasecmp.h" #include "common/eventlog.h" #include "common/setup_after.h" static struct { #ifdef DO_DAEMONIZE unsigned foreground; #endif const char *preffile; const char *logfile; unsigned debug; } cmdline_config; static unsigned exitflag; static const char *progname; static int conf_set_preffile(const char *valstr); static int conf_setdef_preffile(void); static int conf_set_logfile(const char * valstr); static int conf_setdef_logfile(void); static int conf_set_help(const char * valstr); static int conf_setdef_help(void); static int conf_set_version(const char * valstr); static int conf_setdef_version(void); static int conf_set_foreground(const char * valstr); static int conf_setdef_foreground(void); static int conf_set_debug(const char * valstr); static int conf_setdef_debug(void); #ifdef WIN32 static int conf_set_service(char const * valstr); static int conf_setdef_service(void); static int conf_set_servaction(const char * valstr); static int conf_setdef_servaction(void); #endif static t_conf_entry conftab[]={ { "c", conf_set_preffile, NULL, conf_setdef_preffile}, { "config", conf_set_preffile, NULL, conf_setdef_preffile}, { "l", conf_set_logfile, NULL, conf_setdef_logfile }, { "log", conf_set_logfile, NULL, conf_setdef_logfile }, { "h", conf_set_help, NULL, conf_setdef_help }, { "help", conf_set_help, NULL, conf_setdef_help }, { "usage", conf_set_help, NULL, conf_setdef_help }, { "v", conf_set_version, NULL, conf_setdef_version }, { "version", conf_set_version, NULL, conf_setdef_version }, #ifdef DO_DAEMONIZE { "f", conf_set_foreground, NULL, conf_setdef_foreground}, { "foreground", conf_set_foreground, NULL, conf_setdef_foreground}, #endif { "D", conf_set_debug, NULL, conf_setdef_debug }, { "debug", conf_set_debug, NULL, conf_setdef_debug }, #ifdef WIN32 { "service", conf_set_service, NULL, conf_setdef_service }, { "s", conf_set_servaction, NULL, conf_setdef_servaction}, #endif { NULL, NULL, NULL, NULL } }; extern int cmdline_load(int argc, char** argv) { int res; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return -1; } exitflag = 0; progname = argv[0]; res = conf_load_cmdline(argc, argv, conftab); if (res < 0) return -1; return exitflag ? 0 : 1; } extern void cmdline_unload(void) { conf_unload(conftab); } static void usage(void) { fprintf(stderr, "Usage: %s []\n" " -c FILE, --config=FILE use FILE as configuration file (default is " D2DBS_DEFAULT_CONF_FILE ")\n" " -l FILE, --log=FILE set log to FILE\n" #ifdef DO_DAEMONIZE " -f, --foreground: don't daemonize\n" #endif " -D, --debug: run in debug mode (run in foreground and log to stdout)\n" " -h, --help, --usage show this information and exit\n" " -v, --version: print version number and exit\n" #ifdef WIN32 " Running as service functions:\n" " --service run as service\n" " -s install install service\n" " -s uninstall uninstall service\n" #endif "\n" "Notes:\n" " 1.You should always use absolute path here for all FILE names\n\n", progname); } #ifdef DO_DAEMONIZE extern int cmdline_get_foreground(void) { return cmdline_config.foreground; } static int conf_set_foreground(const char *valstr) { return conf_set_bool(&cmdline_config.foreground, valstr, 0); } static int conf_setdef_foreground(void) { return conf_set_bool(&cmdline_config.foreground, NULL, 0); } #endif extern const char* cmdline_get_preffile(void) { return cmdline_config.preffile; } static int conf_set_preffile(const char *valstr) { return conf_set_str(&cmdline_config.preffile, valstr, NULL); } static int conf_setdef_preffile(void) { return conf_set_str(&cmdline_config.preffile, NULL, D2DBS_DEFAULT_CONF_FILE); } extern const char* cmdline_get_logfile(void) { return cmdline_config.logfile; } static int conf_set_logfile(const char *valstr) { return conf_set_str(&cmdline_config.logfile, valstr, NULL); } static int conf_setdef_logfile(void) { return conf_set_str(&cmdline_config.logfile, NULL, NULL); } static int conf_set_debug(const char *valstr) { conf_set_bool(&cmdline_config.debug, valstr, 0); if (cmdline_config.debug) eventlog_set_debugmode(1); #ifdef DO_DAEMONIZE cmdline_config.foreground = 1; #endif return 0; } static int conf_setdef_debug(void) { return conf_set_bool(&cmdline_config.debug, NULL, 0); } static int conf_set_help(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { usage(); exitflag = 1; } return 0; } static int conf_setdef_help(void) { return 0; } static int conf_set_version(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { printf(D2DBS_VERSION"\n"); exitflag = 1; } return 0; } static int conf_setdef_version(void) { return 0; } #ifdef WIN32 static int conf_set_service(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { Win32_ServiceRun(); exitflag = 1; } return 0; } static int conf_setdef_service(void) { return 0; } static int conf_set_servaction(const char *valstr) { const char* tmp = NULL; conf_set_str(&tmp, valstr, NULL); if (tmp) { if (!strcasecmp(tmp, "install")) { fprintf(stderr, "Installing service"); Win32_ServiceInstall(); } else if (!strcasecmp(tmp, "uninstall")) { fprintf(stderr, "Uninstalling service"); Win32_ServiceUninstall(); } else { fprintf(stderr, "Unknown service action '%s'\n", tmp); } exitflag = 1; xfree((void *)tmp); } return 0; } static int conf_setdef_servaction(void) { return 0; } #endif pvpgn-1.8.5/src/d2dbs/charlock.h0000644000175000017500000000314011151345317015364 0ustar aaronaaron/* * Copyright (C) 2001 faster (lqx@cic.tsinghua.edu.cn) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_CHARLOCK_H #define INCLUDED_CHARLOCK_H #define DEFAULT_HASHTBL_LEN 65000 /* char locking info */ typedef struct raw_charlockinfo { unsigned char charname[MAX_CHARNAME_LEN]; unsigned char realmname[MAX_REALMNAME_LEN]; unsigned int gsid; struct raw_charlockinfo *next; struct raw_charlockinfo *gsqnext; struct raw_charlockinfo *gsqprev; } t_charlockinfo; /* functions */ int cl_init(unsigned int tbllen, unsigned int maxgs); int cl_destroy(void); int cl_query_charlock_status(unsigned char *charname, unsigned char *realmnamei, unsigned int *gsid); int cl_lock_char(unsigned char *charname, unsigned char *realmname, unsigned int gsid); int cl_unlock_char(unsigned char *charname, unsigned char *realmname, unsigned int gsid); int cl_unlock_all_char_by_gsid(unsigned int gsid); #endif /* INCLUDED_CHARLOCK_H */ pvpgn-1.8.5/src/d2dbs/prefs.c0000644000175000017500000003461511151345317014723 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2005 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memset.h" #include "common/conf.h" #include "prefs.h" #include "common/eventlog.h" #include "common/setup_after.h" static struct { char const * logfile; char const * logfile_gs; char const * servaddrs; char const * charsave_dir; char const * charinfo_dir; char const * charsave_bak_dir; char const * charinfo_bak_dir; char const * ladder_dir; char const * d2gs_list; unsigned int laddersave_interval; unsigned int ladderinit_time; char const * loglevels; char const * pidfile; unsigned int shutdown_delay; unsigned int shutdown_decr; unsigned int idletime; unsigned int keepalive_interval; unsigned int timeout_checkinterval; unsigned int XML_output_ladder; unsigned int ladderupdate_threshold; unsigned int ladder_chars_only; unsigned int difficulty_hack; } prefs_conf; static int conf_set_logfile(const char* valstr); static int conf_setdef_logfile(void); static int conf_set_logfile_gs(const char* valstr); static int conf_setdef_logfile_gs(void); static int conf_set_servaddrs(const char* valstr); static int conf_setdef_servaddrs(void); static int conf_set_charsave_dir(const char* valstr); static int conf_setdef_charsave_dir(void); static int conf_set_charinfo_dir(const char* valstr); static int conf_setdef_charinfo_dir(void); static int conf_set_charsave_bak_dir(const char* valstr); static int conf_setdef_charsave_bak_dir(void); static int conf_set_charinfo_bak_dir(const char* valstr); static int conf_setdef_charinfo_bak_dir(void); static int conf_set_ladder_dir(const char* valstr); static int conf_setdef_ladder_dir(void); static int conf_set_d2gs_list(const char* valstr); static int conf_setdef_d2gs_list(void); static int conf_set_laddersave_interval(const char* valstr); static int conf_setdef_laddersave_interval(void); static int conf_set_ladderinit_time(const char* valstr); static int conf_setdef_ladderinit_time(void); static int conf_set_loglevels(const char* valstr); static int conf_setdef_loglevels(void); static int conf_set_pidfile(const char* valstr); static int conf_setdef_pidfile(void); static int conf_set_shutdown_delay(const char* valstr); static int conf_setdef_shutdown_delay(void); static int conf_set_shutdown_decr(const char* valstr); static int conf_setdef_shutdown_decr(void); static int conf_set_idletime(const char* valstr); static int conf_setdef_idletime(void); static int conf_set_keepalive_interval(const char* valstr); static int conf_setdef_keepalive_interval(void); static int conf_set_timeout_checkinterval(const char* valstr); static int conf_setdef_timeout_checkinterval(void); static int conf_set_XML_output_ladder(const char* valstr); static int conf_setdef_XML_output_ladder(void); static int conf_set_ladderupdate_threshold(const char* valstr); static int conf_setdef_ladderupdate_threshold(void); static int conf_set_ladder_chars_only(const char* valstr); static int conf_setdef_ladder_chars_only(void); static int conf_set_difficulty_hack(const char* valstr); static int conf_setdef_difficulty_hack(void); static t_conf_entry prefs_conf_table[]={ { "logfile", conf_set_logfile, NULL, conf_setdef_logfile }, { "logfile-gs", conf_set_logfile_gs, NULL, conf_setdef_logfile_gs }, { "servaddrs", conf_set_servaddrs, NULL, conf_setdef_servaddrs }, { "charsavedir", conf_set_charsave_dir, NULL, conf_setdef_charsave_dir }, { "charinfodir", conf_set_charinfo_dir, NULL, conf_setdef_charinfo_dir }, { "bak_charsavedir", conf_set_charsave_bak_dir, NULL, conf_setdef_charsave_bak_dir }, { "bak_charinfodir", conf_set_charinfo_bak_dir, NULL, conf_setdef_charinfo_bak_dir }, { "ladderdir", conf_set_ladder_dir, NULL, conf_setdef_ladder_dir }, { "gameservlist", conf_set_d2gs_list, NULL, conf_setdef_d2gs_list }, { "laddersave_interval", conf_set_laddersave_interval, NULL, conf_setdef_laddersave_interval }, { "ladderinit_time", conf_set_ladderinit_time, NULL, conf_setdef_ladderinit_time }, { "loglevels", conf_set_loglevels, NULL, conf_setdef_loglevels }, { "pidfile", conf_set_pidfile, NULL, conf_setdef_pidfile}, { "shutdown_delay", conf_set_shutdown_delay, NULL, conf_setdef_shutdown_delay }, { "shutdown_decr", conf_set_shutdown_decr, NULL, conf_setdef_shutdown_decr }, { "idletime", conf_set_idletime, NULL, conf_setdef_idletime }, { "keepalive_interval", conf_set_keepalive_interval, NULL, conf_setdef_keepalive_interval }, { "timeout_checkinterval", conf_set_timeout_checkinterval, NULL, conf_setdef_timeout_checkinterval }, { "XML_ladder_output", conf_set_XML_output_ladder, NULL, conf_setdef_XML_output_ladder }, { "ladderupdate_threshold", conf_set_ladderupdate_threshold, NULL, conf_setdef_ladderupdate_threshold }, { "ladder_chars_only", conf_set_ladder_chars_only, NULL, conf_setdef_ladder_chars_only }, { "difficulty_hack", conf_set_difficulty_hack, NULL, conf_setdef_difficulty_hack }, { NULL, NULL, NULL, NULL } }; extern int d2dbs_prefs_load(char const * filename) { FILE *fd; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } fd = fopen(filename,"rt"); if (!fd) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file '%s'",filename); return -1; } if (conf_load_file(fd,prefs_conf_table)) { eventlog(eventlog_level_error,__FUNCTION__,"error loading config file '%s'",filename); fclose(fd); return -1; } fclose(fd); return 0; } extern int d2dbs_prefs_reload(char const * filename) { d2dbs_prefs_unload(); if (d2dbs_prefs_load(filename)<0) return -1; return 0; } extern int d2dbs_prefs_unload(void) { conf_unload(prefs_conf_table); return 0; } extern char const * d2dbs_prefs_get_servaddrs(void) { return prefs_conf.servaddrs; } static int conf_set_servaddrs(const char* valstr) { return conf_set_str(&prefs_conf.servaddrs,valstr,NULL); } static int conf_setdef_servaddrs(void) { return conf_set_str(&prefs_conf.servaddrs,NULL,D2DBS_SERVER_ADDRS); } extern char const * d2dbs_prefs_get_logfile(void) { return prefs_conf.logfile; } static int conf_set_logfile(const char * valstr) { return conf_set_str(&prefs_conf.logfile,valstr,NULL); } static int conf_setdef_logfile(void) { return conf_set_str(&prefs_conf.logfile,NULL,DEFAULT_LOG_FILE); } extern char const * prefs_get_logfile_gs(void) { return prefs_conf.logfile_gs; } static int conf_set_logfile_gs(const char * valstr) { return conf_set_str(&prefs_conf.logfile_gs,valstr,NULL); } static int conf_setdef_logfile_gs(void) { return conf_set_str(&prefs_conf.logfile_gs,NULL,DEFAULT_LOG_FILE); } extern char const * d2dbs_prefs_get_charsave_dir(void) { return prefs_conf.charsave_dir; } static int conf_set_charsave_dir(const char * valstr) { return conf_set_str(&prefs_conf.charsave_dir,valstr,NULL); } static int conf_setdef_charsave_dir(void) { return conf_set_str(&prefs_conf.charsave_dir,NULL,D2DBS_CHARSAVE_DIR); } extern char const * d2dbs_prefs_get_charinfo_dir(void) { return prefs_conf.charinfo_dir; } static int conf_set_charinfo_dir(const char * valstr) { return conf_set_str(&prefs_conf.charinfo_dir,valstr,NULL); } static int conf_setdef_charinfo_dir(void) { return conf_set_str(&prefs_conf.charinfo_dir,NULL,D2DBS_CHARINFO_DIR); } extern char const * prefs_get_charsave_bak_dir(void) { return prefs_conf.charsave_bak_dir; } static int conf_set_charsave_bak_dir(const char * valstr) { return conf_set_str(&prefs_conf.charsave_bak_dir,valstr,NULL); } static int conf_setdef_charsave_bak_dir(void) { return conf_set_str(&prefs_conf.charsave_bak_dir,NULL,D2DBS_CHARSAVEBAK_DIR); } extern char const * prefs_get_charinfo_bak_dir(void) { return prefs_conf.charinfo_bak_dir; } static int conf_set_charinfo_bak_dir(const char * valstr) { return conf_set_str(&prefs_conf.charinfo_bak_dir,valstr,NULL); } static int conf_setdef_charinfo_bak_dir(void) { return conf_set_str(&prefs_conf.charinfo_bak_dir,NULL,D2DBS_CHARINFOBAK_DIR); } extern char const * d2dbs_prefs_get_ladder_dir(void) { return prefs_conf.ladder_dir; } static int conf_set_ladder_dir(const char * valstr) { return conf_set_str(&prefs_conf.ladder_dir,valstr,NULL); } static int conf_setdef_ladder_dir(void) { return conf_set_str(&prefs_conf.ladder_dir,NULL,D2DBS_LADDER_DIR); } extern char const * d2dbs_prefs_get_d2gs_list(void) { return prefs_conf.d2gs_list; } static int conf_set_d2gs_list(const char * valstr) { return conf_set_str(&prefs_conf.d2gs_list,valstr,NULL); } static int conf_setdef_d2gs_list(void) { return conf_set_str(&prefs_conf.d2gs_list,NULL,D2GS_SERVER_LIST); } extern unsigned int prefs_get_laddersave_interval(void) { return prefs_conf.laddersave_interval; } static int conf_set_laddersave_interval(char const * valstr) { return conf_set_int(&prefs_conf.laddersave_interval,valstr,0); } static int conf_setdef_laddersave_interval(void) { return conf_set_int(&prefs_conf.laddersave_interval,NULL,3600); } extern unsigned int prefs_get_ladderinit_time(void) { return prefs_conf.ladderinit_time; } static int conf_set_ladderinit_time(char const * valstr) { return conf_set_int(&prefs_conf.ladderinit_time,valstr,0); } static int conf_setdef_ladderinit_time(void) { return conf_set_int(&prefs_conf.ladderinit_time,NULL,0); } extern char const * d2dbs_prefs_get_loglevels(void) { return prefs_conf.loglevels; } static int conf_set_loglevels(const char* valstr) { return conf_set_str(&prefs_conf.loglevels,valstr,NULL); } static int conf_setdef_loglevels(void) { return conf_set_str(&prefs_conf.loglevels,NULL,DEFAULT_LOG_LEVELS); } extern char const * d2dbs_prefs_get_pidfile(void) { return prefs_conf.pidfile; } static int conf_set_pidfile(const char* valstr) { return conf_set_str(&prefs_conf.pidfile,valstr,NULL); } static int conf_setdef_pidfile(void) { return conf_set_str(&prefs_conf.pidfile,NULL,""); } extern unsigned int d2dbs_prefs_get_shutdown_delay(void) { return prefs_conf.shutdown_delay; } static int conf_set_shutdown_delay(const char * valstr) { return conf_set_int(&prefs_conf.shutdown_delay,valstr,0); } static int conf_setdef_shutdown_delay(void) { return conf_set_int(&prefs_conf.shutdown_delay,NULL,DEFAULT_SHUTDOWN_DELAY); } extern unsigned int d2dbs_prefs_get_shutdown_decr(void) { return prefs_conf.shutdown_decr; } static int conf_set_shutdown_decr(const char * valstr) { return conf_set_int(&prefs_conf.shutdown_decr,valstr,0); } static int conf_setdef_shutdown_decr(void) { return conf_set_int(&prefs_conf.shutdown_decr,NULL,DEFAULT_SHUTDOWN_DECR); } extern unsigned int d2dbs_prefs_get_idletime(void) { return prefs_conf.idletime; } static int conf_set_idletime(const char * valstr) { return conf_set_int(&prefs_conf.idletime,valstr,0); } static int conf_setdef_idletime(void) { return conf_set_int(&prefs_conf.idletime,NULL,DEFAULT_IDLETIME); } extern unsigned int prefs_get_keepalive_interval(void) { return prefs_conf.keepalive_interval; } static int conf_set_keepalive_interval(const char * valstr) { return conf_set_int(&prefs_conf.keepalive_interval,valstr,0); } static int conf_setdef_keepalive_interval(void) { return conf_set_int(&prefs_conf.keepalive_interval,NULL,DEFAULT_KEEPALIVE_INTERVAL); } extern unsigned int d2dbs_prefs_get_timeout_checkinterval(void) { return prefs_conf.timeout_checkinterval; } static int conf_set_timeout_checkinterval(const char * valstr) { return conf_set_int(&prefs_conf.timeout_checkinterval,valstr,0); } static int conf_setdef_timeout_checkinterval(void) { return conf_set_int(&prefs_conf.timeout_checkinterval,NULL,DEFAULT_TIMEOUT_CHECKINTERVAL); } extern unsigned int d2dbs_prefs_get_XML_output_ladder(void) { return prefs_conf.XML_output_ladder; } static int conf_set_XML_output_ladder(const char * valstr) { return conf_set_bool(&prefs_conf.XML_output_ladder,valstr,0); } static int conf_setdef_XML_output_ladder(void) { return conf_set_bool(&prefs_conf.XML_output_ladder,NULL,0); } extern unsigned int prefs_get_ladderupdate_threshold(void) { return prefs_conf.ladderupdate_threshold; } static int conf_set_ladderupdate_threshold(const char * valstr) { return conf_set_int(&prefs_conf.ladderupdate_threshold,valstr,0); } static int conf_setdef_ladderupdate_threshold(void) { return conf_set_int(&prefs_conf.ladderupdate_threshold,NULL,DEFAULT_LADDERUPDATE_THRESHOLD); } extern unsigned int prefs_get_ladder_chars_only(void) { return prefs_conf.ladder_chars_only; } static int conf_set_ladder_chars_only(const char * valstr) { return conf_set_bool(&prefs_conf.ladder_chars_only,valstr,0); } static int conf_setdef_ladder_chars_only(void) { return conf_set_bool(&prefs_conf.ladder_chars_only,NULL,0); } extern unsigned int prefs_get_difficulty_hack(void) { return prefs_conf.difficulty_hack; } static int conf_set_difficulty_hack(const char * valstr) { return conf_set_int(&prefs_conf.difficulty_hack,valstr,0); } static int conf_setdef_difficulty_hack(void) { return conf_set_int(&prefs_conf.difficulty_hack,NULL,0); } pvpgn-1.8.5/src/d2dbs/dbsdupecheck.h0000644000175000017500000000160211151345317016223 0ustar aaronaaron/* * Copyright (C) 2003 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define DBSDUPECHECK_CONTAINS_DUPE 0 #define DBSDUPECHECK_CONTAINS_NO_DUPE 1 extern int dbsdupecheck(char * data, unsigned int datalen); pvpgn-1.8.5/src/d2dbs/dbsdupecheck.c0000644000175000017500000000577311151345317016233 0ustar aaronaaron/* * Copyright (C) 2001 faster (lqx@cic.tsinghua.edu.cn) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strcasecmp.h" #include #ifdef HAVE_LIMITS_H # include #endif #include "dbsdupecheck.h" #include "common/setup_after.h" #include "common/bn_type.h" #include "common/eventlog.h" const char * delimiter = "JM"; int is_delimit(char * data) { if ((data[0]==delimiter[0]) && (data[1]==delimiter[1])) return 1; else return 0; } void * find_delimiter(char * data, unsigned int datalen) { char * datap = data; unsigned int count; for (count=1; count #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strdup.h" #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include "prefs.h" #include "cmdline.h" #include "version.h" #include "common/eventlog.h" #ifdef WIN32 # include "win32/service.h" #endif #include "handle_signal.h" #include "dbserver.h" #include "common/xalloc.h" #include "compat/strerror.h" #ifdef WIN32_GUI # include "win32/winmain.h" #endif #include "common/setup_after.h" static FILE * eventlog_fp; char serviceLongName[] = "d2dbs service"; char serviceName[] = "d2dbs"; char serviceDescription[] = "Diablo 2 DataBase Server"; int g_ServiceStatus = -1; static int init(void); static int cleanup(void); static int config_init(int argc, char * * argv); static int config_cleanup(void); static int setup_daemon(void); static char * write_to_pidfile(void); #ifdef DO_DAEMONIZE static int setup_daemon(void) { int pid; if (chdir("/")<0) { eventlog(eventlog_level_error,__FUNCTION__,"can not change working directory to root directory (chdir: %s)",pstrerror(errno)); return -1; } close(STDIN_FILENO); close(STDOUT_FILENO); if (!cmdline_get_foreground()) { close(STDERR_FILENO); } switch ((pid=fork())) { case 0: break; case -1: eventlog(eventlog_level_error,__FUNCTION__,"error create child process (fork: %s)",pstrerror(errno)); return -1; default: return pid; } umask(0); setsid(); return 0; } #endif static char * write_to_pidfile(void) { char *pidfile = xstrdup(d2dbs_prefs_get_pidfile()); if (pidfile[0]=='\0') { xfree((void *)pidfile); /* avoid warning */ return NULL; } if (pidfile) { #ifdef HAVE_GETPID FILE * fp; if (!(fp = fopen(pidfile,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to open pid file \"%s\" for writing (fopen: %s)",pidfile,pstrerror(errno)); xfree((void *)pidfile); /* avoid warning */ return NULL; } else { fprintf(fp,"%u",(unsigned int)getpid()); if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close pid file \"%s\" after writing (fclose: %s)",pidfile,pstrerror(errno)); } #else eventlog(eventlog_level_warn,__FUNCTION__,"no getpid() system call, disable pid file in d2dbs.conf"); xfree((void *)pidfile); /* avoid warning */ return NULL; #endif } return pidfile; } static int init(void) { return 0; } static int cleanup(void) { return 0; } static int config_init(int argc, char * * argv) { char const * levels; char * temp; char const * tok; int pid; if (cmdline_load(argc, argv)<0) { return -1; } #ifdef DO_DAEMONIZE if (!cmdline_get_foreground()) { if (!((pid = setup_daemon()) == 0)) { return pid; } } #endif if (d2dbs_prefs_load(cmdline_get_preffile())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading configuration file %s",cmdline_get_preffile()); return -1; } eventlog_clear_level(); if ((levels = d2dbs_prefs_get_loglevels())) { temp = xstrdup(levels); tok = strtok(temp,","); /* strtok modifies the string it is passed */ while (tok) { if (eventlog_add_level(tok)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add log level \"%s\"",tok); tok = strtok(NULL,","); } xfree(temp); } #ifdef DO_DAEMONIZE if (cmdline_get_foreground()) { eventlog_set(stderr); } else #endif { if (cmdline_get_logfile()) { if (eventlog_open(cmdline_get_logfile())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error open eventlog file %s",cmdline_get_logfile()); return -1; } } else { if (eventlog_open(d2dbs_prefs_get_logfile())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error open eventlog file %s",d2dbs_prefs_get_logfile()); return -1; } } } return 0; } static int config_cleanup(void) { d2dbs_prefs_unload(); cmdline_unload(); eventlog_close(); if (eventlog_fp) fclose(eventlog_fp); return 0; } #ifdef WIN32_GUI extern int server_main(int argc, char * * argv) #else extern int main(int argc, char * * argv) #endif { int pid; char * pidfile; eventlog_set(stderr); pid = config_init(argc, argv); if (!(pid == 0)) { // if (pid==1) pid=0; return pid; } pidfile = write_to_pidfile(); eventlog(eventlog_level_info,__FUNCTION__,D2DBS_VERSION); if (init()<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to init"); return -1; } else { eventlog(eventlog_level_info,__FUNCTION__,"server initialized"); } #ifndef WIN32 d2dbs_handle_signal_init(); #endif dbs_server_main(); cleanup(); if (pidfile) { if (remove(pidfile)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove pid file \"%s\" (remove: %s)",pidfile,pstrerror(errno)); xfree((void *)pidfile); /* avoid warning */ } config_cleanup(); return 0; } pvpgn-1.8.5/src/d2dbs/handle_signal.h0000644000175000017500000000221111151345317016364 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_HANDLE_SIGNAL_H #define INCLUDED_HANDLE_SIGNAL_H #ifndef WIN32 extern int d2dbs_handle_signal_init(void); #else extern void d2dbs_signal_quit_wrapper(void); extern void d2dbs_signal_reload_config_wrapper(void); extern void d2dbs_signal_save_ladder_wrapper(void); extern void d2dbs_signal_exit_wrapper(void); #endif extern int d2dbs_handle_signal(void); #endif pvpgn-1.8.5/src/d2dbs/prefs.h0000644000175000017500000000430011151345317014714 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_PREFS_H #define INCLUDED_PREFS_H extern int d2dbs_prefs_load(char const * filename); extern int d2dbs_prefs_reload(char const * filename); extern int d2dbs_prefs_unload(void); extern char const * d2dbs_prefs_get_logfile(void); extern char const * prefs_get_logfile_gs(void); extern char const * d2dbs_prefs_get_servaddrs(void); extern char const * d2dbs_prefs_get_charsave_dir(void); extern char const * d2dbs_prefs_get_charinfo_dir(void); extern char const * prefs_get_charsave_bak_dir(void); extern char const * prefs_get_charinfo_bak_dir(void); extern char const * d2dbs_prefs_get_ladder_dir(void); extern char const * d2dbs_prefs_get_d2gs_list(void); extern unsigned int prefs_get_laddersave_interval(void); extern unsigned int prefs_get_ladderinit_time(void); extern char const * d2dbs_prefs_get_loglevels(void); extern unsigned int d2dbs_prefs_get_shutdown_delay(void); extern unsigned int d2dbs_prefs_get_shutdown_decr(void); extern unsigned int d2dbs_prefs_get_idletime(void); extern unsigned int prefs_get_keepalive_interval(void); extern unsigned int d2dbs_prefs_get_timeout_checkinterval(void); extern unsigned int d2dbs_prefs_get_XML_output_ladder(void); extern unsigned int prefs_get_ladderupdate_threshold(void); extern unsigned int prefs_get_ladder_chars_only(void); extern unsigned int prefs_get_difficulty_hack(void); extern char const * d2dbs_prefs_get_pidfile(void); #endif pvpgn-1.8.5/src/d2dbs/d2ladder.c0000644000175000017500000006371511151345317015270 0ustar aaronaaron/* * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_FILE_H #include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include "compat/rename.h" #include "d2ladder.h" #include "prefs.h" #include "common/tag.h" #include "common/list.h" #include "common/eventlog.h" #include "compat/strncasecmp.h" #include "compat/strerror.h" #include "d2cs/d2charfile.h" #include "common/xalloc.h" #include "common/setup_after.h" char * d2ladder_ladder_file = NULL; char * d2ladder_backup_file = NULL; t_d2ladderlist * d2ladder_list = NULL; unsigned long d2ladder_maxtype; int d2ladder_change_count=0; int d2ladder_need_rebuild = 0; char * XMLname = "d2ladder.xml"; int d2ladderlist_init(void); int d2ladderlist_destroy(void); int d2ladder_empty(void); int d2ladder_initladderfile(void); t_d2ladder * d2ladderlist_find_type(unsigned int type); int d2ladder_check(void); int d2ladder_readladder(void); int d2ladder_insert(t_d2ladder * d2ladder,t_d2ladder_info * pcharladderinfo); int d2ladder_find_char_all(t_d2ladder * d2ladder, t_d2ladder_info * info); int d2ladder_find_pos(t_d2ladder * d2ladder, t_d2ladder_info * info); int d2ladder_update_info_and_pos(t_d2ladder * d2ladder, t_d2ladder_info * info, int oldpos, int newpos); int d2ladder_checksum(unsigned char const * data, unsigned int len,unsigned int offset); int d2ladder_checksum_set(void); int d2ladder_checksum_check(void); extern int d2ladder_update(t_d2ladder_info * pcharladderinfo) { t_d2ladder * d2ladder; unsigned short hardcore,expansion,status; unsigned char class; unsigned int ladder_overall_type,ladder_class_type; if (!pcharladderinfo->charname[0]) return 0; class=pcharladderinfo->class; status=pcharladderinfo->status; if (prefs_get_ladder_chars_only() && (!charstatus_get_ladder(status))) return -1; hardcore=charstatus_get_hardcore(status); expansion=charstatus_get_expansion(status); ladder_overall_type=0; if (!expansion && class> D2CHAR_CLASS_MAX ) return -1; if (expansion && class> D2CHAR_EXP_CLASS_MAX ) return -1; if (hardcore && expansion) { ladder_overall_type=D2LADDER_EXP_HC_OVERALL; } else if (!hardcore && expansion) { ladder_overall_type=D2LADDER_EXP_STD_OVERALL; } else if (hardcore && !expansion) { ladder_overall_type=D2LADDER_HC_OVERALL; } else if (!hardcore && !expansion) { ladder_overall_type=D2LADDER_STD_OVERALL; } ladder_class_type=ladder_overall_type + class+1; d2ladder=d2ladderlist_find_type(ladder_overall_type); if(d2ladder_insert(d2ladder,pcharladderinfo)==1) { d2ladder_change_count++; } d2ladder=d2ladderlist_find_type(ladder_class_type); if(d2ladder_insert(d2ladder,pcharladderinfo)==1) { d2ladder_change_count++; } return 0; } int d2ladder_initladderfile(void) { FILE * fdladder; t_d2ladderfile_ladderindex lhead[D2LADDER_MAXTYPE]; t_d2ladderfile_header fileheader; int start; unsigned long maxtype; t_d2ladderfile_ladderinfo emptydata; unsigned int i,j, number; maxtype=D2LADDER_MAXTYPE; start=sizeof(t_d2ladderfile_header)+sizeof(lhead); for(i=0;iD2LADDER_HC_OVERALL && i<=D2LADDER_HC_OVERALL+D2CHAR_CLASS_MAX +1) || (i>D2LADDER_STD_OVERALL && i<=D2LADDER_STD_OVERALL+D2CHAR_CLASS_MAX +1) || (i>D2LADDER_EXP_HC_OVERALL && i<=D2LADDER_EXP_HC_OVERALL+D2CHAR_EXP_CLASS_MAX +1) || (i>D2LADDER_EXP_STD_OVERALL && i<=D2LADDER_EXP_STD_OVERALL+D2CHAR_EXP_CLASS_MAX +1)) { number=D2LADDER_MAXNUM; } else { number=0; } bn_int_set(&lhead[i].number,number); start += number*sizeof(emptydata); } memset(&emptydata,0,sizeof(emptydata)); if (!d2ladder_ladder_file) return -1; fdladder=fopen(d2ladder_ladder_file,"wb"); if(fdladder) { bn_int_set(&fileheader.maxtype,maxtype); bn_int_set(&fileheader.checksum,0); fwrite(&fileheader,1,sizeof(fileheader),fdladder); fwrite(lhead,1,sizeof(lhead),fdladder); for(i=0;iexperience < prefs_get_ladderupdate_threshold()) return -1; i=d2ladder->len; while (i--) { if (d2ladder->info[i].experience > info->experience) { if (strncasecmp(d2ladder->info[i].charname,info->charname, MAX_CHARNAME_LEN)) { i++; } break; } if (i<=0) break; } return i; } int d2ladder_insert(t_d2ladder * d2ladder,t_d2ladder_info * info) { int oldpos, newpos; newpos=d2ladder_find_pos(d2ladder,info); /* we currectly do nothing when character is being kick out of ladder for simple */ /* if (newpos<0 || newpos >= d2ladder->len) return 0; */ oldpos=d2ladder_find_char_all(d2ladder,info); return d2ladder_update_info_and_pos(d2ladder,info,oldpos,newpos); } int d2ladder_find_char_all(t_d2ladder * d2ladder, t_d2ladder_info * info) { int i; t_d2ladder_info * ladderdata; if (!d2ladder || !info) return -1; ladderdata=d2ladder->info; if (!ladderdata) return -1; i=d2ladder->len; while (i--) { if (!strncasecmp(ladderdata[i].charname,info->charname,MAX_CHARNAME_LEN)) return i; } return -1; } int d2ladder_update_info_and_pos(t_d2ladder * d2ladder, t_d2ladder_info * info, int oldpos, int newpos) { int i; int direction; int outflag; t_d2ladder_info * ladderdata; if (!d2ladder || !info) return -1; ladderdata=d2ladder->info; if (!ladderdata) return -1; /* character not in ladder before */ outflag=0; if (oldpos < 0 || oldpos >= (signed)d2ladder->len) { oldpos = d2ladder->len-1; } if (newpos < 0 || newpos >= (signed)d2ladder->len) { newpos = d2ladder->len-1; outflag = 1; } if ((oldpos == (signed)d2ladder->len -1) && outflag) { return 0; } if (newpos > oldpos && !outflag ) newpos--; direction = (newpos > oldpos)? 1: -1; for (i=oldpos; i!=newpos; i+=direction) { ladderdata[i] = ladderdata[i+direction]; } ladderdata[i]=*info; return 1; } extern int d2ladder_rebuild(void) { d2ladder_empty(); d2ladder_need_rebuild = 0; return 0; } int d2ladder_check(void) { if (!d2ladder_ladder_file) return -1; if (!d2ladder_backup_file) return -1; if(d2ladder_checksum_check()!=1) { eventlog(eventlog_level_error,__FUNCTION__,"ladder file checksum error,try to use backup file"); if (p_rename(d2ladder_backup_file,d2ladder_ladder_file)==-1) { eventlog(eventlog_level_error,__FUNCTION__,"error rename %s to %s", d2ladder_backup_file,d2ladder_ladder_file); } if(d2ladder_checksum_check()!=1) { eventlog(eventlog_level_error,__FUNCTION__,"ladder backup file checksum error,rebuild ladder"); if (d2ladder_initladderfile()<0) return -1; else { d2ladder_need_rebuild=1; return 0; } } } return 1; } t_d2ladder * d2ladderlist_find_type(unsigned int type) { t_d2ladder * d2ladder; t_elem const * elem; if (!d2ladder_list) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL d2ladder_list"); return NULL; } LIST_TRAVERSE_CONST(d2ladder_list,elem) { if (!(d2ladder=elem_get_data(elem))) continue; if (d2ladder->type==type) return d2ladder; } eventlog(eventlog_level_error,__FUNCTION__,"could not find type %d in d2ladder_list",type); return NULL; } extern int d2dbs_d2ladder_init(void) { d2ladder_change_count=0; d2ladder_maxtype=0; d2ladder_ladder_file=xmalloc(strlen(d2dbs_prefs_get_ladder_dir())+1+ strlen(LADDER_FILE_PREFIX)+1+strlen(CLIENTTAG_DIABLO2DV)+1+10); d2ladder_backup_file=xmalloc(strlen(d2dbs_prefs_get_ladder_dir())+1+ strlen(LADDER_BACKUP_PREFIX)+1+strlen(CLIENTTAG_DIABLO2DV)+1+10); sprintf(d2ladder_ladder_file,"%s/%s.%s",d2dbs_prefs_get_ladder_dir(),\ LADDER_FILE_PREFIX,CLIENTTAG_DIABLO2DV); sprintf(d2ladder_backup_file,"%s/%s.%s",d2dbs_prefs_get_ladder_dir(),\ LADDER_BACKUP_PREFIX,CLIENTTAG_DIABLO2DV); if (d2ladderlist_init()<0) { return -1; } if(d2ladder_check()<0) { eventlog(eventlog_level_error,__FUNCTION__,"ladder file checking error"); return -1; } if (d2ladder_readladder()<0) { return -1; } if (d2ladder_need_rebuild) d2ladder_rebuild(); d2ladder_saveladder(); return 0; } int d2ladderlist_init(void) { t_d2ladder * d2ladder; unsigned int i; if (!d2ladder_ladder_file) return -1; d2ladder_list=list_create(); d2ladder_maxtype=D2LADDER_MAXTYPE; for (i=0;itype=i; d2ladder->info=NULL; d2ladder->len=0; list_append_data(d2ladder_list,d2ladder); } return 0; } int d2ladder_readladder(void) { t_d2ladder * d2ladder; t_d2ladderfile_header fileheader; FILE * fdladder; t_d2ladderfile_ladderindex * lhead; t_d2ladderfile_ladderinfo * ldata; t_d2ladder_info * info; t_d2ladder_info temp; long leftsize,blocksize; unsigned int laddertype; unsigned int tempmaxtype; int readlen; unsigned int i, number; if (!d2ladder_ladder_file) return -1; fdladder=fopen(d2ladder_ladder_file,"rb"); if(!fdladder) { eventlog(eventlog_level_error,__FUNCTION__,"canot open ladder file"); return -1; } fseek(fdladder,0,SEEK_END); leftsize=ftell(fdladder); rewind(fdladder); blocksize=sizeof(fileheader) ; if (leftsizeD2LADDER_MAXTYPE) { eventlog(eventlog_level_error,__FUNCTION__,"ladder type > D2LADDER_MAXTYPE error"); fclose(fdladder); return -1; } d2ladder_maxtype=tempmaxtype; blocksize=d2ladder_maxtype*sizeof(*lhead); if (leftsize < blocksize ) { eventlog(eventlog_level_error,__FUNCTION__,"file size error"); fclose(fdladder); return -1; } lhead=xmalloc(blocksize); readlen=fread(lhead,1,d2ladder_maxtype*sizeof(*lhead),fdladder); if (readlen<=0) { eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,pstrerror(errno)); xfree(lhead); fclose(fdladder); return -1; } leftsize-=blocksize; blocksize=0; for(i=0;iinfo=info; d2ladder->len=number; for (i=0; i< number; i++) { if (!ldata[i].charname[0]) continue; temp.experience=bn_int_get(ldata[i].experience); temp.status=bn_short_get(ldata[i].status); temp.level=bn_byte_get(ldata[i].level); temp.class=bn_byte_get(ldata[i].class); strncpy(temp.charname,ldata[i].charname,sizeof(info[i].charname)); if (d2ladder_update_info_and_pos(d2ladder,&temp, d2ladder_find_char_all(d2ladder,&temp), d2ladder_find_pos(d2ladder,&temp))==1) { d2ladder_change_count++; } } xfree(ldata); } leftsize-=blocksize; xfree(lhead); fclose(fdladder); return 0; } extern int d2dbs_d2ladder_destroy(void) { unsigned int i; t_d2ladder * d2ladder; d2ladder_saveladder(); for (i=0;iinfo) xfree(d2ladder->info); d2ladder->info=NULL; d2ladder->len=0; } } d2ladderlist_destroy(); if (d2ladder_ladder_file) { xfree(d2ladder_ladder_file); d2ladder_ladder_file=NULL; } if (d2ladder_backup_file) { xfree(d2ladder_backup_file); d2ladder_backup_file=NULL; } return 0; } int d2ladderlist_destroy(void) { t_d2ladder * d2ladder; t_elem * elem; if (!d2ladder_list) return -1; LIST_TRAVERSE(d2ladder_list,elem) { if (!(d2ladder=elem_get_data(elem))) continue; xfree(d2ladder); list_remove_elem(d2ladder_list,&elem); } list_destroy(d2ladder_list); return 0; } int d2ladder_empty(void) { unsigned int i; t_d2ladder * d2ladder; for (i=0;iinfo,0,d2ladder->len * sizeof(*d2ladder->info)); } } return 0; } const char * get_prefix(int type, int status, int class) { int difficulty; static char prefix [4][4][2][16] = {{{"",""},{"",""},{"",""},{"",""}}, {{"Count" ,"Countess"} , {"Sir","Dame"}, {"Destroyer","Destroyer"} , {"Slayer","Slayer"}}, {{"Duke" ,"Duchess"} , {"Lord","Lady"}, {"Conqueror","Conqueror"} , {"Champion","Champion"}}, {{"King" ,"Queen"} , {"Baron","Baroness"}, {"Guardian","Guardian"} , {"Patriarch","Matriarch"}}}; static int sex[11] = {0,1,1,0,0,0,0,1,0,0,0}; difficulty = ((status >> 0x08) & 0x0f) / 5; return prefix[difficulty][type][sex[class]]; } int d2ladder_print_XML(FILE *ladderstrm) { // modified version of d2ladder_print - changes done by jfro with a little help of aaron t_d2ladder * d2ladder; t_d2ladder_info * ldata; int overalltype,classtype; unsigned int i,type; char laddermode[4][20]={"Hardcore", "Standard","Expansion HC","Expansion" }; char charclass[11][12]={"OverAll", "Amazon", "Sorceress", "Necromancer", "Paladin",\ "Barbarian", "Druid", "Assassin", "","",""} ; fprintf(ladderstrm,"\n\n"); for(type=0; type len<=0) continue; ldata=d2ladder->info; overalltype=0; classtype=0; if(type<= D2LADDER_HC_OVERALL+D2CHAR_CLASS_MAX +1) { overalltype=0 ; classtype=type-D2LADDER_HC_OVERALL; } else if(type >= D2LADDER_STD_OVERALL && type<= D2LADDER_STD_OVERALL+D2CHAR_CLASS_MAX +1) { overalltype=1; classtype=type-D2LADDER_STD_OVERALL; } else if(type >= D2LADDER_EXP_HC_OVERALL && type<= D2LADDER_EXP_HC_OVERALL+D2CHAR_EXP_CLASS_MAX +1) { overalltype=2; classtype=type-D2LADDER_EXP_HC_OVERALL; } else if(type >= D2LADDER_EXP_STD_OVERALL && type<= D2LADDER_EXP_STD_OVERALL+D2CHAR_EXP_CLASS_MAX +1) { overalltype=3; classtype=type-D2LADDER_EXP_STD_OVERALL ; } fprintf(ladderstrm,"\n\t%d\n\t%s\n\t%s\n", type,laddermode[overalltype],charclass[classtype]); for(i=0; ilen; i++) { if ((ldata[i].charname != NULL) && (ldata[i].charname[0] != '\0')) { fprintf(ladderstrm,"\t\n\t\t%2d\n\t\t%s\n\t\t%2d\n", i+1,ldata[i].charname,ldata[i].level); fprintf(ladderstrm,"\t\t%u\n\t\t%s\n", ldata[i].experience,charclass[ldata[i].class+1]); fprintf(ladderstrm,"\t\t%s\n", get_prefix(overalltype,ldata[i].status,ldata[i].class+1)); if (((ldata[i].status) & (D2CHARINFO_STATUS_FLAG_DEAD | D2CHARINFO_STATUS_FLAG_HARDCORE)) == (D2CHARINFO_STATUS_FLAG_DEAD | D2CHARINFO_STATUS_FLAG_HARDCORE)) fprintf(ladderstrm,"\t\tdead\n\t\n"); else fprintf(ladderstrm,"\t\talive\n\t\n"); } } fprintf(ladderstrm,"\n"); fflush(ladderstrm); } fprintf(ladderstrm,"\n"); return 0; } extern int d2ladder_saveladder(void) { t_d2ladderfile_ladderindex lhead[D2LADDER_MAXTYPE]; t_d2ladderfile_header fileheader; FILE * fdladder; int start; unsigned int i,j, number; t_d2ladder * d2ladder; t_d2ladderfile_ladderinfo * ldata; char * XMLfilename; FILE * XMLfile; /* if(!d2ladder_change_count) { eventlog(eventlog_level_debug,__FUNCTION__,"ladder data unchanged, skip saving"); return 0; } */ start=sizeof(fileheader)+sizeof(lhead); for(i=0;itype); bn_int_set(&lhead[i].offset,start); bn_int_set(&lhead[i].number,d2ladder->len); start+=d2ladder->len*sizeof(*ldata); } if (!d2ladder_ladder_file) return -1; if (!d2ladder_backup_file) return -1; if(d2ladder_checksum_check()==1) { eventlog(eventlog_level_info,__FUNCTION__,"backup ladder file"); if (p_rename(d2ladder_ladder_file,d2ladder_backup_file)==-1) { eventlog(eventlog_level_warn,__FUNCTION__,"error rename %s to %s", d2ladder_ladder_file, d2ladder_backup_file); } } fdladder=fopen(d2ladder_ladder_file,"wb"); if(!fdladder) { eventlog(eventlog_level_error,__FUNCTION__,"error open ladder file %s",d2ladder_ladder_file); return -1; } // aaron: add extra output for XML ladder here ---> if (d2dbs_prefs_get_XML_output_ladder()) { XMLfilename = xmalloc(strlen(d2dbs_prefs_get_ladder_dir())+1+strlen(XMLname)+1); sprintf(XMLfilename,"%s/%s",d2dbs_prefs_get_ladder_dir(),XMLname); if (!(XMLfile = fopen(XMLfilename,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open XML ladder file for output"); } else { d2ladder_print_XML(XMLfile); fclose(XMLfile); xfree(XMLfilename); } } // <--- bn_int_set(&fileheader.maxtype,d2ladder_maxtype); bn_int_set(&fileheader.checksum,0); fwrite(&fileheader,1,sizeof(fileheader),fdladder); fwrite(lhead,1,sizeof(lhead),fdladder); for(i=0;iinfo[j].experience); bn_short_set(&ldata[j].status, d2ladder->info[j].status); bn_byte_set(&ldata[j].level, d2ladder->info[j].level); bn_byte_set(&ldata[j].class, d2ladder->info[j].class); strncpy(ldata[j].charname,d2ladder->info[j].charname,sizeof(ldata[j].charname)); } fwrite(ldata,1,number*sizeof(*ldata),fdladder); xfree(ldata); } fclose(fdladder); d2ladder_checksum_set(); eventlog(eventlog_level_info,__FUNCTION__,"ladder file saved (%d changes)",d2ladder_change_count); d2ladder_change_count=0; return 0; } int d2ladder_print(FILE *ladderstrm) { t_d2ladder * d2ladder; t_d2ladder_info * ldata; unsigned int i,type; int overalltype,classtype; char laddermode[4][20]={"Hardcore", "Standard","Expansion HC","Expansion" }; char charclass[11][12]={"OverAll", "Amazon", "Sorceress", "Necromancer", "Paladin",\ "Barbarian", "Druid", "Assassin", "","",""} ; for(type=0; type len<=0) continue; ldata=d2ladder->info; overalltype=0; classtype=0; if(type <= D2LADDER_HC_OVERALL+D2CHAR_CLASS_MAX +1) { overalltype=0 ; classtype=type-D2LADDER_HC_OVERALL; } else if (type >= D2LADDER_STD_OVERALL && type<= D2LADDER_STD_OVERALL+D2CHAR_CLASS_MAX +1) { overalltype=1; classtype=type-D2LADDER_STD_OVERALL; } else if (type >= D2LADDER_EXP_HC_OVERALL && type<= D2LADDER_EXP_HC_OVERALL+D2CHAR_EXP_CLASS_MAX +1) { overalltype=2; classtype=type-D2LADDER_EXP_HC_OVERALL; } else if (type >= D2LADDER_EXP_STD_OVERALL && type<= D2LADDER_EXP_STD_OVERALL+D2CHAR_EXP_CLASS_MAX +1) { overalltype=3; classtype=type- D2LADDER_EXP_STD_OVERALL ; } fprintf(ladderstrm,"ladder type %d %s %s\n",type,laddermode[overalltype],charclass[classtype]); fprintf(ladderstrm,"************************************************************************\n"); fprintf(ladderstrm,"No character name level exp status title class \n"); for(i=0; ilen; i++) { fprintf(ladderstrm,"NO.%2d %-16s %2d %10d %2X %1X %s\n", i+1, ldata[i].charname, ldata[i].level, ldata[i].experience, ldata[i].status, 1, charclass[ldata[i].class+1]); } fprintf(ladderstrm,"************************************************************************\n"); fflush(ladderstrm); } return 0; } int d2ladder_checksum(unsigned char const * data, unsigned int len,unsigned int offset) { int checksum; unsigned int i; unsigned int ch; if (!data) return 0; checksum=0; for (i=0; i=offset && i 2000) len = 2000; else len = filesize-curlen; readlen=fread(buffer+curlen,1,len,fdladder); if (readlen<=0) { xfree(buffer); fclose(fdladder); eventlog(eventlog_level_error,__FUNCTION__,"got bad save file or read error(read:%s)",pstrerror(errno)); return -1; } curlen+=readlen; } bn_int_set(&checksum,d2ladder_checksum(buffer,filesize,LADDERFILE_CHECKSUM_OFFSET)); fseek(fdladder,LADDERFILE_CHECKSUM_OFFSET,SEEK_SET); fwrite(&checksum,1,sizeof(checksum),fdladder); xfree(buffer); fclose(fdladder); return 0; } int d2ladder_checksum_check(void) { FILE * fdladder; off_t filesize; int curlen,readlen,len; unsigned char * buffer; int checksum,oldchecksum; t_d2ladderfile_header * header; if (!d2ladder_ladder_file) return -1; fdladder=fopen(d2ladder_ladder_file,"rb"); if(!fdladder) { eventlog(eventlog_level_error,__FUNCTION__,"error open ladder file %s",d2ladder_ladder_file); return -1; } fseek(fdladder,0,SEEK_END); filesize=ftell(fdladder); rewind(fdladder); if(filesize==(off_t)-1) { eventlog(eventlog_level_error,__FUNCTION__,"lseek() error in ladder file %s",d2ladder_ladder_file); fclose(fdladder); return -1; } if(filesize<(signed)sizeof(t_d2ladderfile_header)) { eventlog(eventlog_level_error,__FUNCTION__,"ladder file size error :%s",d2ladder_ladder_file); fclose(fdladder); return -1; } buffer=xmalloc(filesize); header=(t_d2ladderfile_header *)buffer; curlen=0; while(curlen 2000) len = 2000; else len = filesize-curlen; readlen=fread(buffer+curlen,1,len,fdladder); if (readlen<=0) { xfree(buffer); fclose(fdladder); eventlog(eventlog_level_error,__FUNCTION__,"got bad save file or read error(read:%s)",pstrerror(errno)); return -1; } curlen+=readlen; } fclose(fdladder); oldchecksum=bn_int_get(header->checksum); checksum=d2ladder_checksum(buffer,filesize,LADDERFILE_CHECKSUM_OFFSET); xfree(buffer); if(oldchecksum==checksum) { eventlog(eventlog_level_info,__FUNCTION__,"ladder file check pass (checksum=0x%X)",checksum); return 1; } else { eventlog(eventlog_level_debug,__FUNCTION__,"ladder file checksum mismatch 0x%X - 0x%X",oldchecksum, checksum); return 0; } } pvpgn-1.8.5/src/d2dbs/dbserver.h0000644000175000017500000000273011151345317015416 0ustar aaronaaron/* * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_DBSERVER_H #define INCLUDED_DBSERVER_H #include "common/list.h" typedef struct { int sd; unsigned int ipaddr; unsigned char major; unsigned char minor; unsigned char type; unsigned char stats; unsigned int serverid; unsigned int verified; unsigned char serverip[16]; int last_active; int nCharsInReadBuffer; int nCharsInWriteBuffer; char ReadBuf[kBufferSize]; char WriteBuf[kBufferSize]; } t_d2dbs_connection; typedef struct raw_preset_d2gsid { unsigned int ipaddr; unsigned int d2gsid; struct raw_preset_d2gsid *next; } t_preset_d2gsid; int dbs_server_main(void); int dbs_server_shutdown_connection(t_d2dbs_connection* conn); extern t_list * dbs_server_connection_list; #endif pvpgn-1.8.5/src/d2dbs/setup.h0000644000175000017500000000435411151345317014746 0ustar aaronaaron/* * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INLCUDED_D2DBS_SETUP_H #define INLCUDED_D2DBS_SETUP_H #if !defined(MAX_PATH) && !defined(WIN32) # define MAX_PATH 1024 #endif #ifndef WIN32 typedef unsigned int BOOL; #endif #define TRUE 1 #define FALSE 0 #define tf(a) ((a)?1:0) #define SELECT_TIME_OUT 20000 #define kBufferSize (1024*20) #define kMaxPacketLength (1024*5) #define MAX_GAMEPASS_LEN 16 #define MAX_GAMEDESC_LEN 32 #define MAX_CHARNAME_LEN 16 #define MAX_ACCTNAME_LEN 16 #define MAX_GAMENAME_LEN 16 #define MAX_REALMNAME_LEN 32 #define DEFAULT_LOG_FILE "/usr/local/var/d2dbs.log" #define DEFAULT_LOG_FILE_GS "/usr/local/var/d2dbs-gs.log" #define DEFAULT_LOG_LEVELS "info,warn,error" #define D2DBS_CHARSAVE_DIR "/usr/local/var/charsave" #define D2DBS_CHARINFO_DIR "/usr/local/var/charinfo" #define D2DBS_CHARSAVEBAK_DIR "/usr/local/var/bak/charsave" #define D2DBS_CHARINFOBAK_DIR "/usr/local/var/bak/charinfo" #define D2DBS_LADDER_DIR "/usr/local/var/ladders" #ifndef D2DBS_DEFAULT_CONF_FILE # define D2DBS_DEFAULT_CONF_FILE "conf/d2dbs.conf" #endif #define DEFAULT_MEMLOG_FILE "/tmp/d2dbs-mem.log" #define DEFAULT_LISTEN_PORT 6114 #define D2DBS_SERVER_ADDRS "0.0.0.0" #define D2GS_SERVER_LIST "192.168.0.1" #define LOG_LEVEL LOG_MSG #define DEFAULT_GS_MAX 256 #define DEFAULT_SHUTDOWN_DELAY 300 #define DEFAULT_SHUTDOWN_DECR 60 #define DEFAULT_IDLETIME 300 #define DEFAULT_KEEPALIVE_INTERVAL 60 #define DEFAULT_TIMEOUT_CHECKINTERVAL 60 #define DEFAULT_LADDERUPDATE_THRESHOLD 0 #endif pvpgn-1.8.5/src/d2dbs/dbspacket.c0000644000175000017500000007360611151345317015547 0ustar aaronaaron/* * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #include "compat/statmacros.h" #include "compat/mkdir.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memcpy.h" #include "compat/memmove.h" #include "compat/strdup.h" #include "compat/strsep.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #include "compat/psock.h" #include "compat/access.h" #include "compat/rename.h" #include "dbserver.h" #include "dbspacket.h" #include "d2ladder.h" #include "charlock.h" #include "prefs.h" #include "common/bn_type.h" #include "common/d2char_checksum.h" #include "common/xstring.h" #include "d2cs/d2cs_d2gs_character.h" #include "common/list.h" #include "common/eventlog.h" #include "common/addr.h" #include "common/xalloc.h" #include "common/setup_after.h" static unsigned int dbs_packet_savedata_charsave(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int datalen); static unsigned int dbs_packet_savedata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int datalen); static unsigned int dbs_packet_getdata_charsave(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize); static unsigned int dbs_packet_getdata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize); static unsigned int dbs_packet_echoreply(t_d2dbs_connection* conn); static unsigned int dbs_packet_getdata(t_d2dbs_connection* conn); static unsigned int dbs_packet_savedata(t_d2dbs_connection* conn); static unsigned int dbs_packet_charlock(t_d2dbs_connection* conn); static unsigned int dbs_packet_updateladder(t_d2dbs_connection* conn); static int dbs_verify_ipaddr(char const * addrlist,t_d2dbs_connection * c); static int dbs_packet_fix_charinfo(t_d2dbs_connection * conn,char * AccountName,char * CharName,char * charsave); static void dbs_packet_set_charinfo_level(char * CharName,char * charinfo); static unsigned int dbs_packet_savedata_charsave(t_d2dbs_connection* conn, char * AccountName,char * CharName,char * data,unsigned int datalen) { char filename[MAX_PATH]; char savefile[MAX_PATH]; char bakfile[MAX_PATH]; unsigned short curlen,readlen,leftlen,writelen; FILE * fd; int checksum_header; int checksum_calc; strtolower(AccountName); strtolower(CharName); //check if checksum is ok checksum_header = bn_int_get(&data[D2CHARSAVE_CHECKSUM_OFFSET]); checksum_calc = d2charsave_checksum(data,datalen,D2CHARSAVE_CHECKSUM_OFFSET); if (checksum_header != checksum_calc) { eventlog(eventlog_level_error,__FUNCTION__,"received (%x) and calculated(%x) checksum do not match - discarding charsave",checksum_header, checksum_calc); return 0; } sprintf(filename,"%s/.%s.tmp",d2dbs_prefs_get_charsave_dir(),CharName); fd = fopen(filename, "wb"); if (!fd) { eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename); return 0; } curlen=0; leftlen=datalen; while(curlen2000) writelen=2000; else writelen=leftlen; readlen=fwrite(data+curlen,1,writelen,fd); if (readlen<=0) { fclose(fd); eventlog(eventlog_level_error,__FUNCTION__,"write() failed error : %s",pstrerror(errno)); return 0; } curlen+=readlen; leftlen-=readlen; } fclose(fd); sprintf(bakfile,"%s/%s",prefs_get_charsave_bak_dir(),CharName); sprintf(savefile,"%s/%s",d2dbs_prefs_get_charsave_dir(),CharName); if (p_rename(savefile, bakfile)==-1) { eventlog(eventlog_level_warn,__FUNCTION__,"error rename %s to %s", savefile, bakfile); } if (p_rename(filename, savefile)==-1) { eventlog(eventlog_level_error,__FUNCTION__,"error rename %s to %s", filename, savefile); return 0; } eventlog(eventlog_level_info,__FUNCTION__,"saved charsave %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid); return datalen; } static unsigned int dbs_packet_savedata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int datalen) { char savefile[MAX_PATH]; char bakfile[MAX_PATH]; char filepath[MAX_PATH]; char filename[MAX_PATH]; FILE * fd; unsigned short curlen,readlen,leftlen,writelen; struct stat statbuf; strtolower(AccountName); strtolower(CharName); sprintf(filepath,"%s/%s",prefs_get_charinfo_bak_dir(),AccountName); if (stat(filepath,&statbuf)==-1) { p_mkdir(filepath,S_IRWXU|S_IRWXG|S_IRWXO ); eventlog(eventlog_level_info,__FUNCTION__,"created charinfo directory: %s",filepath); } sprintf(filename,"%s/%s/.%s.tmp",d2dbs_prefs_get_charinfo_dir(),AccountName,CharName); fd = fopen(filename, "wb"); if (!fd) { eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename); return 0; } curlen=0; leftlen=datalen; while(curlen2000) writelen=2000; else writelen=leftlen; readlen=fwrite(data+curlen,1,writelen,fd); if (readlen<=0) { fclose(fd); eventlog(eventlog_level_error,__FUNCTION__,"write() failed error : %s",pstrerror(errno)); return 0; } curlen+=readlen; leftlen-=readlen; } fclose(fd); sprintf(bakfile,"%s/%s/%s",prefs_get_charinfo_bak_dir(),AccountName,CharName); sprintf(savefile,"%s/%s/%s",d2dbs_prefs_get_charinfo_dir(),AccountName,CharName); if (p_rename(savefile, bakfile)==-1) { eventlog(eventlog_level_info,__FUNCTION__,"error rename %s to %s", savefile, bakfile); } if (p_rename(filename, savefile)==-1) { eventlog(eventlog_level_error,__FUNCTION__,"error rename %s to %s", filename, savefile); return 0; } eventlog(eventlog_level_info,__FUNCTION__,"saved charinfo %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid); return datalen; } static unsigned int dbs_packet_getdata_charsave(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize) { char filename[MAX_PATH]; char filename_d2closed[MAX_PATH]; FILE * fd; unsigned short curlen,readlen,leftlen,writelen; long filesize; strtolower(AccountName); strtolower(CharName); sprintf(filename,"%s/%s",d2dbs_prefs_get_charsave_dir(),CharName); sprintf(filename_d2closed,"%s/%s.d2s",d2dbs_prefs_get_charsave_dir(),CharName); if ((access(filename, F_OK) < 0) && (access(filename_d2closed, F_OK) == 0)) { rename(filename_d2closed, filename); } fd = fopen(filename, "rb"); if (!fd) { eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename); return 0; } fseek(fd,0,SEEK_END); filesize=ftell(fd); rewind(fd); if (filesize==-1) { fclose(fd); eventlog(eventlog_level_error,__FUNCTION__,"lseek() failed"); return 0; } if ((signed)bufsize < filesize) { fclose(fd); eventlog(eventlog_level_error,__FUNCTION__,"not enough buffer"); return 0; } curlen=0; leftlen=filesize; while(curlen < filesize) { if (leftlen>2000) writelen=2000; else writelen=leftlen; readlen=fread(data+curlen,1,writelen,fd); if (readlen<=0) { fclose(fd); eventlog(eventlog_level_error,__FUNCTION__,"read() failed error : %s",pstrerror(errno)); return 0; } leftlen-=readlen; curlen+=readlen; } fclose(fd); eventlog(eventlog_level_info,__FUNCTION__,"loaded charsave %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid); return filesize; } static unsigned int dbs_packet_getdata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize) { char filename[MAX_PATH]; FILE * fd; unsigned short curlen,readlen,leftlen,writelen; long filesize; strtolower(AccountName); strtolower(CharName); sprintf(filename,"%s/%s/%s",d2dbs_prefs_get_charinfo_dir(),AccountName,CharName); fd = fopen(filename, "rb"); if (!fd) { eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename); return 0; } fseek(fd,0,SEEK_END); filesize=ftell(fd); rewind(fd); if (filesize==-1) { fclose(fd); eventlog(eventlog_level_error,__FUNCTION__,"lseek() failed"); return 0; } if ((signed)bufsize < filesize) { fclose(fd); eventlog(eventlog_level_error,__FUNCTION__,"not enough buffer"); return 0; } curlen=0; leftlen=filesize; while(curlen < filesize) { if (leftlen>2000) writelen=2000; else writelen=leftlen; readlen=fread(data+curlen,1,writelen,fd); if (readlen<=0) { fclose(fd); eventlog(eventlog_level_error,__FUNCTION__,"read() failed error : %s",pstrerror(errno)); return 0; } leftlen-=readlen; curlen+=readlen; } fclose(fd); eventlog(eventlog_level_info,__FUNCTION__,"loaded charinfo %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid); return filesize; } static unsigned int dbs_packet_savedata(t_d2dbs_connection * conn) { unsigned short writelen; unsigned short datatype; unsigned short datalen; unsigned int result; char AccountName[MAX_ACCTNAME_LEN]; char CharName[MAX_CHARNAME_LEN]; char RealmName[MAX_REALMNAME_LEN]; t_d2gs_d2dbs_save_data_request * savecom; t_d2dbs_d2gs_save_data_reply * saveret; char * readpos; unsigned char * writepos; readpos=conn->ReadBuf; savecom=(t_d2gs_d2dbs_save_data_request *)readpos; datatype=bn_short_get(savecom->datatype); datalen=bn_short_get(savecom->datalen); readpos+=sizeof(*savecom); strncpy(AccountName,readpos,MAX_ACCTNAME_LEN); if (AccountName[MAX_ACCTNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max acccount name length exceeded"); return -1; } readpos+=strlen(AccountName)+1; strncpy(CharName,readpos,MAX_CHARNAME_LEN); if (CharName[MAX_CHARNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max char name length exceeded"); return -1; } readpos+=strlen(CharName)+1; strncpy(RealmName,readpos,MAX_REALMNAME_LEN); if (RealmName[MAX_REALMNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max realm name length exceeded"); return -1; } readpos+=strlen(RealmName)+1; if (readpos+datalen!=conn->ReadBuf+bn_short_get(savecom->h.size)) { eventlog(eventlog_level_error,__FUNCTION__,"request packet size error"); return -1; } if (datatype==D2GS_DATA_CHARSAVE) { if (dbs_packet_savedata_charsave(conn,AccountName,CharName,readpos,datalen)>0 && dbs_packet_fix_charinfo(conn,AccountName,CharName,readpos)) { result=D2DBS_SAVE_DATA_SUCCESS; } else { datalen=0; result=D2DBS_SAVE_DATA_FAILED ; } } else if (datatype==D2GS_DATA_PORTRAIT) { /* if level is > 255 , sets level to 255 */ dbs_packet_set_charinfo_level(CharName,readpos); if (dbs_packet_savedata_charinfo(conn,AccountName,CharName,readpos,datalen)>0) { result=D2DBS_SAVE_DATA_SUCCESS; } else { datalen=0; result=D2DBS_SAVE_DATA_FAILED; } } else { eventlog(eventlog_level_error,__FUNCTION__,"unknown data type %d",datatype); return -1; } writelen=sizeof(*saveret)+strlen(CharName)+1; if (writelen > kBufferSize-conn->nCharsInWriteBuffer) return 0; writepos=conn->WriteBuf+conn->nCharsInWriteBuffer; saveret=(t_d2dbs_d2gs_save_data_reply *)writepos; bn_short_set(&saveret->h.type, D2DBS_D2GS_SAVE_DATA_REPLY); bn_short_set(&saveret->h.size,writelen); bn_int_set(&saveret->h.seqno,bn_int_get(savecom->h.seqno)); bn_short_set(&saveret->datatype,bn_short_get(savecom->datatype)); bn_int_set(&saveret->result,result); writepos+=sizeof(*saveret); strncpy(writepos,CharName,MAX_CHARNAME_LEN); conn->nCharsInWriteBuffer += writelen; return 1; } static unsigned int dbs_packet_echoreply(t_d2dbs_connection * conn) { conn->last_active=time(NULL); return 1; } static unsigned int dbs_packet_getdata(t_d2dbs_connection * conn) { unsigned short writelen; unsigned short datatype; unsigned short datalen; unsigned int result; char AccountName[MAX_ACCTNAME_LEN]; char CharName[MAX_CHARNAME_LEN]; char RealmName[MAX_REALMNAME_LEN]; t_d2gs_d2dbs_get_data_request * getcom; t_d2dbs_d2gs_get_data_reply * getret; char * readpos; char * writepos; char databuf[kBufferSize ]; t_d2charinfo_file charinfo; unsigned short charinfolen; unsigned int gsid; readpos=conn->ReadBuf; getcom=(t_d2gs_d2dbs_get_data_request *)readpos; datatype=bn_short_get(getcom->datatype); readpos+=sizeof(*getcom); strncpy(AccountName,readpos,MAX_ACCTNAME_LEN); if (AccountName[MAX_ACCTNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max account name length exceeded"); return -1; } readpos+=strlen(AccountName)+1; strncpy(CharName,readpos,MAX_CHARNAME_LEN); if (CharName[MAX_CHARNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max char name length exceeded"); return -1; } readpos+=strlen(CharName)+1; strncpy(RealmName,readpos,MAX_REALMNAME_LEN); if (RealmName[MAX_REALMNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max realm name length exceeded"); return -1; } readpos+=strlen(RealmName)+1; if (readpos != conn->ReadBuf+bn_short_get(getcom->h.size)) { eventlog(eventlog_level_error,__FUNCTION__,"request packet size error"); return -1; } writepos=conn->WriteBuf+conn->nCharsInWriteBuffer; getret=(t_d2dbs_d2gs_get_data_reply *)writepos; datalen=0; if (datatype==D2GS_DATA_CHARSAVE) { if (cl_query_charlock_status(CharName,RealmName,&gsid)!=0) { eventlog(eventlog_level_warn,__FUNCTION__,"char %s(*%s)@%s is already locked on gs %u",CharName,AccountName,RealmName,gsid); result=D2DBS_GET_DATA_CHARLOCKED; } else if (cl_lock_char(CharName,RealmName,conn->serverid) != 0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to lock char %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid); result=D2DBS_GET_DATA_CHARLOCKED; } else { eventlog(eventlog_level_info,__FUNCTION__,"lock char %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid); datalen=dbs_packet_getdata_charsave(conn,AccountName,CharName,databuf,kBufferSize ); if (datalen>0) { result=D2DBS_GET_DATA_SUCCESS; charinfolen=dbs_packet_getdata_charinfo(conn,AccountName,CharName,(char *)&charinfo,sizeof(charinfo)); if (charinfolen>0) { result=D2DBS_GET_DATA_SUCCESS; } else { result=D2DBS_GET_DATA_FAILED; if (cl_unlock_char(CharName,RealmName,gsid)!=0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to unlock char %s(*%s)@%s for gs %s(%d)",CharName,\ AccountName,RealmName,conn->serverip,conn->serverid); } else { eventlog(eventlog_level_info,__FUNCTION__,"unlock char %s(*%s)@%s for gs %s(%d)",CharName,\ AccountName,RealmName,conn->serverip,conn->serverid); } } } else { datalen=0; result=D2DBS_GET_DATA_FAILED; if (cl_unlock_char(CharName,RealmName,gsid)!=0) { eventlog(eventlog_level_error,__FUNCTION__,"faled to unlock char %s(*%s)@%s for gs %s(%d)",CharName,\ AccountName,RealmName,conn->serverip,conn->serverid); } else { eventlog(eventlog_level_info,__FUNCTION__,"unlock char %s(*%s)@%s for gs %s(%d)",CharName,\ AccountName,RealmName,conn->serverip,conn->serverid); } } } if (result==D2DBS_GET_DATA_SUCCESS) { bn_int_set(&getret->charcreatetime,bn_int_get(charinfo.header.create_time)); /* FIXME: this should be rewritten to support string formatted time */ if (bn_int_get(charinfo.header.create_time)>=prefs_get_ladderinit_time()) { bn_int_set(&getret->allowladder,1); } else { bn_int_set(&getret->allowladder,0); } } else { bn_int_set(&getret->charcreatetime,0); bn_int_set(&getret->allowladder,0); } } else if (datatype==D2GS_DATA_PORTRAIT) { datalen=dbs_packet_getdata_charinfo(conn,AccountName,CharName,databuf,kBufferSize ); if (datalen>0) result=D2DBS_GET_DATA_SUCCESS ; else { datalen=0; result=D2DBS_GET_DATA_FAILED ; } } else { eventlog(eventlog_level_error,__FUNCTION__,"unknown data type %d",datatype); return -1; } writelen=datalen+sizeof(*getret)+strlen(CharName)+1; if (writelen > kBufferSize-conn->nCharsInWriteBuffer) return 0; bn_short_set(&getret->h.type,D2DBS_D2GS_GET_DATA_REPLY); bn_short_set(&getret->h.size,writelen); bn_int_set(&getret->h.seqno,bn_int_get(getcom->h.seqno)); bn_short_set(&getret->datatype,bn_short_get(getcom->datatype)); bn_int_set(&getret->result,result); bn_short_set(&getret->datalen,datalen); writepos+=sizeof(*getret); strncpy(writepos,CharName,MAX_CHARNAME_LEN); writepos+=strlen(CharName)+1; if (datalen) memcpy(writepos,databuf,datalen); conn->nCharsInWriteBuffer += writelen; return 1; } static unsigned int dbs_packet_updateladder(t_d2dbs_connection * conn) { char CharName[MAX_CHARNAME_LEN]; char RealmName[MAX_REALMNAME_LEN]; t_d2gs_d2dbs_update_ladder * updateladder; char * readpos; t_d2ladder_info charladderinfo; readpos=conn->ReadBuf; updateladder=(t_d2gs_d2dbs_update_ladder *)readpos; readpos+=sizeof(*updateladder); strncpy(CharName,readpos,MAX_CHARNAME_LEN); if (CharName[MAX_CHARNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max char name length exceeded"); return -1; } readpos+=strlen(CharName)+1; strncpy(RealmName,readpos,MAX_REALMNAME_LEN); if (RealmName[MAX_REALMNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max realm name length exceeded"); return -1; } readpos+=strlen(RealmName)+1; if (readpos != conn->ReadBuf+bn_short_get(updateladder->h.size)) { eventlog(eventlog_level_error,__FUNCTION__,"request packet size error"); return -1; } strcpy(charladderinfo.charname,CharName); charladderinfo.experience=bn_int_get(updateladder->charexplow); charladderinfo.level=bn_int_get(updateladder->charlevel); charladderinfo.status=bn_short_get(updateladder->charstatus); charladderinfo.class=bn_short_get(updateladder->charclass); eventlog(eventlog_level_info,__FUNCTION__,"update ladder for %s@%s for gs %s(%d)",CharName,RealmName,conn->serverip,conn->serverid); d2ladder_update(&charladderinfo); return 1; } static unsigned int dbs_packet_charlock(t_d2dbs_connection * conn) { char CharName[MAX_CHARNAME_LEN]; char AccountName[MAX_ACCTNAME_LEN]; char RealmName[MAX_REALMNAME_LEN]; t_d2gs_d2dbs_char_lock * charlock; char * readpos; readpos=conn->ReadBuf; charlock=(t_d2gs_d2dbs_char_lock*)readpos; readpos+=sizeof(*charlock); strncpy(AccountName,readpos,MAX_ACCTNAME_LEN); if (AccountName[MAX_ACCTNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max account name length exceeded"); return -1; } readpos+=strlen(AccountName)+1; strncpy(CharName,readpos,MAX_CHARNAME_LEN); if (CharName[MAX_CHARNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max char name length exceeded"); return -1; } readpos+=strlen(CharName)+1; strncpy(RealmName,readpos,MAX_REALMNAME_LEN); if (RealmName[MAX_REALMNAME_LEN-1]!=0) { eventlog(eventlog_level_error,__FUNCTION__,"max realm name length exceeded"); return -1; } readpos+=strlen(RealmName)+1; if (readpos != conn->ReadBuf+ bn_short_get(charlock->h.size)) { eventlog(eventlog_level_error,__FUNCTION__,"request packet size error"); return -1; } if (bn_int_get(charlock->lockstatus)) { if (cl_lock_char(CharName,RealmName,conn->serverid)!=0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to lock character %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid); } else { eventlog(eventlog_level_info,__FUNCTION__,"lock character %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid); } } else { if (cl_unlock_char(CharName,RealmName,conn->serverid) != 0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to unlock character %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid); } else { eventlog(eventlog_level_info,__FUNCTION__,"unlock character %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid); } } return 1; } /* return value: 1 : process one or more packet 0 : not get a whole packet,do nothing -1 : error */ extern int dbs_packet_handle(t_d2dbs_connection* conn) { unsigned short readlen,writelen; t_d2dbs_d2gs_header * readhead; unsigned short retval; if (conn->stats==0) { if (conn->nCharsInReadBuffer<(signed)sizeof(t_d2gs_d2dbs_connect)) { return 0; } conn->stats=1; conn->type=conn->ReadBuf[0]; if (conn->type==CONNECT_CLASS_D2GS_TO_D2DBS) { if (dbs_verify_ipaddr(d2dbs_prefs_get_d2gs_list(),conn)<0) { eventlog(eventlog_level_error,__FUNCTION__,"d2gs connection from unknown ip address"); return -1; } readlen=1; writelen=0; eventlog(eventlog_level_info,__FUNCTION__,"set connection type for gs %s(%d) on socket %d", conn->serverip, conn->serverid, conn->sd); eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"set connection type for gs %s(%d) on socket %d", conn->serverip, conn->serverid, conn->sd); } else { eventlog(eventlog_level_error,__FUNCTION__,"unknown connection type"); return -1; } conn->nCharsInReadBuffer -= readlen; memmove(conn->ReadBuf,conn->ReadBuf+readlen,conn->nCharsInReadBuffer); } else if (conn->stats==1) { if (conn->type==CONNECT_CLASS_D2GS_TO_D2DBS) { while (conn->nCharsInReadBuffer >= (signed)sizeof(*readhead)) { readhead=(t_d2dbs_d2gs_header *)conn->ReadBuf; readlen=bn_short_get(readhead->size); if (conn->nCharsInReadBuffer < readlen) break; switch(bn_short_get(readhead->type)) { case D2GS_D2DBS_SAVE_DATA_REQUEST: retval=dbs_packet_savedata(conn); break; case D2GS_D2DBS_GET_DATA_REQUEST: retval=dbs_packet_getdata(conn); break; case D2GS_D2DBS_UPDATE_LADDER: retval=dbs_packet_updateladder(conn); break; case D2GS_D2DBS_CHAR_LOCK: retval=dbs_packet_charlock(conn); break; case D2GS_D2DBS_ECHOREPLY: retval=dbs_packet_echoreply(conn); break; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown request type %d",\ bn_short_get(readhead->type)); retval=-1; } if (retval!=1) return retval; conn->nCharsInReadBuffer -= readlen; memmove(conn->ReadBuf,conn->ReadBuf+readlen,conn->nCharsInReadBuffer); } } else { eventlog(eventlog_level_error,__FUNCTION__,"unknown connection type %d",conn->type); return -1; } } else { eventlog(eventlog_level_error,__FUNCTION__,"unknown connection stats"); return -1; } return 1; } /* FIXME: we should save client ipaddr into c->ipaddr after accept */ static int dbs_verify_ipaddr(char const * addrlist,t_d2dbs_connection * c) { char * adlist; char * s, * temp; t_elem * elem; t_d2dbs_connection * tempc; unsigned int valid; unsigned int resolveipaddr; adlist = xstrdup(addrlist); temp=adlist; valid=0; while ((s=strsep(&temp, ","))) { host_lookup(s, &resolveipaddr); if(resolveipaddr == 0) continue; if (c->ipaddr == resolveipaddr) { valid=1; break; } } xfree(adlist); if (valid) { eventlog(eventlog_level_info,__FUNCTION__,"ip address %s is valid",addr_num_to_ip_str(c->ipaddr)); LIST_TRAVERSE(dbs_server_connection_list,elem) { if (!(tempc=elem_get_data(elem))) continue; if (tempc !=c && tempc->ipaddr==c->ipaddr) { eventlog(eventlog_level_info,__FUNCTION__,"destroying previous connection %d",tempc->serverid); dbs_server_shutdown_connection(tempc); list_remove_elem(dbs_server_connection_list,&elem); } } c->verified = 1; return 0; } else { eventlog(eventlog_level_info,__FUNCTION__,"ip address %s is invalid",addr_num_to_ip_str(c->ipaddr)); } return -1; } int dbs_check_timeout(void) { t_elem *elem; t_d2dbs_connection *tempc; time_t now; int timeout; now=time(NULL); timeout=d2dbs_prefs_get_idletime(); LIST_TRAVERSE(dbs_server_connection_list,elem) { if (!(tempc=elem_get_data(elem))) continue; if (now-tempc->last_active>timeout) { eventlog(eventlog_level_debug,__FUNCTION__,"connection %d timed out",tempc->serverid); dbs_server_shutdown_connection(tempc); list_remove_elem(dbs_server_connection_list,&elem); continue; } } return 0; } int dbs_keepalive(void) { t_elem *elem; t_d2dbs_connection *tempc; t_d2dbs_d2gs_echorequest *echoreq; unsigned short writelen; unsigned char *writepos; time_t now; writelen = sizeof(t_d2dbs_d2gs_echorequest); now=time(NULL); LIST_TRAVERSE(dbs_server_connection_list,elem) { if (!(tempc=elem_get_data(elem))) continue; if (writelen > kBufferSize - tempc->nCharsInWriteBuffer) continue; writepos = tempc->WriteBuf + tempc->nCharsInWriteBuffer; echoreq = (t_d2dbs_d2gs_echorequest*)writepos; bn_short_set(&echoreq->h.type, D2DBS_D2GS_ECHOREQUEST); bn_short_set(&echoreq->h.size, writelen); /* FIXME: sequence number not set */ bn_int_set(&echoreq->h.seqno, 0); tempc->nCharsInWriteBuffer += writelen; } return 0; } /*************************************************************************************/ #define CHARINFO_SIZE 0xC0 #define CHARINFO_PORTRAIT_LEVEL_OFFSET 0x89 #define CHARINFO_PORTRAIT_STATUS_OFFSET 0x8A #define CHARINFO_SUMMARY_LEVEL_OFFSET 0xB8 #define CHARINFO_SUMMARY_STATUS_OFFSET 0xB4 #define CHARINFO_PORTRAIT_GFX_OFFSET 0x72 #define CHARINFO_PORTRAIT_COLOR_OFFSET 0x7E #define CHARSAVE_LEVEL_OFFSET 0x2B #define CHARSAVE_STATUS_OFFSET 0x24 #define CHARSAVE_GFX_OFFSET 0x88 #define CHARSAVE_COLOR_OFFSET 0x98 #define charstatus_to_portstatus(status) ((((status & 0xFF00) << 1) | (status & 0x00FF)) | 0x8080) #define portstatus_to_charstatus(status) (((status & 0x7F00) >> 1) | (status & 0x007F)) static void dbs_packet_set_charinfo_level(char * CharName,char * charinfo) { if (prefs_get_difficulty_hack()) { /* difficulty hack enabled */ unsigned int level = bn_int_get(&charinfo[CHARINFO_SUMMARY_LEVEL_OFFSET]); unsigned int plevel = bn_byte_get(&charinfo[CHARINFO_PORTRAIT_LEVEL_OFFSET]); /* levels 257 thru 355 */ if (level != plevel) { eventlog(eventlog_level_info,__FUNCTION__,"level mis-match for %s ( %u != %u ) setting to 255",CharName,level,plevel); bn_byte_set((bn_byte *)&charinfo[CHARINFO_PORTRAIT_LEVEL_OFFSET],255); bn_int_set((bn_int *)&charinfo[CHARINFO_SUMMARY_LEVEL_OFFSET],255); } } } static int dbs_packet_fix_charinfo(t_d2dbs_connection * conn,char * AccountName,char * CharName,char * charsave) { if (prefs_get_difficulty_hack()) { unsigned char charinfo[CHARINFO_SIZE]; unsigned int level = bn_byte_get(&charsave[CHARSAVE_LEVEL_OFFSET]); unsigned short status = bn_short_get(&charsave[CHARSAVE_STATUS_OFFSET]); unsigned short pstatus = charstatus_to_portstatus(status); int i; /* * charinfo is only updated from level 1 to 99 (d2gs issue) * from 100 to 256 d2gs does not send it * when value rolls over (level 256 = 0) * and charactar reaches level 257 (rolled over to level 1) * d2gs starts sending it agian until level 356 (rolled over to 100) * is reached agian. etc. etc. etc. */ if (level == 0) /* level 256, 512, 768, etc */ level = 255; if (level < 100) return 1; /* d2gs will send charinfo - level will be set to 255 at that time if needed */ eventlog(eventlog_level_info,__FUNCTION__,"level %u > 99 for %s",level,CharName); if(!(dbs_packet_getdata_charinfo(conn,AccountName,CharName,charinfo,CHARINFO_SIZE))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to get charinfo for %s",CharName); return 0; } /* if level in charinfo file is already set to 255, * then is must have been set when d2gs sent the charinfo * and got a level mis-match (levels 257 - 355) * or level is actually 255. In eather case we set to 255 * this should work for any level mod */ if (bn_byte_get(&charinfo[CHARINFO_PORTRAIT_LEVEL_OFFSET]) == 255) level = 255; eventlog(eventlog_level_info,__FUNCTION__,"updating charinfo for %s -> level = %u , status = 0x%04X , pstatus = 0x%04X",CharName,level,status,pstatus); bn_byte_set((bn_byte *)&charinfo[CHARINFO_PORTRAIT_LEVEL_OFFSET],level); bn_int_set((bn_int *)&charinfo[CHARINFO_SUMMARY_LEVEL_OFFSET],level); bn_short_set((bn_short *)&charinfo[CHARINFO_PORTRAIT_STATUS_OFFSET],pstatus); bn_int_set((bn_int *)&charinfo[CHARINFO_SUMMARY_STATUS_OFFSET],status); for (i=0;i<11;i++) { bn_byte_set((bn_byte *)&charinfo[CHARINFO_PORTRAIT_GFX_OFFSET+i],bn_byte_get(&charsave[CHARSAVE_GFX_OFFSET+i])); bn_byte_set((bn_byte *)&charinfo[CHARINFO_PORTRAIT_COLOR_OFFSET+i],bn_byte_get(&charsave[CHARSAVE_GFX_OFFSET+i])); } if (!(dbs_packet_savedata_charinfo(conn,AccountName,CharName,charinfo,CHARINFO_SIZE))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to save charinfo for %s",CharName); return 0; } return 1; /* charinfo updated */ } return 1; /* difficulty hack not enabled */ } pvpgn-1.8.5/src/d2dbs/dbspacket.h0000644000175000017500000000604211151345317015542 0ustar aaronaaron/* * Copyright (C) 2001 faster (lqx@cic.tsinghua.edu.cn) * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_DBSPACKET_H #define INCLUDED_DBSPACKET_H #include "dbserver.h" #include "common/bn_type.h" /* #pragma pack(1) */ typedef struct { bn_short size; bn_short type; bn_int seqno; } t_d2dbs_d2gs_header; typedef struct { bn_byte class; } t_d2gs_d2dbs_connect; #define CONNECT_CLASS_D2GS_TO_D2DBS 0x65 #define D2GS_D2DBS_SAVE_DATA_REQUEST 0x30 typedef struct { t_d2dbs_d2gs_header h; bn_short datatype; bn_short datalen; /* AccountName */ /* CharName */ /* data */ } t_d2gs_d2dbs_save_data_request; #define D2GS_DATA_CHARSAVE 0x01 #define D2GS_DATA_PORTRAIT 0x02 #define D2DBS_D2GS_SAVE_DATA_REPLY 0x30 typedef struct { t_d2dbs_d2gs_header h; bn_int result; bn_short datatype; /* CharName */ } t_d2dbs_d2gs_save_data_reply; #define D2DBS_SAVE_DATA_SUCCESS 0 #define D2DBS_SAVE_DATA_FAILED 1 #define D2GS_D2DBS_GET_DATA_REQUEST 0x31 typedef struct { t_d2dbs_d2gs_header h; bn_short datatype; /* AccountName */ /* CharName */ } t_d2gs_d2dbs_get_data_request; #define D2DBS_D2GS_GET_DATA_REPLY 0x31 typedef struct { t_d2dbs_d2gs_header h; bn_int result; bn_int charcreatetime; bn_int allowladder; bn_short datatype; bn_short datalen; /* CharName */ /* data */ } t_d2dbs_d2gs_get_data_reply; #define D2DBS_GET_DATA_SUCCESS 0 #define D2DBS_GET_DATA_FAILED 1 #define D2DBS_GET_DATA_CHARLOCKED 2 #define D2GS_D2DBS_UPDATE_LADDER 0x32 typedef struct { t_d2dbs_d2gs_header h; bn_int charlevel; bn_int charexplow; bn_int charexphigh; bn_short charclass; bn_short charstatus; /* CharName */ /* RealmName */ } t_d2gs_d2dbs_update_ladder; #define D2GS_D2DBS_CHAR_LOCK 0x33 typedef struct { t_d2dbs_d2gs_header h; bn_int lockstatus; /* CharName */ /* RealmName */ } t_d2gs_d2dbs_char_lock; #define D2DBS_D2GS_ECHOREQUEST 0x34 typedef struct { t_d2dbs_d2gs_header h; } t_d2dbs_d2gs_echorequest; #define D2GS_D2DBS_ECHOREPLY 0x34 typedef struct { t_d2dbs_d2gs_header h; } t_d2gs_d2dbs_echoreply; #endif extern int dbs_packet_handle(t_d2dbs_connection * conn); extern int dbs_keepalive(void); extern int dbs_check_timeout(void); pvpgn-1.8.5/src/d2dbs/charlock.c0000644000175000017500000001367311151345317015373 0ustar aaronaaron/* * Copyright (C) 2001 faster (lqx@cic.tsinghua.edu.cn) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strcasecmp.h" #include #ifdef HAVE_LIMITS_H # include #endif #include "charlock.h" #include "common/introtate.h" #include "common/xalloc.h" #include "common/setup_after.h" /* FIXME: for simplification, no multiple realm support now */ /* local functions */ static int cl_insert_to_gsq_list(unsigned int gsid, t_charlockinfo *pcl); static int cl_delete_from_gsq_list(t_charlockinfo *pcl); static unsigned int string_hash(char const *string); /* variables */ static unsigned int clitbl_len = 0; static unsigned int gsqtbl_len = 0; static t_charlockinfo * * clitbl = NULL; static t_charlockinfo * * gsqtbl = NULL; int cl_init(unsigned int tbllen, unsigned int maxgs) { if (!tbllen || !maxgs) return -1; cl_destroy(); clitbl = (t_charlockinfo**)xmalloc(tbllen*sizeof(t_charlockinfo**)); gsqtbl = (t_charlockinfo**)xmalloc(maxgs*sizeof(t_charlockinfo**)); memset(clitbl, 0, tbllen*sizeof(t_charlockinfo**)); memset(gsqtbl, 0, maxgs*sizeof(t_charlockinfo**)); clitbl_len = tbllen; gsqtbl_len = maxgs; return 0; } int cl_destroy(void) { unsigned int i; t_charlockinfo * ptl, * ptmp; if (clitbl) { for (i=0; inext; xfree(ptmp); } } xfree(clitbl); } if (gsqtbl) xfree(gsqtbl); clitbl = gsqtbl = NULL; clitbl_len = gsqtbl_len = 0; return 0; } int cl_query_charlock_status(unsigned char *charname, unsigned char *realmname, unsigned int *gsid) { t_charlockinfo *pcl; unsigned int hashval; if (!charname || !realmname) return -1; if (!clitbl_len || !gsqtbl) return -1; if (strlen(charname)>=MAX_CHARNAME_LEN) return -1; hashval = string_hash(charname) % clitbl_len; pcl = clitbl[hashval]; while(pcl) { if (strcasecmp(pcl->charname, charname) == 0) { *gsid = pcl->gsid; return 1; /* found the char, it is locked */ } pcl = pcl->next; } return 0; /* not found, it is unlocked */ } int cl_lock_char(unsigned char *charname, unsigned char *realmname, unsigned int gsid) { t_charlockinfo *pcl, *ptmp; unsigned int hashval; if (!charname || !realmname) return -1; if (!clitbl_len || !gsqtbl) return -1; if (strlen(charname)>=MAX_CHARNAME_LEN) return -1; hashval = string_hash(charname) % clitbl_len; pcl = clitbl[hashval]; ptmp = NULL; while(pcl) { if (strcasecmp(pcl->charname, charname) == 0) return 0; /* found the char is already locked */ ptmp = pcl; pcl = pcl->next; } /* not found, locked it */ pcl = (t_charlockinfo*)xmalloc(sizeof(t_charlockinfo)); memset(pcl, 0, sizeof(t_charlockinfo)); strncpy(pcl->charname, charname, MAX_CHARNAME_LEN-1); strncpy(pcl->realmname, realmname, MAX_REALMNAME_LEN-1); pcl->gsid = gsid; /* add to hash table link list */ if (ptmp) ptmp->next = pcl; else clitbl[hashval] = pcl; /* add to gs specified link list */ cl_insert_to_gsq_list(gsid, pcl); return 0; } int cl_unlock_char(unsigned char *charname, unsigned char *realmname, unsigned int gsid) { t_charlockinfo *pcl, *ptmp; unsigned int hashval; if (!charname || !realmname) return -1; if (!clitbl_len || !gsqtbl) return 0; if (strlen(charname)>=MAX_CHARNAME_LEN) return -1; hashval = string_hash(charname) % clitbl_len; pcl = clitbl[hashval]; ptmp = NULL; while(pcl) { if ((strcasecmp(pcl->charname, charname) == 0) && (pcl->gsid==gsid)) { cl_delete_from_gsq_list(pcl); if (ptmp) ptmp->next = pcl->next; else clitbl[hashval] = pcl->next; xfree(pcl); return 0; } ptmp = pcl; pcl = pcl->next; } return 0; } int cl_unlock_all_char_by_gsid(unsigned int gsid) { unsigned int index_pos; t_charlockinfo *pcl, *pnext; index_pos = gsid % gsqtbl_len; pcl = gsqtbl[index_pos]; while(pcl) { pnext = pcl->gsqnext; cl_unlock_char(pcl->charname, pcl->realmname, gsid); pcl = pnext; } return 0; } static int cl_insert_to_gsq_list(unsigned int gsid, t_charlockinfo *pcl) { unsigned int index_pos; t_charlockinfo *ptmp; if (!pcl) return -1; index_pos = gsid % gsqtbl_len; ptmp = gsqtbl[index_pos]; gsqtbl[index_pos] = pcl; if (ptmp) { pcl->gsqnext = ptmp; ptmp->gsqprev = pcl; } return 0; } static int cl_delete_from_gsq_list(t_charlockinfo *pcl) { unsigned int index_pos; t_charlockinfo *pprev, *pnext; if (!pcl) return -1; index_pos = (pcl->gsid) % gsqtbl_len; pprev = pcl->gsqprev; pnext = pcl->gsqnext; if (pprev) pprev->gsqnext = pnext; else gsqtbl[index_pos] = pnext; if (pnext) pnext->gsqprev = pprev; return 0; } static unsigned int string_hash(char const *string) { unsigned int i; unsigned int pos; unsigned int hash; unsigned int ch; if (!string) return 0; for (hash=0,pos=0,i=0; i #else # ifdef HAVE_MALLOC_H # include # endif #endif #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strdup.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef DO_POSIXSIG # include # include "compat/signal.h" #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include "dbserver.h" #include "prefs.h" #include "d2ladder.h" #include "cmdline.h" #include "handle_signal.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" static void on_signal(int s); static volatile struct { unsigned char do_quit; unsigned char cancel_quit; unsigned char reload_config; unsigned char save_ladder; unsigned int exit_time; } signal_data ={ 0, 0, 0, 0, 0 }; extern int d2dbs_handle_signal(void) { time_t now; char const * levels; char * temp; char const * tok; if (signal_data.cancel_quit) { signal_data.cancel_quit=0; if (!signal_data.exit_time) { eventlog(eventlog_level_info,__FUNCTION__,"there is no previous shutdown to be canceled"); } else { signal_data.exit_time=0; eventlog(eventlog_level_info,__FUNCTION__,"shutdown was canceled due to signal"); } } if (signal_data.do_quit) { signal_data.do_quit=0; now=time(NULL); if (!signal_data.exit_time) { signal_data.exit_time=now+d2dbs_prefs_get_shutdown_delay(); } else { signal_data.exit_time-=d2dbs_prefs_get_shutdown_decr(); } eventlog(eventlog_level_info,__FUNCTION__,"the server is going to shutdown in %lu minutes",(signal_data.exit_time-now)/60); } if (signal_data.exit_time) { now=time(NULL); if (now >= (signed)signal_data.exit_time) { signal_data.exit_time=0; eventlog(eventlog_level_info,__FUNCTION__,"shutdown server due to signal"); return -1; } } if (signal_data.reload_config) { signal_data.reload_config=0; eventlog(eventlog_level_info,__FUNCTION__,"reloading configuartion file due to signal"); if (d2dbs_prefs_reload(cmdline_get_preffile())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error reload configuration file,exitting"); return -1; } eventlog_clear_level(); if ((levels = d2dbs_prefs_get_loglevels())) { temp = xstrdup(levels); tok = strtok(temp,","); /* strtok modifies the string it is passed */ while (tok) { if (eventlog_add_level(tok)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add log level \"%s\"",tok); tok = strtok(NULL,","); } xfree(temp); } #ifdef DO_DAEMONIZE if (!cmdline_get_foreground()) #endif eventlog_open(d2dbs_prefs_get_logfile()); } if (signal_data.save_ladder) { signal_data.save_ladder=0; eventlog(eventlog_level_info,__FUNCTION__,"save ladder data due to signal"); d2ladder_saveladder(); } return 0; } #ifdef WIN32 extern void d2dbs_signal_quit_wrapper(void) { signal_data.do_quit=1; } extern void d2dbs_signal_reload_config_wrapper(void) { signal_data.reload_config = 1; } extern void d2dbs_signal_save_ladder_wrapper(void) { signal_data.save_ladder = 1; } extern void d2dbs_signal_exit_wrapper(void) { signal_data.exit_time = 1; } #else extern int d2dbs_handle_signal_init(void) { signal(SIGINT,on_signal); signal(SIGTERM,on_signal); signal(SIGABRT,on_signal); signal(SIGHUP,on_signal); signal(SIGUSR1,on_signal); signal(SIGPIPE,on_signal); return 0; } static void on_signal(int s) { switch (s) { case SIGINT: eventlog(eventlog_level_debug,__FUNCTION__,"sigint received"); signal_data.do_quit=1; break; case SIGTERM: eventlog(eventlog_level_debug,__FUNCTION__,"sigint received"); signal_data.do_quit=1; break; case SIGABRT: eventlog(eventlog_level_debug,__FUNCTION__,"sigabrt received"); signal_data.cancel_quit=1; break; case SIGHUP: eventlog(eventlog_level_debug,__FUNCTION__,"sighup received"); signal_data.reload_config=1; break; case SIGUSR1: eventlog(eventlog_level_debug,__FUNCTION__,"sigusr1 received"); signal_data.save_ladder=1; break; case SIGPIPE: eventlog(eventlog_level_debug,__FUNCTION__,"sigpipe received"); break; } signal(s,on_signal); } #endif pvpgn-1.8.5/src/d2dbs/cmdline.h0000644000175000017500000000231611151345317015215 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * Copyright (C) 2005 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DDBS_CMDLINE_H_PROTOS__ #define __D2DBS_CMDLINE_H_PROTOS__ extern int cmdline_load(int argc, char * * argv); extern void cmdline_unload(void); /* options exported by cmdline */ #ifdef DO_DAEMONIZE extern int cmdline_get_foreground(void); #endif extern const char* cmdline_get_preffile(void); extern const char* cmdline_get_logfile(void); #endif /* __D2DBS_CMDLINE_H_PROTOS__ */ pvpgn-1.8.5/src/d2dbs/d2ladder.h0000644000175000017500000000343011151345317015261 0ustar aaronaaron/* * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2LADDER_H #define INCLUDED_D2LADDER_H #include #include "common/list.h" #include "d2cs/d2cs_d2dbs_ladder.h" #define JUST_NEED_TYPES #include "d2cs/d2charfile.h" #undef JUST_NEED_TYPES #define LADDER_BACKUP_PREFIX "ladderbk" #define DEFAULT_LADDER_DIR "var/ladders" #define LADDERFILE_CHECKSUM_OFFSET offsetof(t_d2ladderfile_header,checksum) typedef struct { unsigned int experience; unsigned short status; unsigned char level; unsigned char class; char charname[MAX_CHARNAME_LEN]; } t_d2ladder_info; typedef struct { unsigned int type; t_d2ladder_info * info; unsigned int len; } t_d2ladder; typedef t_list t_d2ladderlist; #define D2LADDER_MAXNUM 200 #define D2LADDER_OVERALL_MAXNUM 1000 #define D2LADDER_MAXTYPE 35 extern int d2dbs_d2ladder_init(void); extern int d2dbs_d2ladder_destroy(void); extern int d2ladder_rebuild(void); extern int d2ladder_update(t_d2ladder_info * pcharladderinfo); extern int d2ladder_print(FILE * ladderstrm); extern int d2ladder_saveladder(void); #endif pvpgn-1.8.5/src/client/0000755000175000017500000000000011151345372013710 5ustar aaronaaronpvpgn-1.8.5/src/client/bnbot.c0000644000175000017500000002260211151345317015161 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memset.h" #include "compat/memcpy.h" #include #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_TERMIOS_H # include #endif #include "compat/termios.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/send.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #ifdef HAVE_NETDB_H # include #endif #include "compat/psock.h" #include "common/packet.h" #include "common/init_protocol.h" #include "common/bot_protocol.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/network.h" #include "common/version.h" #include "common/util.h" #ifdef CLIENTDEBUG # include "common/eventlog.h" #endif #include "client.h" #include "common/setup_after.h" static void usage(char const * progname); static void usage(char const * progname) { fprintf(stderr,"usage: %s [] [ []]\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n", progname); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { int a; int sd; struct sockaddr_in saddr; t_packet * packet; t_packet * rpacket; char const * servname=NULL; unsigned short servport=0; char text[MAX_MESSAGE_LEN]; struct hostent * host; unsigned int commpos; struct termios in_attr_old; struct termios in_attr_new; int changed_in; unsigned int currsize; int fd_stdin; unsigned int screen_width,screen_height; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a=argc) { if (str_to_ushort(argv[a],&servport)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (!servname && argv[a][0]!='-' && a+2>=argc) servname = argv[a]; else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0) { printf("version "PVPGN_VERSION"\n"); return STATUS_SUCCESS; } else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage")==0) usage(argv[0]); else { fprintf(stderr,"%s: unknown option \"%s\"\n",argv[0],argv[a]); usage(argv[0]); } if (servport==0) servport = BNETD_SERV_PORT; if (!servname) servname = BNETD_DEFAULT_HOST; if (psock_init()<0) { fprintf(stderr,"%s: could not inialialize socket functions\n",argv[0]); return STATUS_FAILURE; } if (!(host = gethostbyname(servname))) { fprintf(stderr,"%s: unknown host \"%s\"\n",argv[0],servname); return STATUS_FAILURE; } fd_stdin = fileno(stdin); if (tcgetattr(fd_stdin,&in_attr_old)>=0) { in_attr_new = in_attr_old; in_attr_new.c_lflag &= ~(ECHO | ICANON); /* turn off ECHO and ICANON */ in_attr_new.c_cc[VMIN] = 0; /* don't require reads to return data */ in_attr_new.c_cc[VTIME] = 1; /* timeout = .1 second */ tcsetattr(fd_stdin,TCSANOW,&in_attr_new); changed_in = 1; } else { fprintf(stderr,"%s: could not set terminal attributes for stdin\n",argv[0]); changed_in = 0; } if (client_get_termsize(fd_stdin,&screen_width,&screen_height)<0) { fprintf(stderr,"%s: could not determine screen size\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } if ((sd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0) { fprintf(stderr,"%s: could not create socket (psock_socket: %s)\n",argv[0],pstrerror(psock_errno())); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } memset(&saddr,0,sizeof(saddr)); saddr.sin_family = PSOCK_AF_INET; saddr.sin_port = htons(servport); memcpy(&saddr.sin_addr.s_addr,host->h_addr_list[0],host->h_length); if (psock_connect(sd,(struct sockaddr *)&saddr,sizeof(saddr))<0) { fprintf(stderr,"%s: could not connect to server \"%s\" port %hu (psock_connect: %s)\n",argv[0],servname,servport,pstrerror(psock_errno())); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } if (psock_ctl(sd,PSOCK_NONBLOCK)<0) { fprintf(stderr,"%s: could not set TCP socket to non-blocking mode (psock_ctl: %s)\n",argv[0],pstrerror(psock_errno())); psock_close(sd); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } printf("Connected to %s:%hu.\n",inet_ntoa(saddr.sin_addr),servport); #ifdef CLIENTDEBUG eventlog_set(stderr); #endif if (!(packet = packet_create(packet_class_init))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } bn_byte_set(&packet->u.client_initconn.class,CLIENT_INITCONN_CLASS_BOT); client_blocksend_packet(sd,packet); packet_del_ref(packet); if (!(rpacket = packet_create(packet_class_raw))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } if (!(packet = packet_create(packet_class_raw))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } packet_append_ntstring(packet,"\004"); client_blocksend_packet(sd,packet); packet_del_ref(packet); { int highest_fd; t_psock_fd_set rfds; PSOCK_FD_ZERO(&rfds); highest_fd = fd_stdin; if (sd>highest_fd) highest_fd = sd; commpos = 0; text[0] = '\0'; for (;;) { PSOCK_FD_SET(fd_stdin,&rfds); PSOCK_FD_SET(sd,&rfds); if (psock_select(highest_fd+1,&rfds,NULL,NULL,NULL)<0) { if (errno!=PSOCK_EINTR) fprintf(stderr,"%s: select failed (select: %s)\n",argv[0],pstrerror(errno)); continue; } if (PSOCK_FD_ISSET(sd,&rfds)) /* got network data */ { packet_set_size(rpacket,MAX_PACKET_SIZE-1); currsize = 0; if (net_recv_packet(sd,rpacket,&currsize)<0) { psock_close(sd); sd = -1; } if (currsize>0) { char * str=packet_get_raw_data(rpacket,0); str[currsize] = '\0'; printf("%s",str); fflush(stdout); } if (sd==-1) /* if connection was closed */ { printf("Connection closed by server.\n"); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); packet_del_ref(rpacket); return STATUS_SUCCESS; } } if (PSOCK_FD_ISSET(fd_stdin,&rfds)) /* got keyboard data */ { switch (client_get_comm("",text,sizeof(text),&commpos,-1,0,screen_width)) { case -1: /* cancel */ if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; case 0: /* timeout */ break; case 1: if (!(packet = packet_create(packet_class_raw))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); packet_del_ref(rpacket); return STATUS_FAILURE; } packet_append_ntstring(packet,text); packet_append_ntstring(packet,"\r\n"); client_blocksend_packet(sd,packet); packet_del_ref(packet); commpos = 0; text[0] = '\0'; } } } } /* not reached */ } pvpgn-1.8.5/src/client/udptest.c0000644000175000017500000001217711151345317015553 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memset.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/recv.h" #include "compat/send.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #include "compat/psock.h" #include "common/packet.h" #include "common/init_protocol.h" #include "common/udp_protocol.h" #include "common/tag.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/network.h" #include "client.h" #include "udptest.h" #include "common/setup_after.h" #ifdef CLIENTDEBUG #define dprintf printf #else #define dprintf if (0) printf #endif extern int client_udptest_setup(char const * progname, unsigned short * lsock_port_ret) { int lsock; struct sockaddr_in laddr; unsigned short lsock_port; if (!progname) { fprintf(stderr,"got NULL progname\n"); return -1; } if ((lsock = psock_socket(PF_INET,SOCK_DGRAM,PSOCK_IPPROTO_UDP))<0) { fprintf(stderr,"%s: could not create UDP socket (psock_socket: %s)\n",progname,pstrerror(psock_errno())); return -1; } if (psock_ctl(lsock,PSOCK_NONBLOCK)<0) fprintf(stderr,"%s: could not set UDP socket to non-blocking mode (psock_ctl: %s)\n",progname,pstrerror(psock_errno())); for (lsock_port=BNETD_MIN_TEST_PORT; lsock_port<=BNETD_MAX_TEST_PORT; lsock_port++) { memset(&laddr,0,sizeof(laddr)); laddr.sin_family = PSOCK_AF_INET; laddr.sin_port = htons(lsock_port); laddr.sin_addr.s_addr = htonl(INADDR_ANY); if (psock_bind(lsock,(struct sockaddr *)&laddr,(psock_t_socklen)sizeof(laddr))==0) break; if (lsock_port==BNETD_MIN_TEST_PORT) dprintf("Could not bind to standard UDP port %hu, trying others. (psock_bind: %s)\n",BNETD_MIN_TEST_PORT,pstrerror(psock_errno())); } if (lsock_port>BNETD_MAX_TEST_PORT) { fprintf(stderr,"%s: could not bind to any UDP port %hu through %hu (psock_bind: %s)\n",progname,BNETD_MIN_TEST_PORT,BNETD_MAX_TEST_PORT,pstrerror(psock_errno())); psock_close(lsock); return -1; } if (lsock_port_ret) *lsock_port_ret = lsock_port; return lsock; } extern int client_udptest_recv(char const * progname, int lsock, unsigned short lsock_port, unsigned int timeout) { int len; unsigned int count; t_packet * rpacket; time_t start; if (!progname) { fprintf(stderr,"%s: got NULL progname\n",progname); return -1; } if (!(rpacket = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",progname); return -1; } start = time(NULL); count = 0; while (start+(time_t)timeout>=time(NULL)) /* timeout after a few seconds from last packet */ { if ((len = psock_recv(lsock,packet_get_raw_data_build(rpacket,0),MAX_PACKET_SIZE,0))<0) { if (psock_errno()!=PSOCK_EAGAIN && psock_errno()!=PSOCK_EWOULDBLOCK) fprintf(stderr,"%s: failed to receive UDPTEST on port %hu (psock_recv: %s)\n",progname,lsock_port,pstrerror(psock_errno())); continue; } packet_set_size(rpacket,len); if (packet_get_type(rpacket)!=SERVER_UDPTEST) { dprintf("Got unexpected UDP packet type %u on port %hu\n",packet_get_type(rpacket),lsock_port); continue; } if (bn_int_tag_eq(rpacket->u.server_udptest.bnettag,BNETTAG)<0) { fprintf(stderr,"%s: got bad UDPTEST packet on port %hu\n",progname,lsock_port); continue; } count++; if (count>=2) break; start = time(NULL); } packet_destroy(rpacket); if (count<2) { printf("Only received %d UDP packets on port %hu. Connection may be slow or firewalled.\n",count,lsock_port); return -1; } return 0; } pvpgn-1.8.5/src/client/client.h0000644000175000017500000000247211151345317015343 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_CLIENT_PROTOS #define INCLUDED_CLIENT_PROTOS extern int client_blocksend_packet(int sock, t_packet const * packet); extern int client_blockrecv_packet(int sock, t_packet * packet); extern int client_blockrecv_raw_packet(int sock, t_packet * packet, unsigned int len); extern int client_get_termsize(int fd, unsigned int * w, unsigned int * h); extern int client_get_comm(char const * prompt, char * text, unsigned int maxlen, unsigned int * curpos, int visible, int redraw, unsigned int width); #endif #endif pvpgn-1.8.5/src/client/bnchat.c0000644000175000017500000017244711151345317015331 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999 Oleg Drokin (green@ccssu.ccssu.crimea.ua) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/vargs.h" #include #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_TERMIOS_H # include #endif #include "compat/termios.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SIGACTION # include # include "compat/signal.h" #endif #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #include "compat/psock.h" #include "common/packet.h" #include "common/init_protocol.h" #include "common/udp_protocol.h" #include "common/bnet_protocol.h" #include "common/file_protocol.h" #include "common/tag.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/network.h" #include "common/bnethash.h" #include "common/bnethashconv.h" #include "ansi_term.h" #include "common/version.h" #include "common/util.h" #include "common/xalloc.h" #include "common/hexdump.h" #ifdef CLIENTDEBUG # include "common/eventlog.h" #endif #include "client.h" #include "udptest.h" #include "client_connect.h" #ifdef WIN32 # include /* for kbhit() and getch() */ #endif #include "compat/vsnprintf.h" #include "common/setup_after.h" #ifdef CLIENTDEBUG # define dprintf printf #else # define dprintf if (0) printf #endif #define CHANNEL_BNCHATBOT "Chat" #define CHANNEL_STARCRAFT "Starcraft" #define CHANNEL_BROODWARS "Brood War" #define CHANNEL_SHAREWARE "Starcraft Shareware" #define CHANNEL_DIABLORTL "Diablo Retail" #define CHANNEL_DIABLOSHR "Diablo Shareware" /* FIXME: is this one right? */ #define CHANNEL_WARCIIBNE "War2BNE" #define CHANNEL_DIABLO2DV "Diablo II" #define CHANNEL_DIABLO2XP "Diablo II" #define CHANNEL_WARCRAFT3 "W3" #define CHANNEL_WAR3XP "W3" volatile int handle_winch=0; typedef enum { mode_chat, mode_command, mode_waitstat, mode_waitgames, mode_waitladder, mode_gamename, mode_gamepass, mode_gamewait, mode_gamestop, mode_claninvite } t_mode; typedef struct _client_state { int useansi; int sd; struct sockaddr_in saddr; unsigned int sessionkey; unsigned int sessionnum; unsigned int currsize; unsigned int commpos; struct termios in_attr_old; struct termios in_attr_new; int changed_in; int fd_stdin; unsigned int screen_width,screen_height; int munged; t_mode mode; char text[MAX_MESSAGE_LEN]; } t_client_state; typedef struct _user_info { char const * clienttag; char const * archtag; char const * gamelang; char player[MAX_MESSAGE_LEN]; char const * cdowner; char const * cdkey; char const * channel; char curr_gamename[GAME_NAME_LEN]; char curr_gamepass[GAME_PASS_LEN]; int count, clantag; char const * inviter; } t_user_info; static char const * mflags_get_str(unsigned int flags); static char const * cflags_get_str(unsigned int flags); static char const * mode_get_prompt(t_mode mode); static int print_file(struct sockaddr_in * saddr, char const * filename, char const * progname, char const * clienttag); static void usage(char const * progname); #ifdef HAVE_SIGACTION static void winch_sig_handle(int unused); #endif #ifdef HAVE_SIGACTION static void winch_sig_handle(int unused) { handle_winch = 1; } #endif static char const * mflags_get_str(unsigned int flags) { static char buffer[32]; buffer[0]=buffer[1] = '\0'; if (flags&MF_BLIZZARD) strcat(buffer,",Blizzard"); if (flags&MF_GAVEL) strcat(buffer,",Gavel"); if (flags&MF_VOICE) strcat(buffer,",Megaphone"); if (flags&MF_BNET) strcat(buffer,",BNET"); if (flags&MF_PLUG) strcat(buffer,",Plug"); if (flags&MF_X) strcat(buffer,",X"); if (flags&MF_SHADES) strcat(buffer,",Shades"); if (flags&MF_PGLPLAY) strcat(buffer,",PGL_Player"); if (flags&MF_PGLOFFL) strcat(buffer,",PGL_Official"); buffer[0] = '['; strcat(buffer,"]"); return buffer; } static char const * cflags_get_str(unsigned int flags) { static char buffer[32]; buffer[0]=buffer[1] = '\0'; if (flags&CF_PUBLIC) strcat(buffer,",Public"); if (flags&CF_MODERATED) strcat(buffer,",Moderated"); if (flags&CF_RESTRICTED) strcat(buffer,",Restricted"); if (flags&CF_THEVOID) strcat(buffer,",The Void"); if (flags&CF_SYSTEM) strcat(buffer,",System"); if (flags&CF_OFFICIAL) strcat(buffer,",Official"); buffer[0] = '['; strcat(buffer,"]"); return buffer; } static char const * mode_get_prompt(t_mode mode) { switch (mode) { case mode_chat: return "] "; case mode_command: return "command> "; case mode_waitstat: case mode_waitgames: case mode_waitladder: case mode_gamewait: return "*please wait* "; case mode_gamename: return "Name: "; case mode_gamepass: return "Password: "; case mode_gamestop: return "[Return to kill game] "; default: return "? "; } } static int print_file(struct sockaddr_in * saddr, char const * filename, char const * progname, char const * clienttag) { int sd; t_packet * ipacket; t_packet * packet; t_packet * rpacket; t_packet * fpacket; unsigned int currsize; unsigned int filelen; if (!saddr || !filename || !progname) return -1; if ((sd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0) { fprintf(stderr,"%s: could not create socket (psock_socket: %s)\n",progname,pstrerror(psock_errno())); return -1; } if (psock_connect(sd,(struct sockaddr *)saddr,sizeof(*saddr))<0) { fprintf(stderr,"%s: could not connect to server (psock_connect: %s)\n",progname,pstrerror(psock_errno())); return -1; } if (!(ipacket = packet_create(packet_class_init))) { fprintf(stderr,"%s: could not create packet\n",progname); return -1; } bn_byte_set(&ipacket->u.client_initconn.class,CLIENT_INITCONN_CLASS_FILE); client_blocksend_packet(sd,ipacket); packet_del_ref(ipacket); if (!(rpacket = packet_create(packet_class_file))) { fprintf(stderr,"%s: could not create packet\n",progname); return -1; } if (!(fpacket = packet_create(packet_class_raw))) { fprintf(stderr,"%s: could not create packet\n",progname); return -1; } if (!(packet = packet_create(packet_class_file))) { fprintf(stderr,"%s: could not create packet\n",progname); return -1; } packet_set_size(packet,sizeof(t_client_file_req)); packet_set_type(packet,CLIENT_FILE_REQ); bn_int_tag_set(&packet->u.client_file_req.archtag,ARCHTAG_WINX86); bn_int_tag_set(&packet->u.client_file_req.clienttag,clienttag); bn_int_set(&packet->u.client_file_req.adid,0); bn_int_set(&packet->u.client_file_req.extensiontag,0); bn_int_set(&packet->u.client_file_req.startoffset,0); bn_long_set_a_b(&packet->u.client_file_req.timestamp,0x00000000,0x00000000); packet_append_string(packet,filename); client_blocksend_packet(sd,packet); packet_del_ref(packet); do if (client_blockrecv_packet(sd,rpacket)<0) { fprintf(stderr,"%s: server closed file connection\n",progname); packet_del_ref(fpacket); packet_del_ref(rpacket); return -1; } while (packet_get_type(rpacket)!=SERVER_FILE_REPLY); filelen = bn_int_get(rpacket->u.server_file_reply.filelen); packet_del_ref(rpacket); for (currsize=0; currsize+MAX_PACKET_SIZE<=filelen; currsize+=MAX_PACKET_SIZE) { if (client_blockrecv_raw_packet(sd,fpacket,MAX_PACKET_SIZE)<0) { fflush(stdout); fprintf(stderr,"%s: server closed file connection\n",progname); packet_del_ref(fpacket); return -1; } str_print_term(stdout,packet_get_raw_data_const(fpacket,0),MAX_PACKET_SIZE,1); } filelen -= currsize; if (filelen) { if (client_blockrecv_raw_packet(sd,fpacket,filelen)<0) { fflush(stdout); fprintf(stderr,"%s: server closed file connection\n",progname); packet_del_ref(fpacket); return -1; } str_print_term(stdout,packet_get_raw_data_const(fpacket,0),filelen,1); } fflush(stdout); psock_close(sd); packet_del_ref(fpacket); return 0; } static void usage(char const * progname) { fprintf(stderr,"usage: %s [] [ []]\n",progname); fprintf(stderr, " -a, --ansi-color use ANSI colors\n" " -n, --new-account create a new account\n" " -c, --change-password change account password\n" " --client=CHAT report client as a chat bot\n" " -b, --client=SEXP report client as Brood Wars\n" " -d, --client=DRTL report client as Diablo Retail\n" " --client=DSHR report client as Diablo Shareware\n"); fprintf(stderr, " -s, --client=STAR report client as Starcraft (default)\n" " --client=SSHR report client as Starcraft Shareware\n" " -w, --client=W2BN report client as Warcraft II BNE\n" " --client=D2DV report client as Diablo II\n" " --client=D2XP report client as Diablo II: LoD\n" " --client=WAR3 report client as Warcraft III\n" " --client=W3XP report client as Warcraft III Frozen Throne\n" " --arch=IX86 report architecture as Intel x86 (default)\n" " --arch=PMAC report architecture as PowerPC MacOS\n" " --arch=XMAC report architecture as PowerPC MacOSX\n"); fprintf(stderr, " -o NAME, --owner=NAME report CD owner as NAME\n" " -k KEY, --cdkey=KEY report CD key as KEY\n" " -l LANG --lang=LANG report language as LANG (default \"enUS\")\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n"); exit(STATUS_FAILURE); } int read_commandline(int argc, char * * argv, char const * * servname, unsigned short * servport, char const * * clienttag, char const * * archtag, int * changepass, int * newacct, char const * * channel, char const * * cdowner, char const * * cdkey, char const * * gamelang, int * useansi) { int a; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a=argc) { if (str_to_ushort(argv[a],servport)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (!(*servname) && argv[a][0]!='-' && a+2>=argc) *servname = argv[a]; else if (strcmp(argv[a],"-a")==0 || strcmp(argv[a],"--use-ansi")==0) *useansi = 1; else if (strcmp(argv[a],"-n")==0 || strcmp(argv[a],"--new-account")==0) { if (*changepass) { fprintf(stderr,"%s: can not create new account when changing passwords\n",argv[0]); usage(argv[0]); } *newacct = 1; } else if (strcmp(argv[a],"-c")==0 || strcmp(argv[a],"--change-password")==0) { if (*newacct) { fprintf(stderr,"%s: can not change passwords when creating a new account\n",argv[0]); usage(argv[0]); } *changepass = 1; } else if (strcmp(argv[a],"--client=CHAT")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_BNCHATBOT; *channel = CHANNEL_BNCHATBOT; } else if (strcmp(argv[a],"-b")==0 || strcmp(argv[a],"--client=SEXP")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_BROODWARS; *channel = CHANNEL_BROODWARS; } else if (strcmp(argv[a],"-d")==0 || strcmp(argv[a],"--client=DRTL")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_DIABLORTL; *channel = CHANNEL_DIABLORTL; } else if (strcmp(argv[a],"--client=DSHR")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_DIABLOSHR; *channel = CHANNEL_DIABLOSHR; } else if (strcmp(argv[a],"-s")==0 || strcmp(argv[a],"--client=STAR")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_STARCRAFT; *channel = CHANNEL_STARCRAFT; } else if (strcmp(argv[a],"--client=SSHR")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_SHAREWARE; *channel = CHANNEL_SHAREWARE; } else if (strcmp(argv[a],"-w")==0 || strcmp(argv[a],"--client=W2BN")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_WARCIIBNE; *channel = CHANNEL_WARCIIBNE; } else if (strcmp(argv[a],"--client=D2DV")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_DIABLO2DV; *channel = CHANNEL_DIABLO2DV; } else if (strcmp(argv[a],"--client=D2XP")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_DIABLO2XP; *channel = CHANNEL_DIABLO2XP; } else if (strcmp(argv[a],"--client=WAR3")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_WARCRAFT3; *channel = CHANNEL_WARCRAFT3; } else if (strcmp(argv[a],"--client=W3XP")==0) { if (*clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag); usage(argv[0]); } *clienttag = CLIENTTAG_WAR3XP; *channel = CHANNEL_WAR3XP; } else if (strncmp(argv[a],"--client=",9)==0) { fprintf(stderr,"%s: unknown client tag \"%s\"\n",argv[0],&argv[a][9]); usage(argv[0]); } else if (strcmp(argv[a],"--arch=IX86")==0) { *archtag = ARCHTAG_WINX86; } else if (strcmp(argv[a],"--arch=PMAC")==0) { *archtag = ARCHTAG_MACPPC; } else if (strcmp(argv[a],"--arch=XMAC")==0) { *archtag = ARCHTAG_OSXPPC; } else if (strncmp(argv[a],"--arch=",7)==0) { fprintf(stderr,"%s: unknown architecture tag \"%s\"\n",argv[0],&argv[a][7]); usage(argv[0]); } else if (strcmp(argv[a],"-o")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (*cdowner) { fprintf(stderr,"%s: CD owner was already specified as \"%s\"\n",argv[0],*cdowner); usage(argv[0]); } *cdowner = argv[++a]; } else if (strncmp(argv[a],"--owner=",8)==0) { if (*cdowner) { fprintf(stderr,"%s: CD owner was already specified as \"%s\"\n",argv[0],*cdowner); usage(argv[0]); } *cdowner = &argv[a][8]; } else if (strcmp(argv[a],"-k")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (*cdkey) { fprintf(stderr,"%s: CD key was already specified as \"%s\"\n",argv[0],*cdkey); usage(argv[0]); } *cdkey = argv[++a]; } else if (strncmp(argv[a],"--cdkey=",8)==0) { if (*cdkey) { fprintf(stderr,"%s: CD key was already specified as \"%s\"\n",argv[0],*cdkey); usage(argv[0]); } *cdkey = &argv[a][8]; } else if (strcmp(argv[a],"-l")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (strlen(argv[a + 1]) != 4) { fprintf(stderr,"%s: language has to be 4 characters long\n",argv[0]); usage(argv[0]); } *gamelang = argv[++a]; } else if (strncmp(argv[a],"--lang=",7)==0) { if (strlen(argv[a] + 7) != 4) { fprintf(stderr,"%s: language has to be 4 characters long\n",argv[0]); usage(argv[0]); } *gamelang = &argv[a][7]; } else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0) { printf("version "PVPGN_VERSION"\n"); return STATUS_SUCCESS; } else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage")==0) usage(argv[0]); else if (strcmp(argv[a],"--client")==0 || strcmp(argv[a],"--owner")==0 || strcmp(argv[a],"--cdkey")==0) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } else { fprintf(stderr,"%s: unknown option \"%s\"\n",argv[0],argv[a]); usage(argv[0]); } if (*servport==0) *servport = BNETD_SERV_PORT; if (!(*cdowner)) *cdowner = BNETD_DEFAULT_OWNER; if (!(*cdkey)) *cdkey = BNETD_DEFAULT_KEY; if (!(*clienttag)) { *clienttag = CLIENTTAG_STARCRAFT; *channel = CHANNEL_STARCRAFT; } if (!(*servname)) *servname = BNETD_DEFAULT_HOST; return 0; } void munge(t_client_state * client) { int i; if (!client->munged) { printf("\r"); for (i=0; imode)); i++) printf(" "); for (i=0; itext) && iscreen_width-strlen(mode_get_prompt(client->mode)); i++) printf(" "); printf("\r"); client->munged = 1; } } void ansi_printf(t_client_state * client,int color, char const * fmt, ...) { va_list args; char buffer[2048]; if (!(client)) return; if (!(fmt)) return; if (client->useansi) ansi_text_color_fore(color); VA_START(args,fmt); vsnprintf(buffer,2048,fmt,args); va_end(args); str_print_term(stdout,buffer,0,1); if (client->useansi) ansi_text_reset(); fflush(stdout); } extern int main(int argc, char * argv[]) { int newacct=0; int changepass=0; t_client_state client; t_user_info user; t_packet * packet; t_packet * rpacket; char const * servname=NULL; unsigned short servport=0; char const * * channellist; unsigned int statsmatch=24; /* any random number that is rare in uninitialized fields */ memset(&user,0,sizeof(t_user_info)); memset(&client,0,sizeof(t_client_state)); /* default values */ user.archtag = ARCHTAG_WINX86; user.gamelang = CLIENT_COUNTRYINFO_109_GAMELANG; read_commandline(argc,argv,&servname,&servport,&user.clienttag,&user.archtag,&changepass, &newacct,&user.channel,&user.cdowner,&user.cdkey,&user.gamelang,&client.useansi); client.fd_stdin = fileno(stdin); if (tcgetattr(client.fd_stdin,&client.in_attr_old)>=0) { client.in_attr_new = client.in_attr_old; client.in_attr_new.c_lflag &= ~(ECHO | ICANON); /* turn off ECHO and ICANON */ client.in_attr_new.c_cc[VMIN] = 0; /* don't require reads to return data */ client.in_attr_new.c_cc[VTIME] = 1; /* timeout = .1 seconds */ tcsetattr(client.fd_stdin,TCSANOW,&client.in_attr_new); client.changed_in = 1; } else { fprintf(stderr,"%s: could not set terminal attributes for stdin\n",argv[0]); client.changed_in = 0; } #ifdef HAVE_SIGACTION { struct sigaction winch_action; winch_action.sa_handler = winch_sig_handle; sigemptyset(&winch_action.sa_mask); winch_action.sa_flags = SA_RESTART; sigaction(SIGWINCH,&winch_action,NULL); } #endif if (client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height)<0) { fprintf(stderr,"%s: could not determine screen size\n",argv[0]); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } if (client.useansi) { ansi_text_reset(); ansi_screen_clear(); ansi_cursor_move_home(); fflush(stdout); } if ((client.sd = client_connect(argv[0], servname,servport,user.cdowner,user.cdkey,user.clienttag, &client.saddr,&client.sessionkey,&client.sessionnum,user.archtag,user.gamelang))<0) { fprintf(stderr,"%s: fatal error during handshake\n",argv[0]); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } /* reuse this same packet over and over */ if (!(rpacket = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } packet_set_size(packet,sizeof(t_client_fileinforeq)); packet_set_type(packet,CLIENT_FILEINFOREQ); bn_int_set(&packet->u.client_fileinforeq.type,CLIENT_FILEINFOREQ_TYPE_TOS); bn_int_set(&packet->u.client_fileinforeq.unknown2,CLIENT_FILEINFOREQ_UNKNOWN2); if ((user.clienttag == CLIENTTAG_DIABLO2DV) || (user.clienttag == CLIENTTAG_DIABLO2XP)) packet_append_string(packet,CLIENT_FILEINFOREQ_FILE_TOSUNICODEUSA); else packet_append_string(packet,CLIENT_FILEINFOREQ_FILE_TOSUSA); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); do if (client_blockrecv_packet(client.sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } while (packet_get_type(rpacket)!=SERVER_FILEINFOREPLY); /* real client would also send statsreq on past logins here */ printf("----\n"); if (newacct) { if (client.useansi) ansi_text_color_fore(ansi_text_color_red); printf("###### Terms Of Service ######\n"); print_file(&client.saddr,packet_get_str_const(rpacket,sizeof(t_server_fileinforeply),1024),argv[0],user.clienttag); printf("##############################\n\n"); if (client.useansi) ansi_text_reset(); } for (;;) { char password[MAX_MESSAGE_LEN]; unsigned int i; int status; if (newacct) { char passwordvrfy[MAX_MESSAGE_LEN]; t_hash passhash1; printf("Enter information for your new account\n"); client.munged = 1; client.commpos = 0; user.player[0] = '\0'; while ((status = client_get_comm("Username: ",user.player,MAX_MESSAGE_LEN,&client.commpos, 1,client.munged,client.screen_width))==0) if (handle_winch) { client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height); printf(" \r"); client.munged = 1; handle_winch = 0; } else client.munged = 0; printf("\n"); if (status<0) continue; if (strchr(user.player,' ') || strchr(user.player,'\t') || strchr(user.player,'\r') || strchr(user.player,'\n') ) { printf("Spaces are not allowed in usernames. Try again.\n"); continue; } /* we could use strcspn() but it doesn't exist everywhere */ if (strchr(user.player,'#') || strchr(user.player,'%') || strchr(user.player,'&') || strchr(user.player,'*') || strchr(user.player,'\\') || strchr(user.player,'"') || strchr(user.player,',') || strchr(user.player,'<') || strchr(user.player,'/') || strchr(user.player,'>') || strchr(user.player,'?')) { printf("The special characters #%%&*\\\",? are not allowed in usernames. Try again.\n"); } if (strlen(user.player)>=USER_NAME_MAX) { printf("Usernames must not be more than %u characters long. Try again.\n",USER_NAME_MAX-1); continue; } client.munged = 1; client.commpos = 0; password[0] = '\0'; while ((status = client_get_comm("Password: ",password,MAX_MESSAGE_LEN,&client.commpos,0, client.munged,client.screen_width))==0) if (handle_winch) { client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height); printf(" \r"); client.munged = 1; handle_winch = 0; } else client.munged = 0; printf("\n"); if (status<0) continue; if (strlen(password)>USER_PASS_MAX) { printf("password must not be more than %u characters long. Try again.\n",USER_PASS_MAX); continue; } for (i=0; iu.client_createacctreq1.password_hash1); /* avoid warning */ packet_append_string(packet,user.player); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); do if (client_blockrecv_packet(client.sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } while (packet_get_type(rpacket)!=SERVER_CREATEACCTREPLY1); dprintf("Got CREATEACCTREPLY1\n"); if (bn_int_get(rpacket->u.server_createacctreply1.result)==SERVER_CREATEACCTREPLY1_RESULT_NO) { printf("Could not create an account under that name. Try another one.\n"); continue; } printf("Account created.\n"); } else if (changepass) { char passwordprev[MAX_MESSAGE_LEN]; char passwordvrfy[MAX_MESSAGE_LEN]; struct { bn_int ticks; bn_int sessionkey; bn_int passhash1[5]; } temp; t_hash oldpasshash1; t_hash oldpasshash2; t_hash newpasshash1; unsigned int ticks; printf("Enter your old and new login information\n"); client.munged = 1; client.commpos = 0; user.player[0] = '\0'; while ((status = client_get_comm("Username: ",user.player,MAX_MESSAGE_LEN,&client.commpos,1, client.munged,client.screen_width))==0) if (handle_winch) { client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height); printf(" \r"); client.munged = 1; handle_winch = 0; } else client.munged = 0; printf("\n"); if (status<0) continue; if (strchr(user.player,' ')) { printf("Spaces not allowed in username. Try again.\n"); continue; } if (strlen(user.player)>=USER_NAME_MAX) { printf("Usernames must not be more than %u characters long. Try again.\n",USER_NAME_MAX-1); continue; } client.munged = 1; client.commpos = 0; passwordprev[0] = '\0'; while ((status = client_get_comm("Old password: ",passwordprev,MAX_MESSAGE_LEN,&client.commpos,0, client.munged,client.screen_width))==0) if (handle_winch) { client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height); printf(" \r"); client.munged = 1; handle_winch = 0; } else client.munged = 0; printf("\n"); if (status<0) continue; for (i=0; iu.client_changepassreq.ticks,ticks); bn_int_set(&packet->u.client_changepassreq.sessionkey,client.sessionkey); hash_to_bnhash((t_hash const *)&oldpasshash2,packet->u.client_changepassreq.oldpassword_hash2); /* avoid warning */ hash_to_bnhash((t_hash const *)&newpasshash1,packet->u.client_changepassreq.newpassword_hash1); /* avoid warning */ packet_append_string(packet,user.player); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); do if (client_blockrecv_packet(client.sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } while (packet_get_type(rpacket)!=SERVER_CHANGEPASSACK); dprintf("Got CHANGEPASSACK\n"); if (bn_int_get(rpacket->u.server_changepassack.message)==SERVER_CHANGEPASSACK_MESSAGE_FAIL) { printf("Could not change password. Try again.\n"); continue; } printf("Password changed.\n"); } else { printf("Enter your login information\n"); client.munged = 1; client.commpos = 0; user.player[0] = '\0'; while ((status = client_get_comm("Username: ",user.player,MAX_MESSAGE_LEN,&client.commpos,1, client.munged,client.screen_width))==0) if (handle_winch) { client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height); printf(" \r"); client.munged = 1; handle_winch = 0; } else client.munged = 0; printf("\n"); if (status<0) continue; if (strchr(user.player,' ')) { printf("Spaces not allowed in username. Try again.\n"); continue; } if (strlen(user.player)>=USER_NAME_MAX) { printf("Usernames must not be more than %u characters long. Try again.\n",USER_NAME_MAX-1); continue; } client.munged = 1; client.commpos = 0; password[0] = '\0'; while ((status = client_get_comm("Password: ",password,MAX_MESSAGE_LEN,&client.commpos,0, client.munged,client.screen_width))==0) if (handle_winch) { client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height); printf(" \r"); client.munged = 1; handle_winch = 0; } else client.munged = 0; printf("\n"); if (status<0) continue; for (i=0; iu.client_loginreq1.ticks,ticks); bn_int_set(&packet->u.client_loginreq1.sessionkey,client.sessionkey); hash_to_bnhash((t_hash const *)&passhash2,packet->u.client_loginreq1.password_hash2); /* avoid warning */ packet_append_string(packet,user.player); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); } do if (client_blockrecv_packet(client.sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } while (packet_get_type(rpacket)!=SERVER_LOGINREPLY1); if (bn_int_get(rpacket->u.server_loginreply1.message)==SERVER_LOGINREPLY1_MESSAGE_SUCCESS) break; fprintf(stderr,"Login incorrect.\n"); } fprintf(stderr,"Logged in.\n"); printf("----\n"); if (newacct && (strcmp(user.clienttag,CLIENTTAG_DIABLORTL)==0 || strcmp(user.clienttag,CLIENTTAG_DIABLOSHR)==0)) { if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); } else { packet_set_size(packet,sizeof(t_client_playerinforeq)); packet_set_type(packet,CLIENT_PLAYERINFOREQ); packet_append_string(packet,user.player); packet_append_string(packet,"LTRD 1 2 0 20 25 15 20 100 0"); /* FIXME: don't hardcode */ client_blocksend_packet(client.sd,packet); packet_del_ref(packet); } } if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } packet_set_size(packet,sizeof(t_client_progident2)); packet_set_type(packet,CLIENT_PROGIDENT2); bn_int_tag_set(&packet->u.client_progident2.clienttag,user.clienttag); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); do if (client_blockrecv_packet(client.sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } while (packet_get_type(rpacket)!=SERVER_CHANNELLIST); { unsigned int i; unsigned int chann_off; char const * chann; channellist = xmalloc(sizeof(char const *)*1); for (i=0,chann_off=sizeof(t_server_channellist); (chann = packet_get_str_const(rpacket,chann_off,128)); i++,chann_off+=strlen(chann)+1) { if (chann[0] == '\0') break; /* channel list ends with a "" */ channellist = xrealloc(channellist,sizeof(char const *)*(i+2)); channellist[i] = xstrdup(chann); } channellist[i] = NULL; } if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } packet_set_size(packet,sizeof(t_client_joinchannel)); packet_set_type(packet,CLIENT_JOINCHANNEL); bn_int_set(&packet->u.client_joinchannel.channelflag,CLIENT_JOINCHANNEL_GENERIC); packet_append_string(packet,user.channel); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); if (psock_ctl(client.sd,PSOCK_NONBLOCK)<0) fprintf(stderr,"%s: could not set TCP socket to non-blocking mode (psock_ctl: %s)\n",argv[0],pstrerror(psock_errno())); client.mode = mode_chat; { unsigned int i; int highest_fd; t_psock_fd_set rfds; #ifdef WIN32 static struct timeval tv; tv.tv_sec = 50 / 1000; tv.tv_usec = 50 % 1000; #endif PSOCK_FD_ZERO(&rfds); #ifndef WIN32 highest_fd = client.fd_stdin; if (client.sd>highest_fd) #endif highest_fd = client.sd; client.currsize = 0; client.munged = 1; /* == need to draw prompt */ client.commpos = 0; client.text[0] = '\0'; for (;;) { if (handle_winch) { client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height); handle_winch = 0; printf(" \r"); client.munged = 1; } if (client.munged) { printf("%s%s",mode_get_prompt(client.mode),client.text + ((client.screen_width <= strlen(mode_get_prompt(client.mode)) + client.commpos ) ? strlen(mode_get_prompt(client.mode)) + client.commpos + 1 - client.screen_width : 0)); fflush(stdout); client.munged = 0; } PSOCK_FD_ZERO(&rfds); #ifndef WIN32 PSOCK_FD_SET(client.fd_stdin,&rfds); #endif PSOCK_FD_SET(client.sd,&rfds); errno = 0; #ifndef WIN32 if (psock_select(highest_fd+1,&rfds,NULL,NULL,NULL)<0) #else if (psock_select(highest_fd+1,&rfds,NULL,NULL,&tv)<0) #endif { if (psock_errno()!=PSOCK_EINTR) { munge(&client); printf("Select failed (select: %s)\n",pstrerror(psock_errno())); } continue; } #ifndef WIN32 if (PSOCK_FD_ISSET(client.fd_stdin,&rfds)) /* got keyboard data */ #else if (kbhit()) #endif { client.munged = 0; switch (client_get_comm(mode_get_prompt(client.mode),client.text,MAX_MESSAGE_LEN,&client.commpos,1, 0,client.screen_width)) { case -1: /* cancel */ munge(&client); if (client.mode==mode_command) client.mode = mode_chat; else client.mode = mode_command; client.commpos = 0; client.text[0] = '\0'; break; case 0: /* timeout */ break; case 1: switch (client.mode) { case mode_claninvite: printf("\n"); client.munged = 1; if ((client.text[0]!='\0') && strcasecmp(client.text,"yes") && strcasecmp(client.text,"no")) { printf("Do you want to accept invitation (yes/no) ? [yes] "); break; } if (!(packet = packet_create(packet_class_bnet))) { printf("Packet creation failed.\n"); } else { char result; packet_set_size(packet,sizeof(t_client_w3xp_clan_invitereply)); packet_set_type(packet,CLIENT_W3XP_CLAN_INVITEREPLY); bn_int_set(&packet->u.client_w3xp_clan_invitereply.count,user.count); bn_int_set(&packet->u.client_w3xp_clan_invitereply.clantag,user.clantag); packet_append_string(packet,user.inviter); if (!strcasecmp(client.text,"no")) result = W3XP_CLAN_INVITEREPLY_DECLINE; else result = W3XP_CLAN_INVITEREPLY_ACCEPT; packet_append_data(packet,&result,1); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); if (user.inviter) xfree((void *)user.inviter); user.inviter = NULL; } client.mode = mode_chat; break; case mode_gamename: if (client.text[0]=='\0') { munge(&client); printf("Games must have a name.\n"); break; } printf("\n"); client.munged = 1; strncpy(user.curr_gamename,client.text,sizeof(user.curr_gamename)); user.curr_gamename[sizeof(user.curr_gamename)-1] = '\0'; client.mode = mode_gamepass; break; case mode_gamepass: printf("\n"); client.munged = 1; strncpy(user.curr_gamepass,client.text,sizeof(user.curr_gamepass)); user.curr_gamepass[sizeof(user.curr_gamepass)-1] = '\0'; if (!(packet = packet_create(packet_class_bnet))) { printf("Packet creation failed.\n"); client.mode = mode_command; } else { packet_set_size(packet,sizeof(t_client_startgame4)); packet_set_type(packet,CLIENT_STARTGAME4); bn_short_set(&packet->u.client_startgame4.status,CLIENT_STARTGAME4_STATUS_INIT); bn_short_set(&packet->u.client_startgame4.flag,0x0000); bn_int_set(&packet->u.client_startgame4.unknown2,CLIENT_STARTGAME4_UNKNOWN2); bn_short_set(&packet->u.client_startgame4.gametype,CLIENT_GAMELISTREQ_MELEE); bn_short_set(&packet->u.client_startgame4.option,CLIENT_STARTGAME4_OPTION_MELEE_NORMAL); bn_int_set(&packet->u.client_startgame4.unknown4,CLIENT_STARTGAME4_UNKNOWN4); bn_int_set(&packet->u.client_startgame4.unknown5,CLIENT_STARTGAME4_UNKNOWN5); packet_append_string(packet,user.curr_gamename); packet_append_string(packet,user.curr_gamepass); packet_append_string(packet,",,,,1,3,1,3e37a84c,7,Player\rAshrigo\r"); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); client.mode = mode_gamewait; } break; case mode_gamestop: printf("\n"); client.munged = 1; if (!(packet = packet_create(packet_class_bnet))) printf("Packet creation failed.\n"); else { packet_set_size(packet,sizeof(t_client_closegame)); packet_set_type(packet,CLIENT_CLOSEGAME); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); printf("Game closed.\n"); client.mode = mode_command; } break; case mode_command: if (client.text[0]=='\0') break; printf("\n"); client.munged = 1; if (strstart(client.text,"channel")==0) { printf("Available channels:\n"); if (client.useansi) ansi_text_color_fore(ansi_text_color_yellow); for (i=0; channellist[i]; i++) printf(" %s\n",channellist[i]); if (client.useansi) ansi_text_reset(); } else if (strstart(client.text,"create")==0) { printf("Enter new game information\n"); client.mode = mode_gamename; } else if (strstart(client.text,"join")==0) { printf("Not implemented yet.\n"); } else if (strstart(client.text,"ladder")==0) { printf("Not implemented yet.\n"); } else if (strstart(client.text,"stats")==0) { printf("Not implemented yet.\n"); } else if (strstart(client.text,"help")==0 || strcmp(client.text,"?")==0) { printf("Available commands:\n" " channel - join or create a channel\n" " create - create a new game\n" " join - list current games\n" " ladder - list ladder rankings\n" " help - show this text\n" " info - print a player's profile\n" " chinfo - modify your profile\n" " quit - exit bnchat\n" " stats - print a player's game record\n" "Use the escape key to toggle between chat and command modes.\n"); } else if (strstart(client.text,"info")==0) { for (i=4; client.text[i]==' ' || client.text[i]=='\t'; i++); if (client.text[i]=='\0') { ansi_printf(&client,ansi_text_color_red,"You must specify the player.\n"); } else { if (!(packet = packet_create(packet_class_bnet))) fprintf(stderr,"%s: could not create packet\n",argv[0]); else { printf("Profile info for %s:\n",&client.text[i]); packet_set_size(packet,sizeof(t_client_statsreq)); packet_set_type(packet,CLIENT_STATSREQ); bn_int_set(&packet->u.client_statsreq.name_count,1); bn_int_set(&packet->u.client_statsreq.key_count,4); statsmatch = (unsigned int)time(NULL); bn_int_set(&packet->u.client_statsreq.requestid,statsmatch); packet_append_string(packet,&client.text[i]); #if 0 packet_append_string(packet,"BNET\\acct\\username"); packet_append_string(packet,"BNET\\acct\\userid"); #endif packet_append_string(packet,"profile\\sex"); packet_append_string(packet,"profile\\age"); packet_append_string(packet,"profile\\location"); packet_append_string(packet,"profile\\description"); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); client.mode = mode_waitstat; } } } else if (strstart(client.text,"chinfo")==0) { printf("Not implemented yet.\n"); } else if (strstart(client.text,"quit")==0) { psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_SUCCESS; } else { ansi_printf(&client,ansi_text_color_red,"Unknown local command \"%s\".\n",client.text); } break; case mode_chat: if (client.text[0]=='\0') break; if (client.text[0]=='/') { munge(&client); } else { ansi_printf(&client,ansi_text_color_blue,"\r<%s>",user.player); printf(" "); str_print_term(stdout,client.text,0,0); printf("\n"); client.munged = 1; } if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_FAILURE; } packet_set_size(packet,sizeof(t_client_message)); packet_set_type(packet,CLIENT_MESSAGE); packet_append_string(packet,client.text); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); break; default: /* one of the wait states; erase what they typed */ munge(&client); break; } client.commpos = 0; client.text[0] = '\0'; break; } } if (PSOCK_FD_ISSET(client.sd,&rfds)) /* got network data */ { /* rpacket is from server, packet is from client */ switch (net_recv_packet(client.sd,rpacket,&client.currsize)) { case 0: /* nothing */ break; case 1: switch (packet_get_type(rpacket)) { case SERVER_ECHOREQ: /* might as well support it */ if (packet_get_size(rpacket)u.client_echoreply.ticks,bn_int_get(rpacket->u.server_echoreq.ticks)); client_blocksend_packet(client.sd,packet); packet_del_ref(packet); break; case SERVER_STARTGAME4_ACK: if (client.mode==mode_gamewait) { munge(&client); if (bn_int_get(rpacket->u.server_startgame4_ack.reply)==SERVER_STARTGAME4_ACK_OK) { printf("Game created.\n"); client.mode = mode_gamestop; } else { printf("Game could not be created, try another name.\n"); client.mode = mode_gamename; } } break; case SERVER_W3XP_CLAN_INVITEREQ: if (packet_get_size(rpacket)u.server_w3xp_clan_invitereq.count); user.clantag = bn_int_get(rpacket->u.server_w3xp_clan_invitereq.clantag); if (user.inviter) xfree((void *)user.inviter); user.inviter = xstrdup(inviter); munge(&client); printf("%s invited you to Clan %s\n",inviter,clan); printf("Do you want to accept invitation (yes/no) ? [yes] "); client.mode = mode_claninvite; } case SERVER_W3XP_CLANMEMBERUPDATE: if (packet_get_size(rpacket)u.server_statsreply.name_count); keys = bn_int_get(rpacket->u.server_statsreply.key_count); match = bn_int_get(rpacket->u.server_statsreply.requestid); if (names!=1 || keys!=4 || match!=statsmatch) printf("mangled reply (name_count=%u key_count=%u unknown1=%u)\n", names,keys,match); strpos = sizeof(t_server_statsreply); if ((temp = packet_get_str_const(rpacket,strpos,256))) { printf(" Sex: "); ansi_printf(&client,ansi_text_color_yellow,"%s\n",temp); strpos += strlen(temp)+1; } if ((temp = packet_get_str_const(rpacket,strpos,256))) { printf(" Age: "); ansi_printf(&client,ansi_text_color_yellow,"%s\n",temp); strpos += strlen(temp)+1; } if ((temp = packet_get_str_const(rpacket,strpos,256))) { printf(" Location: "); ansi_printf(&client,ansi_text_color_yellow,"%s\n",temp); strpos += strlen(temp)+1; } if ((temp = packet_get_str_const(rpacket,strpos,256))) { char msgtemp[1024]; char * tok; printf(" Description: \n"); if (client.useansi) ansi_text_color_fore(ansi_text_color_yellow); strncpy(msgtemp,temp,sizeof(msgtemp)); msgtemp[sizeof(msgtemp)-1] = '\0'; for (tok=strtok(msgtemp,"\r\n"); tok; tok=strtok(NULL,"\r\n")) printf(" %s\n",tok); if (client.useansi) ansi_text_reset(); strpos += strlen(temp)+1; } if (match==statsmatch) client.mode = mode_command; } break; case SERVER_PLAYERINFOREPLY: /* hmm. we didn't ask for one... */ break; case SERVER_MESSAGE: if (packet_get_size(rpacket)u.server_message.type)) { case SERVER_MESSAGE_TYPE_JOIN: munge(&client); ansi_printf(&client,ansi_text_color_green,"\"%s\" %s enters\n",speaker, mflags_get_str(bn_int_get(rpacket->u.server_message.flags))); break; case SERVER_MESSAGE_TYPE_CHANNEL: munge(&client); ansi_printf(&client,ansi_text_color_green,"Joining channel :\"%s\" %s\n",message, cflags_get_str(bn_int_get(rpacket->u.server_message.flags))); break; case SERVER_MESSAGE_TYPE_ADDUSER: munge(&client); ansi_printf(&client,ansi_text_color_green,"\"%s\" %s is here\n",speaker, mflags_get_str(bn_int_get(rpacket->u.server_message.flags))); break; case SERVER_MESSAGE_TYPE_USERFLAGS: break; case SERVER_MESSAGE_TYPE_PART: munge(&client); ansi_printf(&client,ansi_text_color_green,"\"%s\" %s leaves\n",speaker, mflags_get_str(bn_int_get(rpacket->u.server_message.flags))); break; case SERVER_MESSAGE_TYPE_WHISPER: munge(&client); ansi_printf(&client,ansi_text_color_blue,"",speaker); printf(" "); str_print_term(stdout,message,0,0); printf("\n"); break; case SERVER_MESSAGE_TYPE_WHISPERACK: munge(&client); ansi_printf(&client,ansi_text_color_blue,"",speaker); printf(" "); str_print_term(stdout,message,0,0); printf("\n"); break; case SERVER_MESSAGE_TYPE_BROADCAST: munge(&client); ansi_printf(&client,ansi_text_color_yellow," %s\n",speaker,message); break; case SERVER_MESSAGE_TYPE_ERROR: munge(&client); ansi_printf(&client,ansi_text_color_red," %s\n",message); break; case SERVER_MESSAGE_TYPE_INFO: munge(&client); ansi_printf(&client,ansi_text_color_yellow," %s\n",message); break; case SERVER_MESSAGE_TYPE_EMOTE: munge(&client); ansi_printf(&client,ansi_text_color_yellow,"<%s %s>\n",speaker,message); break; default: case SERVER_MESSAGE_TYPE_TALK: munge(&client); ansi_printf(&client,ansi_text_color_yellow,"<%s>",speaker); printf(" "); str_print_term(stdout,message,0,0); printf("\n"); } } break; default: munge(&client); printf("Unsupported server packet type 0x%04x\n",packet_get_type(rpacket)); hexdump(stdout,packet_get_data_const(rpacket,0,packet_get_size(rpacket)),packet_get_size(rpacket)); printf("\n"); } client.currsize = 0; break; case -1: /* error (probably connection closed) */ default: munge(&client); printf("----\nConnection closed by server.\n"); psock_close(client.sd); if (client.changed_in) tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old); return STATUS_SUCCESS; } } } } /* not reached */ } pvpgn-1.8.5/src/client/client_connect.h0000644000175000017500000000736111151345317017056 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_CLIENT_CONNECT_PROTOS #define INCLUDED_CLIENT_CONNECT_PROTOS #define JUST_NEED_TYPES #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #undef JUST_NEED_TYPES // Diablo 1.09b #define CLIENT_VERSIONID_DRTL 0x0000002a #define CLIENT_GAMEVERSION_DRTL 0x01000902 #define CLIENT_EXEINFO_DRTL "Diablo.exe 05/18/01 23:10:57 767760" #define CLIENT_CHECKSUM_DRTL 0x23135c73 //plain Starcraft 1.15.2 #define CLIENT_VERSIONID_STAR 0x000000d1 #define CLIENT_GAMEVERSION_STAR 0x010f0200 #define CLIENT_EXEINFO_STAR "StarCraft.exe 01/08/08 23:45:36 1220608" #define CLIENT_CHECKSUM_STAR 0x91c0f907 #define CLIENT_VERSIONID_SSHR 0x000000a5 /* FIXME: wrong? */ #define CLIENT_GAMEVERSION_SSHR 0x0100080a /* FIXME: wrong? */ #define CLIENT_EXEINFO_SSHR "starcraft.exe 03/08/99 22:41:50 1042432" /* FIXME: wrong */ #define CLIENT_CHECKSUM_SSHR 0x12345678 //Broodwar 1.15.2 #define CLIENT_VERSIONID_SEXP 0x000000d1 #define CLIENT_GAMEVERSION_SEXP 0x010f0201 #define CLIENT_EXEINFO_SEXP "StarCraft.exe 01/10/08 20:23:42 1220608" #define CLIENT_CHECKSUM_SEXP 0x8fbdf18d //Warcraft 2 Battle.Net Edition 2.02b #define CLIENT_VERSIONID_W2BN 0x0000004f #define CLIENT_GAMEVERSION_W2BN 0x02000201 #define CLIENT_EXEINFO_W2BN "Warcraft II BNE.exe 05/21/01 21:52:22 712704" #define CLIENT_CHECKSUM_W2BN 0xff0d4c4a //Diablo 2 1.11b #define CLIENT_VERSIONID_D2DV 0x0000000b #define CLIENT_GAMEVERSION_D2DV 0x01000b00 #define CLIENT_EXEINFO_D2DV "Game.exe 08/17/05 01:11:43 2125824" #define CLIENT_CHECKSUM_D2DV 0x602f8323 //Diable 2 Expansion 1.11b #define CLIENT_VERSIONID_D2XP 0x0000000b #define CLIENT_GAMEVERSION_D2XP 0x01000b00 #define CLIENT_EXEINFO_D2XP "Game.exe 08/17/05 01:12:38 2129920" #define CLIENT_CHECKSUM_D2XP 0xbfc36199 //Warcraft 3 1.21b and Warcraft 3 Frozen Throne 1.21b #define CLIENT_VERSIONID_WAR3 0x00000015 #define CLIENT_GAMEVERSION_WAR3 0x0115019c #define CLIENT_EXEINFO_WAR3 "war3.exe 07/19/07 18:41:12 409660" #define CLIENT_CHECKSUM_WAR3 0x1b735294 #define CLIENT_COUNTRYINFO_109_PROTOCOL 0x00000000 #define CLIENT_COUNTRYINFO_109_VERSIONID_D2DV 0x00000009 #define CLIENT_COUNTRYINFO_109_GAMELANG "enUS" #define CLIENT_COUNTRYINFO_109_LOCALIP 0x00000000 #define CLIENT_COUNTRYINFO_109_LANGID_USENGLISH 0x00000409 #define CLIENT_COUNTRYINFO_109_LANGSTR_USENGLISH "ENU" #define CLIENT_COUNTRYINFO_109_COUNTRYNAME_USA "United States" extern int client_connect(char const * progname, char const * servname, unsigned short servport, char const * cdowner, char const * cdkey, char const * clienttag, struct sockaddr_in * saddr, unsigned int * sessionkey, unsigned int * sessionnum, char const * archtag, char const * gamelang); #endif #endif pvpgn-1.8.5/src/client/bnftp.c0000644000175000017500000006741511151345317015201 0ustar aaronaaron/* * Copyright (C) 1999,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memset.h" #include "compat/memcpy.h" #include #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/strftime.h" #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_TERMIOS_H # include #endif #include "compat/termios.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/send.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #ifdef HAVE_NETDB_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #include "compat/psock.h" #include "common/packet.h" #include "common/init_protocol.h" #include "common/file_protocol.h" #include "common/tag.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/network.h" #include "common/version.h" #include "common/util.h" #include "common/bnettime.h" #ifdef CLIENTDEBUG #include "common/eventlog.h" #endif #include "common/hexdump.h" #include "client.h" #include "common/xalloc.h" #include "common/setup_after.h" static void usage(char const * progname); static void usage(char const * progname) { fprintf(stderr,"usage: %s [] [ []]\n",progname); fprintf(stderr, " -b, --client=SEXP report client as Brood Wars\n" " -d, --client=DRTL report client as Diablo Retail\n" " --client=DSHR report client as Diablo Shareware\n" " -s, --client=STAR report client as Starcraft (default)\n"); fprintf(stderr, " --client=SSHR report client as Starcraft Shareware\n" " -w, --client=W2BN report client as Warcraft II BNE\n" " --client=D2DV report client as Diablo II\n" " --client=D2XP report client as Diablo II: LoD\n" " --client=WAR3 report client as Warcraft III\n" " --client=W3XP report client as Warcraft III: FT\n" " --hexdump=FILE do hex dump of packets into FILE\n"); fprintf(stderr, " --arch=IX86 report architecture as Windows (x86)\n" " --arch=PMAC report architecture as Macintosh\n" " --arch=XMAC report architecture as Macintosh OSX\n" ); fprintf(stderr, " --startoffset=OFFSET force offset to be OFFSET\n" " --exists=ACTION Ask/Overwrite/Backup/Resume if the file exists\n" " --file=FILENAME use FILENAME instead of asking\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n"); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { int a; int sd; struct sockaddr_in saddr; t_packet * packet; t_packet * rpacket; t_packet * fpacket; char const * clienttag=NULL; char const * archtag=NULL; char const * servname=NULL; unsigned short servport=0; char const * hexfile=NULL; char text[MAX_MESSAGE_LEN]; char const * reqfile=NULL; struct hostent * host; unsigned int commpos; struct termios in_attr_old; struct termios in_attr_new; int changed_in; unsigned int currsize; unsigned int filelen; unsigned int startoffset; int startoffsetoverride=0; #define EXIST_ACTION_UNSPEC -1 #define EXIST_ACTION_ASK 0 #define EXIST_ACTION_OVERWRITE 1 #define EXIST_ACTION_BACKUP 2 #define EXIST_ACTION_RESUME 3 int exist_action=EXIST_ACTION_UNSPEC; struct stat exist_buf; char const * filename; FILE * fp; FILE * hexstrm=NULL; int fd_stdin; t_bnettime bntime; time_t tm; char timestr[FILE_TIME_MAXLEN]; unsigned int screen_width,screen_height; int munged; unsigned int newproto = 0; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a=argc) { if (str_to_ushort(argv[a],&servport)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (!servname && argv[a][0]!='-' && a+2>=argc) servname = argv[a]; else if (strcmp(argv[a],"-b")==0 || strcmp(argv[a],"--client=SEXP")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_BROODWARS; } else if (strcmp(argv[a],"-d")==0 || strcmp(argv[a],"--client=DRTL")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_DIABLORTL; } else if (strcmp(argv[a],"--client=DSHR")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_DIABLOSHR; } else if (strcmp(argv[a],"-s")==0 || strcmp(argv[a],"--client=STAR")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_STARCRAFT; } else if (strcmp(argv[a],"--client=SSHR")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_SHAREWARE; } else if (strcmp(argv[a],"-w")==0 || strcmp(argv[a],"--client=W2BN")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_WARCIIBNE; } else if (strcmp(argv[a],"--client=D2DV")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_DIABLO2DV; } else if (strcmp(argv[a],"--client=D2XP")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_DIABLO2XP; } else if (strcmp(argv[a],"--client=WAR3")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_WARCRAFT3; newproto = 1; } else if (strcmp(argv[a],"--client=W3XP")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_WAR3XP; newproto = 1; } else if (strncmp(argv[a],"--client=",9)==0) { fprintf(stderr,"%s: unknown client tag \"%s\"\n",argv[0],&argv[a][9]); usage(argv[0]); } else if (strcmp(argv[a],"--arch=IX86")==0) { if (archtag) { fprintf(stderr,"%s: architecture type was already specified as \"%s\"\n",argv[0],archtag); usage(argv[0]); } archtag = ARCHTAG_WINX86; } else if (strcmp(argv[a],"--arch=PMAC")==0) { if (archtag) { fprintf(stderr,"%s: architecture type was already specified as \"%s\"\n",argv[0],archtag); usage(argv[0]); } archtag = ARCHTAG_MACPPC; } else if (strcmp(argv[a],"--arch=XMAC")==0) { if (archtag) { fprintf(stderr,"%s: architecture type was already specified as \"%s\"\n",argv[0],archtag); usage(argv[0]); } archtag = ARCHTAG_OSXPPC; } else if (strncmp(argv[a],"--arch=",9)==0) { fprintf(stderr,"%s: unknown architecture tag \"%s\"\n",argv[0],&argv[a][9]); usage(argv[0]); } else if (strncmp(argv[a],"--hexdump=",10)==0) { if (hexfile) { fprintf(stderr,"%s: hexdump file was already specified as \"%s\"\n",argv[0],hexfile); usage(argv[0]); } hexfile = &argv[a][10]; } else if (strncmp(argv[a],"--startoffset=",14)==0) { if (startoffsetoverride) { fprintf(stderr,"%s: startoffset was already specified as %u\n",argv[0],startoffset); usage(argv[0]); } if (str_to_uint(&argv[a][14],&startoffset)<0) { fprintf(stderr,"%s: startoffset \"%s\" should be a positive integer\n",argv[0],&argv[a][14]); usage(argv[0]); } startoffsetoverride = 1; } else if (strncmp(argv[a],"--exists=",9)==0) { if (exist_action!=EXIST_ACTION_UNSPEC) { fprintf(stderr,"%s: exists was already specified\n",argv[0]); usage(argv[0]); } if (argv[a][9]=='o' || argv[a][9]=='O') exist_action = EXIST_ACTION_OVERWRITE; else if (argv[a][9]=='a' || argv[a][9]=='A') exist_action = EXIST_ACTION_ASK; else if (argv[a][9]=='b' || argv[a][9]=='B') exist_action = EXIST_ACTION_BACKUP; else if (argv[a][9]=='r' || argv[a][9]=='R') exist_action = EXIST_ACTION_RESUME; else { fprintf(stderr,"%s: exists must begin with a,A,o,O,b,B,r or R",argv[0]); usage(argv[0]); } } else if (strncmp(argv[a],"--file=",7)==0) { if (reqfile) { fprintf(stderr,"%s: file was already specified as \"%s\"\n",argv[0],reqfile); usage(argv[0]); } reqfile = &argv[a][7]; } else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0) { printf("version "PVPGN_VERSION"\n"); return 0; } else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage")==0) usage(argv[0]); else if (strcmp(argv[a],"--client")==0 || strcmp(argv[a],"--hexdump")==0) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } else { fprintf(stderr,"%s: unknown option \"%s\"\n",argv[0],argv[a]); usage(argv[0]); } if (servport==0) servport = BNETD_SERV_PORT; if (!clienttag) clienttag = CLIENTTAG_STARCRAFT; if (!archtag) archtag = ARCHTAG_WINX86; if (!servname) servname = BNETD_DEFAULT_HOST; if (exist_action==EXIST_ACTION_UNSPEC) exist_action = EXIST_ACTION_ASK; if (hexfile) { if (!(hexstrm = fopen(hexfile,"w"))) fprintf(stderr,"%s: could not open file \"%s\" for writing the hexdump (fopen: %s)",argv[0],hexfile,pstrerror(errno)); else { fprintf(hexstrm,"# dump generated by bnftp version "PVPGN_VERSION"\n"); } } if (psock_init()<0) { fprintf(stderr,"%s: could not inialialize socket functions\n",argv[0]); return STATUS_FAILURE; } if (!(host = gethostbyname(servname))) { fprintf(stderr,"%s: unknown host \"%s\"\n",argv[0],servname); return STATUS_FAILURE; } fd_stdin = fileno(stdin); if (tcgetattr(fd_stdin,&in_attr_old)>=0) { in_attr_new = in_attr_old; in_attr_new.c_lflag &= ~(ECHO | ICANON); /* turn off ECHO and ICANON */ in_attr_new.c_cc[VMIN] = 1; /* require reads to return at least one byte */ in_attr_new.c_cc[VTIME] = 0; /* no timeout */ tcsetattr(fd_stdin,TCSANOW,&in_attr_new); changed_in = 1; } else { fprintf(stderr,"%s: could not get terminal attributes for stdin\n",argv[0]); changed_in = 0; } if (client_get_termsize(fd_stdin,&screen_width,&screen_height)<0) { fprintf(stderr,"%s: could not determine screen size\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } if ((sd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0) { fprintf(stderr,"%s: could not create socket (psock_socket: %s)\n",argv[0],pstrerror(psock_errno())); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } memset(&saddr,0,sizeof(saddr)); saddr.sin_family = PSOCK_AF_INET; saddr.sin_port = htons(servport); memcpy(&saddr.sin_addr.s_addr,host->h_addr_list[0],host->h_length); if (psock_connect(sd,(struct sockaddr *)&saddr,sizeof(saddr))<0) { fprintf(stderr,"%s: could not connect to server \"%s\" port %hu (psock_connect: %s)\n",argv[0],servname,servport,pstrerror(psock_errno())); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } printf("Connected to %s:%hu.\n",inet_ntoa(saddr.sin_addr),servport); #ifdef CLIENTDEBUG eventlog_set(stderr); #endif if (!(packet = packet_create(packet_class_init))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } bn_byte_set(&packet->u.client_initconn.class,CLIENT_INITCONN_CLASS_FILE); if (hexstrm) { fprintf(hexstrm,"%d: send class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n", sd, packet_get_class_str(packet),(unsigned int)packet_get_class(packet), packet_get_type_str(packet,packet_dir_from_client),packet_get_type(packet), packet_get_size(packet)); hexdump(hexstrm,packet_get_raw_data(packet,0),packet_get_size(packet)); } client_blocksend_packet(sd,packet); packet_del_ref(packet); if (!(rpacket = packet_create(packet_class_file))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } if (!(fpacket = packet_create(packet_class_raw))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); packet_del_ref(rpacket); return STATUS_FAILURE; } if (!reqfile) /* if not specified on the command line then prompt for it */ { munged = 1; commpos = 0; text[0] = '\0'; for (;;) { switch (client_get_comm("filename: ",text,sizeof(text),&commpos,1,munged,screen_width)) { case -1: /* cancel or error */ printf("\n"); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); packet_del_ref(fpacket); packet_del_ref(rpacket); return STATUS_FAILURE; case 0: /* timeout */ munged = 0; continue; case 1: munged = 0; if (text[0]=='\0') continue; printf("\n"); } break; } reqfile = text; } if (stat(reqfile,&exist_buf)==0) /* check if the file exists */ { char text2[MAX_MESSAGE_LEN]; munged = 1; commpos = 0; text2[0] = '\0'; while (exist_action==EXIST_ACTION_ASK) { switch (client_get_comm("File exists [O]verwrite, [B]ackup or [R]esume?: ",text2,sizeof(text2),&commpos,1,munged,screen_width)) { case -1: /* cancel or error */ printf("\n"); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); packet_del_ref(fpacket); packet_del_ref(rpacket); return STATUS_FAILURE; case 0: /* timeout */ munged = 0; continue; case 1: munged = 0; if (text2[0]=='\0') continue; printf("\n"); break; } switch (text2[0]) { case 'o': case 'O': exist_action = EXIST_ACTION_OVERWRITE; break; case 'b': case 'B': exist_action = EXIST_ACTION_BACKUP; break; case 'r': case 'R': exist_action = EXIST_ACTION_RESUME; break; default: printf("Please answer with o,O,b,B,r or R.\n"); munged = 1; continue; } break; } switch (exist_action) { case EXIST_ACTION_OVERWRITE: if (!startoffsetoverride) startoffset = 0; break; case EXIST_ACTION_BACKUP: { char * bakfile; unsigned int bnr; int renamed=0; bakfile = xmalloc(strlen(reqfile)+1+2+1); /* assuming we go up to bnr 99 we need reqfile+'.'+'99'+'\0' */ for (bnr=0; bnr<100; bnr++) { sprintf(bakfile,"%s.%d",reqfile,bnr); if (stat(bakfile,&exist_buf)==0) continue; /* backup exists */ /* backup does not exist */ if (rename(reqfile,bakfile)<0) /* just rename the existing file to the backup */ fprintf(stderr,"%s: could not create backup file \"%s\" (rename: %s)\n",argv[0],bakfile,pstrerror(errno)); else { renamed = 1; printf("Renaming \"%s\" to \"%s\".\n",reqfile,bakfile); } break; } xfree(bakfile); if (!renamed) { fprintf(stderr,"%s: could not create backup for \"%s\".\n",argv[0],reqfile); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); packet_del_ref(fpacket); packet_del_ref(rpacket); return STATUS_FAILURE; } if (!startoffsetoverride) startoffset = 0; } break; case EXIST_ACTION_RESUME: if (!startoffsetoverride) startoffset = exist_buf.st_size; break; } } else if (!startoffsetoverride) startoffset = 0; if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); if (!(packet = packet_create(packet_class_file))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); packet_del_ref(fpacket); packet_del_ref(rpacket); return STATUS_FAILURE; } if (newproto) { /* first send ARCH/CTAG */ packet_set_size(packet, sizeof(t_client_file_req2)); packet_set_type(packet, CLIENT_FILE_REQ2); bn_int_tag_set(&packet->u.client_file_req2.archtag,archtag); bn_int_tag_set(&packet->u.client_file_req2.clienttag,clienttag); bn_long_set_a_b(&packet->u.client_file_req2.unknown1,0,0); } else { packet_set_size(packet,sizeof(t_client_file_req)); packet_set_type(packet, CLIENT_FILE_REQ); bn_int_tag_set(&packet->u.client_file_req.archtag,archtag); bn_int_tag_set(&packet->u.client_file_req.clienttag,clienttag); bn_int_set(&packet->u.client_file_req.adid,0); bn_int_set(&packet->u.client_file_req.extensiontag,0); bn_int_set(&packet->u.client_file_req.startoffset,startoffset); bn_long_set_a_b(&packet->u.client_file_req.timestamp,0x00000000,0x00000000); packet_append_string(packet,reqfile); } if (hexstrm) { fprintf(hexstrm,"%d: send class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n", sd, packet_get_class_str(packet),(unsigned int)packet_get_class(packet), packet_get_type_str(packet,packet_dir_from_client),packet_get_type(packet), packet_get_size(packet)); hexdump(hexstrm,packet_get_raw_data(packet,0),packet_get_size(packet)); } if (newproto) printf("\nSending ARCH/CTAG info..."); else printf("\nRequesting info..."); fflush(stdout); client_blocksend_packet(sd,packet); packet_del_ref(packet); if (newproto) { /* received the stupid 4 bytes unknown "packet" */ packet_set_size(fpacket, sizeof(t_server_file_unknown1)); if (client_blockrecv_packet(sd,fpacket)<0) { fprintf(stderr,"%s: server closed connection\n",argv[0]); packet_del_ref(fpacket); packet_del_ref(rpacket); return STATUS_FAILURE; } if (hexstrm) { fprintf(hexstrm,"%d: recv class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n", sd, packet_get_class_str(fpacket),(unsigned int)packet_get_class(fpacket), packet_get_type_str(fpacket,packet_dir_from_server),packet_get_type(fpacket), packet_get_size(fpacket)); hexdump(hexstrm,packet_get_raw_data(fpacket,0),packet_get_size(fpacket)); } /* send file info request */ packet_set_size(fpacket, sizeof(t_client_file_req3)); bn_int_set(&fpacket->u.client_file_req3.unknown1, 0); bn_long_set_a_b(&fpacket->u.client_file_req3.timestamp, 0, 0); bn_long_set_a_b(&fpacket->u.client_file_req3.unknown2, 0, 0); bn_long_set_a_b(&fpacket->u.client_file_req3.unknown3, 0, 0); bn_long_set_a_b(&fpacket->u.client_file_req3.unknown4, 0, 0); bn_long_set_a_b(&fpacket->u.client_file_req3.unknown5, 0, 0); bn_long_set_a_b(&fpacket->u.client_file_req3.unknown6, 0, 0); packet_append_string(fpacket, reqfile); printf("\nRequesting info..."); fflush(stdout); client_blocksend_packet(sd,fpacket); if (hexstrm) { fprintf(hexstrm,"%d: send class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n", sd, packet_get_class_str(fpacket),(unsigned int)packet_get_class(fpacket), packet_get_type_str(fpacket,packet_dir_from_client),packet_get_type(fpacket), packet_get_size(fpacket)); hexdump(hexstrm,packet_get_raw_data(fpacket,0),packet_get_size(fpacket)); } } do { if (client_blockrecv_packet(sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",argv[0]); packet_del_ref(fpacket); packet_del_ref(rpacket); return STATUS_FAILURE; } if (hexstrm) { fprintf(hexstrm,"%d: recv class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n", sd, packet_get_class_str(rpacket),(unsigned int)packet_get_class(rpacket), packet_get_type_str(rpacket,packet_dir_from_server),packet_get_type(rpacket), packet_get_size(rpacket)); hexdump(hexstrm,packet_get_raw_data(rpacket,0),packet_get_size(rpacket)); } } while (packet_get_type(rpacket)!=SERVER_FILE_REPLY); filelen = bn_int_get(rpacket->u.server_file_reply.filelen); bn_long_to_bnettime(rpacket->u.server_file_reply.timestamp,&bntime); tm = bnettime_to_time(bntime); strftime(timestr,FILE_TIME_MAXLEN,FILE_TIME_FORMAT,localtime(&tm)); filename = packet_get_str_const(rpacket,sizeof(t_server_file_reply),MAX_FILENAME_STR); if (exist_action==EXIST_ACTION_RESUME) { if (!(fp = fopen(reqfile,"ab"))) { fprintf(stderr,"%s: could not open file \"%s\" for appending (fopen: %s)\n",argv[0],reqfile,pstrerror(errno)); packet_del_ref(fpacket); packet_del_ref(rpacket); return STATUS_FAILURE; } } else { if (!(fp = fopen(reqfile,"wb"))) { fprintf(stderr,"%s: could not open file \"%s\" for writing (fopen: %s)\n",argv[0],reqfile,pstrerror(errno)); packet_del_ref(fpacket); packet_del_ref(rpacket); return STATUS_FAILURE; } } printf("\n name: \""); str_print_term(stdout,filename,0,0); printf("\"\n changed: %s\n length: %u bytes\n",timestr,filelen); fflush(stdout); if (startoffset>0) { filelen -= startoffset; /* for resuming files */ printf("Resuming at position %u (%u bytes remaining).\n",startoffset,filelen); } printf("\nSaving to \"%s\"...",reqfile); for (currsize=0; currsize+MAX_PACKET_SIZE<=filelen; currsize+=MAX_PACKET_SIZE) { printf("."); fflush(stdout); if (client_blockrecv_raw_packet(sd,fpacket,MAX_PACKET_SIZE)<0) { printf("error\n"); fprintf(stderr,"%s: server closed connection\n",argv[0]); if (fclose(fp)<0) fprintf(stderr,"%s: could not close file \"%s\" after writing (fclose: %s)\n",argv[0],reqfile,pstrerror(errno)); packet_del_ref(fpacket); packet_del_ref(rpacket); return STATUS_FAILURE; } if (hexstrm) { fprintf(hexstrm,"%d: recv class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n", sd, packet_get_class_str(fpacket),(unsigned int)packet_get_class(fpacket), packet_get_type_str(fpacket,packet_dir_from_server),packet_get_type(fpacket), packet_get_size(fpacket)); hexdump(hexstrm,packet_get_raw_data(fpacket,0),packet_get_size(fpacket)); } if (fwrite(packet_get_raw_data_const(fpacket,0),1,MAX_PACKET_SIZE,fp) #ifdef STDC_HEADERS # include #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memset.h" #include "compat/memcpy.h" #include #ifdef HAVE_STRING_H # include #endif #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include "compat/gethostname.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #ifdef HAVE_NETDB_H # include #endif #include "compat/psock.h" #include "common/packet.h" #include "common/init_protocol.h" #include "common/udp_protocol.h" #include "common/bnet_protocol.h" #include "common/file_protocol.h" #include "common/tag.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/bnethash.h" #include "common/bnethashconv.h" #include "common/util.h" #ifdef CLIENTDEBUG # include "common/eventlog.h" #endif #include "client.h" #include "udptest.h" #include "common/bnettime.h" #include "common/proginfo.h" #include "client_connect.h" #include "common/setup_after.h" #define COMPNAMELEN 128 #ifdef CLIENTDEBUG # define dprintf printf #else # define dprintf if (0) printf #endif static int key_interpret(char const * cdkey, unsigned int * productid, unsigned int * keyvalue1, unsigned int * keyvalue2) { /* FIXME: implement... have example code from Eurijk! */ *productid = 0; *keyvalue1 = 0; *keyvalue2 = 0; return 0; } static int get_defversioninfo(char const * progname, char const * clienttag, unsigned int * versionid, unsigned int * gameversion, char const * * exeinfo, unsigned int * checksum) { if (strcmp(clienttag,CLIENTTAG_DIABLORTL)==0) { *versionid = CLIENT_VERSIONID_DRTL; *gameversion = CLIENT_GAMEVERSION_DRTL; *exeinfo = CLIENT_EXEINFO_DRTL; *checksum = CLIENT_CHECKSUM_DRTL; return 0; } if (strcmp(clienttag,CLIENTTAG_STARCRAFT)==0) { *versionid = CLIENT_VERSIONID_STAR; *gameversion = CLIENT_GAMEVERSION_STAR; *exeinfo = CLIENT_EXEINFO_STAR; *checksum = CLIENT_CHECKSUM_STAR; return 0; } if (strcmp(clienttag,CLIENTTAG_SHAREWARE)==0) { *versionid = CLIENT_VERSIONID_SSHR; *gameversion = CLIENT_GAMEVERSION_SSHR; *exeinfo = CLIENT_EXEINFO_SSHR; *checksum = CLIENT_CHECKSUM_SSHR; return 0; } if (strcmp(clienttag,CLIENTTAG_BROODWARS)==0) { *versionid = CLIENT_VERSIONID_SEXP; *gameversion = CLIENT_GAMEVERSION_SEXP; *exeinfo = CLIENT_EXEINFO_SEXP; *checksum = CLIENT_CHECKSUM_SEXP; return 0; } if (strcmp(clienttag,CLIENTTAG_WARCIIBNE)==0) { *versionid = CLIENT_VERSIONID_W2BN; *gameversion = CLIENT_GAMEVERSION_W2BN; *exeinfo = CLIENT_EXEINFO_W2BN; *checksum = CLIENT_CHECKSUM_W2BN; return 0; } if (strcmp(clienttag,CLIENTTAG_DIABLO2DV)==0) { *versionid = CLIENT_VERSIONID_D2DV; *gameversion = CLIENT_GAMEVERSION_D2DV; *exeinfo = CLIENT_EXEINFO_D2DV; *checksum = CLIENT_CHECKSUM_D2DV; return 0; } if (strcmp(clienttag,CLIENTTAG_DIABLO2XP)==0) { *versionid = CLIENT_VERSIONID_D2XP; *gameversion = CLIENT_GAMEVERSION_D2XP; *exeinfo = CLIENT_EXEINFO_D2XP; *checksum = CLIENT_CHECKSUM_D2XP; return 0; } if (strcmp(clienttag,CLIENTTAG_WARCRAFT3)==0 || strcmp(clienttag,CLIENTTAG_WAR3XP)==0) { *versionid = CLIENT_VERSIONID_WAR3; *gameversion = CLIENT_GAMEVERSION_WAR3; *exeinfo = CLIENT_EXEINFO_WAR3; *checksum = CLIENT_CHECKSUM_WAR3; return 0; } *versionid = 0; *gameversion = 0; *exeinfo = ""; *checksum = 0; fprintf(stderr,"%s: unsupported clienttag \"%s\"\n",progname,clienttag); // aaron: dunno what we should return in case of this.. but returning nothing was definetly wrong return -1; } extern int client_connect(char const * progname, char const * servname, unsigned short servport, char const * cdowner, char const * cdkey, char const * clienttag, struct sockaddr_in * saddr, unsigned int * sessionkey, unsigned int * sessionnum, char const * archtag, char const * gamelang) { struct hostent * host; char const * username; int sd; t_packet * packet; t_packet * rpacket; char compname[COMPNAMELEN]; int lsock; unsigned short lsock_port; unsigned int versionid; unsigned int gameversion; char const * exeinfo; unsigned int checksum; if (!progname) { fprintf(stderr,"got NULL progname\n"); return -1; } if (!saddr) { fprintf(stderr,"%s: got NULL saddr\n",progname); return -1; } if (!sessionkey) { fprintf(stderr,"%s: got NULL sessionkey\n",progname); return -1; } if (!sessionnum) { fprintf(stderr,"%s: got NULL sessionnum\n",progname); return -1; } if (psock_init()<0) { fprintf(stderr,"%s: could not inialialize socket functions\n",progname); return -1; } if (!(host = gethostbyname(servname))) { fprintf(stderr,"%s: unknown host \"%s\"\n",progname,servname); return -1; } if (host->h_addrtype!=PSOCK_AF_INET) fprintf(stderr,"%s: host \"%s\" is not in IPv4 address family\n",progname,servname); if (gethostname(compname,COMPNAMELEN)<0) { fprintf(stderr,"%s: could not get host name (gethostname: %s)\n",progname,pstrerror(errno)); return -1; } #ifdef HAVE_GETLOGIN if (!(username = getlogin())) #endif { username = "unknown"; dprintf("%s: could not get login name, using \"%s\" (getlogin: %s)\n",progname,username,pstrerror(errno)); } if ((sd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0) { fprintf(stderr,"%s: could not create socket (psock_socket: %s)\n",progname,pstrerror(psock_errno())); return -1; } memset(saddr,0,sizeof(*saddr)); saddr->sin_family = PSOCK_AF_INET; saddr->sin_port = htons(servport); memcpy(&saddr->sin_addr.s_addr,host->h_addr_list[0],host->h_length); if (psock_connect(sd,(struct sockaddr *)saddr,sizeof(*saddr))<0) { fprintf(stderr,"%s: could not connect to server \"%s\" port %hu (psock_connect: %s)\n",progname,servname,servport,pstrerror(psock_errno())); goto error_sd; } printf("Connected to %s:%hu.\n",inet_ntoa(saddr->sin_addr),servport); #ifdef CLIENTDEBUG eventlog_set(stderr); #endif if ((lsock = client_udptest_setup(progname,&lsock_port))>=0) dprintf("Got UDP data on port %hu\n",lsock_port); if (!(packet = packet_create(packet_class_init))) { fprintf(stderr,"%s: could not create packet\n",progname); goto error_lsock; } bn_byte_set(&packet->u.client_initconn.class,CLIENT_INITCONN_CLASS_BNET); client_blocksend_packet(sd,packet); packet_del_ref(packet); /* reuse this same packet over and over */ if (!(rpacket = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",progname); goto error_lsock; } get_defversioninfo(progname,clienttag,&versionid,&gameversion,&exeinfo,&checksum); if (strcmp(clienttag,CLIENTTAG_DIABLOSHR)==0 || strcmp(clienttag,CLIENTTAG_DIABLORTL)==0) { if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",progname); goto error_rpacket; } packet_set_size(packet,sizeof(t_client_unknown_1b)); packet_set_type(packet,CLIENT_UNKNOWN_1B); bn_short_set(&packet->u.client_unknown_1b.unknown1,CLIENT_UNKNOWN_1B_UNKNOWN3); bn_short_nset(&packet->u.client_unknown_1b.port,lsock_port); bn_int_nset(&packet->u.client_unknown_1b.ip,0); /* FIXME */ bn_int_set(&packet->u.client_unknown_1b.unknown2,CLIENT_UNKNOWN_1B_UNKNOWN3); bn_int_set(&packet->u.client_unknown_1b.unknown3,CLIENT_UNKNOWN_1B_UNKNOWN3); client_blocksend_packet(sd,packet); packet_del_ref(packet); } if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",progname); goto error_rpacket; } packet_set_size(packet,sizeof(t_client_countryinfo_109)); packet_set_type(packet,CLIENT_COUNTRYINFO_109); bn_int_set(&packet->u.client_countryinfo_109.protocol,CLIENT_COUNTRYINFO_109_PROTOCOL); bn_int_tag_set(&packet->u.client_countryinfo_109.archtag,archtag); bn_int_tag_set(&packet->u.client_countryinfo_109.clienttag,clienttag); //AARON bn_int_set(&packet->u.client_countryinfo_109.versionid,versionid); bn_int_tag_set(&packet->u.client_countryinfo_109.gamelang,gamelang); bn_int_set(&packet->u.client_countryinfo_109.localip,CLIENT_COUNTRYINFO_109_LOCALIP); { int bias; bias = local_tzbias(); bn_int_set(&packet->u.client_countryinfo_109.bias,(unsigned int)bias); /* rely on 2's complement */ dprintf("my tzbias = %d (0x%08hx)\n",bias,(unsigned int)bias); } /* FIXME: determine from locale */ bn_int_set(&packet->u.client_countryinfo_109.lcid,CLIENT_COUNTRYINFO_109_LANGID_USENGLISH); bn_int_set(&packet->u.client_countryinfo_109.langid,CLIENT_COUNTRYINFO_109_LANGID_USENGLISH); packet_append_string(packet,CLIENT_COUNTRYINFO_109_LANGSTR_USENGLISH); /* FIXME: determine from locale+timezone... from domain name... nothing really would work. Maybe add some command-line options */ packet_append_string(packet,CLIENT_COUNTRYINFO_109_COUNTRYNAME_USA); client_blocksend_packet(sd,packet); packet_del_ref(packet); do if (client_blockrecv_packet(sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",progname); goto error_rpacket; } while (packet_get_type(rpacket)!=SERVER_AUTHREQ_109 && packet_get_type(rpacket)!=SERVER_AUTHREPLY_109); if (packet_get_type(rpacket)==SERVER_AUTHREQ_109) /* hmm... server wants to check the version number */ { dprintf("Got AUTHREQ_109\n"); *sessionkey = bn_int_get(rpacket->u.server_authreq_109.sessionkey); *sessionnum = bn_int_get(rpacket->u.server_authreq_109.sessionnum); /* FIXME: also get filename and equation */ if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",progname); goto error_rpacket; } packet_set_size(packet,sizeof(t_client_authreq_109)); packet_set_type(packet,CLIENT_AUTHREQ_109); bn_int_set(&packet->u.client_authreq_109.ticks,time(NULL)); { t_cdkey_info cdkey_info; bn_int_set(&packet->u.client_authreq_109.gameversion,gameversion); bn_int_set(&packet->u.client_authreq_109.cdkey_number,1); /* only one */ memset(&cdkey_info,'0',sizeof(cdkey_info)); /* FIXME: put the input cdkey here */ packet_append_data(packet,&cdkey_info,sizeof(cdkey_info)); packet_append_string(packet,exeinfo); packet_append_string(packet,cdowner); } bn_int_set(&packet->u.client_authreq_109.spawn,0x0000); bn_int_set(&packet->u.client_authreq_109.checksum,checksum); client_blocksend_packet(sd,packet); packet_del_ref(packet); /* now wait for reply */ do if (client_blockrecv_packet(sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",progname); goto error_rpacket; } while (packet_get_type(rpacket)!=SERVER_AUTHREPLY_109); //FIXME: check if AUTHREPLY_109 is success or fail if (bn_int_get(rpacket->u.server_authreply_109.message)!=SERVER_AUTHREPLY_109_MESSAGE_OK) { fprintf(stderr,"AUTHREPLY_109 failed - closing connection\n"); goto error_rpacket; } } else fprintf(stderr,"We didn't get a sessionkey, don't expect login to work!"); dprintf("Got AUTHREPLY_109\n"); if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",progname); goto error_rpacket; } packet_set_size(packet,sizeof(t_client_iconreq)); packet_set_type(packet,CLIENT_ICONREQ); client_blocksend_packet(sd,packet); packet_del_ref(packet); do if (client_blockrecv_packet(sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",progname); goto error_rpacket; } while (packet_get_type(rpacket)!=SERVER_ICONREPLY); dprintf("Got ICONREPLY\n"); if (strcmp(clienttag,CLIENTTAG_STARCRAFT)==0 || strcmp(clienttag,CLIENTTAG_BROODWARS)==0 || strcmp(clienttag,CLIENTTAG_WARCIIBNE)==0) { if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",progname); goto error_rpacket; } { struct { bn_int sessionkey; bn_int ticks; bn_int productid; bn_int keyvalue1; bn_int keyvalue2; } temp; t_hash key_hash; unsigned int ticks; unsigned int keyvalue1,keyvalue2,productid; if (key_interpret(cdkey,&productid,&keyvalue1,&keyvalue2)<0) { fprintf(stderr,"%s: specified key is not valid, sending junk\n",progname); productid = 0; keyvalue1 = 0; keyvalue2 = 0; } ticks = 0; /* FIXME: what to use here? */ bn_int_set(&temp.ticks,ticks); bn_int_set(&temp.sessionkey,*sessionkey); bn_int_set(&temp.productid,productid); bn_int_set(&temp.keyvalue1,keyvalue1); bn_int_set(&temp.keyvalue2,keyvalue2); bnet_hash(&key_hash,sizeof(temp),&temp); packet_set_size(packet,sizeof(t_client_cdkey2)); packet_set_type(packet,CLIENT_CDKEY2); bn_int_set(&packet->u.client_cdkey2.spawn,CLIENT_CDKEY2_SPAWN_FALSE); /* FIXME: add option */ bn_int_set(&packet->u.client_cdkey2.keylen,strlen(cdkey)); bn_int_set(&packet->u.client_cdkey2.productid,productid); bn_int_set(&packet->u.client_cdkey2.keyvalue1,keyvalue1); bn_int_set(&packet->u.client_cdkey2.sessionkey,*sessionkey); bn_int_set(&packet->u.client_cdkey2.ticks,ticks); hash_to_bnhash((t_hash const *)&key_hash,packet->u.client_cdkey2.key_hash); /* avoid warning */ packet_append_string(packet,cdowner); client_blocksend_packet(sd,packet); packet_del_ref(packet); } do if (client_blockrecv_packet(sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",progname); goto error_rpacket; } while (packet_get_type(rpacket)!=SERVER_CDKEYREPLY2); dprintf("Got CDKEYREPLY2 (%u)\n",bn_int_get(rpacket->u.server_cdkeyreply2.message)); } packet_destroy(rpacket); return sd; /* error cleanup */ error_rpacket: packet_destroy(rpacket); error_lsock: if (lsock>=0) psock_close(lsock); error_sd: psock_close(sd); return -1; } pvpgn-1.8.5/src/client/bnstat.c0000644000175000017500000011411711151345317015353 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memset.h" #include "compat/memcpy.h" #include #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/strftime.h" #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_TERMIOS_H # include #endif #include "compat/termios.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/recv.h" #include "compat/send.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #include "compat/psock.h" #include "common/packet.h" #include "common/init_protocol.h" #include "common/udp_protocol.h" #include "common/bnet_protocol.h" #include "common/tag.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/network.h" #include "common/version.h" #include "common/util.h" #ifdef CLIENTDEBUG # include "common/eventlog.h" #endif #include "common/bnettime.h" #include "client.h" #include "udptest.h" #include "client_connect.h" #include "common/setup_after.h" #ifdef CLIENTDEBUG # define dprintf printf #else # define dprintf if (0) printf #endif static char const * bnclass_get_str(unsigned int class); /* FIXME: this is also in command.c */ static void usage(char const * progname); static char const * bnclass_get_str(unsigned int class) { switch (class) { case PLAYERINFO_DRTL_CLASS_WARRIOR: return "warrior"; case PLAYERINFO_DRTL_CLASS_ROGUE: return "rogue"; case PLAYERINFO_DRTL_CLASS_SORCERER: return "sorcerer"; default: return "unknown"; } } static void usage(char const * progname) { fprintf(stderr,"usage: %s [] [ []]\n",progname); fprintf(stderr, " -b, --client=SEXP report client as Brood Wars\n" " -d, --client=DRTL report client as Diablo Retail\n" " --client=DSHR report client as Diablo Shareware\n" " -s, --client=STAR report client as Starcraft (default)\n"); fprintf(stderr, " --client=SSHR report client as Starcraft Shareware\n" " -w, --client=W2BN report client as Warcraft II BNE\n" " --client=D2DV report client as Diablo II\n" " --client=D2XP report client as Diablo II: LoD\n" " --client=WAR3 report client as Warcraft III\n"); fprintf(stderr, " -o NAME, --owner=NAME report CD owner as NAME\n" " -k KEY, --cdkey=KEY report CD key as KEY\n" " -p PLR, --player=PLR print stats for player PLR\n" " --bnetd also print BNETD-specific stats\n" " --fsgs also print FSGS-specific stats\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n"); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { int a; int sd; int gotplayer=0; struct sockaddr_in saddr; t_packet * packet; t_packet * rpacket; char const * cdowner=NULL; char const * cdkey=NULL; char const * clienttag=NULL; char const * servname=NULL; unsigned short servport=0; char text[MAX_MESSAGE_LEN]=""; unsigned int commpos; struct termios in_attr_old; struct termios in_attr_new; int changed_in; unsigned int count; unsigned int sessionkey; unsigned int sessionnum; unsigned int val; int fd_stdin=0; int use_bnetd=0; int use_fsgs=0; unsigned int screen_width,screen_height; int munged=0; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a=argc) { if (str_to_ushort(argv[a],&servport)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (!servname && argv[a][0]!='-' && a+2>=argc) servname = argv[a]; else if (strcmp(argv[a],"-b")==0 || strcmp(argv[a],"--client=SEXP")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_BROODWARS; } else if (strcmp(argv[a],"-d")==0 || strcmp(argv[a],"--client=DRTL")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_DIABLORTL; } else if (strcmp(argv[a],"--client=DSHR")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_DIABLOSHR; } else if (strcmp(argv[a],"-s")==0 || strcmp(argv[a],"--client=STAR")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_STARCRAFT; } else if (strcmp(argv[a],"--client=SSHR")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_SHAREWARE; } else if (strcmp(argv[a],"-w")==0 || strcmp(argv[a],"--client=W2BN")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag); usage(argv[0]); } clienttag = CLIENTTAG_WARCIIBNE; } else if (strcmp(argv[a],"--client=D2DV")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag ); usage(argv[0]); } clienttag = CLIENTTAG_DIABLO2DV; } else if (strcmp(argv[a],"--client=D2XP")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag ); usage(argv[0]); } clienttag = CLIENTTAG_DIABLO2XP; } else if (strcmp(argv[a],"--client=WAR3")==0) { if (clienttag) { fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag ); usage(argv[0]); } clienttag = CLIENTTAG_WARCRAFT3; } else if (strncmp(argv[a],"--client=",9)==0) { fprintf(stderr,"%s: unknown client tag \"%s\"\n",argv[0],&argv[a][9]); usage(argv[0]); } else if (strcmp(argv[a],"-o")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (cdowner) { fprintf(stderr,"%s: CD owner was already specified as \"%s\"\n",argv[0],cdowner); usage(argv[0]); } cdowner = argv[++a]; } else if (strncmp(argv[a],"--owner=",8)==0) { if (cdowner) { fprintf(stderr,"%s: CD owner was already specified as \"%s\"\n",argv[0],cdowner); usage(argv[0]); } cdowner = &argv[a][8]; } else if (strcmp(argv[a],"-k")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (cdkey) { fprintf(stderr,"%s: CD key was already specified as \"%s\"\n",argv[0],cdkey); usage(argv[0]); } cdkey = argv[++a]; } else if (strncmp(argv[a],"--cdkey=",8)==0) { if (cdkey) { fprintf(stderr,"%s: CD key was already specified as \"%s\"\n",argv[0],cdkey); usage(argv[0]); } cdkey = &argv[a][8]; } else if (strcmp(argv[a],"-p")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (gotplayer) { fprintf(stderr,"%s: player was already specified as \"%s\"\n",argv[0],text); usage(argv[0]); } a++; if (argv[a][0]=='\0') { fprintf(stderr,"%s: player name can not be empty\n",argv[0]); usage(argv[0]); } strncpy(text,argv[a],sizeof(text)); text[sizeof(text)-1] = '\0'; gotplayer = 1; } else if (strncmp(argv[a],"--player=",9)==0) { if (gotplayer) { fprintf(stderr,"%s: player was already specified as \"%s\"\n",argv[0],text); usage(argv[0]); } if (argv[a][9]=='\0') { fprintf(stderr,"%s: player name can not be empty\n",argv[0]); usage(argv[0]); } strncpy(text,&argv[a][9],sizeof(text)); text[sizeof(text)-1] = '\0'; gotplayer = 1; } else if (strcmp(argv[a],"--bnetd")==0) use_bnetd = 1; else if (strcmp(argv[a],"--fsgs")==0) use_fsgs = 1; else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage") ==0) usage(argv[0]); else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0) { printf("version "PVPGN_VERSION"\n"); return STATUS_SUCCESS; } else if (strcmp(argv[a],"--client")==0 || strcmp(argv[a],"--owner")==0 || strcmp(argv[a],"--cdkey")==0 || strcmp(argv[a],"--player")==0) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } else { fprintf(stderr,"%s: unknown option \"%s\"\n",argv[0],argv[a]); usage(argv[0]); } if (servport==0) servport = BNETD_SERV_PORT; if (!cdowner) cdowner = BNETD_DEFAULT_OWNER; if (!cdkey) cdkey = BNETD_DEFAULT_KEY; if (!clienttag) clienttag = CLIENTTAG_STARCRAFT; if (!servname) servname = BNETD_DEFAULT_HOST; if (gotplayer) changed_in = 0; /* no need to change terminal attributes */ else { fd_stdin = fileno(stdin); if (tcgetattr(fd_stdin,&in_attr_old)>=0) { in_attr_new = in_attr_old; in_attr_new.c_lflag &= ~(ECHO | ICANON); /* turn off ECHO and ICANON */ in_attr_new.c_cc[VMIN] = 1; /* require reads to return at least one byte */ in_attr_new.c_cc[VTIME] = 0; /* no timeout */ tcsetattr(fd_stdin,TCSANOW,&in_attr_new); changed_in = 1; } else { fprintf(stderr,"%s: could not set terminal attributes for stdin\n",argv[0]); changed_in = 0; } if (client_get_termsize(fd_stdin,&screen_width,&screen_height)<0) { fprintf(stderr,"%s: could not determine screen size, assuming 80x24\n",argv[0]); screen_width = 80; screen_height = 24; } } if ((sd = client_connect(argv[0],servname,servport,cdowner,cdkey,clienttag,&saddr,&sessionkey,&sessionnum,ARCHTAG_WINX86,CLIENT_COUNTRYINFO_109_GAMELANG))<0) { fprintf(stderr,"%s: fatal error during handshake\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } /* reuse this same packet over and over */ if (!(rpacket = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); psock_close(sd); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } if (!(packet = packet_create(packet_class_bnet))) { fprintf(stderr,"%s: could not create packet\n",argv[0]); psock_close(sd); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } packet_set_size(packet,sizeof(t_client_fileinforeq)); packet_set_type(packet,CLIENT_FILEINFOREQ); bn_int_set(&packet->u.client_fileinforeq.type,CLIENT_FILEINFOREQ_TYPE_TOS); bn_int_set(&packet->u.client_fileinforeq.unknown2,CLIENT_FILEINFOREQ_UNKNOWN2); packet_append_string(packet,CLIENT_FILEINFOREQ_FILE_TOSUSA); client_blocksend_packet(sd,packet); packet_del_ref(packet); do if (client_blockrecv_packet(sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",argv[0]); psock_close(sd); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } while (packet_get_type(rpacket)!=SERVER_FILEINFOREPLY); dprintf("Got FILEINFOREPLY\n"); if (!gotplayer) { munged = 1; commpos = 0; text[0] = '\0'; } for (;;) { unsigned int i; if (!gotplayer) { switch (client_get_comm("player: ",text,sizeof(text),&commpos,1,munged,screen_width)) { case -1: /* cancel or error */ break; case 0: /* timeout */ munged = 0; continue; case 1: munged = 0; if (text[0]=='\0') continue; } if (text[0]=='\0') break; printf("\r"); for (i=0; iu.client_statsreq.name_count,1); bn_int_set(&packet->u.client_statsreq.requestid,0); packet_append_string(packet,text); count = 0; if (use_bnetd) { packet_append_string(packet,"BNET\\acct\\username"); packet_append_string(packet,"BNET\\acct\\userid"); packet_append_string(packet,"BNET\\acct\\lastlogin_clienttag"); packet_append_string(packet,"BNET\\acct\\lastlogin_connection"); packet_append_string(packet,"BNET\\acct\\lastlogin_time"); packet_append_string(packet,"BNET\\acct\\firstlogin_clienttag"); packet_append_string(packet,"BNET\\acct\\firstlogin_connection"); packet_append_string(packet,"BNET\\acct\\firstlogin_time"); count += 8; } if (use_fsgs) { packet_append_string(packet,"FSGS\\Created"); count += 1; } packet_append_string(packet,"profile\\sex"); packet_append_string(packet,"profile\\age"); packet_append_string(packet,"profile\\location"); packet_append_string(packet,"profile\\description"); count += 4; if (strcmp(clienttag,"STAR")==0) { packet_append_string(packet,"Record\\STAR\\0\\last game"); packet_append_string(packet,"Record\\STAR\\0\\last game result"); packet_append_string(packet,"Record\\STAR\\0\\wins"); packet_append_string(packet,"Record\\STAR\\0\\losses"); packet_append_string(packet,"Record\\STAR\\0\\disconnects"); packet_append_string(packet,"Record\\STAR\\0\\draws"); count += 6; packet_append_string(packet,"Record\\STAR\\1\\last game"); packet_append_string(packet,"Record\\STAR\\1\\last game result"); packet_append_string(packet,"Record\\STAR\\1\\rating"); packet_append_string(packet,"Record\\STAR\\1\\active rating"); packet_append_string(packet,"Record\\STAR\\1\\high rating"); packet_append_string(packet,"Record\\STAR\\1\\rank"); packet_append_string(packet,"Record\\STAR\\1\\active rank"); packet_append_string(packet,"Record\\STAR\\1\\high rank"); packet_append_string(packet,"Record\\STAR\\1\\wins"); packet_append_string(packet,"Record\\STAR\\1\\losses"); packet_append_string(packet,"Record\\STAR\\1\\disconnects"); packet_append_string(packet,"Record\\STAR\\1\\draws"); count += 12; } else if (strcmp(clienttag,"SEXP")==0) { packet_append_string(packet,"Record\\SEXP\\0\\last game"); packet_append_string(packet,"Record\\SEXP\\0\\last game result"); packet_append_string(packet,"Record\\SEXP\\0\\wins"); packet_append_string(packet,"Record\\SEXP\\0\\losses"); packet_append_string(packet,"Record\\SEXP\\0\\disconnects"); packet_append_string(packet,"Record\\SEXP\\0\\draws"); count += 6; packet_append_string(packet,"Record\\SEXP\\1\\last game"); packet_append_string(packet,"Record\\SEXP\\1\\last game result"); packet_append_string(packet,"Record\\SEXP\\1\\rating"); packet_append_string(packet,"Record\\SEXP\\1\\active rating"); packet_append_string(packet,"Record\\SEXP\\1\\high rating"); packet_append_string(packet,"Record\\SEXP\\1\\rank"); packet_append_string(packet,"Record\\SEXP\\1\\active rank"); packet_append_string(packet,"Record\\SEXP\\1\\high rank"); packet_append_string(packet,"Record\\SEXP\\1\\wins"); packet_append_string(packet,"Record\\SEXP\\1\\losses"); packet_append_string(packet,"Record\\SEXP\\1\\disconnects"); packet_append_string(packet,"Record\\SEXP\\1\\draws"); count += 12; } else if (strcmp(clienttag,"SSHR")==0) { packet_append_string(packet,"Record\\SSHR\\0\\last game"); packet_append_string(packet,"Record\\SSHR\\0\\last game result"); packet_append_string(packet,"Record\\SSHR\\0\\wins"); packet_append_string(packet,"Record\\SSHR\\0\\losses"); packet_append_string(packet,"Record\\SSHR\\0\\disconnects"); packet_append_string(packet,"Record\\SSHR\\0\\draws"); count += 6; } else if (strcmp(clienttag,"DSHR")==0 || strcmp(clienttag,"DRTL")==0) { if (use_bnetd) { packet_append_string(packet,"BNET\\Record\\DRTL\\0\\level"); packet_append_string(packet,"BNET\\Record\\DRTL\\0\\class"); packet_append_string(packet,"BNET\\Record\\DRTL\\0\\strength"); packet_append_string(packet,"BNET\\Record\\DRTL\\0\\magic"); packet_append_string(packet,"BNET\\Record\\DRTL\\0\\dexterity"); packet_append_string(packet,"BNET\\Record\\DRTL\\0\\vitality"); packet_append_string(packet,"BNET\\Record\\DRTL\\0\\gold"); packet_append_string(packet,"BNET\\Record\\DRTL\\0\\diablo kills"); count += 8; } } else if (strcmp(clienttag,"W2BN")==0) { packet_append_string(packet,"Record\\W2BN\\0\\last game"); packet_append_string(packet,"Record\\W2BN\\0\\last game result"); packet_append_string(packet,"Record\\W2BN\\0\\wins"); packet_append_string(packet,"Record\\W2BN\\0\\losses"); packet_append_string(packet,"Record\\W2BN\\0\\disconnects"); packet_append_string(packet,"Record\\W2BN\\0\\draws"); count += 6; packet_append_string(packet,"Record\\W2BN\\1\\last game"); packet_append_string(packet,"Record\\W2BN\\1\\last game result"); packet_append_string(packet,"Record\\W2BN\\1\\rating"); packet_append_string(packet,"Record\\W2BN\\1\\active rating"); packet_append_string(packet,"Record\\W2BN\\1\\high rating"); packet_append_string(packet,"Record\\W2BN\\1\\rank"); packet_append_string(packet,"Record\\W2BN\\1\\active rank"); packet_append_string(packet,"Record\\W2BN\\1\\high rank"); packet_append_string(packet,"Record\\W2BN\\1\\wins"); packet_append_string(packet,"Record\\W2BN\\1\\losses"); packet_append_string(packet,"Record\\W2BN\\1\\disconnects"); packet_append_string(packet,"Record\\W2BN\\1\\draws"); count += 12; packet_append_string(packet,"Record\\W2BN\\3\\last game"); packet_append_string(packet,"Record\\W2BN\\3\\last game result"); packet_append_string(packet,"Record\\W2BN\\3\\rating"); packet_append_string(packet,"Record\\W2BN\\3\\active rating"); packet_append_string(packet,"Record\\W2BN\\3\\high rating"); packet_append_string(packet,"Record\\W2BN\\3\\rank"); packet_append_string(packet,"Record\\W2BN\\3\\active rank"); packet_append_string(packet,"Record\\W2BN\\3\\high rank"); packet_append_string(packet,"Record\\W2BN\\3\\wins"); packet_append_string(packet,"Record\\W2BN\\3\\losses"); packet_append_string(packet,"Record\\W2BN\\3\\disconnects"); packet_append_string(packet,"Record\\W2BN\\3\\draws"); count += 12; } bn_int_set(&packet->u.client_statsreq.key_count,count); client_blocksend_packet(sd,packet); packet_del_ref(packet); do if (client_blockrecv_packet(sd,rpacket)<0) { fprintf(stderr,"%s: server closed connection\n",argv[0]); if (changed_in) tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old); return STATUS_FAILURE; } while (packet_get_type(rpacket)!=SERVER_STATSREPLY); dprintf("Got STATSREPLY\n"); { unsigned int names,keys; unsigned int j; unsigned int strpos; char const * temp; unsigned int uid; struct in_addr laddr; time_t tm; char timestr[STAT_TIME_MAXLEN]; names = bn_int_get(rpacket->u.server_statsreply.name_count); keys = bn_int_get(rpacket->u.server_statsreply.key_count); printf("----\n"); strpos = sizeof(t_server_statsreply); for (i=0; i0) printf(" Level: %u\n",level); else printf(" Level: NONE\n"); if (j #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strrchr.h" #ifdef HAVE_UNISTD_H # include #endif #include "compat/read.h" #ifdef HAVE_SYS_IOCTL_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/psock.h" #include "common/packet.h" #include "common/network.h" #ifdef WIN32 # include /* for kbhit() and getch() */ #endif #include "client.h" #include "common/setup_after.h" extern int client_blocksend_packet(int sock, t_packet const * packet) { unsigned int size=0; for (;;) switch (net_send_packet(sock,packet,&size)) { case -1: return -1; case 0: continue; default: return 0; } } extern int client_blockrecv_packet(int sock, t_packet * packet) { unsigned int size=0; for (;;) switch (net_recv_packet(sock,packet,&size)) { case -1: return -1; case 0: continue; default: /* printf("Got packet len %u/%u type 0x%04x\n",size,packet_get_size(packet),packet_get_type(packet)); */ return 0; } } extern int client_blockrecv_raw_packet(int sock, t_packet * packet, unsigned int len) { unsigned int size=0; packet_set_size(packet,len); for (;;) switch (net_recv_packet(sock,packet,&size)) { case -1: return -1; case 0: continue; case 1: default: return 0; } } extern int client_get_termsize(int fd, unsigned int * w, unsigned int * h) { if (fd<0 || !w || !h) return -1; *w = 0; *h = 0; #ifdef HAVE_IOCTL #ifdef TIOCGWINSZ { struct winsize ws; if (ioctl(fd,TIOCGWINSZ,&ws)>=0) { *w = (unsigned int)ws.ws_col; *h = (unsigned int)ws.ws_row; } } #endif #endif #ifdef HAVE_GETENV { char const * str; int val; if (!*w && (str = getenv("COLUMNS")) && (val = atoi(str))>0) *w = val; if (!*h && (str = getenv("LINES")) && (val = atoi(str))>0) *h = val; } #endif if (!*w) *w = DEF_SCREEN_WIDTH; if (!*h) *h = DEF_SCREEN_HEIGHT; return 0; } /* This routine gets keyboard input. It handles printing the prompt, cursor positioning, and text scrolling. It unfortunatly assumes that the chars read from stdin are in ASCII. */ /* visible: -1=nothing, 0=prompt only, 1=prompt and text */ extern int client_get_comm(char const * prompt, char * text, unsigned int maxlen, unsigned int * curpos, int visible, int redraw, unsigned int width) { char temp; unsigned int addlen; unsigned int i; unsigned int count; int beg_pos; for (count=0; count<16; count++) { beg_pos = 0; if (strlen(prompt)+1>=width) visible = 0; /* no room to show any of the text */ else if (*curpos+strlen(prompt)+1>=width) beg_pos = (int)(*curpos+strlen(prompt)+1-width); if (redraw) { if (visible!=-1) printf("\r%s",prompt); if (visible==1) printf("%s",text+beg_pos); } fflush(stdout); #ifndef WIN32 addlen = read(fileno(stdin),&temp,1); #else if (kbhit()) { temp = getch(); addlen=1; } else { temp = 0; addlen=0; } #endif if (addlen<1) return addlen; switch (temp) { case '\033': /* ESC */ return -1; case '\r': case '\n': return 1; case '\b': /* BS */ case '\177': /* DEL */ if (*curpos<1) /* already empty */ { if (visible==1) printf("\a"); continue; } (*curpos)--; text[*curpos] = '\0'; if (visible==1) { if (beg_pos>0) { beg_pos--; printf("\r%s%s",prompt,text+beg_pos); } else { printf("\b \b"); } } continue; case '\024': /* ^T */ if (*curpos<2) { if (visible==1) printf("\a"); continue; } { char swap; swap = text[*curpos-1]; text[*curpos-1] = text[*curpos-2]; text[*curpos-2] = swap; if (visible==1) { printf("\b\b"); printf("%s",&text[*curpos-2]); } } continue; case '\027': /* ^W */ if (*curpos<1) { if (visible==1) printf("\a"); continue; } { char * t=strrchr(text,' '); unsigned int t1=beg_pos,t2; addlen = t ? t - text : 0; text[addlen] = '\0'; beg_pos -= *curpos - addlen; if (beg_pos < 0) beg_pos=0; if (visible==1) { if (t1 == 0) for (i=0; i < *curpos - addlen; i++) printf("\b \b"); else { /* the \r is counted in the return value, but that's ok because the last column is always blank */ t2 = printf("\r%s%s",prompt,text+beg_pos); if (t1 > 0 && beg_pos == 0) { for (i=0; i0 && temp<32) /* unhandled control char */ { if (visible==1) printf("\a"); continue; } if ((*curpos+1)>=maxlen) /* too full */ { if (visible==1) printf("\a"); continue; } if (visible==1) { if (beg_pos>0 || (*curpos + strlen(prompt) + 2 > width)) { beg_pos++; printf("\r%s%s",prompt,text+beg_pos); } printf("%c",temp); } text[*curpos] = temp; (*curpos)++; text[*curpos] = '\0'; continue; } } return 0; } pvpgn-1.8.5/src/client/ansi_term.h0000644000175000017500000000432611151345317016046 0ustar aaronaaron/* * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_ANSI_TERM_PROTOS #define INCLUDED_ANSI_TERM_PROTOS #define JUST_NEED_TYPES #include #undef JUST_NEED_TYPES #define ansi_beep()\ printf("\007"); #define ansi_screen_clear()\ printf("\033[2J"); #define ansi_line_clear()\ printf("\033[K"); #define ansi_cursor_move_up(lines)\ printf("\033[%dA",lines); #define ansi_cursor_move_down(lines)\ printf("\033[%dB",lines); #define ansi_cursor_move_left(chars)\ printf("\033[%dD",chars); #define ansi_cursor_move_right(chars)\ printf("\033[%dC",chars); #define ansi_cursor_move_home()\ printf("\033[1;0H"); #define ansi_cursor_move(y,x)\ printf("\033[%d;%dH",x+1,y); #define ansi_cursor_save()\ printf("\033[u"); #define ansi_cursor_load()\ printf("\033[s"); #define ansi_text_reset()\ printf("\033[0m"); #define ansi_text_style(style)\ printf("\033[%dm",style); #define ansi_text_color_fore(color)\ printf("\033[3%dm",color); #define ansi_text_color_back(color)\ printf("\033[4%dm",color); #define ansi_text_style_bold 1 #define ansi_text_style_underline 4 #define ansi_text_style_blink 5 #define ansi_text_style_inverse 7 #define ansi_text_color_black 0 #define ansi_text_color_red 1 #define ansi_text_color_green 2 #define ansi_text_color_yellow 3 #define ansi_text_color_blue 4 #define ansi_text_color_magenta 5 #define ansi_text_color_cyan 6 #define ansi_text_color_white 7 #endif #endif pvpgn-1.8.5/src/tinycdb/0000755000175000017500000000000011151345372014066 5ustar aaronaaronpvpgn-1.8.5/src/tinycdb/cdb_make.c0000644000175000017500000001003711151345317015757 0ustar aaronaaron/* basic cdb creation routines * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "common/xalloc.h" #include "cdb_int.h" #include "common/setup_after.h" void cdb_pack(unsigned num, unsigned char buf[4]) { buf[0] = num & 255; num >>= 8; buf[1] = num & 255; num >>= 8; buf[2] = num & 255; buf[3] = num >> 8; } int cdb_make_start(struct cdb_make *cdbmp, FILE *fd) { memset(cdbmp, 0, sizeof(*cdbmp)); cdbmp->cdb_fd = fd; cdbmp->cdb_dpos = 2048; cdbmp->cdb_bpos = cdbmp->cdb_buf + 2048; return 0; } static int ewrite(FILE *fd, const char *buf, int len) { while(len) { int l = fwrite(buf, 1, len, fd); if (l < 0 && errno != EINTR) return -1; len -= l; buf += l; } return 0; } int _cdb_make_write(struct cdb_make *cdbmp, const char *ptr, unsigned len) { unsigned l = sizeof(cdbmp->cdb_buf) - (cdbmp->cdb_bpos - cdbmp->cdb_buf); cdbmp->cdb_dpos += len; if (len > l) { memcpy(cdbmp->cdb_bpos, ptr, l); if (ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf, sizeof(cdbmp->cdb_buf)) < 0) return -1; ptr += l; len -= l; l = len / sizeof(cdbmp->cdb_buf); if (l) { l *= sizeof(cdbmp->cdb_buf); if (ewrite(cdbmp->cdb_fd, ptr, l) < 0) return -1; ptr += l; len -= l; } cdbmp->cdb_bpos = cdbmp->cdb_buf; } if (len) { memcpy(cdbmp->cdb_bpos, ptr, len); cdbmp->cdb_bpos += len; } return 0; } static int cdb_make_finish_internal(struct cdb_make *cdbmp) { unsigned hcnt[256]; /* hash table counts */ unsigned hpos[256]; /* hash table positions */ struct cdb_rec *htab; unsigned char *p; struct cdb_rl *rl; unsigned hsize; unsigned t, i; if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt) return errno = ENOMEM, -1; /* count htab sizes and reorder reclists */ hsize = 0; for (t = 0; t < 256; ++t) { struct cdb_rl *rlt = NULL; i = 0; rl = cdbmp->cdb_rec[t]; while(rl) { struct cdb_rl *rln = rl->next; rl->next = rlt; rlt = rl; i += rl->cnt; rl = rln; } cdbmp->cdb_rec[t] = rlt; if (hsize < (hcnt[t] = i << 1)) hsize = hcnt[t]; } /* allocate memory to hold max htable */ htab = (struct cdb_rec*)xmalloc((hsize + 2) * sizeof(struct cdb_rec)); if (!htab) return errno = ENOENT, -1; p = (unsigned char *)htab; htab += 2; /* build hash tables */ for (t = 0; t < 256; ++t) { unsigned len, hi; hpos[t] = cdbmp->cdb_dpos; if ((len = hcnt[t]) == 0) continue; for (i = 0; i < len; ++i) htab[i].hval = htab[i].rpos = 0; for (rl = cdbmp->cdb_rec[t]; rl; rl = rl->next) for (i = 0; i < rl->cnt; ++i) { hi = (rl->rec[i].hval >> 8) % len; while(htab[hi].rpos) if (++hi == len) hi = 0; htab[hi] = rl->rec[i]; } for (i = 0; i < len; ++i) { cdb_pack(htab[i].hval, p + (i << 3)); cdb_pack(htab[i].rpos, p + (i << 3) + 4); } if (_cdb_make_write(cdbmp, p, len << 3) < 0) { xfree(p); return -1; } } xfree(p); if (cdbmp->cdb_bpos != cdbmp->cdb_buf && ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf, cdbmp->cdb_bpos - cdbmp->cdb_buf) != 0) return -1; p = cdbmp->cdb_buf; for (t = 0; t < 256; ++t) { cdb_pack(hpos[t], p + (t << 3)); cdb_pack(hcnt[t], p + (t << 3) + 4); } rewind(cdbmp->cdb_fd); if (ewrite(cdbmp->cdb_fd, p, 2048) != 0) return -1; return 0; } static void cdb_make_free(struct cdb_make *cdbmp) { unsigned t; for(t = 0; t < 256; ++t) { struct cdb_rl *rl = cdbmp->cdb_rec[t]; while(rl) { struct cdb_rl *tm = rl; rl = rl->next; xfree(tm); } } } int cdb_make_finish(struct cdb_make *cdbmp) { int r = cdb_make_finish_internal(cdbmp); cdb_make_free(cdbmp); return r; } pvpgn-1.8.5/src/tinycdb/cdb_seq.c0000644000175000017500000000136311151345317015634 0ustar aaronaaron/* sequential record retrieval routines * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include "cdb_int.h" #include "common/setup_after.h" int cdb_seqnext(unsigned *cptr, struct cdb *cdbp) { unsigned klen, vlen; unsigned pos = *cptr; unsigned dend = cdbp->cdb_dend; const unsigned char *mem = cdbp->cdb_mem; if (pos > dend - 8) return 0; klen = cdb_unpack(mem + pos); vlen = cdb_unpack(mem + pos + 4); pos += 8; if (dend - klen < pos || dend - vlen < pos + klen) return errno = EPROTO, -1; cdbp->cdb_kpos = pos; cdbp->cdb_klen = klen; cdbp->cdb_vpos = pos + klen; cdbp->cdb_vlen = vlen; *cptr = pos + klen + vlen; return 1; } pvpgn-1.8.5/src/tinycdb/cdb_seek.c0000644000175000017500000000523711151345317015777 0ustar aaronaaron/* old interface for reading cdb file * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include #include "cdb_int.h" #include "common/setup_after.h" #ifndef SEEK_SET # define SEEK_SET 0 #endif /* read a chunk from file, ignoring interrupts (EINTR) */ int cdb_bread(FILE *fd, void *buf, int len) { int l; while(len > 0) { do l = fread(buf, 1, len, fd); while(l < 0 && errno == EINTR); if (l <= 0) { if (!l) errno = EIO; return -1; } buf = (char*)buf + l; len -= l; } return 0; } /* find a given key in cdb file, seek a file pointer to it's value and place data length to *dlenp. */ int cdb_seek(FILE *fd, const void *key, unsigned klen, unsigned *dlenp) { unsigned htstart; /* hash table start position */ unsigned htsize; /* number of elements in a hash table */ unsigned httodo; /* hash table elements left to look */ unsigned hti; /* hash table index */ unsigned pos; /* position in a file */ unsigned hval; /* key's hash value */ unsigned char rbuf[64]; /* read buffer */ int needseek = 1; /* if we should seek to a hash slot */ hval = cdb_hash(key, klen); pos = (hval & 0xff) << 3; /* position in TOC */ /* read the hash table parameters */ if (fseek(fd, pos, SEEK_SET) || cdb_bread(fd, rbuf, 8) < 0) return -1; if ((htsize = cdb_unpack(rbuf + 4)) == 0) return 0; hti = (hval >> 8) % htsize; /* start position in hash table */ httodo = htsize; htstart = cdb_unpack(rbuf); for(;;) { if (needseek && fseek(fd, htstart + (hti << 3), SEEK_SET)) return -1; if (cdb_bread(fd, rbuf, 8) < 0) return -1; if ((pos = cdb_unpack(rbuf + 4)) == 0) /* not found */ return 0; if (cdb_unpack(rbuf) != hval) /* hash value not matched */ needseek = 0; else { /* hash value matched */ if (fseek(fd, pos, SEEK_SET) || cdb_bread(fd, rbuf, 8) < 0) return -1; if (cdb_unpack(rbuf) == klen) { /* key length matches */ /* read the key from file and compare with wanted */ unsigned l = klen, c; const char *k = (const char*)key; if (*dlenp) *dlenp = cdb_unpack(rbuf + 4); /* save value length */ for(;;) { if (!l) /* the whole key read and matches, return */ return 1; c = l > sizeof(rbuf) ? sizeof(rbuf) : l; if (cdb_bread(fd, rbuf, c) < 0) return -1; if (memcmp(rbuf, k, c) != 0) /* no, it differs, stop here */ break; k += c; l -= c; } } needseek = 1; /* we're looked to other place, should seek back */ } if (!--httodo) return 0; if (++hti == htsize) { hti = 0; needseek = 1; } } } pvpgn-1.8.5/src/tinycdb/cdb_hash.c0000644000175000017500000000076111151345317015770 0ustar aaronaaron/* cdb hashing routine * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include "cdb.h" #include "common/setup_after.h" unsigned cdb_hash(const void *buf, unsigned len) { register const unsigned char *p = (const unsigned char *)buf; register const unsigned char *end = p + len; register unsigned hash = 5381; /* start value */ while (p < end) hash = (hash + (hash << 5)) ^ *p++; return hash; } pvpgn-1.8.5/src/tinycdb/cdb_find.c0000644000175000017500000000437711151345317015774 0ustar aaronaaron/* cdb_find routine * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include "cdb_int.h" #include "common/setup_after.h" int cdb_find(struct cdb *cdbp, const void *key, unsigned klen) { const unsigned char *htp; /* hash table pointer */ const unsigned char *htab; /* hash table */ const unsigned char *htend; /* end of hash table */ unsigned httodo; /* ht bytes left to look */ unsigned pos, n; unsigned hval; if (klen >= cdbp->cdb_dend) /* if key size is too large */ return 0; hval = cdb_hash(key, klen); /* find (pos,n) hash table to use */ /* first 2048 bytes (toc) are always available */ /* (hval % 256) * 8 */ htp = cdbp->cdb_mem + ((hval << 3) & 2047); /* index in toc (256x8) */ n = cdb_unpack(htp + 4); /* table size */ if (!n) /* empty table */ return 0; /* not found */ httodo = n << 3; /* bytes of htab to lookup */ pos = cdb_unpack(htp); /* htab position */ if (n > (cdbp->cdb_fsize >> 3) /* overflow of httodo ? */ || pos < cdbp->cdb_dend /* is htab inside data section ? */ || pos > cdbp->cdb_fsize /* htab start within file ? */ || httodo > cdbp->cdb_fsize - pos) /* entrie htab within file ? */ return errno = EPROTO, -1; htab = cdbp->cdb_mem + pos; /* htab pointer */ htend = htab + httodo; /* after end of htab */ /* htab starting position: rest of hval modulo htsize, 8bytes per elt */ htp = htab + (((hval >> 8) % n) << 3); for(;;) { pos = cdb_unpack(htp + 4); /* record position */ if (!pos) return 0; if (cdb_unpack(htp) == hval) { if (pos > cdbp->cdb_dend - 8) /* key+val lengths */ return errno = EPROTO, -1; if (cdb_unpack(cdbp->cdb_mem + pos) == klen) { if (cdbp->cdb_dend - klen < pos + 8) return errno = EPROTO, -1; if (memcmp(key, cdbp->cdb_mem + pos + 8, klen) == 0) { n = cdb_unpack(cdbp->cdb_mem + pos + 4); pos += 8; if (cdbp->cdb_dend < n || cdbp->cdb_dend - n < pos + klen) return errno = EPROTO, -1; cdbp->cdb_kpos = pos; cdbp->cdb_klen = klen; cdbp->cdb_vpos = pos + klen; cdbp->cdb_vlen = n; return 1; } } } httodo -= 8; if (!httodo) return 0; if ((htp += 8) >= htend) htp = htab; } } pvpgn-1.8.5/src/tinycdb/cdb_make_put.c0000644000175000017500000000347711151345317016661 0ustar aaronaaron/* "advanced" cdb_make_put routine * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "common/xalloc.h" #include "cdb_int.h" #include "common/setup_after.h" int cdb_make_put(struct cdb_make *cdbmp, const void *key, unsigned klen, const void *val, unsigned vlen, int flags) { unsigned char rlen[8]; unsigned hval = cdb_hash(key, klen); struct cdb_rl *rl; int c, r; switch(flags) { case CDB_PUT_REPLACE: case CDB_PUT_INSERT: case CDB_PUT_WARN: c = _cdb_make_find(cdbmp, key, klen, hval, &rl); if (c < 0) return -1; if (c) { if (flags == CDB_PUT_INSERT) return errno = EEXIST, 1; else if (flags == CDB_PUT_REPLACE) { --c; r = 1; break; } else r = 1; } /* fall */ case CDB_PUT_ADD: rl = cdbmp->cdb_rec[hval&255]; if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) { rl = (struct cdb_rl*)xmalloc(sizeof(struct cdb_rl)); if (!rl) return errno = ENOMEM, -1; rl->cnt = 0; rl->next = cdbmp->cdb_rec[hval&255]; cdbmp->cdb_rec[hval&255] = rl; } c = rl->cnt; r = 0; break; default: return errno = EINVAL, -1; } if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) || vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) return errno = ENOMEM, -1; rl->rec[c].hval = hval; rl->rec[c].rpos = cdbmp->cdb_dpos; if ((unsigned)c == rl->cnt) { ++rl->cnt; ++cdbmp->cdb_rcnt; } cdb_pack(klen, rlen); cdb_pack(vlen, rlen + 4); if (_cdb_make_write(cdbmp, rlen, 8) < 0 || _cdb_make_write(cdbmp, key, klen) < 0 || _cdb_make_write(cdbmp, val, vlen) < 0) return -1; return r; } pvpgn-1.8.5/src/tinycdb/cdb_findnext.c0000644000175000017500000000402611151345317016662 0ustar aaronaaron/* sequential cdb_find routines * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ /* see cdb_find.c for comments */ #include "common/setup_before.h" #include "cdb_int.h" #include "common/setup_after.h" int cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp, const void *key, unsigned klen) { unsigned n, pos; cdbfp->cdb_cdbp = cdbp; cdbfp->cdb_key = key; cdbfp->cdb_klen = klen; cdbfp->cdb_hval = cdb_hash(key, klen); cdbfp->cdb_htp = cdbp->cdb_mem + ((cdbfp->cdb_hval << 3) & 2047); n = cdb_unpack(cdbfp->cdb_htp + 4); cdbfp->cdb_httodo = n << 3; if (!n) return 0; pos = cdb_unpack(cdbfp->cdb_htp); if (n > (cdbp->cdb_fsize >> 3) || pos < cdbp->cdb_dend || pos > cdbp->cdb_fsize || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos) return errno = EPROTO, -1; cdbfp->cdb_htab = cdbp->cdb_mem + pos; cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo; cdbfp->cdb_htp = cdbfp->cdb_htab + (((cdbfp->cdb_hval >> 8) % n) << 3); return 1; } int cdb_findnext(struct cdb_find *cdbfp) { struct cdb *cdbp = cdbfp->cdb_cdbp; unsigned pos, n; unsigned klen = cdbfp->cdb_klen; while(cdbfp->cdb_httodo) { pos = cdb_unpack(cdbfp->cdb_htp + 4); if (!pos) return 0; n = cdb_unpack(cdbfp->cdb_htp) == cdbfp->cdb_hval; if ((cdbfp->cdb_htp += 8) >= cdbfp->cdb_htend) cdbfp->cdb_htp = cdbfp->cdb_htab; cdbfp->cdb_httodo -= 8; if (n) { if (pos > cdbp->cdb_fsize - 8) return errno = EPROTO, -1; if (cdb_unpack(cdbp->cdb_mem + pos) == klen) { if (cdbp->cdb_fsize - klen < pos + 8) return errno = EPROTO, -1; if (memcmp(cdbfp->cdb_key, cdbp->cdb_mem + pos + 8, klen) == 0) { n = cdb_unpack(cdbp->cdb_mem + pos + 4); pos += 8; if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos + klen) return errno = EPROTO, -1; cdbp->cdb_kpos = pos; cdbp->cdb_klen = klen; cdbp->cdb_vpos = pos + klen; cdbp->cdb_vlen = n; return 1; } } } } return 0; } pvpgn-1.8.5/src/tinycdb/cdb_make_add.c0000644000175000017500000000245611151345317016575 0ustar aaronaaron/* basic cdb_make_add routine * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "common/xalloc.h" #include "cdb_int.h" #include "common/setup_after.h" int cdb_make_add(struct cdb_make *cdbmp, const void *key, unsigned klen, const void *val, unsigned vlen) { unsigned char rlen[8]; unsigned hval; struct cdb_rl *rl; if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) || vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) return errno = ENOMEM, -1; hval = cdb_hash(key, klen); rl = cdbmp->cdb_rec[hval&255]; if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) { rl = (struct cdb_rl*)xmalloc(sizeof(struct cdb_rl)); if (!rl) return errno = ENOMEM, -1; rl->cnt = 0; rl->next = cdbmp->cdb_rec[hval&255]; cdbmp->cdb_rec[hval&255] = rl; } rl->rec[rl->cnt].hval = hval; rl->rec[rl->cnt].rpos = cdbmp->cdb_dpos; ++rl->cnt; ++cdbmp->cdb_rcnt; cdb_pack(klen, rlen); cdb_pack(vlen, rlen + 4); if (_cdb_make_write(cdbmp, rlen, 8) < 0 || _cdb_make_write(cdbmp, key, klen) < 0 || _cdb_make_write(cdbmp, val, vlen) < 0) return -1; return 0; } pvpgn-1.8.5/src/tinycdb/cdb_unpack.c0000644000175000017500000000056111151345317016324 0ustar aaronaaron/* unpack 32bit integer * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include "cdb.h" #include "common/setup_after.h" unsigned cdb_unpack(const unsigned char buf[4]) { unsigned n = buf[3]; n <<= 8; n |= buf[2]; n <<= 8; n |= buf[1]; n <<= 8; n |= buf[0]; return n; } pvpgn-1.8.5/src/tinycdb/cdb_make_find.c0000644000175000017500000000420111151345317016753 0ustar aaronaaron/* routines to search in in-progress cdb file * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include #include "cdb_int.h" #include "common/setup_after.h" static int match(FILE *fd, unsigned pos, const char *key, unsigned klen) { unsigned char buf[64]; /*XXX cdb_buf may be used here instead */ if (fseek(fd, pos, SEEK_SET) || fread(buf, 1, 8, fd) != 8) return -1; if (cdb_unpack(buf) != klen) return 0; while(klen > sizeof(buf)) { if (fread(buf, 1, sizeof(buf), fd) != sizeof(buf)) return -1; if (memcmp(buf, key, sizeof(buf)) != 0) return 0; key += sizeof(buf); klen -= sizeof(buf); } if (klen) { if (fread(buf, 1, klen, fd) != klen) return -1; if (memcmp(buf, key, klen) != 0) return 0; } return 1; } int _cdb_make_find(struct cdb_make *cdbmp, const void *key, unsigned klen, unsigned hval, struct cdb_rl **rlp) { struct cdb_rl *rl = cdbmp->cdb_rec[hval&255]; int r, i; int seeked = 0; while(rl) { for(i = rl->cnt - 1; i >= 0; --i) { /* search backward */ if (rl->rec[i].hval != hval) continue; /*XXX this explicit flush may be unnecessary having * smarter match() that looks to cdb_buf too, but * most of a time here spent in finding hash values * (above), not keys */ if (cdbmp->cdb_bpos != cdbmp->cdb_buf) { if (fwrite(cdbmp->cdb_buf, 1, cdbmp->cdb_bpos - cdbmp->cdb_buf, cdbmp->cdb_fd) < 0) return -1; cdbmp->cdb_bpos = cdbmp->cdb_buf; } seeked = 1; r = match(cdbmp->cdb_fd, rl->rec[i].rpos, key, klen); if (!r) continue; if (r < 0) return -1; if (fseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET)) return -1; if (rlp) *rlp = rl; return i + 1; } rl = rl->next; } if (seeked && fseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET)) return -1; return 0; } int cdb_make_exists(struct cdb_make *cdbmp, const void *key, unsigned klen) { return _cdb_make_find(cdbmp, key, klen, cdb_hash(key, klen), NULL); } pvpgn-1.8.5/src/tinycdb/ChangeLog0000644000175000017500000000773211151345317015650 0ustar aaronaaron2003-11-04 Michael Tokarev * added cdb_get() routine: tinycdb officially uses mmap. * added cdb_{get,read}{data,key}() macros to read and get current data and key. * fixed bug in cdb_seek() - incorrect wrap, sometimes cdb_seek()+cdb_bread() may return EIO instead of finding correct record. * added some tweaks to Makefile to build position-independent libcdb_pic.a and shared libcdb.so libraries. Note that using libcdb as shared library is probably not a good idea, due to tiny size of the library. * added initial nss_cdb module. Still not well-tested. Probably will not build on non-GNU system. * adjusted tests.{ok,sh} for latest cdb utility modifications (-a mode in query by default) * Victor Porton (porton at ex-code.com) provided a patch to allow tinycdb to be built on win32 platform (cdb_init.c). Completely untested. 2003-08-13 Michael Tokarev * s/cdbi_t/unsigned/g. No need to keep this type. * changed usage of cdb_findnext(): one need to pass pointer to cdb structure to cdb_findnext() now, and should use cdb_datapos(struct cdb_find *) instead of cdb_datapos(struct cdb *) * added cdb_seqinit() and cdb_seqnext() routines for sequential record enumeration * addded cdb_dend to the cdb structure: end of data position. Use that in cdb_seq*(). * more strict checking: ensure data is within data section, and hash tables are within hash section of a file. * cdb_make.c (cdb_make_start): zerofill cdb_make structure to shut valgrind up (writing uninitialized data to file) * cdb.c (cmode): always open file in RDWR mode to allow duplicate key detection 2002-12-08 Michael Tokarev * version 0.73 * de-Debianization. Oh well... ;) * no code changes, just like in 0.72 2002-10-13 Michael Tokarev * version 0.72 * cleaned up debian packaging and made it actually work * no code changes 2002-07-22 Michael Tokarev * version 0.71 * rearranged object files to not depend on ranlib on systems that requires it (i.e. OpenBSD) * use ranlib but mark it's possible error as non-fatal 2001-12-10 Michael Tokarev * version 0.7a * converted to CVS, added two missing #include for malloc declaration and spec target to the Makefile 2001-10-14 Michael Tokarev * version 0.7 * added cdb_seek() and cdb_bread() routines as found in freecdb/cdb-0.64 2001-07-26 Michael Tokarev * version 0.6 * added another option, CDB_PUT_WARN, to cdb_make_put's flags (to allow adding unconditionally but still warn about dups), now cdb_make_put seems to be logically complete. * added and documented -r and -u options for cdb(1) command, and made them consistent with -w and -e also. * reorganized cdb(1) manpage and added changes made to cdb command. * added version references to manpages (and make them autogenerated to simplify maintenance). * added cdb(5) manpage describing CDB file format. 2001-07-25 Michael Tokarev * version 0.5 * added missing #include in cdb_init.c, thanks to ppetru@ppetru.net (Petru Paler) * removed usage of pread() in cdb_make_find() and friends, suggested by Liviu Daia * autogenerate tinycdb.spec file from template and debian/changelog * autogenerate cdb.h from cdb.h.in (substituting version) 2001-06-29 Michael Tokarev * version 0.4 * added cdb_make_put() routine to conditionnaly add a record * split cdb library to more files (finer granularity) * added cdb_findinit() and cdb_findnext() routines * renamed cdbtool to cdb * simplified cdb utility (dropped various format spec, changed options parsing) and a manpage * added small note and copyright to every file in package * added some testsuite (make test) 2001-05-27 Michael Tokarev * version 0.3 * Initial Release. pvpgn-1.8.5/src/tinycdb/cdb_init.c0000644000175000017500000000402311151345317016003 0ustar aaronaaron/* cdb_init, cdb_free and cdb_read routines * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include #ifdef HAVE_SYS_STAT_H # include #endif #include "compat/mmap.h" #include "cdb_int.h" #include "common/setup_after.h" int cdb_init(struct cdb *cdbp, FILE *fd) { unsigned char *mem; unsigned fsize, dend; /* get file size */ if (fseek(fd, 0, SEEK_END)) return -1; fsize = (unsigned)(ftell(fd)); rewind(fd); /* trivial sanity check: at least toc should be here */ if (fsize < 2048) return errno = EPROTO, -1; /* memory-map file */ if ((mem = pmmap(NULL, fsize, PROT_READ, MAP_SHARED, fileno(fd), 0)) == (unsigned char *)-1) return -1; cdbp->cdb_fd = fd; cdbp->cdb_fsize = fsize; cdbp->cdb_mem = mem; #if 0 /* XXX don't know well about madvise syscall -- is it legal to set different options for parts of one mmap() region? There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc... */ #ifdef MADV_RANDOM /* set madvise() parameters. Ignore errors for now if system doesn't support it */ madvise(mem, 2048, MADV_WILLNEED); madvise(mem + 2048, cdbp->cdb_fsize - 2048, MADV_RANDOM); #endif #endif cdbp->cdb_vpos = cdbp->cdb_vlen = 0; cdbp->cdb_kpos = cdbp->cdb_klen = 0; dend = cdb_unpack(mem); if (dend < 2048) dend = 2048; else if (dend >= fsize) dend = fsize; cdbp->cdb_dend = dend; return 0; } void cdb_free(struct cdb *cdbp) { if (cdbp->cdb_mem) { pmunmap((void*)cdbp->cdb_mem, cdbp->cdb_fsize); cdbp->cdb_mem = NULL; } cdbp->cdb_fsize = 0; } const void * cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos) { if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) { errno = EPROTO; return NULL; } return cdbp->cdb_mem + pos; } int cdb_read(const struct cdb *cdbp, void *buf, unsigned len, unsigned pos) { const void *data = cdb_get(cdbp, len, pos); if (!data) return -1; memcpy(buf, data, len); return 0; } pvpgn-1.8.5/src/tinycdb/cdb.h0000644000175000017500000000637311151345317014777 0ustar aaronaaron/* public cdb include file * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include #ifndef TINYCDB_VERSION #define TINYCDB_VERSION 0.74 typedef unsigned int cdbi_t; /* compatibility */ /* common routines */ unsigned cdb_hash(const void *buf, unsigned len); unsigned cdb_unpack(const unsigned char buf[4]); void cdb_pack(unsigned num, unsigned char buf[4]); struct cdb { FILE *cdb_fd; /* file descriptor */ /* private members */ unsigned cdb_fsize; /* datafile size */ unsigned cdb_dend; /* end of data ptr */ const unsigned char *cdb_mem; /* mmap'ed file memory */ unsigned cdb_vpos, cdb_vlen; /* found data */ unsigned cdb_kpos, cdb_klen; /* found key */ }; #define CDB_STATIC_INIT {0,0,0,0,0,0,0,0} #define cdb_datapos(c) ((c)->cdb_vpos) #define cdb_datalen(c) ((c)->cdb_vlen) #define cdb_keypos(c) ((c)->cdb_kpos) #define cdb_keylen(c) ((c)->cdb_klen) #define cdb_fileno(c) ((c)->cdb_fd) int cdb_init(struct cdb *cdbp, FILE *fd); void cdb_free(struct cdb *cdbp); int cdb_read(const struct cdb *cdbp, void *buf, unsigned len, unsigned pos); #define cdb_readdata(cdbp, buf) \ cdb_read((cdbp), (buf), cdb_datalen(cdbp), cdb_datapos(cdbp)) #define cdb_readkey(cdbp, buf) \ cdb_read((cdbp), (buf), cdb_keylen(cdbp), cdb_keypos(cdbp)) const void *cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos); #define cdb_getdata(cdbp) \ cdb_get((cdbp), cdb_datalen(cdbp), cdb_datapos(cdbp)) #define cdb_getkey(cdbp) \ cdb_get((cdbp), cdb_keylen(cdbp), cdb_keypos(cdbp)) int cdb_find(struct cdb *cdbp, const void *key, unsigned klen); struct cdb_find { struct cdb *cdb_cdbp; unsigned cdb_hval; const unsigned char *cdb_htp, *cdb_htab, *cdb_htend; unsigned cdb_httodo; const void *cdb_key; unsigned cdb_klen; }; int cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp, const void *key, unsigned klen); int cdb_findnext(struct cdb_find *cdbfp); #define cdb_seqinit(cptr, cdbp) ((*(cptr))=2048) int cdb_seqnext(unsigned *cptr, struct cdb *cdbp); /* old simple interface */ /* open file using standard routine, then: */ int cdb_seek(FILE *fd, const void *key, unsigned klen, unsigned *dlenp); int cdb_bread(FILE *fd, void *buf, int len); /* cdb_make */ struct cdb_make { FILE *cdb_fd; /* file descriptor */ /* private */ unsigned cdb_dpos; /* data position so far */ unsigned cdb_rcnt; /* record count so far */ char cdb_buf[4096]; /* write buffer */ char *cdb_bpos; /* current buf position */ struct cdb_rl *cdb_rec[256]; /* list of arrays of record infos */ }; int cdb_make_start(struct cdb_make *cdbmp, FILE *fd); int cdb_make_add(struct cdb_make *cdbmp, const void *key, unsigned klen, const void *val, unsigned vlen); int cdb_make_exists(struct cdb_make *cdbmp, const void *key, unsigned klen); int cdb_make_put(struct cdb_make *cdbmp, const void *key, unsigned klen, const void *val, unsigned vlen, int flag); #define CDB_PUT_ADD 0 /* add unconditionnaly, like cdb_make_add() */ #define CDB_PUT_REPLACE 1 /* replace: do not place to index OLD record */ #define CDB_PUT_INSERT 2 /* add only if not already exists */ #define CDB_PUT_WARN 3 /* add unconditionally but ret. 1 if exists */ int cdb_make_finish(struct cdb_make *cdbmp); #endif /* include guard */ pvpgn-1.8.5/src/tinycdb/cdb_int.h0000644000175000017500000000142011151345317015635 0ustar aaronaaron/* internal cdb library declarations * * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include "cdb.h" #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "common/setup_after.h" #ifndef EPROTO # define EPROTO EINVAL #endif struct cdb_rec { cdbi_t hval; cdbi_t rpos; }; struct cdb_rl { struct cdb_rl *next; cdbi_t cnt; struct cdb_rec rec[254]; }; int _cdb_make_find(struct cdb_make *cdbmp, const void *key, cdbi_t klen, cdbi_t hval, struct cdb_rl **rlp); int _cdb_make_write(struct cdb_make *cdbmp, const char *ptr, cdbi_t len); pvpgn-1.8.5/src/tinycdb/cdb.c0000644000175000017500000003015711151345317014767 0ustar aaronaaron/* * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru. * Public domain. */ #include "common/setup_before.h" #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "compat/getopt.h" #include "compat/strerror.h" #include #include "common/xalloc.h" #include "cdb.h" #include "common/setup_after.h" #ifndef EPROTO # define EPROTO EINVAL #endif static char *progname; #define F_DUPMASK 0x000f #define F_WARNDUP 0x0100 #define F_ERRDUP 0x0200 #define F_MAP 0x1000 /* map format (or else CDB native format) */ static char *buf; static unsigned blen; static void #ifdef __GNUC__ __attribute__((noreturn,format(printf,2,3))) #endif error(int errnum, const char *fmt, ...) { if (fmt) { va_list ap; fprintf(stderr, "%s: ", progname); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } if (errnum) fprintf(stderr, ": %s\n", pstrerror(errnum)); else { if (fmt) putc('\n', stderr); fprintf(stderr, "%s: try `%s -h' for help\n", progname, progname); } fflush(stderr); exit(errnum ? 111 : 2); } static void allocbuf(unsigned len) { if (blen < len) { if (buf) buf = (char*)xrealloc(buf, len); else buf = (char*)xmalloc(len); if (!buf) error(ENOMEM, "unable to allocate %u bytes", len); blen = len; } } static int qmode(char *dbname, char *key, int num, int flags) { struct cdb c; struct cdb_find cf; FILE *fd; int r; int n, found; fd = fopen(dbname, "rb"); if (fd == NULL || cdb_init(&c, fd) != 0) error(errno, "unable to open database `%s'", dbname); r = cdb_findinit(&cf, &c, key, strlen(key)); if (!r) return 100; else if (r < 0) error(errno, "%s", key); n = 0; found = 0; while((r = cdb_findnext(&cf)) > 0) { ++n; if (num && num != n) continue; ++found; allocbuf(cdb_datalen(&c)); if (cdb_read(&c, buf, cdb_datalen(&c), cdb_datapos(&c)) != 0) error(errno, "unable to read value"); fwrite(buf, 1, cdb_datalen(&c), stdout); if (flags & F_MAP) putchar('\n'); if (num) break; } if (r < 0) error(0, "%s", key); return found ? 0 : 100; } static void fget(FILE *f, unsigned char *b, unsigned len, unsigned *posp, unsigned limit) { if (posp && limit - *posp < len) error(EPROTO, "invalid database format"); if (fread(b, 1, len, f) != len) { if (ferror(f)) error(errno, "unable to read"); fprintf(stderr, "%s: unable to read: short file\n", progname); exit(2); } if (posp) *posp += len; } static int fcpy(FILE *fi, FILE *fo, unsigned len, unsigned *posp, unsigned limit) { while(len > blen) { fget(fi, buf, blen, posp, limit); if (fo && fwrite(buf, 1, blen, fo) != blen) return -1; len -= blen; } if (len) { fget(fi, buf, len, posp, limit); if (fo && fwrite(buf, 1, len, fo) != len) return -1; } return 0; } static int dmode(char *dbname, char mode, int flags) { unsigned eod, klen, vlen; unsigned pos = 0; FILE *f; if (strcmp(dbname, "-") == 0) f = stdin; else if ((f = fopen(dbname, "rb")) == NULL) error(errno, "open %s", dbname); allocbuf(2048); fget(f, buf, 2048, &pos, 2048); eod = cdb_unpack(buf); while(pos < eod) { fget(f, buf, 8, &pos, eod); klen = cdb_unpack(buf); vlen = cdb_unpack(buf + 4); if (!(flags & F_MAP)) if (printf(mode == 'd' ? "+%u,%u:" : "+%u:", klen, vlen) < 0) return -1; if (fcpy(f, stdout, klen, &pos, eod) != 0) return -1; if (mode == 'd') if (fputs(flags & F_MAP ? " " : "->", stdout) < 0) return -1; if (fcpy(f, mode == 'd' ? stdout : NULL, vlen, &pos, eod) != 0) return -1; if (putc('\n', stdout) < 0) return -1; } if (pos != eod) error(EPROTO, "invalid cdb file format"); if (!(flags & F_MAP)) if (putc('\n', stdout) < 0) return -1; return 0; } static int smode(char *dbname) { FILE *f; unsigned pos, eod; unsigned cnt = 0; unsigned kmin = 0, kmax = 0, ktot = 0; unsigned vmin = 0, vmax = 0, vtot = 0; unsigned hmin = 0, hmax = 0, htot = 0, hcnt = 0; #define NDIST 11 unsigned dist[NDIST]; unsigned char toc[2048]; unsigned k; if (strcmp(dbname, "-") == 0) f = stdin; else if ((f = fopen(dbname, "rb")) == NULL) error(errno, "open %s", dbname); pos = 0; fget(f, toc, 2048, &pos, 2048); allocbuf(2048); eod = cdb_unpack(toc); while(pos < eod) { unsigned klen, vlen; fget(f, buf, 8, &pos, eod); klen = cdb_unpack(buf); vlen = cdb_unpack(buf + 4); fcpy(f, NULL, klen, &pos, eod); fcpy(f, NULL, vlen, &pos, eod); ++cnt; ktot += klen; if (!kmin || kmin > klen) kmin = klen; if (kmax < klen) kmax = klen; vtot += vlen; if (!vmin || vmin > vlen) vmin = vlen; if (vmax < vlen) vmax = vlen; vlen += klen; } if (pos != eod) error(EPROTO, "invalid cdb file format"); for (k = 0; k < NDIST; ++k) dist[k] = 0; for (k = 0; k < 256; ++k) { unsigned i = cdb_unpack(toc + (k << 3)); unsigned hlen = cdb_unpack(toc + (k << 3) + 4); if (i != pos) error(EPROTO, "invalid cdb hash table"); if (!hlen) continue; for (i = 0; i < hlen; ++i) { unsigned h; fget(f, buf, 8, &pos, 0xffffffff); if (!cdb_unpack(buf + 4)) continue; h = (cdb_unpack(buf) >> 8) % hlen; if (h == i) h = 0; else { if (h < i) h = i - h; else h = hlen - h + i; if (h >= NDIST) h = NDIST - 1; } ++dist[h]; } if (!hmin || hmin > hlen) hmin = hlen; if (hmax < hlen) hmax = hlen; htot += hlen; ++hcnt; } printf("number of records: %u\n", cnt); printf("key min/avg/max length: %u/%u/%u\n", kmin, cnt ? (ktot + cnt / 2) / cnt : 0, kmax); printf("val min/avg/max length: %u/%u/%u\n", vmin, cnt ? (vtot + cnt / 2) / cnt : 0, vmax); printf("hash tables/entries/collisions: %u/%u/%u\n", hcnt, htot, cnt - dist[0]); printf("hash table min/avg/max length: %u/%u/%u\n", hmin, hcnt ? (htot + hcnt / 2) / hcnt : 0, hmax); printf("hash table distances:\n"); for(k = 0; k < NDIST; ++k) printf(" %c%u: %6u %2u%%\n", k == NDIST - 1 ? '>' : 'd', k == NDIST - 1 ? k - 1 : k, dist[k], cnt ? dist[k] * 100 / cnt : 0); return 0; } static void badinput(const char *fn) { fprintf(stderr, "%s: %s: bad format\n", progname, fn); exit(2); } static int getnum(FILE *f, unsigned *np, const char *fn) { unsigned n; int c = getc(f); if (c < '0' || c > '9') badinput(fn); n = c - '0'; while((c = getc(f)) >= '0' && c <= '9') { c -= '0'; if (0xffffffff / 10 - c < n) badinput(fn); n = n * 10 + c; } *np = n; return c; } static void addrec(struct cdb_make *cdbmp, char *key, unsigned klen, char *val, unsigned vlen, int flags) { int r = cdb_make_put(cdbmp, key, klen, val, vlen, flags & F_DUPMASK); if (r < 0) error(errno, "cdb_make_put"); else if (r && (flags & F_WARNDUP)) { fprintf(stderr, "%s: key `", progname); fwrite(key, 1, klen, stderr); fputs("' duplicated\n", stderr); if (flags & F_ERRDUP) exit(1); } } static void dofile_cdb(struct cdb_make *cdbmp, FILE *f, const char *fn, int flags) { unsigned klen, vlen; int c; while((c = getc(f)) == '+') { if ((c = getnum(f, &klen, fn)) != ',' || (c = getnum(f, &vlen, fn)) != ':' || 0xffffffff - klen < vlen) badinput(fn); allocbuf(klen + vlen); fget(f, buf, klen, NULL, 0); if (getc(f) != '-' || getc(f) != '>') badinput(fn); fget(f, buf + klen, vlen, NULL, 0); switch (getc(f)) { case '\n': break; case '\r': if (getc(f)=='\n') break; default: badinput(fn); } addrec(cdbmp, buf, klen, buf + klen, vlen, flags); } switch (c) { case '\n': break; case '\r': if (getc(f)=='\n') break; default: badinput(fn); } } static void dofile_ln(struct cdb_make *cdbmp, FILE *f, const char *fn, int flags) { char *k, *v; while(fgets(buf, blen, f) != NULL) { unsigned l = 0; for (;;) { l += strlen(buf + l); v = buf + l; if (v > buf && v[-1] == '\n') { v[-1] = '\0'; break; } if (l < blen) allocbuf(l + 512); if (!fgets(buf + l, blen - l, f)) break; } k = buf; while(*k == ' ' || *k == '\t') ++k; if (!*k || *k == '#') continue; v = k; while(*v && *v != ' ' && *v != '\t') ++v; if (*v) *v++ = '\0'; while(*v == ' ' || *v == '\t') ++v; addrec(cdbmp, k, strlen(k), v, strlen(v), flags); } } static void dofile(struct cdb_make *cdbmp, FILE *f, const char *fn, int flags) { if (flags & F_MAP) dofile_ln(cdbmp, f, fn, flags); else dofile_cdb(cdbmp, f, fn, flags); if (ferror(f)) error(errno, "read error"); } static int cmode(char *dbname, char *tmpname, int argc, char **argv, int flags) { struct cdb_make cdb; FILE *fd; if (!tmpname) { tmpname = (char*)xmalloc(strlen(dbname) + 5); if (!tmpname) error(ENOMEM, "unable to allocate memory"); strcat(strcpy(tmpname, dbname), ".tmp"); } fd = fopen(tmpname, "w+b"); if (fd == 0) error(errno, "unable to create %s", tmpname); cdb_make_start(&cdb, fd); allocbuf(4096); if (argc) { int i; for (i = 0; i < argc; ++i) { if (strcmp(argv[i], "-") == 0) dofile(&cdb, stdin, "(stdin)", flags); else { FILE *f = fopen(argv[i], "rb"); if (!f) error(errno, "%s", argv[i]); dofile(&cdb, f, argv[i], flags); fclose(f); } } } else dofile(&cdb, stdin, "(stdin)", flags); if (cdb_make_finish(&cdb) != 0) error(errno, "cdb_make_finish"); fclose(fd); if (rename(tmpname, dbname) != 0) error(errno, "rename %s->%s", tmpname, dbname); return 0; } int main(int argc, char **argv) { int c; char mode = 0; char *tmpname = NULL; int flags = 0; int num = 0; int r; extern char *optarg; extern int optind; if ((progname = strrchr(argv[0], '/')) != NULL) argv[0] = ++progname; else progname = argv[0]; if (argc == 1) error(0, "no arguments given"); while((c = getopt(argc, argv, "qdlcsht:n:mwrue")) != EOF) switch(c) { case 'q': case 'd': case 'l': case 'c': case 's': if (mode && mode != c) error(0, "different modes of operation requested"); mode = c; break; case 't': tmpname = optarg; break; case 'w': flags |= F_WARNDUP; break; case 'e': flags |= F_WARNDUP | F_ERRDUP; break; case 'r': flags = (flags & ~F_DUPMASK) | CDB_PUT_REPLACE; break; case 'u': flags = (flags & ~F_DUPMASK) | CDB_PUT_INSERT; break; case 'm': flags |= F_MAP; break; case 'n': if ((num = atoi(optarg)) <= 0) error(0, "invalid record number `%s'", optarg); break; case 'h': printf("\ %s: Constant DataBase (CDB) tool. Usage is:\n\ query: %s -q [-m] [-n recno|-a] cdbfile key\n\ dump: %s -d [-m] [cdbfile|-]\n\ list: %s -l [-m] [cdbfile|-]\n\ create: %s -c [-m] [-wrue] [-t tempfile] cdbfile [infile...]\n\ stats: %s -s [cdbfile|-]\n\ help: %s -h\n\ ", progname, progname, progname, progname, progname, progname, progname); return 0; default: error(0, NULL); } argv += optind; argc -= optind; switch(mode) { case 'q': if (argc < 2) error(0, "no database or key to query specified"); if (argc > 2) error(0, "extra arguments in command line"); r = qmode(argv[0], argv[1], num, flags); break; case 'c': if (!argc) error(0, "no database name specified"); if ((flags & F_WARNDUP) && !(flags & F_DUPMASK)) flags |= CDB_PUT_WARN; r = cmode(argv[0], tmpname, argc - 1, argv + 1, flags); break; case 'd': case 'l': if (argc > 1) error(0, "extra arguments for dump/list"); r = dmode(argc ? argv[0] : "-", mode, flags); break; case 's': if (argc > 1) error(0, "extra argument(s) for stats"); r = smode(argc ? argv[0] : "-"); break; default: error(0, "no -q, -c, -d, -l or -s option specified"); } if (r < 0 || fflush(stdout) < 0) error(errno, "unable to write: %d", c); return r; } pvpgn-1.8.5/src/compat/0000755000175000017500000000000011151345372013715 5ustar aaronaaronpvpgn-1.8.5/src/compat/memcpy.c0000644000175000017500000000301711151345317015353 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_MEMCPY #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_BCOPY # ifdef HAVE_STRING_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "memcpy.h" #include "common/setup_after.h" extern void * memcpy(void * dest, void const * src, unsigned long n) { #ifdef HAVE_BCOPY bcopy(src,dest,n); return dest; #else /* very slow, but we don't care */ unsigned char * td=dest; unsigned char * ts=src; unsigned long i; if (!td || !ts) return NULL; for (i=0; i #endif #endif pvpgn-1.8.5/src/compat/strncasecmp.c0000644000175000017500000000341311151345317016403 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_STRCASECMP #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "strncasecmp.h" #include "common/setup_after.h" extern int strncasecmp(char const * str1, char const * str2, unsigned int cnt) { unsigned int i; int a; int b; if (!str1 || !str2) return -1; /* some versions of tolower() break when given already lowercase characters */ for (i=0; ib) return +1; } if (i #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strchr.h" #include "strsep.h" #include "common/setup_after.h" extern char * strsep(char * * str, char const * delims) { char * begin; begin = *str; if (!begin) return NULL; /* already returned last token */ /* FIXME: optimiz case of 1 char delims (maybe not worth the effort) */ for (; **str!='\0'; (*str)++) if (strchr(delims,**str)) { **str = '\0'; /* terminate token */ (*str)++; /* remember the position of the next char */ return begin; } *str = NULL; return begin; /* return the whole input string */ } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/strerror.c0000644000175000017500000002306711151345317015752 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_STRERROR #include #include "strerror.h" #include "common/setup_after.h" extern char const * pstrerror(int errornum) { if (errornum==0) return "No error"; #ifdef EPERM if (errornum==EPERM) return "Operation not permitted"; #endif #ifdef ENOENT if (errornum==ENOENT) return "No such file or directory"; #endif #ifdef ESRCH if (errornum==ESRCH) return "No such process"; #endif #ifdef EINTR if (errornum==EINTR) return "Interrupted system call"; #endif #ifdef EIO if (errornum==EIO) return "I/O error"; #endif #ifdef ENXIO if (errornum==EIO) return "No such device or address"; #endif #ifdef EBADF if (errornum==EBADF) return "Bad file number"; #endif #ifdef EAGAIN if (errornum==EAGAIN) return "Try again"; #endif #ifdef ENOMEM if (errornum==ENOMEM) return "Out of memory"; #endif #ifdef EACCES if (errornum==EACCES) return "Permission denied"; #endif #ifdef EFAULT if (errornum==EFAULT) return "Bad address"; #endif #ifdef EBUSY if (errornum==EBUSY) return "Device or resource busy"; #endif #ifdef EEXIST if (errornum==EEXIST) return "File exists"; #endif #ifdef EXDEV if (errornum==EXDEV) return "Cross-device link"; #endif #ifdef EDEADLK if (errornum==EXDEV) return "Resource deadlock would occur"; #endif #ifdef EDEADLOCK if (errornum==EDEADLOCK) return "Resource deadlock would occur"; #endif #ifdef ENODEV if (errornum==ENODEV) return "No such device"; #endif #ifdef ENOTDIR if (errornum==ENOTDIR) return "Not a directory"; #endif #ifdef EISDIR if (errornum==EISDIR) return "Is a directory"; #endif #ifdef EINVAL if (errornum==EINVAL) return "Invalid argument"; #endif #ifdef ENFILE if (errornum==ENFILE) return "Too many open files in system"; #endif #ifdef EMFILE if (errornum==EMFILE) return "Too many open files"; #endif #ifdef ENOTTY if (errornum==ENOTTY) return "Not a typewriter"; #endif #ifdef ETXTBSY if (errornum==ETXTBSY) return "Text file busy"; #endif #ifdef EFBIG if (errornum==EFBIG) return "File too large"; #endif #ifdef ENOSPC if (errornum==ENOSPC) return "No space left on device"; #endif #ifdef ESPIPE if (errornum==ESPIPE) return "Illegal seek"; #endif #ifdef EROFS if (errornum==EROFS) return "Read-only file system"; #endif #ifdef EMLINK if (errornum==EMLINK) return "Too many links"; #endif #ifdef EPIPE if (errornum==EPIPE) return "Broken pipe"; #endif #ifdef EDOM if (errornum==EDOM) return "Math argument out of domain of func"; #endif #ifdef ERANGE if (errornum==ERANGE) return "Math result not representable"; #endif #ifdef ENAMETOOLONG if (errornum==ENAMETOOLONG) return "File name too long"; #endif #ifdef ENOLCK if (errornum==ENOLCK) return "No record locks available"; #endif #ifdef ENOSYS if (errornum==ENOSYS) return "Function not implemented"; #endif #ifdef ENOTEMPTY if (errornum==ENOTEMPTY) return "Directory not empty"; #endif #ifdef ELOOP if (errornum==ELOOP) return "Too many symbolic links encountered"; #endif #ifdef EHOSTDOWN if (errornum==EHOSTDOWN) return "Host is down"; #endif #ifdef EHOSTUNREACH if (errornum==EHOSTUNREACH) return "No route to host"; #endif #ifdef EALREADY if (errornum==EALREADY) return "Operation already in progress"; #endif #ifdef EINPROGRESS if (errornum==EINPROGRESS) return "Operation now in progress"; #endif #ifdef ESTALE if (errornum==ESTALE) return "Stale NFS filehandle"; #endif #ifdef EDQUOT if (errornum==EDQUOT) return "Quota exceeded"; #endif #ifdef EWOULDBLOCK if (errornum==EWOULDBLOCK) return "Operation would block"; #endif #ifdef ECOMM if (errornum==ECOMM) return "Communication error on send"; #endif #ifdef EPROTO if (errornum==EPROTO) return "Protocol error"; #endif #ifdef EPROTONOSUPPORT if (errornum==EPROTONOSUPPORT) return "Protocol not supported"; #endif #ifdef ESOCKTNOSUPPORT if (errornum==ESOCKTNOSUPPORT) return "Socket type not supported"; #endif #ifdef ESOCKTNOSUPPORT if (errornum==EOPNOTSUPP) return "Operation not supported"; #endif #ifdef EPFNOSUPPORT if (errornum==EPFNOSUPPORT) return "Protocol family not supported"; #endif #ifdef EAFNOSUPPORT if (errornum==EAFNOSUPPORT) return "Address family not supported by protocol family"; #endif #ifdef EADDRINUSE if (errornum==EADDRINUSE) return "Address already in use"; #endif #ifdef EADDRNOTAVAIL if (errornum==EADDRNOTAVAIL) return "Cannot assign requested address"; #endif #ifdef ENETDOWN if (errornum==ENETDOWN) return "Network is down"; #endif #ifdef ENETUNREACH if (errornum==ENETUNREACH) return "Network is unreachable"; #endif #ifdef ENETRESET if (errornum==ENETRESET) return "Network dropped connection on reset"; #endif #ifdef ECONNABORTED if (errornum==ECONNABORTED) return "Software caused connection abort"; #endif #ifdef ECONNRESET if (errornum==ECONNRESET) return " Connection reset by peer"; #endif #ifdef ENOBUFS if (errornum==ENOBUFS) return "No buffer space available"; #endif #ifdef EISCONN if (errornum==EISCONN) return "Socket is already connected"; #endif #ifdef ENOTCONN if (errornum==ENOTCONN) return "Socket is not connected"; #endif #ifdef ESHUTDOWN if (errornum==ESHUTDOWN) return " Cannot send after socket shutdown"; #endif #ifdef ETIMEDOUT if (errornum==ETIMEDOUT) return "Connection timed out"; #endif #ifdef ECONNREFUSED if (errornum==ECONNREFUSED) return "Connection refused"; #endif return "Unknown error"; } #else #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef WIN32 #include extern char const * pstrerror(int errornum) { switch (errornum) { case WSAEINTR: return "Interrupted function call"; case WSAEACCES: return "Permission denied"; case WSAEFAULT: return "Bad address"; case WSAEINVAL: return "Inavlid argument"; case WSAEMFILE: return "Too many open files"; case WSAEWOULDBLOCK: return "Resource temorarily unavailable"; case WSAEINPROGRESS: return "Operation now in progress"; case WSAEALREADY: return "Operation already in progress"; case WSAENOTSOCK: return "Socket operation on nonsocket"; case WSAEDESTADDRREQ: return "Destination address required"; case WSAEMSGSIZE: return "Message too long"; case WSAEPROTOTYPE: return "Protocol wrong type fpr socket"; case WSAENOPROTOOPT: return "Bad protocol option"; case WSAEPROTONOSUPPORT: return "Protocol not supported"; case WSAESOCKTNOSUPPORT: return "Socket type not supported"; case WSAEOPNOTSUPP: return "Operation not supported"; case WSAEPFNOSUPPORT: return "Protocol family not supported"; case WSAEAFNOSUPPORT: return "Address family not supported by protocol family"; case WSAEADDRINUSE: return "Address already in use"; case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; case WSAENETDOWN: return "Network is down"; case WSAENETUNREACH: return "Network is unreachable"; case WSAENETRESET: return "Network dropped connection on reset"; case WSAECONNABORTED: return "Software caused connection abort"; case WSAECONNRESET: return "Connection reset by peer"; case WSAENOBUFS: return "No buffer space available"; case WSAEISCONN: return "Socket is already connected"; case WSAENOTCONN: return "Socket is not connected"; case WSAESHUTDOWN: return "Cannot send after socket shutdown"; case WSAETIMEDOUT: return "Connection timed out"; case WSAECONNREFUSED: return "Connection refused"; case WSAEHOSTDOWN: return "Host is down"; case WSAEHOSTUNREACH: return "No route to host"; case WSAEPROCLIM: return "Too many processes"; case WSASYSNOTREADY: return "Network subsystem is unavailable"; case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; case WSANOTINITIALISED: return "Successful WSAStartup not yet performed"; case WSAEDISCON: return "Graceful shutdown in progress"; case WSATYPE_NOT_FOUND: return "Class type not found"; case WSAHOST_NOT_FOUND: return "Host not found"; case WSATRY_AGAIN: return "Nonauthoriative host not found"; case WSANO_RECOVERY: return "This is a nonrecoverable error"; case WSANO_DATA: return "Valid name, no data record of requested type"; case WSA_INVALID_HANDLE: return "Specified event object handle is invalid"; case WSA_INVALID_PARAMETER: return "One or more parameters are invalid"; case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state"; case WSA_IO_PENDING: return "Overlapped operation will complete later"; case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available"; case WSA_OPERATION_ABORTED: return "Overlapped operation aborted"; case WSASYSCALLFAILURE: return "System call failure"; default: return strerror(errornum); } } #endif #endif pvpgn-1.8.5/src/compat/strftime.h0000644000175000017500000000171511151345317015726 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STRFTIME_PROTOS #define INCLUDED_STRFTIME_PROTOS #ifndef HAVE_STRFTIME extern int strftime(char * buf, int bufsize, char const * fmt, struct tm const * tm); #endif #endif pvpgn-1.8.5/src/compat/snprintf.h0000644000175000017500000000231511151345317015731 0ustar aaronaaron/* * Copyright (C) 2005 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SNPRINTF_PROTOS #define INCLUDED_SNPRINTF_PROTOS #include #include "compat/vargs.h" #if !defined(HAVE_SNPRINTF) #ifdef HAVE__SNPRINTF #define snprintf _snprintf #else #if defined(HAVE_VSNPRINTF) || defined(HAVE__VSNPRINTF) extern int snprintf(char *str, size_t size, const char *format, ...); #else #error "Your system lacks ANY kind of snprintf support!" #endif #endif #endif #endif /* INCLUDED_SNPRINTF_PROTOS */ pvpgn-1.8.5/src/compat/signal.h0000644000175000017500000000164311151345317015346 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SIGNAL_PROTOS #define INCLUDED_SIGNAL_PROTOS /* for Cygnus B20.1 on win32 */ #ifndef SA_RESTART #define SA_RESTART 0 #endif #endif pvpgn-1.8.5/src/compat/strsep.h0000644000175000017500000000165111151345317015410 0ustar aaronaaron/* * Copyright (C) 2002 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STRSEP_PROTOS #define INCLUDED_STRSEP_PROTOS #ifndef HAVE_STRSEP extern char * strsep(char * * str, char const * delim); #endif #endif pvpgn-1.8.5/src/compat/strncasecmp.h0000644000175000017500000000215311151345317016410 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STRNCASECMP_PROTOS #define INCLUDED_STRNCASECMP_PROTOS #ifndef HAVE_STRNCASECMP #ifdef HAVE_STRNICMP # define strncasecmp(s1, s2, cnt) strnicmp(s1, s2, cnt) # define HAVE_STRNCASECMP /* don't include our own function */ #else extern int strncasecmp(char const * str1, char const * str2, unsigned int cnt); #endif #endif #endif pvpgn-1.8.5/src/compat/uname.h0000644000175000017500000000234311151345317015174 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_UNAME_TYPES #define INCLUDED_UNAME_TYPES #ifndef HAVE_UNAME #ifndef SYS_NMLN # define SYS_NMLN 64 #endif struct utsname { char sysname[SYS_NMLN]; char nodename[SYS_NMLN]; char release[SYS_NMLN]; char version[SYS_NMLN]; char machine[SYS_NMLN]; char domainname[SYS_NMLN]; }; #endif #endif #ifndef INCLUDED_UNAME_PROTOS #define INCLUDED_UNAME_PROTOS #ifndef HAVE_UNAME extern int uname(struct utsname * buf); #endif #endif pvpgn-1.8.5/src/compat/mmap.c0000644000175000017500000000421211151345317015011 0ustar aaronaaron/* * Copyright (C) 2003 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_MMAP #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #include "common/xalloc.h" #include "mmap.h" #ifdef WIN32 # include # include #endif #include "common/setup_after.h" extern void * pmmap(void *addr, unsigned len, int prot, int flags, int fd, unsigned offset) { void *mem; #ifdef WIN32 HANDLE hFile, hMapping; /* under win32 we only support readonly mappings, the only ones used in pvpgn now :) */ if (prot != PROT_READ) return NULL; hFile = (HANDLE) _get_osfhandle(fd); if (hFile == (HANDLE) - 1) return MAP_FAILED; hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (!hMapping) return MAP_FAILED; mem = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0 ,0); #else /* systems without mmap or win32 */ unsigned pos; int res; mem = xmalloc(len); pos = 0; while(pos < len) { res = read(fd, (char *)mem + pos, len - pos); if (res < 0) { xfree(mem); return MAP_FAILED; } pos += res; } #endif return mem; } extern int pmunmap(void *addr, unsigned len) { #ifdef WIN32 UnmapViewOfFile(addr); #else xfree(addr); #endif return 0; } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/strrchr.h0000644000175000017500000000175111151345317015560 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STRRCHR_PROTOS #define INCLUDED_STRRCHR_PROTOS #ifndef HAVE_STRRCHR #ifdef HAVE_RINDEX # define strrchr rindex #else # error "This program requires either strrchr() or rindex()" #endif #endif #endif pvpgn-1.8.5/src/compat/vargs.h0000644000175000017500000000233111151345317015206 0ustar aaronaaron/* ANSI and traditional C compatability macros Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _VARGS_H #define _VARGS_H 1 #ifdef HAVE_STDARG_H # include # define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR) #else /* Not ANSI C. */ # ifdef HAVE_VARAGRS_H # include # define VA_START(va_list, var) va_start(va_list) # else # error "Your system neither offers stdarg.h nor varargs.h!" # endif #endif #endif /* vargs.h */ pvpgn-1.8.5/src/compat/uname.c0000644000175000017500000000400411151345317015163 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_UNAME #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "uname.h" #include "common/setup_after.h" extern int uname(struct utsname * buf) { if (!buf) { errno = EFAULT; return -1; } #ifdef WIN32 /* FIXME: distinguish between: */ /* Microsoft Windows 3.1-32s/3.11-32s/95/95SP1/95A/95B/95OSR2/95OSR2.1/95OSR2.5/95B+MSIE/98/98OEM/98SE/2000ME "New Technology" 3.1/3.5 Server/3.51 Server/4.0 Server/4.0SP1 Server/4.0SP2 Server/4.0SP3 Server/4.0SP4 Server/4.0SP6 Server/3.5 Workstation/3.51 Workstation/4.0 Workstation/4.0SP1 Workstation/4.0SP2 Workstation/4.0SP3 Workstation/4.0SP4 Workstation/4.0SP6 Workstation/"2000 Professional Edition"/"2000 Server"/"2000 Advanced Server"/"Windows 2000 Terminal Server" Win CE/"Windows Powered"/"Pocket OS" 1.0/1.1/2.0/2.1 */ /* maybe report the build number too */ strcpy(buf->sysname,"Win32"); #else strcpy(buf->sysname,""); #endif strcpy(buf->nodename,""); strcpy(buf->release,""); strcpy(buf->version,""); strcpy(buf->machine,""); strcpy(buf->domainname,""); return 0; } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/memset.h0000644000175000017500000000175311151345317015365 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_MEMSET_PROTOS #define INCLUDED_MEMSET_PROTOS #ifndef HAVE_MEMSET /* this should use size_t, but some systems don't define it */ extern void * memset(void * dest, int c, unsigned long n); #endif #endif pvpgn-1.8.5/src/compat/gettimeofday.h0000644000175000017500000000241111151345317016544 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_GETTIMEOFDAY_TYPES #define INCLUDED_GETTIMEOFDAY_TYPES #ifndef HAVE_GETTIMEOFDAY struct timezone { int tz_minuteswest; int tz_dsttime; }; #endif /* we always require select thus we always require timeval which should * be available through portable socket layer */ #include "psock.h" #endif #ifndef INCLUDED_GETTIMEOFDAY_PROTOS #define INCLUDED_GETTIMEOFDAY_PROTOS #ifndef HAVE_GETTIMEOFDAY extern int gettimeofday(struct timeval * tv, struct timezone * tz); #endif #endif pvpgn-1.8.5/src/compat/access.h0000644000175000017500000000220411151345317015324 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_ACCESS_PROTOS #define INCLUDED_ACCESS_PROTOS #ifdef WIN32 # include /* Values for the second argument to access. These may be OR'd together. */ # define R_OK 4 /* Test for read permission. */ # define W_OK 2 /* Test for write permission. */ # define X_OK 1 /* Test for execute permission. */ # define F_OK 0 /* Test for existence. */ #endif #endif pvpgn-1.8.5/src/compat/gethostname.h0000644000175000017500000000213611151345317016405 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_GETHOSTNAME_PROTOS #define INCLUDED_GETHOSTNAME_PROTOS /* * This is from unistd.h on Unix systems, but it's included with * the socket stuff under Windows. This tries to hide that. */ #ifdef WIN32 # include #endif #ifndef HAVE_GETHOSTNAME # error "This program requires gethostname()" #endif #endif pvpgn-1.8.5/src/compat/strdup.c0000644000175000017500000000263311151345317015405 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_STRDUP #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "strdup.h" #include "common/setup_after.h" extern char * strdup(char const * str) { char * out; if (!(out = malloc(strlen(str)+1))) return NULL; strcpy(out,str); return out; } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/getopt.h0000644000175000017500000001146311151345317015374 0ustar aaronaaron/* Declarations for getopt. Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _PVPGN_GETOPT_H_ #define _PVPGN_GETOPT_H_ 1 #include "common/setup_before.h" #ifdef HAVE_UNISTD_H # include #endif #ifndef HAVE_GETOPT #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #ifdef WIN32 #define extern #endif #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* __STDC__ */ #ifdef WIN32 #undef extern #endif #ifdef __cplusplus } #endif #endif /* !HAVE_GETOPT */ #endif /* _PVPGN_GETOPT_H_ */ pvpgn-1.8.5/src/compat/memmove.c0000644000175000017500000000262411151345317015531 0ustar aaronaaron/* * Copyright (C) 2000,2002 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_MEMMOVE #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include "memmove.h" #include "common/setup_after.h" extern void * memmove(void * dest, void const * src, unsigned long n) { /* very slow, but we don't care */ /* FIXME: does this handle all overlapping cases correctly? */ unsigned char * td=dest; const unsigned char * ts=src; unsigned long i; if (!td || !ts) return NULL; for (i=0; i #endif #ifdef HAVE_SYS_MMAN_H # include #endif #ifdef __BORLANDC__ # include #endif #ifndef PROT_NONE #define PROT_NONE 0x00 /* no permissions */ #endif #ifndef PROT_READ #define PROT_READ 0x01 /* pages can be read */ #endif #ifndef PROT_WRITE #define PROT_WRITE 0x02 /* pages can be written */ #endif #ifndef PROT_EXEC #define PROT_EXEC 0x04 /* pages can be executed */ #endif #ifndef MAP_SHARED #define MAP_SHARED 0x0001 /* share changes */ #endif #ifndef MAP_PRIVATE #define MAP_PRIVATE 0x0002 /* changes are private */ #endif #ifndef MAP_COPY #define MAP_COPY MAP_PRIVATE /* Obsolete */ #endif #ifndef MAP_FAILED #define MAP_FAILED ((void *)-1) #endif #ifdef HAVE_MMAP #define pmmap(a,b,c,d,e,f) mmap(a,b,c,d,e,f) #define pmunmap(a,b) munmap(a,b) #else extern void * pmmap(void *addr, unsigned len, int prot, int flags, int fd, unsigned offset); extern int pmunmap(void *addr, unsigned len); #endif #endif pvpgn-1.8.5/src/compat/recv.h0000644000175000017500000000226211151345317015026 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_RECV_PROTOS #define INCLUDED_RECV_PROTOS #ifndef HAVE_RECV /* some recvfrom()s don't handle NULL, but recv is called depreciated on BSD */ #ifdef HAVE_RECVFROM # ifdef HAVE_STDDEF_H # include # else # ifndef NULL # define NULL ((void *)0) # endif # endif # define recv(s, b, l, f) recvfrom(s, b, l, f, NULL, NULL) #else # error "This program requires recvfrom()" #endif #endif #endif pvpgn-1.8.5/src/compat/getopt.c0000644000175000017500000007016511151345317015373 0ustar aaronaaron/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #ifndef HAVE_GETOPT /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #if !defined (__STDC__) || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #include #endif /* GNU C library. */ #ifdef VMS #include #if HAVE_STRING_H - 0 #include #endif #endif #if defined (WIN32) && !defined (__CYGWIN32__) /* It's not Unix, really. See? Capital letters. */ #include #define getpid() GetCurrentProcessId() #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ #ifdef HAVE_LIBINTL_H # include # define _(msgid) gettext (msgid) #else # define _(msgid) (msgid) #endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" #include "common/setup_after.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ char *getenv (); static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ #if !defined (__STDC__) || !__STDC__ /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); #endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ static const char *nonoption_flags; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void store_args (int argc, char *const *argv) __attribute__ ((unused)); static void store_args (int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } text_set_element (__libc_subinit, store_args); #endif /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined (__STDC__) && __STDC__ static void exchange (char **); #endif static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined (__STDC__) && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind = 1; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #ifdef _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { /* Bash 2.0 puts a special variable in the environment for each command it runs, specifying which ARGV elements are the results of file name wildcard expansion and therefore should not be considered as options. */ char var[100]; sprintf (var, "_%d_GNU_nonoption_argv_flags_", getpid ()); nonoption_flags = getenv (var); if (nonoption_flags == NULL) nonoption_flags_len = 0; else nonoption_flags_len = strlen (nonoption_flags); } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { optarg = NULL; if (!__getopt_initialized || optind == 0) { optstring = _getopt_initialize (argc, argv, optstring); optind = 1; /* Don't scan ARGV[0], the program name. */ __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC #define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && nonoption_flags[optind] == '1')) #else #define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, _("%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ #endif /* !HAVE_GETOPT */ pvpgn-1.8.5/src/compat/strdup.h0000644000175000017500000000163111151345317015407 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STRDUP_PROTOS #define INCLUDED_STRDUP_PROTOS #ifndef HAVE_STRDUP extern char * strdup(char const * str); #endif #endif pvpgn-1.8.5/src/compat/statmacros.h0000644000175000017500000000635111151345317016252 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STATMACROS_PROTOS #define INCLUDED_STATMACROS_PROTOS #ifdef STAT_MACROS_BROKEN # ifdef S_ISREG # undef S_ISREG # endif # ifdef S_ISDIR # undef S_ISDIR # endif # ifdef S_ISCHR # undef S_ISCHR # endif # ifdef S_ISBLK # undef S_ISBLK # endif # ifdef S_ISFIFO # undef S_ISFIFO # endif # ifdef S_ISSOCK # undef S_ISSOCK # endif # ifdef S_ISLNK # undef S_ISLNK # endif #endif #ifndef S_IFMT # define S_IFMT 0170000 #endif #ifndef S_ISREG # ifdef S_IFREG # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) # endif #endif #ifndef S_ISDIR # ifdef S_IFDIR # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) # endif #endif #ifndef S_ISCHR # ifdef S_IFCHR # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) # endif #endif #ifndef S_ISBLK # ifdef S_IFBLK # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) # endif #endif #ifndef S_ISFIFO # ifdef S_IFIFO # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) # endif #endif #ifndef S_ISLNK # ifdef S_IFLNK # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) # endif #endif #ifndef S_ISSOCK # ifdef S_IFSOCK # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) # endif #endif #ifndef S_ISCDF # ifdef S_CDF # define S_ISCDF(m) (S_ISDIR(m) && ((m) & S_CDF)) # endif #endif #ifndef S_ISMPB # ifdef S_IFMPB /* V7 */ # define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) # define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) # endif #endif #ifndef S_ISNWK # ifdef S_IFNWK /* HP/UX */ # define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) # endif #endif #ifndef S_ISUID # define S_ISUID 01000 /* set user ID */ #endif #ifndef S_ISGID # define S_ISGID 01000 /* set group ID */ #endif #ifndef S_ISVTX # define S_ISVTX 01000 /* sticky bit */ #endif #ifndef S_IRUSR # ifdef S_IREAD # define S_IRUSR S_IREAD # else # define S_IRUSR 00400 # endif #endif #ifndef S_IWUSR # ifdef S_IWRITE # define S_IWUSR S_IWRITE # else # define S_IWUSR 00200 # endif #endif #ifndef S_IXUSR # ifdef S_IEXEC # define S_IXUSR S_IEXEC # else # define S_IXUSR 00100 # endif #endif #ifndef S_IRWXU # define S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR) #endif #ifndef S_IRGRP # define S_IRGRP (S_IRUSR >> 3) #endif #ifndef S_IWGRP # define S_IWGRP (S_IWUSR >> 3) #endif #ifndef S_IXGRP # define S_IXGRP (S_IXUSR >> 3) #endif #ifndef S_IRWXG # define S_IRWXG (S_IRGRP|S_IWGRP|S_IXGRP) #endif #ifndef S_IROTH # define S_IROTH (S_IRGRP >> 3) #endif #ifndef S_IWOTH # define S_IWOTH (S_IWGRP >> 3) #endif #ifndef S_IXOTH # define S_IXOTH (S_IXGRP >> 3) #endif #ifndef S_IRWXO # define S_IRWXO (S_IROTH|S_IWOTH|S_IXOTH) #endif #endif pvpgn-1.8.5/src/compat/inet_ntoa.h0000644000175000017500000000203511151345317016045 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_INET_NTOA_H #define INCLUDED_INET_NTOA_H #ifndef HAVE_INET_NTOA #ifdef HAVE_NETINET_IN_H # include #endif #ifdef HAVE_ARPA_INET_H # include #endif extern char const * inet_ntoa(struct in_addr const * addr); #endif #endif pvpgn-1.8.5/src/compat/seek.h0000644000175000017500000000217711151345317015023 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SEEK_PROTOS #define INCLUDED_SEEK_PROTOS #ifndef SEEK_SET # ifdef L_SET # define SEEK_SET L_SET # else # define SEEK_SET 0 # endif #endif #ifndef SEEK_CUR # ifdef L_INCR # define SEEK_CUR L_INCR # else # define SEEK_CUR 1 # endif #endif #ifndef SEEK_END # ifdef L_XTND # define SEEK_END L_XTND # else # define SEEK_END 2 # endif #endif #endif pvpgn-1.8.5/src/compat/strtoul.c0000644000175000017500000000370011151345317015574 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_STRTOUL #include #include "strtoul.h" #include "common/setup_after.h" extern unsigned long strtoul(char const * str, char * * endptr, int base) { unsigned long val; char symbolval; char * pos; if (!str) return 0; /* EINVAL */ for (pos=(char *)str; *pos==' ' || *pos=='\t'; pos++); if (*pos=='-' || *pos=='+') pos++; if ((base==0 || base==16) && *pos=='0' && (*(pos+1)=='x' || *(pos+1)=='X')) { base = 16; pos += 2; /* skip 0x prefix */ } else if ((base==0 || base==8) && *pos=='0') { base = 8; pos += 1; } else if (base==0) { base = 10; } if (base<2 || base>16) /* sorry, not complete emulation (should do up to 36) */ return 0; /* EINVAL */ val = 0; for (; *pos!='\0'; pos++) { val *= base; if (isxdigit(*pos)) { symbolval = isdigit(*pos) ? *pos-'0' : tolower(*pos)-'a'+10; if (base>symbolval) val += symbolval; else break; } } if (endptr) *endptr = (void *)pos; /* avoid warning */ return val; } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/stdfileno.h0000644000175000017500000000213211151345317016052 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STDFILENO_PROTOS #define INCLUDED_STDFILENO_PROTOS #ifdef STDIN_FILENO # define STDINFD STDIN_FILENO #else # define STDINFD 0 #endif #ifdef STDOUT_FILENO # define STDOUTFD STDOUT_FILENO #else # define STDOUTFD 1 #endif #ifdef STDERR_FILENO # define STDERRFD STDERR_FILENO #else # define STDERRFD 2 #endif #endif pvpgn-1.8.5/src/compat/mkdir.h0000644000175000017500000000305411151345317015175 0ustar aaronaaron/* * Copyright (C) 2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_MKDIR_PROTOS #define INCLUDED_MKDIR_PROTOS /* Unix puts this in unistd.h, Borland/Win32 puts it in dir.h, MSVC++/Win32 puts it in direct.h */ /* Windows and MacOS also typically take only one argument */ #ifdef HAVE_DIR_H # include #endif #ifdef HAVE_DIRECT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef MKDIR_TAKES_ONE_ARG # ifdef HAVE_MKDIR # define p_mkdir(A,B) mkdir(A) # else # ifdef HAVE__MKDIR # define p_mkdir(A,B) _mkdir(A) # else # error "This program requires either mkdir() or _mkdir()" # endif # endif #else # ifdef HAVE_MKDIR # define p_mkdir mkdir # else # ifdef HAVE__MKDIR # define p_mkdir _mkdir # else # error "This program requires either mkdir() or _mkdir()" # endif # endif #endif #endif pvpgn-1.8.5/src/compat/memcpy.h0000644000175000017500000000176611151345317015371 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_MEMCPY_PROTOS #define INCLUDED_MEMCPY_PROTOS #ifndef HAVE_MEMCPY /* this should use size_t, but some systems don't define it */ extern void * memcpy(void * dest, void const * src, unsigned long n); #endif #endif pvpgn-1.8.5/src/compat/memmove.h0000644000175000017500000000177211151345317015541 0ustar aaronaaron/* * Copyright (C) 2002 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_MEMMOVE_PROTOS #define INCLUDED_MEMMOVE_PROTOS #ifndef HAVE_MEMMOVE /* this should use size_t, but some systems don't define it */ extern void * memmove(void * dest, void const * src, unsigned long n); #endif #endif pvpgn-1.8.5/src/compat/uint.h0000644000175000017500000001012311151345317015041 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_UINT_TYPES #define INCLUDED_UINT_TYPES #ifdef HAVE_STDINT_H # include typedef uint8_t t_uint8; typedef uint16_t t_uint16; typedef uint32_t t_uint32; typedef uint64_t t_uint64; typedef int8_t t_int8; typedef int16_t t_int16; typedef int32_t t_int32; typedef int64_t t_int64; # define HAVE_UINT64_T #else #ifdef HAVE_MODE_ATTR typedef unsigned int t_uint8 MODE_ATTR(__QI__); typedef unsigned int t_uint16 MODE_ATTR(__HI__); typedef unsigned int t_uint32 MODE_ATTR(__SI__); typedef unsigned int t_uint64 MODE_ATTR(__DI__); /* FIXME: I guess DI is always available... Is there a way to check? */ typedef signed int t_int8 MODE_ATTR(__QI__); typedef signed int t_int16 MODE_ATTR(__HI__); typedef signed int t_int32 MODE_ATTR(__SI__); typedef signed int t_int64 MODE_ATTR(__DI__); /* FIXME: I guess DI is always available... Is there a way to check? */ # define HAVE_UINT64_T # else # ifdef HAVE_LIMITS_H # include # endif # ifndef CHAR_BIT # define MY_CHAR_BIT 8 /* well, this is usually true :) */ # else # define MY_CHAR_BIT CHAR_BIT # endif # if SIZEOF_UNSIGNED_CHAR*MY_CHAR_BIT == 8 typedef unsigned char t_uint8; # else # error "Unable to find 8-bit integer type" # endif # if SIZEOF_SIGNED_CHAR*MY_CHAR_BIT == 8 typedef signed char t_int8; # else # error "Unable to find 8-bit integer type" # endif # if SIZEOF_UNSIGNED_SHORT*MY_CHAR_BIT == 16 typedef unsigned short t_uint16; # else # if SIZEOF_UNSIGNED_INT*MY_CHAR_BIT == 16 typedef unsigned int t_uint16; # else # error "Unable to find 16-bit integer type" # endif # endif # if SIZEOF_SIGNED_SHORT*MY_CHAR_BIT == 16 typedef signed short t_int16; # else # if SIZEOF_SIGNED_INT*MY_CHAR_BIT == 16 typedef signed int t_int16; # else # error "Unable to find 16-bit integer type" # endif # endif # if SIZEOF_UNSIGNED_SHORT*MY_CHAR_BIT == 32 typedef unsigned short t_uint32; # else # if SIZEOF_UNSIGNED_INT*MY_CHAR_BIT == 32 typedef unsigned int t_uint32; # else # if SIZEOF_UNSIGNED_LONG*MY_CHAR_BIT == 32 typedef unsigned long t_uint32; # else # error "Unable to find 32-bit integer type" # endif # endif # endif # if SIZEOF_SIGNED_SHORT*MY_CHAR_BIT == 32 typedef signed short t_int32; # else # if SIZEOF_SIGNED_INT*MY_CHAR_BIT == 32 typedef signed int t_int32; # else # if SIZEOF_SIGNED_LONG*MY_CHAR_BIT == 32 typedef signed long t_int32; # else # error "Unable to find 32-bit integer type" # endif # endif # endif # if SIZEOF_UNSIGNED_INT*MY_CHAR_BIT == 64 typedef unsigned int t_uint64; # define HAVE_UINT64_T # else # if SIZEOF_UNSIGNED_LONG*MY_CHAR_BIT == 64 typedef unsigned long t_uint64; # define HAVE_UINT64_T # else # if SIZEOF_UNSIGNED_LONG_LONG*MY_CHAR_BIT == 64 typedef unsigned long long t_uint64; # define HAVE_UINT64_T # endif # endif # endif # if SIZEOF_SIGNED_INT*MY_CHAR_BIT == 64 typedef signed int t_int64; # define HAVE_INT64_T # else # if SIZEOF_SIGNED_LONG*MY_CHAR_BIT == 64 typedef signed long t_int64; # define HAVE_INT64_T # else # if SIZEOF_SIGNED_LONG_LONG*MY_CHAR_BIT == 64 typedef signed long long t_int64; # define HAVE_INT64_T # endif # endif # endif # undef MY_CHAR_BIT # endif #endif #endif pvpgn-1.8.5/src/compat/difftime.c0000644000175000017500000000231411151345317015647 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_DIFFTIME #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "difftime.h" #include "common/setup_after.h" extern double difftime(time_t after, time_t before) { return ((double)after)-((double)before); } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/strcasecmp.h0000644000175000017500000000204211151345317016227 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STRCASECMP_PROTOS #define INCLUDED_STRCASECMP_PROTOS #ifndef HAVE_STRCASECMP #ifdef HAVE_STRICMP # define strcasecmp(s1, s2) stricmp(s1, s2) # define HAVE_STRCASECMP #else extern int strcasecmp(char const * str1, char const * str2); #endif #endif #endif pvpgn-1.8.5/src/compat/vsnprintf.c0000644000175000017500000000256011151345317016114 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #include "compat/vargs.h" #include "common/setup_after.h" #if !defined(HAVE_VSNPRINTF) && !defined(HAVE__VSNPRINTF) && defined(HAVE_DOPRNT) && defined(_IOWRT) && defined(_IOSTRG) extern int vsnprintf(char *str, int size, const char *format, va_list ap) { FILE b; int ret; #ifdef VMS b->_flag = _IOWRT|_IOSTRG; b->_ptr = str; b->_cnt = size; #else b._flag = _IOWRT|_IOSTRG; b._ptr = str; b._cnt = size; #endif ret = _doprnt(format, ap, &b); putc('\0', &b); return ret; } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/pdir.c0000644000175000017500000001364711151345317015031 0ustar aaronaaron/* * Copyright (C) 2001 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define PDIR_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #ifdef HAVE_DIRENT_H # include #else # ifdef HAVE_SYS_NDIR_H # include # endif # if HAVE_SYS_DIR_H # include # endif # if HAVE_NDIR_H # include # endif # define dirent direct #endif #ifdef WIN32 # include /* for _findfirst(), _findnext(), etc */ #endif #include #include "compat/strerror.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "pdir.h" #include "common/setup_after.h" extern t_pdir * p_opendir(const char * path) { #ifdef WIN32 char npath[_MAX_PATH]; #endif t_pdir * pdir; if (path==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL path"); return NULL; } /* while(path[strlen(path)]=='/') path[strlen(path)]='\0'; */ /* win32 can use slash in addition to backslash */ pdir=xmalloc(sizeof(t_pdir)); #ifdef WIN32 if (strlen(path)+1+3+1>_MAX_PATH) { eventlog(eventlog_level_error,__FUNCTION__,"WIN32: path too long"); xfree(pdir); return NULL; } strcpy(npath, path); strcat(npath, "/*.*"); pdir->path=xstrdup(npath); pdir->status = 0; memset(&pdir->fileinfo, 0, sizeof(pdir->fileinfo)); /* no need for compat because WIN32 always has memset() */ pdir->lFindHandle = _findfirst(npath, &pdir->fileinfo); if (pdir->lFindHandle < 0) { xfree((void *)pdir->path); /* avoid warning */ xfree(pdir); return NULL; } #else /* POSIX style */ pdir->path=xstrdup(path); if ((pdir->dir=opendir(path))==NULL) { xfree((void *)pdir->path); /* avoid warning */ xfree(pdir); return NULL; } #endif /* WIN32-POSIX */ return pdir; } extern int p_rewinddir(t_pdir * pdir) { if (pdir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL pdir"); return -1; } if (pdir->path==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got pdir with NULL path"); return -1; } #ifdef WIN32 /* i dont have any win32 around so i dont know if io.h has any rewinddir equivalent */ /* FIXME: for the time being ill just close and reopen it */ if (pdir->status!=-1) { if (pdir->lFindHandle<0) { eventlog(eventlog_level_error,__FUNCTION__,"WIN32: got negative lFindHandle"); return -1; } _findclose(pdir->lFindHandle); } pdir->status = 0; memset(&pdir->fileinfo, 0, sizeof(pdir->fileinfo)); /* no need for compat because WIN32 always has memset() */ pdir->lFindHandle = _findfirst(pdir->path, &pdir->fileinfo); if (pdir->lFindHandle < 0) { pdir->status = -1; return -1; } #else /* POSIX */ if (pdir->dir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"POSIX: got pdir with NULL dir"); return -1; } rewinddir(pdir->dir); #endif return 0; } extern char const * p_readdir(t_pdir * pdir) { if (pdir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL pdir"); return NULL; } if (pdir->path==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got pdir with NULL path"); return NULL; } #ifdef WIN32 switch (pdir->status) { default: case -1: /* couldn't rewind */ eventlog(eventlog_level_error,__FUNCTION__,"got pdir with status -1"); return NULL; case 0: /* freshly opened */ pdir->status = 1; return pdir->fileinfo.name; case 1: /* reading */ if (_findnext(pdir->lFindHandle, &pdir->fileinfo)<0) { pdir->status = 2; return NULL; } else return pdir->fileinfo.name; break; case 2: /* EOF */ return NULL; } #else /* POSIX */ { struct dirent * dentry; if (pdir->dir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"POSIX: got pdir with NULL dir"); return NULL; } if ((dentry=readdir(pdir->dir))==NULL) return NULL; return dentry->d_name; } #endif /* WIN32-POSIX */ } extern int p_closedir(t_pdir * pdir) { int ret; if (pdir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL pdir"); return -1; } if (pdir->path==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got pdir with NULL path"); return -1; } #ifdef WIN32 if (pdir->status!=-1) { if (pdir->lFindHandle<0) { eventlog(eventlog_level_info,__FUNCTION__,"WIN32: got NULL findhandle"); return -1; } _findclose(pdir->lFindHandle); /* FIXME: what does _findclose() return on error? */ } ret = 0; #else /* POSIX */ if (pdir->dir==NULL) { eventlog(eventlog_level_info,__FUNCTION__,"POSIX: got NULL dir"); return -1; } # ifdef CLOSEDIR_VOID closedir(pdir->dir); ret = 0; # else ret = closedir(pdir->dir); # endif #endif /* WIN32-POSIX */ xfree((void *)pdir->path); /* avoid warning */ xfree(pdir); return ret; } pvpgn-1.8.5/src/compat/difftime.h0000644000175000017500000000212111151345317015650 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_DIFFTIME_PROTOS #define INCLUDED_DIFFTIME_PROTOS #ifndef HAVE_DIFFTIME #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif extern double difftime(time_t after, time_t before); #endif #endif pvpgn-1.8.5/src/compat/strerror.h0000644000175000017500000000174411151345317015755 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STRERROR_PROTOS #define INCLUDED_STRERROR_PROTOS #if !defined(HAVE_STRERROR) || defined(WIN32) extern char const * pstrerror(int errornum); #else # define pstrerror(e) strerror(e) #endif #endif pvpgn-1.8.5/src/compat/inet_aton.h0000644000175000017500000000623011151345317016046 0ustar aaronaaron/* * ++Copyright++ 1983, 1990, 1993 * - * Copyright (c) 1983, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ #ifndef INCLUDED_INET_ATON_H #define INCLUDED_INET_ATON_H #ifndef HAVE_INET_ATON #ifdef HAVE_NETINET_IN_H # include #endif #ifdef HAVE_ARPA_INET_H # include #endif extern int inet_aton(char const * cp, struct in_addr * addr); #endif #endif pvpgn-1.8.5/src/compat/strcasecmp.c0000644000175000017500000000332711151345317016231 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_STRCASECMP #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "strcasecmp.h" #include "common/setup_after.h" extern int strcasecmp(char const * str1, char const * str2) { unsigned int i; int a; int b; if (!str1 || !str2) return -1; /* some versions of tolower() break when given already lowercase characters */ for (i=0; str1[i]!='\0' && str2[i]!='\0'; i++) { if (isupper((int)str1[i])) a = (int)tolower((int)str1[i]); else a = (int)str1[i]; if (isupper((int)str2[i])) b = (int)tolower((int)str2[i]); else b = (int)str2[i]; if (ab) return +1; } if (str1[i]!='\0') return -1; if (str2[i]!='\0') return +1; return 0; } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/gettimeofday.c0000644000175000017500000000354211151345317016545 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_GETTIMEOFDAY #include #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TIMEB_H # include #endif #include "gettimeofday.h" #include "common/setup_after.h" extern int gettimeofday(struct timeval * tv, struct timezone * tz) { #ifdef HAVE_FTIME struct timeb tb; #endif if (!tv) { errno = EFAULT; return -1; } #ifdef HAVE_FTIME tb.millitm = 0; /* apparently the MS CRT version of this doesn't set this member */ /* FIXME: what would be a more appropriate function for that platform? */ ftime(&tb); /* FIXME: some versions are void return others int */ tv->tv_sec = tb.time; tv->tv_usec = ((long)tb.millitm)*1000; if (tz) { tz->tz_minuteswest = 0; tz->tz_dsttime = 0; } return 0; #else # error "This program requires either gettimeofday() or ftime()" #endif } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/psock.h0000644000175000017500000002041411151345317015205 0ustar aaronaaron/* * Copyright (C) 1999 Philippe Dubois (pdubois1@hotmail.com) * Copyright (C) 1999,2000,2002 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_PSOCK_PROTOS #define INCLUDED_PSOCK_PROTOS /* * This file is like the other compat header files in that it * tries to hide differences between systems. It is somewhat * different in that it doesn't present a "normal" interface * to the rest of the code, but instead defines its own macros * and functions. This is done since Win32 uses closesocket() * instead of close() for sockets, but it can't be remapped * since it already has a close() for file descriptors. Also, * this allows us to hide the fact that some systems use * fcntl() and some use ioctl(). The select() function is * included here even though it isn't strictly for sockets. * Just call this version if any of the file descriptors might * be sockets. * * This file must be included _after_ any other socket related * headers and any other compat socket fixup headers. */ #ifdef WIN32 /* winsock2 */ #include /* protocol families */ #define PSOCK_PF_INET PF_INET /* address families */ #define PSOCK_AF_INET AF_INET /* socket types */ #define PSOCK_SOCK_STREAM SOCK_STREAM #define PSOCK_SOCK_DGRAM SOCK_DGRAM /* socket protocols */ #ifdef IPPROTO_TCP # define PSOCK_IPPROTO_TCP IPPROTO_TCP #else # define PSOCK_IPPROTO_TCP 0 #endif #ifdef IPPROTO_UDP # define PSOCK_IPPROTO_UDP IPPROTO_UDP #else # define PSOCK_IPPROTO_UDP 0 #endif /* psock_[gs]etsockopt() flags */ #define PSOCK_SOL_SOCKET SOL_SOCKET #define PSOCK_SO_REUSEADDR SO_REUSEADDR #define PSOCK_SO_KEEPALIVE SO_KEEPALIVE #define PSOCK_SO_ERROR SO_ERROR /* psock_ctl() flags */ #define PSOCK_NONBLOCK FIONBIO /* psock_errno() values */ #ifdef WSAEWOULDBLOCK # define PSOCK_EWOULDBLOCK WSAEWOULDBLOCK #endif #ifdef WSAEINPROGRESS # define PSOCK_EINPROGRESS WSAEINPROGRESS #endif #ifdef WSAEINTR # define PSOCK_EINTR WSAEINTR #endif #ifdef WSAECONNABORTED # define PSOCK_ECONNABORTED WSAECONNABORTED #endif #ifdef WSATRY_AGAIN # define PSOCK_EAGAIN WSATRY_AGAIN #endif #ifdef WSAECONNRESET # define PSOCK_ECONNRESET WSAECONNRESET #endif #ifdef WSAENOTCONN # define PSOCK_ENOTCONN WSAENOTCONN #endif #ifdef WSAEPIPE # define PSOCK_EPIPE WSAEPIPE #endif #ifdef WSAEPROTO # define PSOCK_EPROTO WSAEPROTO #endif #ifdef WSAENOBUFS # define PSOCK_ENOBUFS WSAENOBUFS #endif #ifdef WSAENOMEM # define PSOCK_ENOMEM WSAENOMEM #endif /* psock_shutdown() flags */ #define PSOCK_SHUT_RD 0 #define PSOCK_SHUT_WR 1 #define PSOCK_SHUT_RDWR 2 /* psock types */ #define psock_t_socklen int /* psock_select() macros and types */ #define t_psock_fd_set fd_set #define PSOCK_FD_ZERO FD_ZERO #define PSOCK_FD_CLR FD_CLR #define PSOCK_FD_SET FD_SET #define PSOCK_FD_ISSET FD_ISSET /* psock functions */ extern int psock_init(void); /* a real functions in */ extern int psock_deinit(void); /* compat/psock.c */ #define psock_errno() WSAGetLastError() #define psock_socket(pf, t, ps) socket(pf, t, ps) #define psock_getsockopt(s, l, o, v, size) getsockopt(s, l, o, (void *)(v), size) #define psock_setsockopt(s, l, o, v, size) setsockopt(s, l, o, (void *)(v), size) extern int psock_ctl(int sd, int mode); /* a real function in compat/psock.c */ #define psock_listen(s, b) listen(s, b) #define psock_bind(s, a, l) bind(s, a, l) #define psock_accept(s, a, l) accept(s, a, l) #define psock_connect(s, a, l) connect(s, a, l) #define psock_send(s, b, l, f) send(s, (void *)(b), l, f) #define psock_sendto(s, b, l, f, a, al) sendto(s, (void *)(b), l, f, a, al) #define psock_recv(s, b, l, f) recv(s, (void *)(b), l, f) #define psock_recvfrom(s, b, l, f, a, al) recvfrom(s, (void *)(b), l, f, a, al) #define psock_shutdown(s, how) shutdown(s, how) #define psock_close(s) closesocket(s) #define psock_select(s, r, w, e, t) select(s, r, w, e ,t) #define psock_getsockname(s, a, l) getsockname(s, a, l) /* PDubois - 991111 */ /*#define inet_aton(cp, pAdd) (((*pAdd).s_addr = inet_addr(cp)) != INADDR_NONE)*/ /* (this should be done in compat/inet_aton.h and this isn't a 100% correct implementation anyway -Ross) */ #else /* assume POSIX */ /* protocol families */ #define PSOCK_PF_INET PF_INET /* address families */ #define PSOCK_AF_INET AF_INET /* socket types */ #define PSOCK_SOCK_STREAM SOCK_STREAM #define PSOCK_SOCK_DGRAM SOCK_DGRAM /* socket protocols */ #ifdef IPPROTO_TCP # define PSOCK_IPPROTO_TCP IPPROTO_TCP #else # define PSOCK_IPPROTO_TCP 0 #endif #ifdef IPPROTO_UDP # define PSOCK_IPPROTO_UDP IPPROTO_UDP #else # define PSOCK_IPPROTO_UDP 0 #endif /* psock_[gs]etsockopt() flags */ #define PSOCK_SOL_SOCKET SOL_SOCKET #define PSOCK_SO_REUSEADDR SO_REUSEADDR #define PSOCK_SO_KEEPALIVE SO_KEEPALIVE #define PSOCK_SO_ERROR SO_ERROR /* psock_ctl() flags */ #define PSOCK_NONBLOCK O_NONBLOCK /* psock_errno() values */ #ifdef EWOULDBLOCK # define PSOCK_EWOULDBLOCK EWOULDBLOCK #endif #ifdef EINPROGRESS # define PSOCK_EINPROGRESS EINPROGRESS #endif #ifdef EINTR # define PSOCK_EINTR EINTR #endif #ifdef ECONNABORTED # define PSOCK_ECONNABORTED ECONNABORTED #endif #ifdef EAGAIN # define PSOCK_EAGAIN EAGAIN #endif #ifdef ECONNRESET # define PSOCK_ECONNRESET ECONNRESET #endif #ifdef ENOTCONN # define PSOCK_ENOTCONN ENOTCONN #endif #ifdef EPIPE # define PSOCK_EPIPE EPIPE #endif #ifdef EPROTO # define PSOCK_EPROTO EPROTO #endif #ifdef ENOBUFS # define PSOCK_ENOBUFS ENOBUFS #endif #ifdef ENOMEM # define PSOCK_ENOMEM ENOMEM #endif /* psock_shutdown() flags */ #ifdef SHUT_RD # define PSOCK_SHUT_RD SHUT_RD #else # define PSOCK_SHUT_RD 0 #endif #ifdef SHUT_WR # define PSOCK_SHUT_WR SHUT_WR #else # define PSOCK_SHUT_WR 1 #endif #ifdef SHUT_RDWR # define PSOCK_SHUT_RDWR SHUT_RDWR #else # define PSOCK_SHUT_RDWR 2 #endif /* psock types */ /* FIXME: write configure test to check for this type */ #ifdef HAVE_SOCKLEN_T # define psock_t_socklen socklen_t #else # define psock_t_socklen unsigned int #endif /* psock_select() macros and types */ #define t_psock_fd_set fd_set #define PSOCK_FD_ZERO FD_ZERO #define PSOCK_FD_CLR FD_CLR #define PSOCK_FD_SET FD_SET #define PSOCK_FD_ISSET FD_ISSET /* psock functions */ #define psock_init() (0) #define psock_deinit() (0) #define psock_errno() (errno) #define psock_socket(pf, t, ps) socket(pf, t, ps) #define psock_getsockopt(s, l, o, v, size) getsockopt(s, l, o, (void *)(v), size) #define psock_setsockopt(s, l, o, v, size) setsockopt(s, l, o, (void *)(v), size) extern int psock_ctl(int sd, long int mode); /* a real function in compat/psock.c */ #define psock_listen(s, b) listen(s, b) #define psock_bind(s, a, l) bind(s, a, l) #define psock_accept(s, a, l) accept(s, a, l) #define psock_connect(s, a, l) connect(s, a, l) #define psock_send(s, b, l, f) send(s, (void *)(b), l, f) #define psock_sendto(s, b, l, f, a, al) sendto(s, (void *)(b), l, f, a, al) #define psock_recv(s, b, l, f) recv(s, (void *)(b), l, f) #define psock_recvfrom(s, b, l, f, a, al) recvfrom(s, (void *)(b), l, f, a, al) #define psock_shutdown(s, how) shutdown(s, how) #define psock_close(s) close(s) #define psock_select(s, r, w, e, t) select(s, r, w, e ,t) #define psock_getsockname(s, a, l) getsockname(s, a, l) #endif #endif #endif pvpgn-1.8.5/src/compat/pdir.h0000644000175000017500000000427111151345317015027 0ustar aaronaaron/* * Copyright (C) 2001 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_PDIR_TYPES #define INCLUDED_PDIR_TYPES #ifdef PDIR_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # ifdef HAVE_DIRENT_H # include # else # ifdef HAVE_SYS_NDIR_H # include # endif # if HAVE_SYS_DIR_H # include # endif # if HAVE_NDIR_H # include # endif # define dirent direct # endif # ifdef WIN32 # include /* for _findfirst(), _findnext(), etc */ # endif #else # define JUST_NEED_TYPES # ifdef HAVE_DIRENT_H # include # else # ifdef HAVE_SYS_NDIR_H # include # endif # if HAVE_SYS_DIR_H # include # endif # if HAVE_NDIR_H # include # endif # define dirent direct # endif # ifdef WIN32 # include /* for _findfirst(), _findnext(), etc */ # endif # undef JUST_NEED_TYPES #endif #endif typedef struct pdir_struct #ifdef PDIR_INTERNAL_ACCESS { char const * path; char const * lastret; #ifdef WIN32 long lFindHandle; struct _finddata_t fileinfo; int status; /* -1 == failure, 0 == freshly opened, 1 == opened and read, 2 == eof */ #else /* POSIX */ DIR * dir; #endif } #endif t_pdir; #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_PDIR_PROTOS #define INCLUDED_PDIR_PROTOS extern t_pdir * p_opendir(const char * dirname); extern int p_rewinddir(t_pdir * pdir); extern char const * p_readdir(t_pdir * pdir); extern int p_closedir(t_pdir * pdir); #endif #endif pvpgn-1.8.5/src/compat/send.h0000644000175000017500000000225211151345317015017 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SEND_PROTOS #define INCLUDED_SEND_PROTOS #ifndef HAVE_SEND /* some sendto()s don't handle NULL, but send is called depreciated on BSD */ #ifdef HAVE_SENDTO # ifdef HAVE_STDDEF_H # include # else # ifndef NULL # define NULL ((void *)0) # endif # endif # define send(s, b, l, f) sendto(s, b, l, f, NULL, NULL) #else # error "This program requires sendto()" #endif #endif #endif pvpgn-1.8.5/src/compat/char_bit.h0000644000175000017500000000212511151345317015640 0ustar aaronaaron/* * Copyright (C) 2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_CHAR_BIT_TYPES #define INCLUDED_CHAR_BIT_TYPES # ifdef HAVE_LIMITS_H # include # endif # ifdef HAVE_SYS_PARAM_H # include # endif # ifndef CHAR_BIT # ifdef NBBY # define CHAR_BIT NBBY # else # define CHAR_BIT 8 /* well, this is usually true :) */ # endif # endif #endif pvpgn-1.8.5/src/compat/strchr.h0000644000175000017500000000174111151345317015375 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STRCHR_PROTOS #define INCLUDED_STRCHR_PROTOS #ifndef HAVE_STRCHR #ifdef HAVE_INDEX # define strchr index #else # error "This program requires either strchr() or index()" #endif #endif #endif pvpgn-1.8.5/src/compat/rename.h0000644000175000017500000000214711151345317015340 0ustar aaronaaron/* * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_RENAME_PROTOS #define INCLUDED_RENAME_PROTOS #ifdef HAVE_UNISTD_H # include #endif #include "compat/access.h" static inline int p_rename(const char * old, const char * new) { #ifdef WIN32 if(access(new, F_OK) == 0) if(remove(new) < 0) return -1; #endif return rename(old, new); } #endif pvpgn-1.8.5/src/compat/memset.c0000644000175000017500000000245211151345317015355 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_MEMSET #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include "memset.h" #include "common/setup_after.h" /* very slow, but we don't care */ extern void * memset(void * dest, int c, unsigned long n) { unsigned char * temp=dest; unsigned long i; if (!temp) return NULL; for (i=0; i #include "compat/vargs.h" #if !defined(HAVE_VSNPRINTF) #ifdef HAVE__VSNPRINTF #define vsnprintf(str,size,format,ap) _vsnprintf(str,size,format,ap) #else #if defined(_IOSTRG) && defined(_IOSTRG) && defined(HAVE_DOPRNT) extern int vsnprintf(char *str, int size, const char *format, va_list ap); #else #error "Your system lacks ANY kind of vsnprintf support!" #endif #endif #endif #endif /* INCLUDED_VSNPRINTF_PROTOS */ pvpgn-1.8.5/src/compat/snprintf.c0000644000175000017500000000236511151345317015731 0ustar aaronaaron/* * Copyright (C) 2005 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #include "compat/vargs.h" #include "compat/vsnprintf.h" #include "common/setup_after.h" #if !defined(HAVE_SNPRINTF) && !defined(HAVE__SNPRINTF) extern int snprintf(char *str, size_t size, const char *format, ...) { int result; va_list args; VA_START(args,format); result = vsnprintf(str,size,format,args); va_end(args); return result; } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/socket.h0000644000175000017500000000232311151345317015355 0ustar aaronaaron/* * Copyright (C) 1999 Philippe Dubois (pdubois1@hotmail.com) * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SOCKET_PROTOS #define INCLUDED_SOCKET_PROTOS #ifdef WIN32 /* assume winsock2 is available */ # include /* * Including that file is basically equivalent to including: * * * * * * * * It should be included once for any file needing one or more * of those headers. */ #endif #endif pvpgn-1.8.5/src/compat/termios.h0000644000175000017500000000302511151345317015547 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_TERMIOS_TYPES #define INCLUDED_TERMIOS_TYPES /* FIXME: this might already exist even if termios.h doesn't... check for the type in autoconf */ # ifndef HAVE_TERMIOS_H struct termios { int c_lflag; int c_cc[1]; }; # define ECHO 1 # define ICANON 1 # define VMIN 1 # define VTIME 1 # endif #endif #ifndef INCLUDED_TERMIOS_PROTOS #define INCLUDED_TERMIOS_PROTOS /* FIXME: check for functions or macros (autoconf doesn't protect header inclusion for function tests so it isn't easy */ #ifndef HAVE_TERMIOS_H # define tcgetattr(F,T) (-1) #endif /* FIXME: check for functions or macros (autoconf doesn't protect header inclusion for function tests so it isn't easy */ #ifndef HAVE_TERMIOS_H # define tcsetattr(F,A,T) (-1) #endif #endif pvpgn-1.8.5/src/compat/strftime.c0000644000175000017500000000316211151345317015717 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_STRFTIME #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "strftime.h" #include "common/setup_after.h" /* We are not even trying to copy the functionality. We are just trying to get a timestamp. */ extern int strftime(char * buf, int bufsize, char const * fmt, struct tm const * tm) { if (!buf || !fmt || !tm) return 0; if (bufsize>24) sprintf(buf,"%.4d %.2d %.2d %02.2d:%02.2d:%02.2d", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); else if (bufsize>10) sprintf(buf,"%02.2d:%02.2d:%02.2d", tm->tm_hour, tm->tm_min, tm->tm_sec); else buf[0] = '\0'; return strlen(buf); } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/inet_ntoa.c0000644000175000017500000000313211151345317016037 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef HAVE_INET_NTOA #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_SYS_TYPES # include #endif #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #ifdef HAVE_ARPA_INET_H # include #endif #include "inet_ntoa.h" #include "common/setup_after.h" extern char const * inet_ntoa(struct in_addr const * addr) { static char buff[16]; unsigned long val; if (!addr) return NULL; val = ntohl(addr->s_addr); sprintf(buff,"%u.%u.%u.%u", (val>>24)&0xff, (val>>16)&0xff, (val>> 8)&0xff, (val )&0xff); return buff; } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/compat/strtoul.h0000644000175000017500000000167711151345317015614 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STRTOUL_PROTOS #define INCLUDED_STRTOUL_PROTOS #ifndef HAVE_STRTOUL extern unsigned long strtoul(char const * str, char * * endptr, int base); #endif #endif pvpgn-1.8.5/src/compat/psock.c0000644000175000017500000000357511151345317015211 0ustar aaronaaron/* * Copyright (C) 1999 Philippe Dubois (pdubois1@hotmail.com) * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef WIN32 #include "psock.h" #include "common/setup_after.h" extern int psock_init(void) { WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2, 2); if (WSAStartup(wVersionRequested, &wsaData)!=0) { /* FIXME: Tell the user that we could not find a usable WinSock DLL. */ return -1; } return 0; } extern int psock_deinit(void) { if (WSACleanup()!=0) { return -1; } return 0; } extern int psock_ctl(int sd, int mode) { unsigned long nParam=1; /* u_long or DWORD or what? */ return ioctlsocket(sd,mode,&nParam); } #else #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #include "psock.h" #include "common/setup_after.h" extern int psock_ctl(int sd, long int mode) { long int oldmode; if ((oldmode = fcntl(sd,F_GETFL))<0) oldmode = 0; oldmode |= mode; return fcntl(sd,F_SETFL,mode); } #endif pvpgn-1.8.5/src/compat/inet_aton.c0000644000175000017500000001323611151345317016045 0ustar aaronaaron/* * ++Copyright++ 1983, 1990, 1993 * - * Copyright (c) 1983, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ #include "common/setup_before.h" #ifndef HAVE_INET_ATON #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; static char rcsid[] = "$Id: inet_aton.c,v 1.1.1.1 2002/12/27 08:45:08 dizzy Exp $"; #endif /* LIBC_SCCS and not lint */ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/socket.h" /* for Win32 address types, maybe there should be compat/netinet_in.h */ #include "inet_aton.h" #include "common/setup_after.h" /* * Check whether "cp" is a valid ASCII representation * of an Internet address and convert to a binary address. * Returns 1 if the address is valid, 0 if not. * This replaces inet_addr, the return value from which * cannot distinguish between failure and a local wildcard address. * Only handles IPv4. * Assumes 32-bit ints. */ extern int inet_aton(char const * cp, struct in_addr * addr) { unsigned int val; int base, n; char c; unsigned int parts[4]; unsigned int *pp = parts; c = *cp; for (;;) { /* * Collect number up to ``.''. * Values are specified as for C: * 0x=hex, 0=octal, isdigit=decimal. */ if (!isdigit((int)c)) return (0); val = 0; base = 10; if (c == '0') { c = *++cp; if (c == 'x' || c == 'X') base = 16, c = *++cp; else base = 8; } for (;;) { if (isascii((int)c) && isdigit((int)c)) { val = (val * base) + (c - '0'); c = *++cp; } else if (base == 16 && isascii((int)c) && isxdigit((int)c)) { val = (val << 4) | (c + 10 - (islower((int)c) ? 'a' : 'A')); c = *++cp; } else break; } if (c == '.') { /* * Internet format: * a.b.c.d * a.b.c (with c treated as 16 bits) * a.b (with b treated as 24 bits) */ if (pp >= parts + 3) return (0); *pp++ = val; c = *++cp; } else break; } /* * Check for trailing characters. */ if (c != '\0' && (!isascii((int)c) || !isspace((int)c))) return (0); /* * Concoct the address according to * the number of parts specified. */ n = pp - parts + 1; switch (n) { case 0: return (0); /* initial nondigit */ case 1: /* a -- 32 bits */ break; case 2: /* a.b -- 8.24 bits */ if (val > 0xffffff) return (0); val |= parts[0] << 24; break; case 3: /* a.b.c -- 8.8.16 bits */ if (val > 0xffff) return (0); val |= (parts[0] << 24) | (parts[1] << 16); break; case 4: /* a.b.c.d -- 8.8.8.8 bits */ if (val > 0xff) return (0); val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); break; } if (addr) addr->s_addr = htonl(val); return (1); } #else typedef int filenotempty; /* make ISO standard happy */ #endif pvpgn-1.8.5/src/d2cs/0000755000175000017500000000000011151345372013265 5ustar aaronaaronpvpgn-1.8.5/src/d2cs/handle_d2gs.h0000644000175000017500000000230511151345317015607 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_HANDLE_D2GS_H #define INCLUDED_HANDLE_D2GS_H #include "connection.h" #include "common/packet.h" /* FIXME: why include the time stuff? */ #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif extern int handle_d2gs_packet(t_connection * c, t_packet * packet); extern int handle_d2gs_init(t_connection * c); #endif pvpgn-1.8.5/src/d2cs/game.c0000644000175000017500000002760411151345317014352 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strcasecmp.h" #include "compat/strdup.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "bit.h" #include "prefs.h" #include "game.h" #include "common/list.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" static t_list * gamelist_head=NULL; static t_elem const * gamelist_curr_elem=NULL; static unsigned int total_game=0; static unsigned int game_id=0; static t_game_charinfo * game_find_character(t_game * game, char const * charname); extern t_list * d2cs_gamelist(void) { return gamelist_head; } extern t_elem const * gamelist_get_curr_elem(void) { return gamelist_curr_elem; } extern void gamelist_set_curr_elem(t_elem const * elem) { gamelist_curr_elem=elem; return; } extern int d2cs_gamelist_create(void) { gamelist_head=list_create(); return 0; } extern int d2cs_gamelist_destroy(void) { t_game * game; BEGIN_LIST_TRAVERSE_DATA(gamelist_head, game) { game_destroy(game,&curr_elem_); } END_LIST_TRAVERSE_DATA(); if (list_destroy(gamelist_head)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error destroy connection list"); return -1; } gamelist_head=NULL; return 0; } extern t_game * d2cs_gamelist_find_game(char const * gamename) { t_game * game; ASSERT(gamename,NULL); BEGIN_LIST_TRAVERSE_DATA(gamelist_head,game) { if (!strcasecmp(game->name,gamename)) return game; } END_LIST_TRAVERSE_DATA() return NULL; } extern t_game * gamelist_find_game_by_id(unsigned int id) { t_game * game; BEGIN_LIST_TRAVERSE_DATA(gamelist_head,game) { if (game->id==id) return game; } END_LIST_TRAVERSE_DATA() return NULL; } extern t_game * gamelist_find_game_by_d2gs_and_id(unsigned int d2gs_id, unsigned int d2gs_gameid) { t_game * game; BEGIN_LIST_TRAVERSE_DATA(gamelist_head,game) { if (!game->created) continue; if (game->d2gs_gameid!=d2gs_gameid) continue; if (d2gs_get_id(game->d2gs) != d2gs_id) continue; return game; } END_LIST_TRAVERSE_DATA() return NULL; } extern t_game * gamelist_find_character(char const * charname) { t_game * game; ASSERT(charname,NULL); BEGIN_LIST_TRAVERSE_DATA(gamelist_head, game) { if (game_find_character(game,charname)) return game; } END_LIST_TRAVERSE_DATA(); return NULL; } extern void d2cs_gamelist_check_voidgame(void) { t_game * game; time_t now; int timeout; timeout=prefs_get_max_game_idletime(); if (!timeout) return; now=time(NULL); BEGIN_LIST_TRAVERSE_DATA(gamelist_head, game) { if (!game->currchar) { if ((now-game->lastaccess_time)>timeout) { eventlog(eventlog_level_info,__FUNCTION__,"game %s is empty too long time,destroying it",game->name); game_destroy(game,&curr_elem_); } } } END_LIST_TRAVERSE_DATA() } extern t_game * d2cs_game_create(char const * gamename, char const * gamepass, char const * gamedesc, unsigned int gameflag) { t_game * game; time_t now; ASSERT(gamename,NULL); ASSERT(gamepass,NULL); ASSERT(gamedesc,NULL); if (d2cs_gamelist_find_game(gamename)) { eventlog(eventlog_level_error,__FUNCTION__,"game %s already exist",gamename); return NULL; } game=xmalloc(sizeof(t_game)); game->name=xstrdup(gamename); game->pass=xstrdup(gamepass); game->desc=xstrdup(gamedesc); game->charlist=list_create(); now=time(NULL); game_id++; if (game_id==0) game_id=1; game->id=game_id; game->created=0; game->create_time=now; game->lastaccess_time=now; game->gameflag=gameflag; game->charlevel=0; game->leveldiff=0; game->d2gs_gameid=0; game->d2gs=NULL; game->maxchar=MAX_CHAR_PER_GAME; game->currchar=0; list_prepend_data(gamelist_head,game); total_game++; eventlog(eventlog_level_info,__FUNCTION__,"game %s pass=%s desc=%s gameflag=0x%08X created (%d total)",gamename,gamepass, gamedesc,gameflag,total_game); return game; } extern int game_destroy(t_game * game, t_elem ** elem) { t_elem * curr; t_game_charinfo * charinfo; ASSERT(game,-1); if (gamelist_curr_elem && (game==elem_get_data(gamelist_curr_elem))) { gamelist_curr_elem=elem_get_next_const(gamelist_head,gamelist_curr_elem); } if (list_remove_data(gamelist_head,game,elem)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error remove game %s on game list",game->name); return -1; } total_game--; eventlog(eventlog_level_info,__FUNCTION__,"game %s removed from game list (%d left)",game->name,total_game); LIST_TRAVERSE(game->charlist,curr) { if ((charinfo=elem_get_data(curr))) { if (charinfo->charname) xfree((void *)charinfo->charname); xfree(charinfo); } list_remove_elem(game->charlist,&curr); } list_destroy(game->charlist); if (game->d2gs) { d2gs_add_gamenum(game->d2gs,-1); gqlist_check_creategame(d2gs_get_maxgame(game->d2gs) - d2gs_get_gamenum(game->d2gs)); } if (game->desc) xfree((void *)game->desc); if (game->pass) xfree((void *)game->pass); if (game->name) xfree((void *)game->name); xfree(game); return 0; } static t_game_charinfo * game_find_character(t_game * game, char const * charname) { t_game_charinfo * charinfo; ASSERT(game,NULL); ASSERT(charname,NULL); if (!game->charlist) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character list in game %s",game->name); return NULL; } BEGIN_LIST_TRAVERSE_DATA(game->charlist,charinfo) { if (!charinfo->charname) continue; if (!strcmp_charname(charinfo->charname,charname)) return charinfo; } END_LIST_TRAVERSE_DATA() return NULL; } extern int game_add_character(t_game * game, char const * charname, unsigned char class, unsigned char level) { t_game_charinfo * charinfo; ASSERT(game,-1); ASSERT(charname,-1); charinfo=game_find_character(game,charname); if (charinfo) { eventlog(eventlog_level_info,__FUNCTION__,"updating character %s (game %s) status", charname,game->name); charinfo->class=class; charinfo->level=level; return 0; } charinfo=xmalloc(sizeof(t_game_charinfo)); charinfo->charname=xstrdup(charname); charinfo->class=class; charinfo->level=level; list_append_data(game->charlist,charinfo); game->currchar++; game->lastaccess_time=time(NULL); eventlog(eventlog_level_info,__FUNCTION__,"added character %s to game %s (%d total)",charname,game->name,game->currchar); return 0; } extern int game_del_character(t_game * game, char const * charname) { t_game_charinfo * charinfo; t_elem * elem; ASSERT(game,-1); ASSERT(charname,-1); if (!(charinfo=game_find_character(game,charname))) { eventlog(eventlog_level_error,__FUNCTION__,"character %s not found in game %s",charname,game->name); return -1; } if (list_remove_data(game->charlist,charinfo,&elem)) { eventlog(eventlog_level_error,__FUNCTION__,"error remove character %s from game %s",charname,game->name); return -1; } if (charinfo->charname) xfree((void *)charinfo->charname); xfree(charinfo); game->currchar--; game->lastaccess_time=time(NULL); eventlog(eventlog_level_info,__FUNCTION__,"removed character %s from game %s (%d left)",charname,game->name,game->currchar); return 0; } extern int game_set_d2gs_gameid(t_game * game, unsigned int d2gs_gameid) { ASSERT(game,-1); game->d2gs_gameid=d2gs_gameid; return 0; } extern unsigned int game_get_d2gs_gameid(t_game const * game) { ASSERT(game,0); return game->d2gs_gameid; } extern unsigned int d2cs_game_get_id(t_game const * game) { ASSERT(game,0); return game->id; } extern unsigned int game_get_gameflag_ladder(t_game const * game) { ASSERT(game,0); return gameflag_get_ladder(game->gameflag); } extern int game_set_d2gs(t_game * game, t_d2gs * gs) { ASSERT(game,-1); game->d2gs=gs; return 0; } extern t_d2gs * game_get_d2gs(t_game const * game) { ASSERT(game,NULL); return game->d2gs; } extern int game_set_leveldiff(t_game * game, unsigned int leveldiff) { ASSERT(game,-1); game->leveldiff=leveldiff; return 0; } extern int game_set_charlevel(t_game * game, unsigned int charlevel) { ASSERT(game,-1); game->charlevel=charlevel; return 0; } extern unsigned int game_get_charlevel(t_game const * game) { ASSERT(game,0); return game->charlevel; } extern unsigned int game_get_leveldiff(t_game const * game) { ASSERT(game,0); return game->leveldiff; } extern unsigned int game_get_maxlevel(t_game const * game) { int maxlevel; ASSERT(game,0); maxlevel=game->charlevel+game->leveldiff; if (maxlevel>0xff) maxlevel=0xff; return maxlevel; } extern unsigned int game_get_minlevel(t_game const * game) { int minlevel; ASSERT(game,0); minlevel=game->charlevel-game->leveldiff; if (minlevel<0) minlevel=0; return minlevel; } extern unsigned int game_get_gameflag_expansion(t_game const * game) { ASSERT(game,0); return gameflag_get_expansion(game->gameflag); } extern unsigned int game_get_gameflag_hardcore(t_game const * game) { ASSERT(game,0); return gameflag_get_hardcore(game->gameflag); } extern unsigned int game_get_gameflag_difficulty(t_game const * game) { ASSERT(game,0); return gameflag_get_difficulty(game->gameflag); } extern int game_set_gameflag_ladder(t_game * game, unsigned int ladder) { ASSERT(game,-1); gameflag_set_ladder(game->gameflag,ladder); return 0; } extern int game_set_gameflag_expansion(t_game * game, unsigned int expansion) { ASSERT(game,-1); gameflag_set_expansion(game->gameflag,expansion); return 0; } extern int game_set_gameflag_hardcore(t_game * game, unsigned int hardcore) { ASSERT(game,-1); gameflag_set_hardcore(game->gameflag,hardcore); return 0; } extern int game_set_gameflag_difficulty(t_game * game, unsigned int difficulty) { ASSERT(game,-1); gameflag_set_difficulty(game->gameflag,difficulty); return 0; } extern unsigned int game_get_created(t_game const * game) { ASSERT(game,0); return game->created; } extern int game_set_created(t_game * game, unsigned int created) { ASSERT(game,-1); game->created=created; return 0; } extern unsigned int game_get_maxchar(t_game const * game) { ASSERT(game,0); return game->maxchar; } extern int game_set_maxchar(t_game * game, unsigned int maxchar) { ASSERT(game,-1); game->maxchar=maxchar; return 0; } extern unsigned int game_get_currchar(t_game const * game) { ASSERT(game,0); return game->currchar; } extern char const * d2cs_game_get_name(t_game const * game) { ASSERT(game,NULL); return game->name; } extern char const * game_get_desc(t_game const * game) { ASSERT(game,NULL); return game->desc; } extern char const * d2cs_game_get_pass(t_game const * game) { ASSERT(game,NULL); return game->pass; } extern unsigned int game_get_gameflag(t_game const * game) { ASSERT(game,0); return game->gameflag; } extern int d2cs_game_get_create_time(t_game const * game) { ASSERT(game,-1); return game->create_time; } extern int game_set_create_time(t_game * game, int create_time) { ASSERT(game,-1); game->create_time=create_time; return 0; } extern t_list * game_get_charlist(t_game const * game) { ASSERT(game,NULL); return game->charlist; } extern unsigned int gamelist_get_totalgame(void) { return total_game; } pvpgn-1.8.5/src/d2cs/handle_d2gs.c0000644000175000017500000004713711151345317015616 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include /* needed to include netinet/in.h */ #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include /* FIXME: probably not needed... do some systems put types in here or something? */ #endif #include "compat/psock.h" #include "d2gs.h" #include "handle_d2gs.h" #include "serverqueue.h" #include "game.h" #include "connection.h" #include "prefs.h" #include "d2cs_d2gs_protocol.h" #include "common/trans.h" #include "common/addr.h" #include "common/eventlog.h" #include "common/queue.h" #include "common/bn_type.h" #include "common/packet.h" #include "common/xalloc.h" #include "common/setup_after.h" DECLARE_PACKET_HANDLER(on_d2gs_authreply) DECLARE_PACKET_HANDLER(on_d2gs_setgsinfo) DECLARE_PACKET_HANDLER(on_d2gs_echoreply) DECLARE_PACKET_HANDLER(on_d2gs_creategamereply) DECLARE_PACKET_HANDLER(on_d2gs_joingamereply) DECLARE_PACKET_HANDLER(on_d2gs_updategameinfo) DECLARE_PACKET_HANDLER(on_d2gs_closegame) static t_packet_handle_table d2gs_packet_handle_table[]={ /* 0x00 */ { 0, conn_state_none, NULL }, /* 0x01 */ { 0, conn_state_none, NULL }, /* 0x02 */ { 0, conn_state_none, NULL }, /* 0x03 */ { 0, conn_state_none, NULL }, /* 0x04 */ { 0, conn_state_none, NULL }, /* 0x05 */ { 0, conn_state_none, NULL }, /* 0x06 */ { 0, conn_state_none, NULL }, /* 0x07 */ { 0, conn_state_none, NULL }, /* 0x08 */ { 0, conn_state_none, NULL }, /* 0x09 */ { 0, conn_state_none, NULL }, /* 0x0a */ { 0, conn_state_none, NULL }, /* 0x0b */ { 0, conn_state_none, NULL }, /* 0x0c */ { 0, conn_state_none, NULL }, /* 0x0d */ { 0, conn_state_none, NULL }, /* 0x0e */ { 0, conn_state_none, NULL }, /* 0x0f */ { 0, conn_state_none, NULL }, /* 0x10 */ { 0, conn_state_none, NULL }, /* FIXME: shouldn't these three be at 0x10-0x12? (But I'm pretty sure I preserved the padding) */ /* 0x11 */ { sizeof(t_d2gs_d2cs_authreply), conn_state_connected, on_d2gs_authreply }, /* 0x12 */ { sizeof(t_d2gs_d2cs_setgsinfo), conn_state_authed, on_d2gs_setgsinfo }, /* 0x13 */ { sizeof(t_d2gs_d2cs_echoreply), conn_state_any, on_d2gs_echoreply }, /* 0x14 */ { 0, conn_state_none, NULL }, /* 0x15 */ { 0, conn_state_none, NULL }, /* 0x16 */ { 0, conn_state_none, NULL }, /* 0x17 */ { 0, conn_state_none, NULL }, /* 0x18 */ { 0, conn_state_none, NULL }, /* 0x19 */ { 0, conn_state_none, NULL }, /* 0x1a */ { 0, conn_state_none, NULL }, /* 0x1b */ { 0, conn_state_none, NULL }, /* 0x1c */ { 0, conn_state_none, NULL }, /* 0x1d */ { 0, conn_state_none, NULL }, /* 0x1e */ { 0, conn_state_none, NULL }, /* 0x1f */ { 0, conn_state_none, NULL }, /* 0x20 */ { sizeof(t_d2gs_d2cs_creategamereply),conn_state_authed, on_d2gs_creategamereply }, /* 0x21 */ { sizeof(t_d2gs_d2cs_joingamereply), conn_state_authed, on_d2gs_joingamereply }, /* 0x22 */ { sizeof(t_d2gs_d2cs_updategameinfo), conn_state_authed, on_d2gs_updategameinfo }, /* 0x23 */ { sizeof(t_d2gs_d2cs_closegame), conn_state_authed, on_d2gs_closegame }, }; static void d2gs_send_init_info(t_d2gs * gs, t_connection * c) { t_packet * rpacket; if ((rpacket=packet_create(packet_class_d2gs))) { packet_set_size(rpacket,sizeof(t_d2cs_d2gs_setinitinfo)); packet_set_type(rpacket,D2CS_D2GS_SETINITINFO); bn_int_set(&rpacket->u.d2cs_d2gs_setinitinfo.h.seqno,0); bn_int_set(&rpacket->u.d2cs_d2gs_setinitinfo.time, time(NULL)); bn_int_set(&rpacket->u.d2cs_d2gs_setinitinfo.gs_id, d2gs_get_id(gs)); bn_int_set(&rpacket->u.d2cs_d2gs_setinitinfo.ac_version, 0); // packet_append_string(rpacket,prefs_get_d2gs_ac_checksum()); packet_append_string(rpacket,"bogus_ac_checksum"); // packet_append_string(rpacket,prefs_get_d2gs_ac_string()); packet_append_string(rpacket,"bogus_ac_string"); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return; } static void d2gs_send_server_conffile(t_d2gs *gs, t_connection *c) { t_packet *rpacket; FILE *fp; char buff[256]; int rno; struct stat sfile; /* open d2gs server config file */ fp = fopen(prefs_get_d2gsconffile(), "rb"); if (!fp) goto err; /* get file size */ if (fstat(fileno(fp),&sfile)) { eventlog(eventlog_level_debug,__FUNCTION__,"failed fstat()"); goto err_fp; } rpacket = packet_create(packet_class_d2cs); packet_set_size(rpacket,sizeof(t_d2cs_d2gs_setconffile)); packet_set_type(rpacket,D2CS_D2GS_SETCONFFILE); bn_int_set(&rpacket->u.d2cs_d2gs_setconffile.h.seqno,0); bn_int_set(&rpacket->u.d2cs_d2gs_setconffile.size, sfile.st_size); bn_int_set(&rpacket->u.d2cs_d2gs_setconffile.reserved1, time(NULL)); while((rno = fread(buff,1,sizeof(buff),fp)) > 0) { if (packet_append_data(rpacket,buff,rno) < 0) { /* file too big */ eventlog(eventlog_level_debug,__FUNCTION__,"conffile too big for a single packet"); goto err_packet; } } conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); fclose(fp); return; err_packet: packet_del_ref(rpacket); err_fp: fclose(fp); err: return; } static int on_d2gs_authreply(t_connection * c, t_packet * packet) { t_d2gs * gs; t_packet * rpacket; unsigned int reply; unsigned int try_checksum, checksum; unsigned int version, conf_version; unsigned int randnum, signlen; unsigned char *sign; if (!(gs=d2gslist_find_gs(conn_get_d2gs_id(c)))) { eventlog(eventlog_level_error,__FUNCTION__,"game server %d not found",conn_get_d2gs_id(c)); return -1; } version=bn_int_get(packet->u.d2gs_d2cs_authreply.version); try_checksum=bn_int_get(packet->u.d2gs_d2cs_authreply.checksum); checksum=d2gs_calc_checksum(c); conf_version = prefs_get_d2gs_version(); randnum = bn_int_get(packet->u.d2gs_d2cs_authreply.randnum); signlen = bn_int_get(packet->u.d2gs_d2cs_authreply.signlen); sign = packet->u.d2gs_d2cs_authreply.sign; if (conf_version && conf_version != version) { eventlog(eventlog_level_warn,__FUNCTION__,"game server %d version mismatch 0x%X - 0x%X",conn_get_d2gs_id(c), version,conf_version); } if (conf_version && !MAJOR_VERSION_EQUAL(version, conf_version, D2GS_MAJOR_VERSION_MASK)) { eventlog(eventlog_level_error,__FUNCTION__,"game server %d major version mismatch 0x%X - 0x%X",conn_get_d2gs_id(c), version,conf_version); reply=D2CS_D2GS_AUTHREPLY_BAD_VERSION; } else if (prefs_get_d2gs_checksum() && try_checksum != checksum) { eventlog(eventlog_level_error,__FUNCTION__,"game server %d checksum mismach 0x%X - 0x%X",conn_get_d2gs_id(c),try_checksum,checksum); reply=D2CS_D2GS_AUTHREPLY_BAD_CHECKSUM; // } else if (license_verify_reply(c, randnum, sign, signlen)) { // eventlog(eventlog_level_error,__FUNCTION__,"game server %d signal mismach", conn_get_d2gs_id(c)); // reply=D2CS_D2GS_AUTHREPLY_BAD_CHECKSUM; } else { reply=D2CS_D2GS_AUTHREPLY_SUCCEED; } if (reply==D2CS_D2GS_AUTHREPLY_SUCCEED) { eventlog(eventlog_level_info,__FUNCTION__,"game server %s authed",addr_num_to_ip_str(d2cs_conn_get_addr(c))); d2cs_conn_set_state(c,conn_state_authed); d2gs_send_server_conffile(gs, c); d2gs_send_init_info(gs, c); d2gs_active(gs,c); } else { eventlog(eventlog_level_error,__FUNCTION__,"game server %s failed to auth",addr_num_to_ip_str(d2cs_conn_get_addr(c))); /* d2cs_conn_set_state(c,conn_state_destroy); */ } if ((rpacket=packet_create(packet_class_d2gs))) { packet_set_size(rpacket,sizeof(t_d2cs_d2gs_authreply)); packet_set_type(rpacket,D2CS_D2GS_AUTHREPLY); bn_int_set(&rpacket->u.d2cs_d2gs_authreply.h.seqno,0); bn_int_set(&rpacket->u.d2cs_d2gs_authreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } static int on_d2gs_setgsinfo(t_connection * c, t_packet * packet) { t_d2gs * gs; t_packet * rpacket; unsigned int maxgame, prev_maxgame; unsigned int currgame, gameflag; if (!(gs=d2gslist_find_gs(conn_get_d2gs_id(c)))) { eventlog(eventlog_level_error,__FUNCTION__,"game server %d not found",conn_get_d2gs_id(c)); return -1; } maxgame=bn_int_get(packet->u.d2gs_d2cs_setgsinfo.maxgame); gameflag=bn_int_get(packet->u.d2gs_d2cs_setgsinfo.gameflag); prev_maxgame=d2gs_get_maxgame(gs); currgame = d2gs_get_gamenum(gs); eventlog(eventlog_level_info, __FUNCTION__, "change game server %s max game from %d to %d (%d current)",addr_num_to_ip_str(d2cs_conn_get_addr(c)),prev_maxgame, maxgame, currgame); d2gs_set_maxgame(gs,maxgame); if ((rpacket=packet_create(packet_class_d2gs))) { packet_set_size(rpacket,sizeof(t_d2cs_d2gs_setgsinfo)); packet_set_type(rpacket,D2CS_D2GS_SETGSINFO); bn_int_set(&rpacket->u.d2cs_d2gs_setgsinfo.h.seqno,0); bn_int_set(&rpacket->u.d2cs_d2gs_setgsinfo.maxgame,maxgame); bn_int_set(&rpacket->u.d2cs_d2gs_setgsinfo.gameflag,gameflag); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } gqlist_check_creategame(maxgame - currgame); return 0; } static int on_d2gs_echoreply(t_connection * c, t_packet * packet) { if (!c || !packet) return 0; return 0; } static int on_d2gs_creategamereply(t_connection * c, t_packet * packet) { t_packet * opacket, * rpacket; t_sq * sq; t_connection * client; t_game * game; int result; int reply; int seqno; t_elem * curr; seqno=bn_int_get(packet->u.d2cs_d2gs.h.seqno); if (!(sq=sqlist_find_sq(seqno))) { eventlog(eventlog_level_error,__FUNCTION__,"seqno %d not found",seqno); return 0; } if (!(client=d2cs_connlist_find_connection_by_sessionnum(sq_get_clientid(sq)))) { eventlog(eventlog_level_error,__FUNCTION__,"client %d not found",sq_get_clientid(sq)); sq_destroy(sq,&curr); return 0; } if (!(game=gamelist_find_game_by_id(sq_get_gameid(sq)))) { eventlog(eventlog_level_error,__FUNCTION__,"game %d not found",sq_get_gameid(sq)); sq_destroy(sq,&curr); return 0; } if (!(opacket=sq_get_packet(sq))) { eventlog(eventlog_level_error,__FUNCTION__,"previous packet not found (seqno: %d)",seqno); sq_destroy(sq,&curr); return 0; } result=bn_int_get(packet->u.d2gs_d2cs_creategamereply.result); if (result==D2GS_D2CS_CREATEGAME_SUCCEED) { game_set_d2gs_gameid(game,bn_int_get(packet->u.d2gs_d2cs_creategamereply.gameid)); game_set_created(game,1); eventlog(eventlog_level_info,__FUNCTION__,"game %s created on gs %d",d2cs_game_get_name(game),conn_get_d2gs_id(c)); reply=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED; } else { eventlog(eventlog_level_warn,__FUNCTION__,"failed to create game %s on gs %d",d2cs_game_get_name(game),conn_get_d2gs_id(c)); game_destroy(game,&curr); reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED; } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_creategamereply)); packet_set_type(rpacket,D2CS_CLIENT_CREATEGAMEREPLY); bn_short_set(&rpacket->u.d2cs_client_creategamereply.seqno, bn_short_get(opacket->u.client_d2cs_creategamereq.seqno)); bn_short_set(&rpacket->u.d2cs_client_creategamereply.gameid,1); bn_short_set(&rpacket->u.d2cs_client_creategamereply.u1,1); bn_int_set(&rpacket->u.d2cs_client_creategamereply.reply,reply); conn_push_outqueue(client,rpacket); packet_del_ref(rpacket); } sq_destroy(sq,&curr); return 0; } static int on_d2gs_joingamereply(t_connection * c, t_packet * packet) { t_sq * sq; t_d2gs * gs; t_connection * client; t_game * game; t_packet * opacket, * rpacket; int result; int reply; int seqno; unsigned int gsaddr; t_elem * curr; unsigned short gsport; seqno=bn_int_get(packet->u.d2cs_d2gs.h.seqno); if (!(sq=sqlist_find_sq(seqno))) { eventlog(eventlog_level_error,__FUNCTION__,"seqno %d not found",seqno); return 0; } if (!(client=d2cs_connlist_find_connection_by_sessionnum(sq_get_clientid(sq)))) { eventlog(eventlog_level_error,__FUNCTION__,"client %d not found",sq_get_clientid(sq)); sq_destroy(sq,&curr); return 0; } if (!(game=gamelist_find_game_by_id(sq_get_gameid(sq)))) { eventlog(eventlog_level_error,__FUNCTION__,"game %d not found",sq_get_gameid(sq)); sq_destroy(sq,&curr); return 0; } if (!(gs=game_get_d2gs(game))) { eventlog(eventlog_level_error,__FUNCTION__,"try join game without game server set"); sq_destroy(sq,&curr); return 0; } if (!(opacket=sq_get_packet(sq))) { eventlog(eventlog_level_error,__FUNCTION__,"previous packet not found (seqno: %d)",seqno); sq_destroy(sq,&curr); return 0; } result=bn_int_get(packet->u.d2gs_d2cs_joingamereply.result); switch (result) { case D2GS_D2CS_JOINGAME_SUCCEED: eventlog(eventlog_level_info,__FUNCTION__,"added %s to game %s on gs %d",d2cs_conn_get_charname(client), d2cs_game_get_name(game),conn_get_d2gs_id(c)); reply=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED; break; case D2GS_D2CS_JOINGAME_GAME_FULL: eventlog(eventlog_level_info,__FUNCTION__,"failed to add %s to game %s on gs %d (game full)",d2cs_conn_get_charname(client), d2cs_game_get_name(game),conn_get_d2gs_id(c)); reply=D2CS_CLIENT_JOINGAMEREPLY_GAME_FULL; break; default: eventlog(eventlog_level_info,__FUNCTION__,"failed to add %s to game %s on gs %d",d2cs_conn_get_charname(client), d2cs_game_get_name(game),conn_get_d2gs_id(c)); reply=D2CS_CLIENT_JOINGAMEREPLY_FAILED; } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_joingamereply)); packet_set_type(rpacket,D2CS_CLIENT_JOINGAMEREPLY); bn_short_set(&rpacket->u.d2cs_client_joingamereply.seqno, bn_short_get(opacket->u.client_d2cs_joingamereq.seqno)); /* specific flag for anti-cheating support */ /* bn_short_set(&rpacket->u.d2cs_client_joingamereply.gameid,(unsigned short)game_get_d2gs_gameid(game)|0x8000); */ bn_short_set(&rpacket->u.d2cs_client_joingamereply.gameid,(unsigned short)game_get_d2gs_gameid(game)); bn_short_set(&rpacket->u.d2cs_client_joingamereply.u1,0); bn_int_set(&rpacket->u.d2cs_client_joingamereply.reply,reply); // if (reply == SERVER_JOINGAMEREPLY2_REPLY_OK) { if (reply == D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) { bn_int_set(&rpacket->u.d2cs_client_joingamereply.token,sq_get_gametoken(sq)); gsaddr = d2gs_get_ip(gs); gsport = 4000; trans_net(d2cs_conn_get_addr(client), &gsaddr, &gsport); if(d2gs_get_ip(gs)!=gsaddr) { eventlog(eventlog_level_info,__FUNCTION__,"translated gameserver %s -> %s",addr_num_to_ip_str(d2gs_get_ip(gs)),addr_num_to_ip_str(gsaddr)); } else { eventlog(eventlog_level_info,__FUNCTION__,"no translation required for gamserver %s",addr_num_to_ip_str(gsaddr)); } bn_int_nset(&rpacket->u.d2cs_client_joingamereply.addr,gsaddr); } else { bn_int_set(&rpacket->u.d2cs_client_joingamereply.token,0); bn_int_set(&rpacket->u.d2cs_client_joingamereply.addr,0); } conn_push_outqueue(client,rpacket); packet_del_ref(rpacket); } sq_destroy(sq,&curr); return 0; } static int on_d2gs_updategameinfo(t_connection * c, t_packet * packet) { unsigned int flag; char const * charname; t_game * game; unsigned int charclass; unsigned int charlevel; unsigned int d2gs_gameid; unsigned int d2gs_id; if (!(charname=packet_get_str_const(packet,sizeof(t_d2gs_d2cs_updategameinfo),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad charname"); return 0; } d2gs_id=conn_get_d2gs_id(c); d2gs_gameid=bn_int_get(packet->u.d2gs_d2cs_updategameinfo.gameid); charclass=bn_int_get(packet->u.d2gs_d2cs_updategameinfo.charclass); charlevel=bn_int_get(packet->u.d2gs_d2cs_updategameinfo.charlevel); flag=bn_int_get(packet->u.d2gs_d2cs_updategameinfo.flag); if (!(game=gamelist_find_game_by_d2gs_and_id(d2gs_id,d2gs_gameid))) { eventlog(eventlog_level_error,__FUNCTION__,"game %d not found on gs %d",d2gs_gameid,d2gs_id); return -1; } if (flag==D2GS_D2CS_UPDATEGAMEINFO_FLAG_ENTER) { game_add_character(game,charname,charclass,charlevel); } else if (flag==D2GS_D2CS_UPDATEGAMEINFO_FLAG_LEAVE) { game_del_character(game,charname); } else if (flag==D2GS_D2CS_UPDATEGAMEINFO_FLAG_UPDATE) { game_add_character(game,charname,charclass,charlevel); } else { eventlog(eventlog_level_error,__FUNCTION__,"got bad updategameinfo flag %d",flag); } return 0; } static int on_d2gs_closegame(t_connection * c, t_packet * packet) { t_game * game; t_elem * curr; if (!(game=gamelist_find_game_by_d2gs_and_id(conn_get_d2gs_id(c), bn_int_get(packet->u.d2gs_d2cs_closegame.gameid)))) { return 0; } game_destroy(game, &curr); return 0; } extern int handle_d2gs_packet(t_connection * c, t_packet * packet) { conn_process_packet(c,packet,d2gs_packet_handle_table,NELEMS(d2gs_packet_handle_table)); return 0; } extern int handle_d2gs_init(t_connection * c) { t_packet * packet; if ((packet=packet_create(packet_class_d2gs))) { packet_set_size(packet,sizeof(t_d2cs_d2gs_authreq)); packet_set_type(packet,D2CS_D2GS_AUTHREQ); bn_int_set(&packet->u.d2cs_d2gs_authreq.h.seqno,0); bn_int_set(&packet->u.d2cs_d2gs_authreq.sessionnum,d2cs_conn_get_sessionnum(c)); bn_int_set(&packet->u.d2cs_d2gs_authreq.signlen, 0); packet_append_string(packet,prefs_get_realmname()); // packet_append_data(packet, sign, signlen); conn_push_outqueue(c,packet); packet_del_ref(packet); } eventlog(eventlog_level_info,__FUNCTION__,"sent init packet to d2gs %d (sessionnum=%d)",conn_get_d2gs_id(c),d2cs_conn_get_sessionnum(c)); return 0; } pvpgn-1.8.5/src/d2cs/d2gs.c0000644000175000017500000002632211151345317014274 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strsep.h" #include "compat/char_bit.h" #ifdef HAVE_SYS_TYPES_H # include /* needed to include netinet/in.h */ #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include /* FIXME: probably not needed... do some systems put types in here or something? */ #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/psock.h" #include "d2gs.h" #include "game.h" #include "net.h" #include "bit.h" #include "prefs.h" #include "connection.h" #include "common/introtate.h" #include "common/addr.h" #include "common/list.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" static t_list * d2gslist_head=NULL; static unsigned int d2gs_id=0; static unsigned int total_d2gs=0; extern t_list * d2gslist(void) { return d2gslist_head; } extern int d2gslist_create(void) { d2gslist_head=list_create(); return d2gslist_reload(prefs_get_d2gs_list()); } extern int d2gslist_reload(char const * gslist) { t_addrlist * gsaddrs; t_d2gs * gs; if (!d2gslist_head) return -1; BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs) { BIT_CLR_FLAG(gs->flag, D2GS_FLAG_VALID); } END_LIST_TRAVERSE_DATA() gsaddrs = addrlist_create(gslist, INADDR_ANY, 0); if (gsaddrs) { t_elem const *acurr; t_addr * curr_laddr; LIST_TRAVERSE_CONST(gsaddrs, acurr) { curr_laddr = (t_addr*)elem_get_data(acurr); if (!curr_laddr) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL value in gslist"); continue; } if (!(gs=d2gslist_find_gs_by_ip(addr_get_ip(curr_laddr)))) gs = d2gs_create(addr_num_to_ip_str(addr_get_ip(curr_laddr))); if (gs) BIT_SET_FLAG(gs->flag, D2GS_FLAG_VALID); } addrlist_destroy(gsaddrs); } BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs) { if (!BIT_TST_FLAG(gs->flag, D2GS_FLAG_VALID)) { d2gs_destroy(gs,&curr_elem_); } } END_LIST_TRAVERSE_DATA() return 0; } extern int d2gslist_destroy(void) { t_d2gs * gs; BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs) { d2gs_destroy(gs,(t_elem **)&curr_elem_); } END_LIST_TRAVERSE_DATA_CONST() d2cs_connlist_reap(); if (list_destroy(d2gslist_head)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error destroy d2gs list"); return -1; } d2gslist_head=NULL; return 0; } extern t_d2gs * d2gslist_find_gs_by_ip(unsigned int ip) { t_d2gs * gs; BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs) { if (gs->ip==ip) return gs; } END_LIST_TRAVERSE_DATA_CONST() return NULL; } extern t_d2gs * d2gslist_find_gs(unsigned int id) { t_d2gs * gs; BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs) { if (gs->id==id) return gs; } END_LIST_TRAVERSE_DATA_CONST() return NULL; } extern t_d2gs * d2gs_create(char const * ipaddr) { t_d2gs * gs; unsigned int ip; ASSERT(ipaddr,NULL); if ((ip=net_inet_addr(ipaddr))==~0U) { eventlog(eventlog_level_error,__FUNCTION__,"got bad ip address %s",ipaddr); return NULL; } if (d2gslist_find_gs_by_ip(ntohl(ip))) { eventlog(eventlog_level_error,__FUNCTION__,"game server %s already in list",ipaddr); return NULL; } gs=xmalloc(sizeof(t_d2gs)); gs->ip=ntohl(ip); gs->id=++d2gs_id; gs->active=0; gs->token=0; gs->state=d2gs_state_none; gs->gamenum=0; gs->maxgame=0; gs->connection=NULL; if (list_append_data(d2gslist_head,gs)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error add gs to list"); xfree(gs); return NULL; } eventlog(eventlog_level_info,__FUNCTION__,"added game server %s (id: %d) to list",ipaddr,gs->id); return gs; } extern int d2gs_destroy(t_d2gs * gs, t_elem ** curr) { ASSERT(gs,-1); if (list_remove_data(d2gslist_head,gs,curr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error remove gs from list"); return -1; } if (gs->active && gs->connection) { d2cs_conn_set_state(gs->connection, conn_state_destroy); d2gs_deactive(gs, gs->connection); } eventlog(eventlog_level_info,__FUNCTION__,"removed game server %s (id: %d) from list",addr_num_to_ip_str(gs->ip),gs->id); xfree(gs); return 0; } extern t_d2gs * d2gslist_get_server_by_id(unsigned int id) { t_d2gs * gs; BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs) { if (gs->id==id) return gs; } END_LIST_TRAVERSE_DATA_CONST() return NULL; } extern t_d2gs * d2gslist_choose_server(void) { t_d2gs * gs; t_d2gs * ogs; unsigned int percent; unsigned int min_percent=100; ogs=NULL; BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs) { if (!gs->active) continue; if (!gs->connection) continue; if (gs->state!=d2gs_state_authed) continue; if (!gs->maxgame) continue; if (gs->gamenum>=gs->maxgame) continue; percent=100*gs->gamenum/gs->maxgame; if (percentstate=state; return 0; } extern t_d2gs_state d2gs_get_state(t_d2gs const * gs) { ASSERT(gs,d2gs_state_none); return gs->state; } extern int d2gs_add_gamenum(t_d2gs * gs, int number) { ASSERT(gs,-1); gs->gamenum += number; return 0; } extern unsigned int d2gs_get_gamenum(t_d2gs const * gs) { ASSERT(gs,0); return gs->gamenum; } extern int d2gs_set_maxgame(t_d2gs * gs,unsigned int maxgame) { ASSERT(gs,-1); gs->maxgame=maxgame; return 0; } extern unsigned int d2gs_get_maxgame(t_d2gs const * gs) { ASSERT(gs,0); return gs->maxgame; } extern unsigned int d2gs_get_id(t_d2gs const * gs) { ASSERT(gs,0); return gs->id; } extern unsigned int d2gs_get_ip(t_d2gs const * gs) { ASSERT(gs,0); return gs->ip; } extern unsigned int d2gs_get_token(t_d2gs const * gs) { return gs->token; } extern unsigned int d2gs_make_token(t_d2gs * gs) { return ((unsigned int)rand())^((++(gs->token))+((unsigned int)time(NULL))); } extern t_connection * d2gs_get_connection(t_d2gs const * gs) { ASSERT(gs,NULL); return gs->connection; } extern int d2gs_active(t_d2gs * gs, t_connection * c) { ASSERT(gs,-1); ASSERT(c,-1); if (gs->active && gs->connection) { eventlog(eventlog_level_warn,__FUNCTION__,"game server %d is already actived, deactive previous connection first",gs->id); d2gs_deactive(gs, gs->connection); } total_d2gs++; eventlog(eventlog_level_info,__FUNCTION__,"game server %s (id: %d) actived (%d total)",addr_num_to_addr_str(d2cs_conn_get_addr(c), d2cs_conn_get_port(c)),gs->id,total_d2gs); gs->state=d2gs_state_authed; gs->connection=c; gs->active=1; gs->gamenum=0; gs->maxgame=0; return 0; } extern int d2gs_deactive(t_d2gs * gs, t_connection * c) { t_game * game; ASSERT(gs,-1); if (!gs->active || !gs->connection) { eventlog(eventlog_level_warn,__FUNCTION__,"game server %d is not actived yet", gs->id); return -1; } if (gs->connection != c) { eventlog(eventlog_level_debug,__FUNCTION__,"game server %d connection mismatch,ignore it", gs->id); return 0; } total_d2gs--; eventlog(eventlog_level_info,__FUNCTION__,"game server %s (id: %d) deactived (%d left)",addr_num_to_addr_str(d2cs_conn_get_addr(gs->connection),d2cs_conn_get_port(gs->connection)),gs->id,total_d2gs); gs->state=d2gs_state_none; gs->connection=NULL; gs->active=0; gs->maxgame=0; eventlog(eventlog_level_info,__FUNCTION__,"destroying all games on game server %d",gs->id); BEGIN_LIST_TRAVERSE_DATA(d2cs_gamelist(),game) { if (game_get_d2gs(game)==gs) game_destroy(game,&curr_elem_); } END_LIST_TRAVERSE_DATA() if (gs->gamenum!=0) { eventlog(eventlog_level_error,__FUNCTION__,"game server %d deactived but still with games left",gs->id); } gs->gamenum=0; return 0; } extern unsigned int d2gs_calc_checksum(t_connection * c) { unsigned int sessionnum, checksum, port, addr; unsigned int i, len, ch; char const * realmname; char const * password; ASSERT(c,0); sessionnum=d2cs_conn_get_sessionnum(c); checksum=prefs_get_d2gs_checksum(); port=d2cs_conn_get_port(c); addr=d2cs_conn_get_addr(c); realmname=prefs_get_realmname(); password=prefs_get_d2gs_password(); len=strlen(realmname); for (i=0; iu.d2cs_d2gs.h.seqno,0); BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs) { if (gs->active && gs->connection) { conn_push_outqueue(gs->connection,packet); } } END_LIST_TRAVERSE_DATA() packet_del_ref(packet); return 0; } extern int d2gs_restart_all_gs(void) { t_packet * packet; t_d2gs * gs; if (!(packet=packet_create(packet_class_d2gs))) { eventlog(eventlog_level_error, __FUNCTION__, "error creating packet"); return -1; } packet_set_size(packet,sizeof(t_d2cs_d2gs_control)); packet_set_type(packet,D2CS_D2GS_CONTROL); /* FIXME: sequence number not set */ bn_int_set(&packet->u.d2cs_d2gs.h.seqno,0); bn_int_set(&packet->u.d2cs_d2gs_control.cmd, D2CS_D2GS_CONTROL_CMD_RESTART); bn_int_set(&packet->u.d2cs_d2gs_control.value, prefs_get_d2gs_restart_delay()); BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs) { if (gs->connection) { conn_push_outqueue(gs->connection,packet); } } END_LIST_TRAVERSE_DATA() packet_del_ref(packet); return 0; } pvpgn-1.8.5/src/d2cs/serverqueue.h0000644000175000017500000000327711151345317016021 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SERVERQUEUE_H #define INCLUDED_SERVERQUEUE_H #include "common/list.h" #include "common/packet.h" typedef struct serverqueue { unsigned int seqno; unsigned int ctime; unsigned int clientid; t_packet * packet; unsigned int gameid; unsigned int gametoken; } t_sq; extern t_list * sqlist(void); extern int sqlist_create(void); extern int sqlist_destroy(void); extern int sq_destroy(t_sq * sq,t_elem ** curr); extern int sqlist_check_timeout(void); extern t_sq * sqlist_find_sq(unsigned int seqno); extern t_sq * sq_create(unsigned int clientid, t_packet * packet,unsigned int gameid); extern unsigned int sq_get_clientid(t_sq const * sq); extern unsigned int sq_get_gameid(t_sq const * sq); extern unsigned int sq_get_seqno(t_sq const * sq); extern int sq_set_gametoken(t_sq * sq, unsigned int gametoken); extern unsigned int sq_get_gametoken(t_sq const * sq); extern t_packet * sq_get_packet(t_sq const * sq); #endif pvpgn-1.8.5/src/d2cs/d2cs_d2dbs_ladder.h0000644000175000017500000000276011151345317016666 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2CS_D2DBS_LADDER_H #define INCLUDED_D2CS_D2DBS_LADDER_H #include "common/bn_type.h" typedef struct { bn_int type; bn_int offset; bn_int number; } t_d2ladderfile_ladderindex; typedef struct { bn_int experience; bn_short status; bn_byte level; bn_byte class; char charname[MAX_CHARNAME_LEN]; } t_d2ladderfile_ladderinfo; typedef struct { bn_int maxtype; bn_int checksum; } t_d2ladderfile_header; #define LADDER_FILE_PREFIX "ladder" #define D2LADDER_HC_OVERALL 0x00 #define D2LADDER_STD_OVERALL 0x09 #define D2LADDER_EXP_HC_OVERALL 0x13 #define D2LADDER_EXP_STD_OVERALL 0x1B #define D2CHAR_CLASS_MAX 0x04 #define D2CHAR_EXP_CLASS_MAX 0x06 #endif pvpgn-1.8.5/src/d2cs/handle_bnetd.c0000644000175000017500000002617111151345317016046 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "connection.h" #include "handle_bnetd.h" #include "serverqueue.h" #include "d2cs_bnetd_protocol.h" #include "d2cs_protocol.h" #include "version.h" #include "prefs.h" #include "game.h" #include "common/init_protocol.h" #include "common/packet.h" #include "common/eventlog.h" #include "common/setup_after.h" DECLARE_PACKET_HANDLER(on_bnetd_accountloginreply) DECLARE_PACKET_HANDLER(on_bnetd_charloginreply) DECLARE_PACKET_HANDLER(on_bnetd_authreq) DECLARE_PACKET_HANDLER(on_bnetd_authreply) DECLARE_PACKET_HANDLER(on_bnetd_gameinforeq) static t_packet_handle_table bnetd_packet_handle_table[]={ /* 0x00 */ { 0, conn_state_none, NULL }, /* 0x01 */ { sizeof(t_bnetd_d2cs_authreq), conn_state_connected, on_bnetd_authreq }, /* 0x02 */ { sizeof(t_bnetd_d2cs_authreply), conn_state_connected, on_bnetd_authreply }, /* 0x03 */ { 0, conn_state_none, NULL }, /* 0x04 */ { 0, conn_state_none, NULL }, /* 0x05 */ { 0, conn_state_none, NULL }, /* 0x06 */ { 0, conn_state_none, NULL }, /* 0x07 */ { 0, conn_state_none, NULL }, /* 0x08 */ { 0, conn_state_none, NULL }, /* 0x09 */ { 0, conn_state_none, NULL }, /* 0x0a */ { 0, conn_state_none, NULL }, /* 0x0b */ { 0, conn_state_none, NULL }, /* 0x0c */ { 0, conn_state_none, NULL }, /* 0x0d */ { 0, conn_state_none, NULL }, /* 0x03 */ { 0, conn_state_none, NULL }, /* 0x0f */ { 0, conn_state_none, NULL }, /* 0x10 */ { sizeof(t_bnetd_d2cs_accountloginreply), conn_state_authed, on_bnetd_accountloginreply }, /* 0x11 */ { sizeof(t_bnetd_d2cs_charloginreply), conn_state_authed, on_bnetd_charloginreply }, /* 0x12 */ { sizeof(t_bnetd_d2cs_gameinforeq), conn_state_authed, on_bnetd_gameinforeq } }; extern int handle_bnetd_packet(t_connection * c, t_packet * packet) { conn_process_packet(c,packet,bnetd_packet_handle_table,NELEMS(bnetd_packet_handle_table)); return 0; } extern int handle_bnetd_init(t_connection * c) { t_packet * packet; packet=packet_create(packet_class_init); packet_set_size(packet,sizeof(t_client_initconn)); bn_byte_set(&packet->u.client_initconn.class, CLIENT_INITCONN_CLASS_D2CS_BNETD); conn_push_outqueue(c,packet); packet_del_ref(packet); d2cs_conn_set_state(c,conn_state_connected); eventlog(eventlog_level_info,__FUNCTION__,"sent init class packet to bnetd"); return 0; } static int on_bnetd_authreq(t_connection * c, t_packet * packet) { t_packet * rpacket; unsigned int sessionnum; sessionnum=bn_int_get(packet->u.bnetd_d2cs_authreq.sessionnum); eventlog(eventlog_level_info,__FUNCTION__,"received bnetd sessionnum %d",sessionnum); if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket,sizeof(t_d2cs_bnetd_authreply)); packet_set_type(rpacket,D2CS_BNETD_AUTHREPLY); bn_int_set(&rpacket->u.d2cs_bnetd_authreply.h.seqno,1); bn_int_set(&rpacket->u.d2cs_bnetd_authreply.version,D2CS_VERSION_NUMBER); packet_append_string(rpacket,prefs_get_realmname()); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } static int on_bnetd_authreply(t_connection * c, t_packet * packet) { unsigned int reply; reply=bn_int_get(packet->u.bnetd_d2cs_authreply.reply); if (reply == BNETD_D2CS_AUTHREPLY_SUCCEED) { eventlog(eventlog_level_info,__FUNCTION__,"authed by bnetd"); d2cs_conn_set_state(c,conn_state_authed); } else { eventlog(eventlog_level_error,__FUNCTION__,"failed to auth by bnetd (error=%d)",reply); d2cs_conn_set_state(c,conn_state_destroy); } return 0; } static int on_bnetd_accountloginreply(t_connection * c, t_packet * packet) { unsigned int seqno; t_sq * sq; t_packet * opacket, * rpacket; t_connection * client; int result, reply; char const * account; t_elem * elem; if (!packet || !c) return -1; seqno=bn_int_get(packet->u.d2cs_bnetd.h.seqno); if (!(sq=sqlist_find_sq(seqno))) { eventlog(eventlog_level_error,__FUNCTION__,"seqno %d not found",seqno); return -1; } if (!(client=d2cs_connlist_find_connection_by_sessionnum(sq_get_clientid(sq)))) { eventlog(eventlog_level_error,__FUNCTION__,"client %d not found",sq_get_clientid(sq)); sq_destroy(sq,&elem); return -1; } if (!(opacket=sq_get_packet(sq))) { eventlog(eventlog_level_error,__FUNCTION__,"previous packet missing (seqno: %d)",seqno); sq_destroy(sq,&elem); return -1; } result=bn_int_get(packet->u.bnetd_d2cs_accountloginreply.reply); if (result==BNETD_D2CS_CHARLOGINREPLY_SUCCEED) { reply=D2CS_CLIENT_LOGINREPLY_SUCCEED; account=packet_get_str_const(opacket,sizeof(t_client_d2cs_loginreq),MAX_CHARNAME_LEN); d2cs_conn_set_account(client,account); d2cs_conn_set_state(client,conn_state_authed); eventlog(eventlog_level_info,__FUNCTION__,"account %s authed",account); } else { eventlog(eventlog_level_warn,__FUNCTION__,"client %d login request was rejected by bnetd",sq_get_clientid(sq)); reply=D2CS_CLIENT_LOGINREPLY_BADPASS; } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_loginreply)); packet_set_type(rpacket,D2CS_CLIENT_LOGINREPLY); bn_int_set(&rpacket->u.d2cs_client_loginreply.reply,reply); conn_push_outqueue(client,rpacket); packet_del_ref(rpacket); } sq_destroy(sq,&elem); return 0; } static int on_bnetd_charloginreply(t_connection * c, t_packet * packet) { unsigned int seqno; t_sq * sq; t_connection * client; t_packet * opacket, * rpacket; int result, reply, type; char const * charname; t_elem * elem; if (!packet || !c) return -1; seqno=bn_int_get(packet->u.d2cs_bnetd.h.seqno); if (!(sq=sqlist_find_sq(seqno))) { eventlog(eventlog_level_error,__FUNCTION__,"seqno %d not found",seqno); return -1; } if (!(client=d2cs_connlist_find_connection_by_sessionnum(sq_get_clientid(sq)))) { eventlog(eventlog_level_error,__FUNCTION__,"client %d not found",sq_get_clientid(sq)); sq_destroy(sq,&elem); return -1; } if (!(opacket=sq_get_packet(sq))) { eventlog(eventlog_level_error,__FUNCTION__,"previous packet missing (seqno: %d)",seqno); sq_destroy(sq,&elem); return -1; } type=packet_get_type(opacket); result=bn_int_get(packet->u.bnetd_d2cs_charloginreply.reply); if (type==CLIENT_D2CS_CREATECHARREQ) { charname=packet_get_str_const(opacket,sizeof(t_client_d2cs_createcharreq),MAX_CHARNAME_LEN); if (result==BNETD_D2CS_CHARLOGINREPLY_SUCCEED) { if (conn_check_multilogin(client,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname); reply = D2CS_CLIENT_CHARLOGINREPLY_FAILED; } else { reply= D2CS_CLIENT_CREATECHARREPLY_SUCCEED; eventlog(eventlog_level_info,__FUNCTION__,"character %s authed",charname); d2cs_conn_set_charname(client,charname); d2cs_conn_set_state(client,conn_state_char_authed); } } else { reply = D2CS_CLIENT_CREATECHARREPLY_FAILED; eventlog(eventlog_level_error,__FUNCTION__,"failed to auth character %s",charname); } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_createcharreply)); packet_set_type(rpacket,D2CS_CLIENT_CREATECHARREPLY); bn_int_set(&rpacket->u.d2cs_client_createcharreply.reply,reply); conn_push_outqueue(client,rpacket); packet_del_ref(rpacket); } } else if (type==CLIENT_D2CS_CHARLOGINREQ) { charname=packet_get_str_const(opacket,sizeof(t_client_d2cs_charloginreq),MAX_CHARNAME_LEN); if (result==BNETD_D2CS_CHARLOGINREPLY_SUCCEED) { if (conn_check_multilogin(client,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname); reply = D2CS_CLIENT_CHARLOGINREPLY_FAILED; } else { reply = D2CS_CLIENT_CHARLOGINREPLY_SUCCEED; eventlog(eventlog_level_info,__FUNCTION__,"character %s authed",charname); d2cs_conn_set_charname(client,charname); d2cs_conn_set_state(client,conn_state_char_authed); } } else { reply = D2CS_CLIENT_CHARLOGINREPLY_FAILED; eventlog(eventlog_level_error,__FUNCTION__,"failed to auth character %s",charname); } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_charloginreply)); packet_set_type(rpacket,D2CS_CLIENT_CHARLOGINREPLY); bn_int_set(&rpacket->u.d2cs_client_charloginreply.reply,reply); conn_push_outqueue(client,rpacket); packet_del_ref(rpacket); } } else { eventlog(eventlog_level_error,__FUNCTION__,"got bad packet type %d",type); sq_destroy(sq,&elem); return -1; } sq_destroy(sq,&elem); return 0; } int on_bnetd_gameinforeq(t_connection * c, t_packet * packet) { t_packet * rpacket; t_game * game; char const * gamename; if (!(c)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!(gamename = packet_get_str_const(packet,sizeof(t_bnetd_d2cs_gameinforeq),GAME_NAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"missing or too long gamename"); return -1; } if (!(game = d2cs_gamelist_find_game(gamename))) { eventlog(eventlog_level_error,__FUNCTION__,"request for unknown game \"%s\"",gamename); return -1; } if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket, sizeof(t_d2cs_bnetd_gameinforeply)); packet_set_type(rpacket, D2CS_BNETD_GAMEINFOREPLY); bn_int_set(&rpacket->u.d2cs_bnetd_gameinforeply.h.seqno,0); packet_append_string(rpacket, gamename); bn_byte_set(&rpacket->u.d2cs_bnetd_gameinforeply.difficulty, game_get_gameflag_difficulty(game)); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } pvpgn-1.8.5/src/d2cs/connection.h0000644000175000017500000001301511151345317015574 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_CONNECTION_H #define INCLUDED_CONNECTION_H #include "common/queue.h" #include "common/hashtable.h" #include "common/packet.h" #include "common/fdwatch.h" #include "d2charfile.h" #include "gamequeue.h" typedef enum { conn_state_none = 0x00, conn_state_init = 0x01, conn_state_connecting = 0x02, conn_state_connected = 0x04, conn_state_authed = 0x08, conn_state_char_authed = 0x10, conn_state_destroy = 0x20, conn_state_destroying = 0x40, conn_state_any = 0xff } t_conn_state; typedef enum { conn_class_none, conn_class_init, conn_class_d2cs, conn_class_d2gs, conn_class_bnetd } t_conn_class; typedef struct { char const * charname; char const * account; int sock; int fdw_idx; unsigned int socket_flag; unsigned int addr; unsigned int local_addr; unsigned short port; unsigned short local_port; unsigned int last_active; t_conn_class class; t_conn_state state; unsigned int sessionnum; t_queue * outqueue; unsigned int outsize; unsigned int outsizep; t_packet * inqueue; unsigned int insize; t_d2charinfo_summary const * charinfo; unsigned int d2gs_id; t_gq * gamequeue; unsigned int bnetd_sessionnum; unsigned int sessionnum_hash; unsigned int charname_hash; } t_connection; typedef int ( * packet_handle_func) (t_connection * c, t_packet * packet); typedef struct { unsigned int size; t_conn_state state; packet_handle_func handler; } t_packet_handle_table; #define SOCKET_FLAG_READ 0x1 #define SOCKET_FLAG_WRITE 0x2 extern t_hashtable * d2cs_connlist(void); extern int d2cs_connlist_destroy(void); extern int d2cs_connlist_reap(void); extern int d2cs_connlist_create(void); extern int conn_check_multilogin(t_connection const * c,char const * charname); extern t_connection * d2cs_connlist_find_connection_by_sessionnum(unsigned int sessionnum); extern t_connection * d2cs_connlist_find_connection_by_charname(char const * charname); extern int conn_handle_socket(t_connection * c); extern t_connection * d2cs_conn_create(int sock, unsigned int local_addr, unsigned short local_port, unsigned int addr, unsigned short port); extern int d2cs_conn_destroy(t_connection * c, t_elem ** elem); extern int d2cs_conn_get_socket(t_connection const * c); extern unsigned int d2cs_conn_get_sessionnum(t_connection const * c); extern t_conn_class d2cs_conn_get_class(t_connection const * c); extern int d2cs_conn_set_class(t_connection * c, t_conn_class class); extern t_conn_state d2cs_conn_get_state(t_connection const * c); extern int d2cs_conn_set_state(t_connection * c, t_conn_state state); extern t_queue * * d2cs_conn_get_out_queue(t_connection const * c); extern t_packet * d2cs_conn_get_in_queue(t_connection const * c); extern void d2cs_conn_set_in_queue(t_connection * c, t_packet * packet); extern unsigned int d2cs_conn_get_in_size(t_connection const * c); extern unsigned int d2cs_conn_get_out_size(t_connection const * c); extern int conn_push_outqueue(t_connection * c, t_packet * packet); extern t_packet * conn_peek_outqueue(t_connection * c); extern t_packet * conn_pull_outqueue(t_connection * c); extern int conn_add_socket_flag(t_connection * c, unsigned int flag); extern int conn_process_packet(t_connection * c, t_packet * packet, t_packet_handle_table * table, unsigned int table_size); extern int d2cs_conn_set_account(t_connection * c, char const * account); extern int d2cs_conn_set_charname(t_connection * c, char const * charname); extern char const * d2cs_conn_get_account(t_connection const * c); extern char const * d2cs_conn_get_charname(t_connection const * c); extern int conn_set_charinfo(t_connection * c, t_d2charinfo_summary const * charinfo); extern unsigned int conn_get_charinfo_ladder(t_connection const * c); extern unsigned int conn_get_charinfo_expansion(t_connection const * c); extern unsigned int conn_get_charinfo_hardcore(t_connection const * c); extern unsigned int conn_get_charinfo_dead(t_connection const * c); extern unsigned int conn_get_charinfo_difficulty(t_connection const * c); extern unsigned int conn_get_charinfo_level(t_connection const * c); extern unsigned int conn_get_charinfo_class(t_connection const * c); extern unsigned int conn_get_d2gs_id(t_connection const * c); extern int conn_set_d2gs_id(t_connection * c, unsigned int d2gs_id); extern unsigned int d2cs_conn_get_addr(t_connection const * c); extern unsigned short d2cs_conn_get_port(t_connection const * c); extern t_gq * conn_get_gamequeue(t_connection const * c); extern int conn_set_gamequeue(t_connection * c, t_gq * gq); extern int conn_set_bnetd_sessionnum(t_connection * c, unsigned int sessionnum); extern unsigned int conn_get_bnetd_sessionnum(t_connection const * c); extern int conn_add_fd(t_connection * c, t_fdwatch_type rw, fdwatch_handler handler); extern int connlist_check_timeout(void); #endif pvpgn-1.8.5/src/d2cs/gamequeue.h0000644000175000017500000000302611151345317015414 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_GAMEQUEUE_H #define INCLUDED_GAMEQUEUE_H #include "common/packet.h" #include "common/list.h" typedef struct { unsigned int seqno; unsigned int clientid; t_packet * packet; char gamename[MAX_GAMENAME_LEN]; } t_gq; extern unsigned int gq_get_clientid(t_gq const * gq); extern int gq_destroy(t_gq * gq, t_elem ** elem); extern t_gq * gq_create(unsigned int clientid, t_packet * packet, char const * gamename); extern int gqlist_destroy(void); extern int gqlist_create(void); extern t_list * gqlist(void); extern unsigned int gqlist_get_gq_position(t_gq * gq); extern int gqlist_update_all_clients(void); extern int gqlist_check_creategame(int number); extern t_gq * gqlist_find_game(char const * gamename); extern unsigned int gqlist_get_length(void); #endif pvpgn-1.8.5/src/d2cs/version.h0000644000175000017500000000175211151345317015127 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_VERSION_H #define INCLUDED_VERSION_H #define D2CS_VERSION_NUMBER 0x010A0101 #define D2CS_VERSION_STRING "1.10.1.1" #define D2CS_VERSION "D2CS Version " D2CS_VERSION_STRING " Built " __DATE__ #endif pvpgn-1.8.5/src/d2cs/handle_d2cs.c0000644000175000017500000012264511151345317015610 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2004 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/memcpy.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/socket.h" #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #include "compat/pdir.h" #include "compat/mkdir.h" #include "d2charfile.h" #include "connection.h" #include "game.h" #include "bnetd.h" #include "d2cs_protocol.h" #include "d2cs_bnetd_protocol.h" #include "handle_d2cs.h" #include "d2ladder.h" #include "gamequeue.h" #include "serverqueue.h" #include "prefs.h" #include "common/bn_type.h" #include "common/queue.h" #include "common/packet.h" #include "common/eventlog.h" #include "d2charlist.h" #include "common/elist.h" #include "common/xalloc.h" #include "common/setup_after.h" static int d2cs_send_client_ladder(t_connection * c, unsigned char type, unsigned short from); static unsigned int d2cs_try_joingame(t_connection const * c, t_game const * game, char const * gamepass); DECLARE_PACKET_HANDLER(on_client_loginreq) DECLARE_PACKET_HANDLER(on_client_createcharreq) DECLARE_PACKET_HANDLER(on_client_creategamereq) DECLARE_PACKET_HANDLER(on_client_joingamereq) DECLARE_PACKET_HANDLER(on_client_gamelistreq) DECLARE_PACKET_HANDLER(on_client_gameinforeq) DECLARE_PACKET_HANDLER(on_client_charloginreq) DECLARE_PACKET_HANDLER(on_client_deletecharreq) DECLARE_PACKET_HANDLER(on_client_ladderreq) DECLARE_PACKET_HANDLER(on_client_motdreq) DECLARE_PACKET_HANDLER(on_client_cancelcreategame) DECLARE_PACKET_HANDLER(on_client_charladderreq) DECLARE_PACKET_HANDLER(on_client_charlistreq) DECLARE_PACKET_HANDLER(on_client_charlistreq_110) DECLARE_PACKET_HANDLER(on_client_convertcharreq) static t_packet_handle_table d2cs_packet_handle_table[]={ /* 0x00 */ { 0, conn_state_none, NULL }, /* 0x01 */ { sizeof(t_client_d2cs_loginreq), conn_state_connected, on_client_loginreq }, /* 0x02 */ { sizeof(t_client_d2cs_createcharreq), conn_state_authed|conn_state_char_authed, on_client_createcharreq }, /* 0x03 */ { sizeof(t_client_d2cs_creategamereq), conn_state_char_authed, on_client_creategamereq }, /* 0x04 */ { sizeof(t_client_d2cs_joingamereq), conn_state_char_authed, on_client_joingamereq }, /* 0x05 */ { sizeof(t_client_d2cs_gamelistreq), conn_state_char_authed, on_client_gamelistreq }, /* 0x06 */ { sizeof(t_client_d2cs_gameinforeq), conn_state_char_authed, on_client_gameinforeq }, /* 0x07 */ { sizeof(t_client_d2cs_charloginreq), conn_state_authed|conn_state_char_authed, on_client_charloginreq }, /* 0x08 */ { 0, conn_state_none, NULL }, /* 0x09 */ { 0, conn_state_none, NULL }, /* 0x0a */ { sizeof(t_client_d2cs_deletecharreq), conn_state_authed|conn_state_char_authed, on_client_deletecharreq }, /* 0x0b */ { 0, conn_state_none, NULL }, /* 0x0c */ { 0, conn_state_none, NULL }, /* 0x0d */ { 0, conn_state_none, NULL }, /* 0x0e */ { 0, conn_state_none, NULL }, /* 0x0f */ { 0, conn_state_none, NULL }, /* 0x10 */ { 0, conn_state_none, NULL }, /* 0x11 */ { sizeof(t_client_d2cs_ladderreq), conn_state_char_authed, on_client_ladderreq }, /* 0x12 */ { sizeof(t_client_d2cs_motdreq), conn_state_char_authed, on_client_motdreq }, /* 0x13 */ { sizeof(t_client_d2cs_cancelcreategame),conn_state_char_authed, on_client_cancelcreategame}, /* 0x14 */ { 0, conn_state_none, NULL }, /* 0x15 */ { 0, conn_state_none, NULL }, /* 0x16 */ { sizeof(t_client_d2cs_charladderreq), conn_state_char_authed, on_client_charladderreq }, /* 0x17 */ { sizeof(t_client_d2cs_charlistreq), conn_state_authed|conn_state_char_authed, on_client_charlistreq }, /* 0x18 */ { sizeof(t_client_d2cs_convertcharreq), conn_state_authed|conn_state_char_authed, on_client_convertcharreq }, /* 0x19 */ { sizeof(t_client_d2cs_charlistreq_110), conn_state_authed|conn_state_char_authed, on_client_charlistreq_110 } }; extern int d2cs_handle_d2cs_packet(t_connection * c, t_packet * packet) { return conn_process_packet(c,packet,d2cs_packet_handle_table,NELEMS(d2cs_packet_handle_table)); } static int on_client_loginreq(t_connection * c, t_packet * packet) { t_packet * bnpacket; char const * account; t_sq * sq; unsigned int sessionnum; if (!(account=packet_get_str_const(packet,sizeof(t_client_d2cs_loginreq),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name"); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name"); return -1; } if (!bnetd_conn()) { eventlog(eventlog_level_warn,__FUNCTION__,"d2cs is offline with bnetd, login request will be rejected"); return -1; } sessionnum=bn_int_get(packet->u.client_d2cs_loginreq.sessionnum); conn_set_bnetd_sessionnum(c,sessionnum); eventlog(eventlog_level_info,__FUNCTION__,"got client (*%s) login request sessionnum=0x%X",account,sessionnum); if ((bnpacket=packet_create(packet_class_d2cs_bnetd))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,0))) { packet_set_size(bnpacket,sizeof(t_d2cs_bnetd_accountloginreq)); packet_set_type(bnpacket,D2CS_BNETD_ACCOUNTLOGINREQ); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.h.seqno,sq_get_seqno(sq)); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.seqno, bn_int_get(packet->u.client_d2cs_loginreq.seqno)); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionkey, bn_int_get(packet->u.client_d2cs_loginreq.sessionkey)); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionnum,sessionnum); memcpy(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash, packet->u.client_d2cs_loginreq.secret_hash, sizeof(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash)); packet_append_string(bnpacket,account); conn_push_outqueue(bnetd_conn(),bnpacket); } packet_del_ref(bnpacket); } return 0; } static int on_client_createcharreq(t_connection * c, t_packet * packet) { t_packet * rpacket, * bnpacket; char const * charname; char const * account; char * path; t_pdir * dir; t_sq * sq; unsigned int reply; unsigned short status, class; t_d2charinfo_file data; if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_createcharreq),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name"); return -1; } if (!(account=d2cs_conn_get_account(c))) { eventlog(eventlog_level_error,__FUNCTION__,"missing account for character %s",charname); return -1; } class=bn_short_get(packet->u.client_d2cs_createcharreq.class); status=bn_short_get(packet->u.client_d2cs_createcharreq.status); path=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1); d2char_get_infodir_name(path,account); if (!(dir=p_opendir(path))) { eventlog(eventlog_level_info,__FUNCTION__,"(*%s) charinfo directory do not exist, building it",account); p_mkdir(path,S_IRWXU); } else p_closedir(dir); xfree(path); if (d2char_create(account,charname,class,status)<0) { eventlog(eventlog_level_warn,__FUNCTION__,"error create character %s for account %s",charname,account); reply=D2CS_CLIENT_CREATECHARREPLY_ALREADY_EXIST; } else if (d2charinfo_load(account,charname,&data)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for character %s(*%s)",charname,account); reply=D2CS_CLIENT_CREATECHARREPLY_FAILED; } else { eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) created",charname,account); reply=D2CS_CLIENT_CREATECHARREPLY_SUCCEED; conn_set_charinfo(c,&data.summary); if ((bnpacket=packet_create(packet_class_d2cs_bnetd))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,0))) { packet_set_size(bnpacket,sizeof(t_d2cs_bnetd_charloginreq)); packet_set_type(bnpacket,D2CS_BNETD_CHARLOGINREQ); bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.h.seqno,sq_get_seqno(sq)); bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.sessionnum, conn_get_bnetd_sessionnum(c)); packet_append_string(bnpacket,charname); packet_append_string(bnpacket,(char const *)&data.portrait); conn_push_outqueue(bnetd_conn(),bnpacket); } packet_del_ref(bnpacket); } return 0; } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_createcharreply)); packet_set_type(rpacket,D2CS_CLIENT_CREATECHARREPLY); bn_int_set(&rpacket->u.d2cs_client_createcharreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } static int on_client_creategamereq(t_connection * c, t_packet * packet) { char const * gamename; char const * gamepass; char const * gamedesc; t_game * game; t_d2gs * gs; t_gq * gq; unsigned int tempflag,gameflag; unsigned int leveldiff, maxchar, difficulty, expansion, hardcore, ladder; unsigned int seqno, reply; unsigned int pos; t_elem * elem; pos=sizeof(t_client_d2cs_creategamereq); if (!(gamename=packet_get_str_const(packet,pos,MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game name"); return -1; } pos+=strlen(gamename)+1; if (!(gamepass=packet_get_str_const(packet,pos,MAX_GAMEPASS_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game pass"); return -1; } pos+=strlen(gamepass)+1; if (!(gamedesc=packet_get_str_const(packet,pos,MAX_GAMEDESC_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game desc"); return -1; } tempflag=bn_int_get(packet->u.client_d2cs_creategamereq.gameflag); leveldiff=bn_byte_get(packet->u.client_d2cs_creategamereq.leveldiff); maxchar=bn_byte_get(packet->u.client_d2cs_creategamereq.maxchar); difficulty=gameflag_get_difficulty(tempflag); if (difficulty > conn_get_charinfo_difficulty(c)) { eventlog(eventlog_level_error,__FUNCTION__,"game difficulty exceed character limit %d %d",difficulty, conn_get_charinfo_difficulty(c)); return 0; } expansion=conn_get_charinfo_expansion(c); hardcore=conn_get_charinfo_hardcore(c); ladder=conn_get_charinfo_ladder(c); gameflag=gameflag_create(ladder,expansion,hardcore,difficulty); gs = NULL; game = NULL; gq=conn_get_gamequeue(c); if (d2cs_gamelist_find_game(gamename)) { eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in gamelist",gamename); reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else if (!gq && gqlist_find_game(gamename)) { eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in game queue",gamename); reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else if (!(gs=d2gslist_choose_server())) { if (gq) { eventlog(eventlog_level_error,__FUNCTION__,"client %d is already in game queue",d2cs_conn_get_sessionnum(c)); conn_set_gamequeue(c,NULL); gq_destroy(gq,&elem); return 0; } else if ((gq=gq_create(d2cs_conn_get_sessionnum(c), packet, gamename))) { conn_set_gamequeue(c,gq); d2cs_send_client_creategamewait(c,gqlist_get_length()); return 0; } reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED; } else if (hardcore && conn_get_charinfo_dead(c)) { reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED; } else if (!(game=d2cs_game_create(gamename,gamepass,gamedesc,gameflag))) { reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else { reply=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED; game_set_d2gs(game,gs); d2gs_add_gamenum(gs, 1); game_set_gameflag_ladder(game,ladder); game_set_gameflag_expansion(game,expansion); game_set_created(game,0); game_set_leveldiff(game,leveldiff); game_set_charlevel(game,conn_get_charinfo_level(c)); game_set_maxchar(game,maxchar); game_set_gameflag_difficulty(game,difficulty); game_set_gameflag_hardcore(game,hardcore); } seqno=bn_short_get(packet->u.client_d2cs_creategamereq.seqno); if (reply!=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED) { t_packet * rpacket; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_creategamereply)); packet_set_type(rpacket,D2CS_CLIENT_CREATEGAMEREPLY); bn_short_set(&rpacket->u.d2cs_client_creategamereply.seqno,seqno); bn_short_set(&rpacket->u.d2cs_client_creategamereply.u1,0); bn_short_set(&rpacket->u.d2cs_client_creategamereply.gameid,0); bn_int_set(&rpacket->u.d2cs_client_creategamereply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } else { t_packet * gspacket; t_sq * sq; struct in_addr addr; if ((gspacket=packet_create(packet_class_d2gs))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,d2cs_game_get_id(game)))) { packet_set_size(gspacket,sizeof(t_d2cs_d2gs_creategamereq)); packet_set_type(gspacket,D2CS_D2GS_CREATEGAMEREQ); bn_int_set(&gspacket->u.d2cs_d2gs_creategamereq.h.seqno,sq_get_seqno(sq)); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.difficulty,difficulty); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.hardcore,hardcore); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.expansion,expansion); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.ladder,ladder); packet_append_string(gspacket,gamename); packet_append_string(gspacket,gamepass); packet_append_string(gspacket,gamedesc); packet_append_string(gspacket,d2cs_conn_get_account(c)); packet_append_string(gspacket,d2cs_conn_get_charname(c)); addr.s_addr = htonl(d2cs_conn_get_addr(c)); packet_append_string(gspacket,inet_ntoa(addr)); conn_push_outqueue(d2gs_get_connection(gs),gspacket); } packet_del_ref(gspacket); eventlog(eventlog_level_info,__FUNCTION__,"request create game %s on gs %d",gamename,d2gs_get_id(gs)); } } return 0; } static int on_client_joingamereq(t_connection * c, t_packet * packet) { char const * gamename; char const * gamepass; char const * charname; char const * account; t_game * game; t_d2gs * gs; int reply; unsigned int pos; unsigned int seqno; gs = NULL; pos=sizeof(t_client_d2cs_joingamereq); if (!(gamename=packet_get_str_const(packet,pos,MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game name"); return -1; } pos+=strlen(gamename)+1; if (!(gamepass=packet_get_str_const(packet,pos,MAX_GAMEPASS_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game pass"); return -1; } if (!(charname=d2cs_conn_get_charname(c))) { eventlog(eventlog_level_error,__FUNCTION__,"missing character name for connection"); return -1; } if (!(account=d2cs_conn_get_account(c))) { eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection"); return -1; } if (conn_check_multilogin(c,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname); return -1; } if (!(game=d2cs_gamelist_find_game(gamename))) { eventlog(eventlog_level_info,__FUNCTION__,"game %s not found",gamename); reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST; } else if (!(gs=game_get_d2gs(game))) { eventlog(eventlog_level_error,__FUNCTION__,"missing game server for game %s",gamename); reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST; } else { reply=d2cs_try_joingame(c,game,gamepass); } seqno=bn_short_get(packet->u.client_d2cs_joingamereq.seqno); if (reply!=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) { t_packet * rpacket; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_joingamereply)); packet_set_type(rpacket,D2CS_CLIENT_JOINGAMEREPLY); bn_short_set(&rpacket->u.d2cs_client_joingamereply.seqno,seqno); bn_short_set(&rpacket->u.d2cs_client_joingamereply.u1,0); bn_short_set(&rpacket->u.d2cs_client_joingamereply.gameid,0); bn_int_set(&rpacket->u.d2cs_client_joingamereply.addr,0); bn_int_set(&rpacket->u.d2cs_client_joingamereply.token,0); bn_int_set(&rpacket->u.d2cs_client_joingamereply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } else { t_packet * gspacket; t_sq * sq; struct in_addr addr; if ((gspacket=packet_create(packet_class_d2gs))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,d2cs_game_get_id(game)))) { packet_set_size(gspacket,sizeof(t_d2cs_d2gs_joingamereq)); packet_set_type(gspacket,D2CS_D2GS_JOINGAMEREQ); bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.h.seqno,sq_get_seqno(sq)); bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.gameid, game_get_d2gs_gameid(game)); sq_set_gametoken(sq,d2gs_make_token(gs)); bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.token,sq_get_gametoken(sq)); packet_append_string(gspacket,charname); packet_append_string(gspacket,account); addr.s_addr = htonl(d2cs_conn_get_addr(c)); packet_append_string(gspacket,inet_ntoa(addr)); conn_push_outqueue(d2gs_get_connection(gs),gspacket); } packet_del_ref(gspacket); eventlog(eventlog_level_info,__FUNCTION__,"request join game %s for character %s on gs %d",gamename, charname,d2gs_get_id(gs)); } } return 0; } static int on_client_gamelistreq(t_connection * c, t_packet * packet) { t_packet * rpacket; t_game * game; unsigned int count; unsigned int seqno; time_t now; unsigned int maxlifetime; t_elem const * start_elem; t_elem const * elem; seqno=bn_short_get(packet->u.client_d2cs_gamelistreq.seqno); /* if (seqno%2) return 0; */ count=0; now=time(NULL); maxlifetime=prefs_get_game_maxlifetime(); elem=start_elem=gamelist_get_curr_elem(); if (!elem) elem=list_get_first_const(d2cs_gamelist()); else elem=elem_get_next_const(d2cs_gamelist(),elem); for (; elem != start_elem; elem=elem_get_next_const(d2cs_gamelist(),elem)) { if (!elem) { elem=list_get_first_const(d2cs_gamelist()); if (elem == start_elem) break; } if (!(game=elem_get_data(elem))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); break; } if (maxlifetime && (now-game->create_time>maxlifetime)) continue; if (!game_get_currchar(game)) continue; if (!prefs_allow_gamelist_showall()) { if (conn_get_charinfo_difficulty(c)!=game_get_gameflag_difficulty(game)) continue; } if (d2cs_try_joingame(c,game,"")!=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) continue; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply)); packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY); bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,d2cs_game_get_id(game)); bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,game_get_currchar(game)); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,game_get_gameflag(game)); packet_append_string(rpacket,d2cs_game_get_name(game)); packet_append_string(rpacket,game_get_desc(game)); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); count++; if (prefs_get_maxgamelist() && count>=prefs_get_maxgamelist()) break; } } gamelist_set_curr_elem(elem); if (count) { if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply)); packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY); bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,0); bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,0); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,0); packet_append_string(rpacket,""); packet_append_string(rpacket,""); packet_append_string(rpacket,""); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } return 0; } static int on_client_gameinforeq(t_connection * c, t_packet * packet) { t_game_charinfo * info; t_packet * rpacket; char const * gamename; t_game * game; unsigned int seqno, n; if (!(gamename=packet_get_str_const(packet,sizeof(t_client_d2cs_gameinforeq),MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game name"); return -1; } if (!(game=d2cs_gamelist_find_game(gamename))) { eventlog(eventlog_level_error,__FUNCTION__,"game %s not found",gamename); return 0; } seqno=bn_short_get(packet->u.client_d2cs_gameinforeq.seqno); if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_gameinforeply)); packet_set_type(rpacket,D2CS_CLIENT_GAMEINFOREPLY); bn_short_set(&rpacket->u.d2cs_client_gameinforeply.seqno,seqno); bn_int_set(&rpacket->u.d2cs_client_gameinforeply.gameflag,game_get_gameflag(game)); bn_int_set(&rpacket->u.d2cs_client_gameinforeply.etime,time(NULL)-d2cs_game_get_create_time(game)); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.charlevel,game_get_charlevel(game)); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.leveldiff,game_get_leveldiff(game)); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.maxchar,game_get_maxchar(game)); packet_append_string(rpacket, game_get_desc(game) ? game_get_desc(game) : NULL); n=0; BEGIN_LIST_TRAVERSE_DATA_CONST(game_get_charlist(game),info) { if (!info->charname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL charname in game %s char list",gamename); continue; } packet_append_string(rpacket,info->charname); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.class[n],info->class); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.level[n],info->level); n++; } END_LIST_TRAVERSE_DATA_CONST() bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.currchar,n); if (n!=game_get_currchar(game)) { eventlog(eventlog_level_error,__FUNCTION__,"game %s character list corrupted",gamename); } conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } static int on_client_charloginreq(t_connection * c, t_packet * packet) { t_packet * bnpacket; char const * charname; char const * account; t_sq * sq; t_d2charinfo_file data; unsigned int expire_time; if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_charloginreq),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name"); return -1; } if (!(account=d2cs_conn_get_account(c))) { eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection"); return -1; } if (d2charinfo_load(account,charname,&data)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for character %s(*%s)",charname,account); return -1; } else if (!bnetd_conn()) { eventlog(eventlog_level_error,__FUNCTION__,"no bnetd connection available,character login rejected"); return -1; } expire_time = prefs_get_char_expire_time(); if (expire_time && (time(NULL) > bn_int_get(data.header.last_time) + expire_time)) { t_packet * rpacket; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_charloginreply)); packet_set_type(rpacket,D2CS_CLIENT_CHARLOGINREPLY); bn_int_set(&rpacket->u.d2cs_client_charloginreply.reply, D2CS_CLIENT_CHARLOGINREPLY_EXPIRED); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) login rejected due to char expired",charname,account); return 0; } conn_set_charinfo(c,&data.summary); eventlog(eventlog_level_info,__FUNCTION__,"got character %s(*%s) login request",charname,account); if ((bnpacket=packet_create(packet_class_d2cs_bnetd))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,0))) { packet_set_size(bnpacket,sizeof(t_d2cs_bnetd_charloginreq)); packet_set_type(bnpacket,D2CS_BNETD_CHARLOGINREQ); bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.h.seqno,sq_get_seqno(sq)); bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.sessionnum, conn_get_bnetd_sessionnum(c)); packet_append_string(bnpacket,charname); packet_append_string(bnpacket,(char const *)&data.portrait); conn_push_outqueue(bnetd_conn(),bnpacket); } packet_del_ref(bnpacket); } return 0; } static int on_client_deletecharreq(t_connection * c, t_packet * packet) { t_packet * rpacket; char const * charname; char const * account; unsigned int reply; if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_deletecharreq),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name"); return -1; } if (conn_check_multilogin(c,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname); return -1; } d2cs_conn_set_charname(c,NULL); account=d2cs_conn_get_account(c); if (d2char_delete(account,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to delete character %s(*%s)",charname,account); reply = D2CS_CLIENT_DELETECHARREPLY_FAILED; } else { reply = D2CS_CLIENT_DELETECHARREPLY_SUCCEED; } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_deletecharreply)); packet_set_type(rpacket,D2CS_CLIENT_DELETECHARREPLY); bn_short_set(&rpacket->u.d2cs_client_deletecharreply.u1,0); bn_int_set(&rpacket->u.d2cs_client_deletecharreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } static int on_client_ladderreq(t_connection * c, t_packet * packet) { unsigned char type; unsigned short start_pos; type=bn_byte_get(packet->u.client_d2cs_ladderreq.type); start_pos=bn_short_get(packet->u.client_d2cs_ladderreq.start_pos); d2cs_send_client_ladder(c,type,start_pos); return 0; } static int d2cs_send_client_ladder(t_connection * c, unsigned char type, unsigned short from) { t_packet * rpacket; t_d2cs_client_ladderinfo const * ladderinfo; unsigned int curr_len, cont_len, total_len; t_d2cs_client_ladderheader ladderheader; t_d2cs_client_ladderinfoheader infoheader; unsigned int start_pos, count, count_per_packet, npacket; unsigned int i, n, curr_pos; start_pos=from; count=prefs_get_ladderlist_count(); if (d2ladder_get_ladder(&start_pos,&count,type,&ladderinfo)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error get ladder for type %d start_pos %d",type,from); return 0; } count_per_packet=14; npacket=count/count_per_packet; if (count % count_per_packet) npacket++; curr_len=0; cont_len=0; total_len = count * sizeof(*ladderinfo) + sizeof(ladderheader) + sizeof(infoheader) * npacket; total_len -= 4; bn_short_set(&ladderheader.start_pos,start_pos); bn_short_set(&ladderheader.u1,0); bn_int_set(&ladderheader.count1,count); for (i=0; i< npacket; i++) { curr_len=0; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_ladderreply)); packet_set_type(rpacket,D2CS_CLIENT_LADDERREPLY); bn_byte_set(&rpacket->u.d2cs_client_ladderreply.type, type); bn_short_set(&rpacket->u.d2cs_client_ladderreply.total_len, total_len); bn_short_set(&rpacket->u.d2cs_client_ladderreply.cont_len,cont_len); if (i==0) { bn_int_set(&infoheader.count2,count); packet_append_data(rpacket,&ladderheader,sizeof(ladderheader)); curr_len += sizeof(ladderheader); } else { bn_int_set(&infoheader.count2,0); } packet_append_data(rpacket,&infoheader,sizeof(infoheader)); curr_len += sizeof(infoheader); for (n=0; n< count_per_packet; n++) { curr_pos = n + i * count_per_packet; if (curr_pos >= count) break; packet_append_data(rpacket, ladderinfo+curr_pos, sizeof(*ladderinfo)); curr_len += sizeof(*ladderinfo); } if (i==0) { packet_set_size(rpacket, packet_get_size(rpacket)-4); curr_len -= 4; } bn_short_set(&rpacket->u.d2cs_client_ladderreply.curr_len,curr_len); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } cont_len += curr_len; } return 0; } #define MAX_MOTD_LENGTH 511 static int on_client_motdreq(t_connection * c, t_packet * packet) { t_packet * rpacket; char * motd; int motd_len; if (!packet) return -1; /* client will crash if motd is too long */ motd = xstrdup(prefs_get_motd()); motd_len = strlen(motd); if (motd_len > MAX_MOTD_LENGTH) { WARN2("motd length (%i) exceeds maximun value (%i)",motd_len,MAX_MOTD_LENGTH); motd[MAX_MOTD_LENGTH]='\0'; } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_motdreply)); packet_set_type(rpacket,D2CS_CLIENT_MOTDREPLY); bn_byte_set(&rpacket->u.d2cs_client_motdreply.u1,0); packet_append_string(rpacket,motd); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } xfree(motd); return 0; } static int on_client_cancelcreategame(t_connection * c, t_packet * packet) { t_gq * gq; t_elem * elem; if (!packet) return -1; if (!(gq=conn_get_gamequeue(c))) { return 0; } conn_set_gamequeue(c,NULL); gq_destroy(gq,&elem); return 0; } static int on_client_charladderreq(t_connection * c, t_packet * packet) { t_packet * rpacket; char const * charname; unsigned int expansion, hardcore, type; int pos; if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_charladderreq),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name"); return -1; } expansion=bn_int_get(packet->u.client_d2cs_charladderreq.expansion); hardcore=bn_int_get(packet->u.client_d2cs_charladderreq.hardcore); type=0; /* avoid warning */ if (hardcore && expansion) { type=D2LADDER_EXP_HC_OVERALL; } else if (!hardcore && expansion) { type=D2LADDER_EXP_STD_OVERALL; } else if (hardcore && !expansion) { type=D2LADDER_HC_OVERALL; } else if (!hardcore && !expansion) { type=D2LADDER_STD_OVERALL; } if ((pos=d2ladder_find_character_pos(type,charname))<0) { if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_ladderreply)); packet_set_type(rpacket,D2CS_CLIENT_LADDERREPLY); bn_byte_set(&rpacket->u.d2cs_client_ladderreply.type, type); bn_short_set(&rpacket->u.d2cs_client_ladderreply.total_len,0); bn_short_set(&rpacket->u.d2cs_client_ladderreply.curr_len,0); bn_short_set(&rpacket->u.d2cs_client_ladderreply.cont_len,0); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } pos -= prefs_get_ladderlist_count()/2; if (pos < 0) pos=0; d2cs_send_client_ladder(c,type,pos); return 0; } static int on_client_charlistreq(t_connection * c, t_packet * packet) { t_packet * rpacket; t_pdir * dir; char const * account; char const * charname; char * path; t_d2charinfo_file * charinfo; unsigned int n, maxchar; t_elist charlist_head; char const * charlist_sort_order; if (!packet) return -1; if (!(account=d2cs_conn_get_account(c))) { eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection"); return -1; } path=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1); charlist_sort_order = prefs_get_charlist_sort_order(); elist_init(&charlist_head); d2char_get_infodir_name(path,account); maxchar=prefs_get_maxchar(); if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_charlistreply)); packet_set_type(rpacket,D2CS_CLIENT_CHARLISTREPLY); bn_short_set(&rpacket->u.d2cs_client_charlistreply.u1,0); n=0; if (!(dir=p_opendir(path))) { eventlog(eventlog_level_info,__FUNCTION__,"(*%s) charinfo directory do not exist, building it",account); p_mkdir(path,S_IRWXU); } else { while ((charname=p_readdir(dir))) { if (charname[0]=='.') continue; charinfo = xmalloc(sizeof(t_d2charinfo_file)); if (d2charinfo_load(account,charname,charinfo)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for %s(*%s)",charname,account); xfree((void *)charinfo); continue; } eventlog(eventlog_level_debug,__FUNCTION__,"adding char %s (*%s)", charname, account); d2charlist_add_char(&charlist_head,charinfo,0); n++; if (n>=maxchar) break; } if (prefs_allow_newchar() && (nu.d2cs_client_charlistreply.maxchar,maxchar); } else { bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,0); } p_closedir(dir); if (!strcmp(charlist_sort_order, "ASC")) { t_elist * curr, * safe; t_d2charlist * ccharlist; elist_for_each_safe(curr,&charlist_head,safe) { ccharlist = elist_entry(curr,t_d2charlist,list); packet_append_string(rpacket,ccharlist->charinfo->header.charname); packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait); xfree((void *)ccharlist->charinfo); xfree((void *)ccharlist); } } else { t_elist * curr, * safe; t_d2charlist * ccharlist; elist_for_each_safe_rev(curr,&charlist_head,safe) { ccharlist = elist_entry(curr,t_d2charlist,list); packet_append_string(rpacket,ccharlist->charinfo->header.charname); packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait); xfree((void *)ccharlist->charinfo); xfree((void *)ccharlist); } } } bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar,n); bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar2,n); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } xfree(path); return 0; } static int on_client_charlistreq_110(t_connection * c, t_packet * packet) { t_packet * rpacket; t_pdir * dir; char const * account; char const * charname; char * path; t_d2charinfo_file * charinfo; unsigned int n, maxchar; t_elist charlist_head; unsigned int exp_time; unsigned int curr_exp_time; char const * charlist_sort_order; if (!packet) return -1; if (!(account=d2cs_conn_get_account(c))) { eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection"); return -1; } path=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1); charlist_sort_order = prefs_get_charlist_sort_order(); elist_init(&charlist_head); d2char_get_infodir_name(path,account); if (prefs_allow_newchar()) maxchar=prefs_get_maxchar(); else maxchar=0; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_charlistreply_110)); packet_set_type(rpacket,D2CS_CLIENT_CHARLISTREPLY_110); bn_short_set(&rpacket->u.d2cs_client_charlistreply_110.u1,0); n=0; if (!(dir=p_opendir(path))) { eventlog(eventlog_level_info,__FUNCTION__,"(*%s) charinfo directory do not exist, building it",account); p_mkdir(path,S_IRWXU); } else { exp_time = prefs_get_char_expire_time(); while ((charname=p_readdir(dir))) { if (charname[0]=='.') continue; charinfo = xmalloc(sizeof(t_d2charinfo_file)); if (d2charinfo_load(account,charname,charinfo)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for %s(*%s)",charname,account); xfree(charinfo); continue; } if (exp_time) { curr_exp_time = bn_int_get(charinfo->header.last_time)+exp_time; } else { curr_exp_time = 0x7FFFFFFF; } eventlog(eventlog_level_debug,__FUNCTION__,"adding char %s (*%s)", charname, account); d2charlist_add_char(&charlist_head,charinfo,curr_exp_time); n++; if (n>=maxchar) break; } if (n>=maxchar) maxchar = 0; p_closedir(dir); if (!strcmp(charlist_sort_order, "ASC")) { t_elist * curr, *safe; t_d2charlist * ccharlist; elist_for_each_safe(curr,&charlist_head,safe) { bn_int bn_exp_time; ccharlist = elist_entry(curr,t_d2charlist,list); bn_int_set(&bn_exp_time,ccharlist->expiration_time); packet_append_data(rpacket,bn_exp_time,sizeof(bn_exp_time)); packet_append_string(rpacket,ccharlist->charinfo->header.charname); packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait); xfree((void *)ccharlist->charinfo); xfree((void *)ccharlist); } } else { t_elist * curr, *safe; t_d2charlist * ccharlist; elist_for_each_safe_rev(curr,&charlist_head,safe) { bn_int bn_exp_time; ccharlist = elist_entry(curr,t_d2charlist,list); bn_int_set(&bn_exp_time,ccharlist->expiration_time); packet_append_data(rpacket,bn_exp_time,sizeof(bn_exp_time)); packet_append_string(rpacket,ccharlist->charinfo->header.charname); packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait); xfree((void *)ccharlist->charinfo); xfree((void *)ccharlist); } } } bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar,n); bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar2,n); bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,maxchar); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } xfree(path); return 0; } static int on_client_convertcharreq(t_connection * c, t_packet * packet) { t_packet * rpacket; char const * charname; char const * account; unsigned int reply; if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_convertcharreq),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name"); return -1; } if (conn_check_multilogin(c,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname); return -1; } account=d2cs_conn_get_account(c); if (d2char_convert(account,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to convert character %s(*%s)",charname,account); reply = D2CS_CLIENT_CONVERTCHARREPLY_FAILED; } else { reply = D2CS_CLIENT_CONVERTCHARREPLY_SUCCEED; } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_convertcharreply)); packet_set_type(rpacket,D2CS_CLIENT_CONVERTCHARREPLY); bn_int_set(&rpacket->u.d2cs_client_convertcharreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } extern int d2cs_send_client_creategamewait(t_connection * c, unsigned int position) { t_packet * packet; ASSERT(c,-1); if ((packet=packet_create(packet_class_d2cs))) { packet_set_size(packet,sizeof(t_d2cs_client_creategamewait)); packet_set_type(packet,D2CS_CLIENT_CREATEGAMEWAIT); bn_int_set(&packet->u.d2cs_client_creategamewait.position,position); conn_push_outqueue(c,packet); packet_del_ref(packet); } return 0; } extern int d2cs_handle_client_creategame(t_connection * c, t_packet * packet) { return on_client_creategamereq(c,packet); } static unsigned int d2cs_try_joingame(t_connection const * c, t_game const * game, char const * gamepass) { unsigned int reply; ASSERT(c,D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST); ASSERT(game,D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST); if (!game_get_created(game)) { reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST; } else if (!game_get_d2gs(game)) { reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST; } else if (conn_get_charinfo_ladder(c) != game_get_gameflag_ladder(game)) { reply=D2CS_CLIENT_JOINGAMEREPLY_NORMAL_LADDER; } else if (conn_get_charinfo_expansion(c) != game_get_gameflag_expansion(game)) { reply=D2CS_CLIENT_JOINGAMEREPLY_CLASSIC_EXPANSION; } else if (conn_get_charinfo_hardcore(c) != game_get_gameflag_hardcore(game)) { reply=D2CS_CLIENT_JOINGAMEREPLY_HARDCORE_SOFTCORE; } else if (conn_get_charinfo_difficulty(c) < game_get_gameflag_difficulty(game)) { reply=D2CS_CLIENT_JOINGAMEREPLY_NORMAL_NIGHTMARE; } else if (prefs_allow_gamelimit()) { if (game_get_maxchar(game) <= game_get_currchar(game)) { reply=D2CS_CLIENT_JOINGAMEREPLY_GAME_FULL; } else if (conn_get_charinfo_level(c) > game_get_maxlevel(game)) { reply=D2CS_CLIENT_JOINGAMEREPLY_LEVEL_LIMIT; } else if (conn_get_charinfo_level(c) < game_get_minlevel(game)) { reply=D2CS_CLIENT_JOINGAMEREPLY_LEVEL_LIMIT; } else if (strcmp(d2cs_game_get_pass(game),gamepass)) { reply=D2CS_CLIENT_JOINGAMEREPLY_BAD_PASS; } else { reply=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED; } } else { if (game_get_currchar(game) >= MAX_CHAR_PER_GAME) { reply=D2CS_CLIENT_JOINGAMEREPLY_GAME_FULL; } else { reply=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED; } } return reply; } pvpgn-1.8.5/src/d2cs/serverqueue.c0000644000175000017500000000702611151345317016010 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "prefs.h" #include "serverqueue.h" #include "common/packet.h" #include "common/list.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" static t_list * sqlist_head=NULL; static unsigned int sqlist_seqno=0; extern t_list * sqlist(void) { return sqlist_head; } extern int sqlist_create(void) { sqlist_head=list_create(); return 0; } extern int sqlist_destroy(void) { t_sq * sq; BEGIN_LIST_TRAVERSE_DATA_CONST(sqlist_head,sq) { sq_destroy(sq,(t_elem **)curr_elem_); } END_LIST_TRAVERSE_DATA_CONST() if (list_destroy(sqlist_head)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error destroy server queue list"); return -1; } sqlist_head=NULL; return 0; } extern int sqlist_check_timeout(void) { t_sq * sq; time_t now; now=time(NULL); BEGIN_LIST_TRAVERSE_DATA(sqlist_head, sq) { if (now - sq->ctime > prefs_get_sq_timeout()) { eventlog(eventlog_level_info,__FUNCTION__,"destroying expired server queue %d",sq->seqno); sq_destroy(sq,&curr_elem_); } } END_LIST_TRAVERSE_DATA() return 0; } extern t_sq * sqlist_find_sq(unsigned int seqno) { t_sq * sq; BEGIN_LIST_TRAVERSE_DATA_CONST(sqlist_head,sq) { if (sq->seqno==seqno) return sq; } END_LIST_TRAVERSE_DATA_CONST() return NULL; } extern t_sq * sq_create(unsigned int clientid, t_packet * packet,unsigned int gameid ) { t_sq * sq; sq=xmalloc(sizeof(t_sq)); sq->seqno=++sqlist_seqno; sq->ctime=time(NULL); sq->clientid=clientid; sq->gameid=gameid; sq->packet=packet; sq->gametoken=0; if (packet) packet_add_ref(packet); list_append_data(sqlist_head,sq); return sq; } extern int sq_destroy(t_sq * sq,t_elem ** curr) { ASSERT(sq,-1); if (list_remove_data(sqlist_head,sq,curr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error remove server queue from list"); return -1; } if (sq->packet) packet_del_ref(sq->packet); xfree(sq); return 0; } extern unsigned int sq_get_clientid(t_sq const * sq) { ASSERT(sq,0); return sq->clientid; } extern t_packet * sq_get_packet(t_sq const * sq) { ASSERT(sq,NULL); return sq->packet; } extern unsigned int sq_get_gameid(t_sq const * sq) { ASSERT(sq,0); return sq->gameid; } extern unsigned int sq_get_seqno(t_sq const * sq) { ASSERT(sq,0); return sq->seqno; } extern int sq_set_gametoken(t_sq * sq, unsigned int gametoken) { ASSERT(sq,-1); sq->gametoken=gametoken; return 0; } extern unsigned int sq_get_gametoken(t_sq const * sq) { ASSERT(sq,0); return sq->gametoken; } pvpgn-1.8.5/src/d2cs/d2charlist.h0000644000175000017500000000212311151345317015472 0ustar aaronaaron/* * Copyright (C) 2004 ls_sons (ls@gamelife.org) * Copyright (C) 2004 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/elist.h" #include "d2cs_d2gs_character.h" typedef struct d2charlist{ t_d2charinfo_file *charinfo; int expiration_time; t_elist list; } t_d2charlist; extern int d2charlist_add_char(t_elist *, t_d2charinfo_file *i, unsigned int); pvpgn-1.8.5/src/d2cs/cmdline.c0000644000175000017500000001620011151345317015042 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * Copyright (C) 2005 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memset.h" #ifdef WIN32 # include "win32/service.h" #endif #include "common/conf.h" #include "common/xalloc.h" #include "version.h" #include "cmdline.h" #include "compat/strcasecmp.h" #include "common/eventlog.h" #include "common/setup_after.h" static struct { #ifdef DO_DAEMONIZE unsigned foreground; #endif const char *preffile; const char *logfile; unsigned debug; } cmdline_config; static unsigned exitflag; static const char *progname; static int conf_set_preffile(const char *valstr); static int conf_setdef_preffile(void); static int conf_set_logfile(const char * valstr); static int conf_setdef_logfile(void); static int conf_set_help(const char * valstr); static int conf_setdef_help(void); static int conf_set_version(const char * valstr); static int conf_setdef_version(void); static int conf_set_foreground(const char * valstr); static int conf_setdef_foreground(void); static int conf_set_debug(const char * valstr); static int conf_setdef_debug(void); #ifdef WIN32 static int conf_set_service(char const * valstr); static int conf_setdef_service(void); static int conf_set_servaction(const char * valstr); static int conf_setdef_servaction(void); #endif static t_conf_entry conftab[]={ { "c", conf_set_preffile, NULL, conf_setdef_preffile}, { "config", conf_set_preffile, NULL, conf_setdef_preffile}, { "l", conf_set_logfile, NULL, conf_setdef_logfile }, { "log", conf_set_logfile, NULL, conf_setdef_logfile }, { "h", conf_set_help, NULL, conf_setdef_help }, { "help", conf_set_help, NULL, conf_setdef_help }, { "usage", conf_set_help, NULL, conf_setdef_help }, { "v", conf_set_version, NULL, conf_setdef_version }, { "version", conf_set_version, NULL, conf_setdef_version }, #ifdef DO_DAEMONIZE { "f", conf_set_foreground, NULL, conf_setdef_foreground}, { "foreground", conf_set_foreground, NULL, conf_setdef_foreground}, #endif { "D", conf_set_debug, NULL, conf_setdef_debug }, { "debug", conf_set_debug, NULL, conf_setdef_debug }, #ifdef WIN32 { "service", conf_set_service, NULL, conf_setdef_service }, { "s", conf_set_servaction, NULL, conf_setdef_servaction}, #endif { NULL, NULL, NULL, NULL } }; extern int cmdline_load(int argc, char** argv) { int res; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return -1; } exitflag = 0; progname = argv[0]; res = conf_load_cmdline(argc, argv, conftab); if (res < 0) return -1; return exitflag ? 0 : 1; } extern void cmdline_unload(void) { conf_unload(conftab); } static void usage(void) { fprintf(stderr, "Usage: %s []\n" " -c FILE, --config=FILE use FILE as configuration file (default is " D2CS_DEFAULT_CONF_FILE ")\n" " -l FILE, --log=FILE set log to FILE\n" #ifdef DO_DAEMONIZE " -f, --foreground: don't daemonize\n" #endif " -D, --debug: run in debug mode (run in foreground and log to stdout)\n" " -h, --help, --usage show this information and exit\n" " -v, --version: print version number and exit\n" #ifdef WIN32 " Running as service functions:\n" " --service run as service\n" " -s install install service\n" " -s uninstall uninstall service\n" #endif "\n" "Notes:\n" " 1.You should always use absolute path here for all FILE names\n\n", progname); } #ifdef DO_DAEMONIZE extern int cmdline_get_foreground(void) { return cmdline_config.foreground; } static int conf_set_foreground(const char *valstr) { return conf_set_bool(&cmdline_config.foreground, valstr, 0); } static int conf_setdef_foreground(void) { return conf_set_bool(&cmdline_config.foreground, NULL, 0); } #endif extern const char* cmdline_get_preffile(void) { return cmdline_config.preffile; } static int conf_set_preffile(const char *valstr) { return conf_set_str(&cmdline_config.preffile, valstr, NULL); } static int conf_setdef_preffile(void) { return conf_set_str(&cmdline_config.preffile, NULL, D2CS_DEFAULT_CONF_FILE); } extern const char* cmdline_get_logfile(void) { return cmdline_config.logfile; } static int conf_set_logfile(const char *valstr) { return conf_set_str(&cmdline_config.logfile, valstr, NULL); } static int conf_setdef_logfile(void) { return conf_set_str(&cmdline_config.logfile, NULL, NULL); } static int conf_set_debug(const char *valstr) { conf_set_bool(&cmdline_config.debug, valstr, 0); if (cmdline_config.debug) eventlog_set_debugmode(1); #ifdef DO_DAEMONIZE cmdline_config.foreground = 1; #endif return 0; } static int conf_setdef_debug(void) { return conf_set_bool(&cmdline_config.debug, NULL, 0); } static int conf_set_help(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { usage(); exitflag = 1; } return 0; } static int conf_setdef_help(void) { return 0; } static int conf_set_version(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { printf(D2CS_VERSION"\n"); exitflag = 1; } return 0; } static int conf_setdef_version(void) { return 0; } #ifdef WIN32 static int conf_set_service(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { Win32_ServiceRun(); exitflag = 1; } return 0; } static int conf_setdef_service(void) { return 0; } static int conf_set_servaction(const char *valstr) { const char* tmp = NULL; conf_set_str(&tmp, valstr, NULL); if (tmp) { if (!strcasecmp(tmp, "install")) { fprintf(stderr, "Installing service"); Win32_ServiceInstall(); } else if (!strcasecmp(tmp, "uninstall")) { fprintf(stderr, "Uninstalling service"); Win32_ServiceUninstall(); } else { fprintf(stderr, "Unknown service action '%s'\n", tmp); } exitflag = 1; xfree((void *)tmp); } return 0; } static int conf_setdef_servaction(void) { return 0; } #endif pvpgn-1.8.5/src/d2cs/handle_init.c0000644000175000017500000000574111151345317015715 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "connection.h" #include "handle_init.h" #include "handle_d2gs.h" #include "d2gs.h" #include "prefs.h" #include "common/init_protocol.h" #include "common/addr.h" #include "common/packet.h" #include "common/queue.h" #include "common/eventlog.h" #include "common/bn_type.h" #include "common/setup_after.h" static int on_d2gs_initconn(t_connection * c); static int on_d2cs_initconn(t_connection * c); extern int d2cs_handle_init_packet(t_connection * c, t_packet * packet) { int class; int retval; ASSERT(c,-1); ASSERT(packet,-1); class=bn_byte_get(packet->u.client_initconn.class); switch (class) { case CLIENT_INITCONN_CLASS_D2CS: retval=on_d2cs_initconn(c); break; case CLIENT_INITCONN_CLASS_D2GS: retval=on_d2gs_initconn(c); break; default: eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d",class); retval=-1; break; } return retval; } static int on_d2gs_initconn(t_connection * c) { t_d2gs * gs; eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated d2gs connection",d2cs_conn_get_socket(c)); if (!(gs=d2gslist_find_gs_by_ip(d2cs_conn_get_addr(c)))) { // reload list and see if any dns addy's has changed if (d2gslist_reload(prefs_get_d2gs_list())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error reloading game server list,exitting"); return -1; } //recheck if (!(gs=d2gslist_find_gs_by_ip(d2cs_conn_get_addr(c)))) { eventlog(eventlog_level_error,__FUNCTION__,"d2gs connection from invalid ip address %s",addr_num_to_ip_str(d2cs_conn_get_addr(c))); return -1; } } d2cs_conn_set_class(c,conn_class_d2gs); d2cs_conn_set_state(c,conn_state_connected); conn_set_d2gs_id(c,d2gs_get_id(gs)); if (handle_d2gs_init(c)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to init d2gs connection"); return -1; } return 0; } static int on_d2cs_initconn(t_connection * c) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated d2cs connection",d2cs_conn_get_socket(c)); d2cs_conn_set_class(c,conn_class_d2cs); d2cs_conn_set_state(c,conn_state_connected); return 0; } pvpgn-1.8.5/src/d2cs/d2charlist.c0000644000175000017500000000611411151345317015471 0ustar aaronaaron/* * Copyright (C) 2004 ls_sons (ls@gamelife.org) * Copyright (C) 2004 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "connection.h" #include "prefs.h" #include "common/eventlog.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include "compat/strdup.h" #include "common/xalloc.h" #include "common/elist.h" #include "d2charlist.h" #include "common/setup_after.h" extern int d2charlist_add_char(t_elist * list_head, t_d2charinfo_file * charinfo, unsigned int expiration_time) { t_d2charlist * charlist, * ccharlist; char const * d2char_sort; t_elist * curr; d2char_sort = prefs_get_charlist_sort(); charlist = xmalloc(sizeof(t_d2charlist)); charlist->charinfo = charinfo; charlist->expiration_time = expiration_time; if (elist_empty(list_head)) elist_add(list_head,&charlist->list); else { if (strcasecmp(d2char_sort, "name")==0) { elist_for_each(curr,list_head) { ccharlist = elist_entry(curr,t_d2charlist,list); if (strncasecmp(charinfo->header.charname,ccharlist->charinfo->header.charname,strlen(charinfo->header.charname))<0) break; } elist_add_tail(curr,&charlist->list); } else if (strcasecmp(d2char_sort, "mtime")==0) { elist_for_each(curr,list_head) { ccharlist = elist_entry(curr,t_d2charlist,list); if (bn_int_get(charinfo->header.last_time) < bn_int_get(ccharlist->charinfo->header.last_time)) break; } elist_add_tail(curr,&charlist->list); } else if (strcasecmp(d2char_sort, "level")==0) { elist_for_each(curr,list_head) { ccharlist = elist_entry(curr,t_d2charlist,list); if (bn_int_get(charinfo->summary.experience) < bn_int_get(ccharlist->charinfo->summary.experience)) break; } elist_add_tail(curr,&charlist->list); } else { eventlog(eventlog_level_debug,__FUNCTION__,"unsorted"); elist_add_tail(list_head,&charlist->list); } } return 0; } pvpgn-1.8.5/src/d2cs/prefs.c0000644000175000017500000007275311151345317014565 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memset.h" #include "common/conf.h" #include "prefs.h" #include "common/eventlog.h" #include "common/setup_after.h" static struct { char const * logfile; char const * loglevels; char const * servaddrs; char const * gameservlist; char const * bnetdaddr; char const * charsavedir; char const * charinfodir; char const * bak_charsavedir; char const * bak_charinfodir; char const * ladderdir; char const * newbiefile; char const * motd; char const * realmname; char const * d2gs_password; char const * transfile; char const * account_allowed_symbols; char const * d2gsconffile; char const * pidfile; unsigned int ladder_refresh_interval; unsigned int maxchar; unsigned int listpurgeinterval; unsigned int gqcheckinterval; unsigned int s2s_retryinterval; unsigned int s2s_timeout; unsigned int s2s_idletime; unsigned int sq_checkinterval; unsigned int sq_timeout; unsigned int maxgamelist; unsigned int max_game_idletime; unsigned int gamelist_showall; unsigned int game_maxlifetime; unsigned int allow_gamelimit; unsigned int allow_newchar; unsigned int idletime; unsigned int shutdown_delay; unsigned int shutdown_decr; unsigned int d2gs_checksum; unsigned int d2gs_version; unsigned int check_multilogin; unsigned int timeout_checkinterval; unsigned int s2s_keepalive_interval; unsigned int lod_realm; unsigned int allow_convert; unsigned int d2gs_restart_delay; time_t ladder_start_time; unsigned int char_expire_day; char const * charlist_sort; char const * charlist_sort_order; unsigned int max_connections; } prefs_conf; static int conf_set_logfile(const char* valstr); static int conf_setdef_logfile(void); static int conf_set_loglevels(const char* valstr); static int conf_setdef_loglevels(void); static int conf_set_servaddrs(const char* valstr); static int conf_setdef_servaddrs(void); static int conf_set_gameservlist(const char* valstr); static int conf_setdef_gameservlist(void); static int conf_set_bnetdaddr(const char* valstr); static int conf_setdef_bnetaddr(void); static int conf_set_charsavedir(const char* valstr); static int conf_setdef_charsavedir(void); static int conf_set_charinfodir(const char* valstr); static int conf_setdef_charinfodir(void); static int conf_set_bakcharsavedir(const char* valstr); static int conf_setdef_backcharsavedir(void); static int conf_set_bakcharinfodir(const char* valstr); static int conf_setdef_backcharinfodir(void); static int conf_set_ladderdir(const char* valstr); static int conf_setdef_ladderdir(void); static int conf_set_ladder_start_time(const char* valstr); static int conf_setdef_ladder_start_time(void); static int conf_set_ladder_refresh_interval(const char* valstr); static int conf_setdef_ladder_refresh_interval(void); static int conf_set_newbiefile(const char* valstr); static int conf_setdef_newbiefile(void); static int conf_set_transfile(const char* valstr); static int conf_setdef_transfile(void); static int conf_set_motd(const char* valstr); static int conf_setdef_motd(void); static int conf_set_realmname(const char* valstr); static int conf_setdef_realmname(void); static int conf_set_maxchar(const char* valstr); static int conf_setdef_maxchar(void); static int conf_set_listpurgeinterval(const char* valstr); static int conf_setdef_listpurgeinterval(void); static int conf_set_gqcheckinterval(const char* valstr); static int conf_setdef_gqcheckinterval(void); static int conf_set_maxgamelist(const char* valstr); static int conf_setdef_maxgamelist(void); static int conf_set_max_game_idletime(const char* valstr); static int conf_setdef_max_game_idletime(void); static int conf_set_gamelist_showall(const char* valstr); static int conf_setdef_gamelist_showall(void); static int conf_set_game_maxlifetime(const char* valstr); static int conf_setdef_game_maxlifetime(void); static int conf_set_allow_gamelimit(const char* valstr); static int conf_setdef_allow_gamelimit(void); static int conf_set_allow_newchar(const char* valstr); static int conf_setdef_allow_newchar(void); static int conf_set_idletime(const char* valstr); static int conf_setdef_idletime(void); static int conf_set_shutdown_delay(const char* valstr); static int conf_setdef_shutdown_delay(void); static int conf_set_shutdown_decr(const char* valstr); static int conf_setdef_shutdown_decr(void); static int conf_set_s2s_retryinterval(const char* valstr); static int conf_setdef_s2s_retryinterval(void); static int conf_set_s2s_timeout(const char* valstr); static int conf_setdef_s2s_timeout(void); static int conf_set_sq_checkinterval(const char* valstr); static int conf_setdef_sq_checkinterval(void); static int conf_set_sq_timeout(const char* valstr); static int conf_setdef_sq_timeout(void); static int conf_set_d2gs_checksum(const char* valstr); static int conf_setdef_d2gs_checksum(void); static int conf_set_d2gs_version(const char* valstr); static int conf_setdef_d2gs_version(void); static int conf_set_d2gs_password(const char* valstr); static int conf_setdef_d2gs_password(void); static int conf_set_check_multilogin(const char* valstr); static int conf_setdef_check_multilogin(void); static int conf_set_s2s_idletime(const char* valstr); static int conf_setdef_s2s_idletime(void); static int conf_set_s2s_keepalive_interval(const char* valstr); static int conf_setdef_s2s_keepalive_interval(void); static int conf_set_timeout_checkinterval(const char* valstr); static int conf_setdef_timeout_checkinterval(void); static int conf_set_lod_realm(const char* valstr); static int conf_setdef_lod_realm(void); static int conf_set_allow_convert(const char* valstr); static int conf_setdef_allow_convert(void); static int conf_set_account_allowed_symbols(const char* valstr); static int conf_setdef_account_allowed_symbols(void); static int conf_set_d2gs_restart_delay(const char* valstr); static int conf_setdef_d2gs_restart_delay(void); static int conf_set_char_expire_day(const char* valstr); static int conf_setdef_char_expire_day(void); static int conf_set_d2gsconffile(const char* valstr); static int conf_setdef_d2gsconffile(void); static int conf_set_charlist_sort(const char* valstr); static int conf_setdef_charlist_sort(void); static int conf_set_charlist_sort_order(const char* valstr); static int conf_setdef_charlist_sort_order(void); static int conf_set_max_connections(const char* valstr); static int conf_setdef_max_connections(void); static int conf_set_pidfile(const char* valstr); static int conf_setdef_pidfile(void); static t_conf_entry prefs_conf_table[]={ { "logfile", conf_set_logfile, NULL, conf_setdef_logfile }, { "loglevels", conf_set_loglevels, NULL, conf_setdef_loglevels}, { "servaddrs", conf_set_servaddrs, NULL, conf_setdef_servaddrs}, { "gameservlist", conf_set_gameservlist, NULL, conf_setdef_gameservlist}, { "bnetdaddr", conf_set_bnetdaddr, NULL, conf_setdef_bnetaddr}, { "charsavedir", conf_set_charsavedir, NULL, conf_setdef_charsavedir}, { "charinfodir", conf_set_charinfodir, NULL, conf_setdef_charinfodir}, { "bak_charsavedir", conf_set_bakcharsavedir, NULL, conf_setdef_backcharsavedir}, { "bak_charinfodir", conf_set_bakcharinfodir, NULL, conf_setdef_backcharinfodir}, { "ladderdir", conf_set_ladderdir, NULL, conf_setdef_ladderdir}, { "ladder_start_time", conf_set_ladder_start_time, NULL, conf_setdef_ladder_start_time}, { "ladder_refresh_interval",conf_set_ladder_refresh_interval,NULL, conf_setdef_ladder_refresh_interval}, { "newbiefile", conf_set_newbiefile, NULL, conf_setdef_newbiefile}, { "transfile", conf_set_transfile, NULL, conf_setdef_transfile}, { "pidfile", conf_set_pidfile, NULL, conf_setdef_pidfile}, { "motd", conf_set_motd, NULL, conf_setdef_motd}, { "realmname", conf_set_realmname, NULL, conf_setdef_realmname}, { "maxchar", conf_set_maxchar, NULL, conf_setdef_maxchar}, { "listpurgeinterval", conf_set_listpurgeinterval, NULL, conf_setdef_listpurgeinterval}, { "gqcheckinterval", conf_set_gqcheckinterval, NULL, conf_setdef_gqcheckinterval}, { "maxgamelist", conf_set_maxgamelist, NULL, conf_setdef_maxgamelist}, { "max_game_idletime", conf_set_max_game_idletime, NULL, conf_setdef_max_game_idletime}, { "gamelist_showall", conf_set_gamelist_showall, NULL, conf_setdef_gamelist_showall}, { "game_maxlifetime", conf_set_game_maxlifetime, NULL, conf_setdef_game_maxlifetime}, { "allow_gamelimit", conf_set_allow_gamelimit, NULL, conf_setdef_allow_gamelimit}, { "allow_newchar", conf_set_allow_newchar, NULL, conf_setdef_allow_newchar}, { "idletime", conf_set_idletime, NULL, conf_setdef_idletime}, { "shutdown_delay", conf_set_shutdown_delay, NULL, conf_setdef_shutdown_delay}, { "shutdown_decr", conf_set_shutdown_decr, NULL, conf_setdef_shutdown_decr}, { "s2s_retryinterval", conf_set_s2s_retryinterval, NULL, conf_setdef_s2s_retryinterval}, { "s2s_timeout", conf_set_s2s_timeout, NULL, conf_setdef_s2s_timeout}, { "sq_checkinterval", conf_set_sq_checkinterval, NULL, conf_setdef_sq_checkinterval}, { "sq_timeout", conf_set_sq_timeout, NULL, conf_setdef_sq_timeout}, { "d2gs_checksum", conf_set_d2gs_checksum, NULL, conf_setdef_d2gs_checksum}, { "d2gs_version", conf_set_d2gs_version, NULL, conf_setdef_d2gs_version}, { "d2gs_password", conf_set_d2gs_password, NULL, conf_setdef_d2gs_password}, { "check_multilogin", conf_set_check_multilogin, NULL, conf_setdef_check_multilogin}, { "s2s_idletime", conf_set_s2s_idletime, NULL, conf_setdef_s2s_idletime}, { "s2s_keepalive_interval", conf_set_s2s_keepalive_interval, NULL, conf_setdef_s2s_keepalive_interval}, { "timeout_checkinterval", conf_set_timeout_checkinterval, NULL, conf_setdef_timeout_checkinterval}, { "lod_realm", conf_set_lod_realm, NULL, conf_setdef_lod_realm}, { "allow_convert", conf_set_allow_convert, NULL, conf_setdef_allow_convert}, { "account_allowed_symbols",conf_set_account_allowed_symbols,NULL, conf_setdef_account_allowed_symbols}, { "d2gs_restart_delay", conf_set_d2gs_restart_delay, NULL, conf_setdef_d2gs_restart_delay}, { "char_expire_day", conf_set_char_expire_day, NULL, conf_setdef_char_expire_day}, { "d2gsconffile", conf_set_d2gsconffile, NULL, conf_setdef_d2gsconffile}, { "charlist_sort", conf_set_charlist_sort, NULL, conf_setdef_charlist_sort}, { "charlist_sort_order", conf_set_charlist_sort_order, NULL, conf_setdef_charlist_sort_order}, { "max_connections", conf_set_max_connections, NULL, conf_setdef_max_connections}, { NULL, NULL, NULL, NULL } }; extern int d2cs_prefs_load(char const * filename) { FILE *fd; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } fd = fopen(filename,"rt"); if (!fd) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file '%s'",filename); return -1; } if (conf_load_file(fd,prefs_conf_table)) { eventlog(eventlog_level_error,__FUNCTION__,"error loading config file '%s'",filename); fclose(fd); return -1; } fclose(fd); return 0; } extern int prefs_reload(char const * filename) { d2cs_prefs_unload(); if (d2cs_prefs_load(filename)<0) return -1; return 0; } extern int d2cs_prefs_unload(void) { conf_unload(prefs_conf_table); return 0; } extern char const * prefs_get_servaddrs(void) { return prefs_conf.servaddrs; } static int conf_set_servaddrs(const char* valstr) { return conf_set_str(&prefs_conf.servaddrs,valstr,NULL); } static int conf_setdef_servaddrs(void) { return conf_set_str(&prefs_conf.servaddrs,NULL,D2CS_SERVER_ADDRS); } extern char const * prefs_get_charsave_dir(void) { return prefs_conf.charsavedir; } static int conf_set_charsavedir(const char* valstr) { return conf_set_str(&prefs_conf.charsavedir,valstr,NULL); } static int conf_setdef_charsavedir(void) { return conf_set_str(&prefs_conf.charsavedir,NULL,D2CS_CHARSAVE_DIR); } extern char const * prefs_get_charinfo_dir(void) { return prefs_conf.charinfodir; } static int conf_set_charinfodir(const char* valstr) { return conf_set_str(&prefs_conf.charinfodir,valstr,NULL); } static int conf_setdef_charinfodir(void) { return conf_set_str(&prefs_conf.charinfodir,NULL,D2CS_CHARINFO_DIR); } extern char const * prefs_get_bak_charsave_dir(void) { return prefs_conf.bak_charsavedir; } static int conf_set_bakcharsavedir(const char* valstr) { return conf_set_str(&prefs_conf.bak_charsavedir,valstr,NULL); } static int conf_setdef_backcharsavedir(void) { return conf_set_str(&prefs_conf.bak_charsavedir,NULL,D2CS_BAK_CHARSAVE_DIR); } extern char const * prefs_get_bak_charinfo_dir(void) { return prefs_conf.bak_charinfodir; } static int conf_set_bakcharinfodir(const char* valstr) { return conf_set_str(&prefs_conf.bak_charinfodir,valstr,NULL); } static int conf_setdef_backcharinfodir(void) { return conf_set_str(&prefs_conf.bak_charinfodir,NULL,D2CS_BAK_CHARINFO_DIR); } extern char const * prefs_get_charsave_newbie(void) { return prefs_conf.newbiefile; } static int conf_set_newbiefile(const char* valstr) { return conf_set_str(&prefs_conf.newbiefile,valstr,NULL); } static int conf_setdef_newbiefile(void) { return conf_set_str(&prefs_conf.newbiefile,NULL,D2CS_CHARSAVE_NEWBIE); } extern char const * prefs_get_motd(void) { return prefs_conf.motd; } static int conf_set_motd(const char* valstr) { return conf_set_str(&prefs_conf.motd,valstr,NULL); } static int conf_setdef_motd(void) { return conf_set_str(&prefs_conf.motd,NULL,D2CS_MOTD); } extern char const * prefs_get_d2gs_list(void) { return prefs_conf.gameservlist; } static int conf_set_gameservlist(const char* valstr) { return conf_set_str(&prefs_conf.gameservlist,valstr,NULL); } static int conf_setdef_gameservlist(void) { return conf_set_str(&prefs_conf.gameservlist,NULL,D2GS_SERVER_LIST); } extern unsigned int prefs_get_maxchar(void) { return (prefs_conf.maxchar>MAX_MAX_CHAR_PER_ACCT)?MAX_MAX_CHAR_PER_ACCT:prefs_conf.maxchar; } static int conf_set_maxchar(const char* valstr) { return conf_set_int(&prefs_conf.maxchar,valstr,0); } static int conf_setdef_maxchar(void) { return conf_set_int(&prefs_conf.maxchar,NULL,MAX_CHAR_PER_ACCT); } extern unsigned int prefs_get_list_purgeinterval(void) { return prefs_conf.listpurgeinterval; } static int conf_set_listpurgeinterval(const char* valstr) { return conf_set_int(&prefs_conf.listpurgeinterval,valstr,0); } static int conf_setdef_listpurgeinterval(void) { return conf_set_int(&prefs_conf.listpurgeinterval,NULL,LIST_PURGE_INTERVAL); } extern unsigned int prefs_get_gamequeue_checkinterval(void) { return prefs_conf.gqcheckinterval; } static int conf_set_gqcheckinterval(const char* valstr) { return conf_set_int(&prefs_conf.gqcheckinterval,valstr,0); } static int conf_setdef_gqcheckinterval(void) { return conf_set_int(&prefs_conf.gqcheckinterval,NULL,GAMEQUEUE_CHECK_INTERVAL); } extern unsigned int prefs_get_maxgamelist(void) { return prefs_conf.maxgamelist; } static int conf_set_maxgamelist(const char* valstr) { return conf_set_int(&prefs_conf.maxgamelist,valstr,0); } static int conf_setdef_maxgamelist(void) { return conf_set_int(&prefs_conf.maxgamelist,NULL,MAX_GAME_LIST); } extern unsigned int prefs_allow_newchar(void) { return prefs_conf.allow_newchar; } static int conf_set_allow_newchar(const char* valstr) { return conf_set_bool(&prefs_conf.allow_newchar,valstr,0); } static int conf_setdef_allow_newchar(void) { return conf_set_bool(&prefs_conf.allow_newchar,NULL,1); } extern unsigned int prefs_get_idletime(void) { return prefs_conf.idletime; } static int conf_set_idletime(const char* valstr) { return conf_set_int(&prefs_conf.idletime,valstr,0); } static int conf_setdef_idletime(void) { return conf_set_int(&prefs_conf.idletime,NULL,MAX_CLIENT_IDLETIME); } extern char const * d2cs_prefs_get_logfile(void) { return prefs_conf.logfile; } static int conf_set_logfile(const char* valstr) { return conf_set_str(&prefs_conf.logfile,valstr,NULL); } static int conf_setdef_logfile(void) { return conf_set_str(&prefs_conf.logfile,NULL,DEFAULT_LOG_FILE); } extern unsigned int d2cs_prefs_get_shutdown_delay(void) { return prefs_conf.shutdown_delay; } static int conf_set_shutdown_delay(const char* valstr) { return conf_set_int(&prefs_conf.shutdown_delay,valstr,0); } static int conf_setdef_shutdown_delay(void) { return conf_set_int(&prefs_conf.shutdown_delay,NULL,DEFAULT_SHUTDOWN_DELAY); } extern unsigned int d2cs_prefs_get_shutdown_decr(void) { return prefs_conf.shutdown_decr; } static int conf_set_shutdown_decr(const char* valstr) { return conf_set_int(&prefs_conf.shutdown_decr,valstr,0); } static int conf_setdef_shutdown_decr(void) { return conf_set_int(&prefs_conf.shutdown_decr,NULL,DEFAULT_SHUTDOWN_DECR); } extern char const * prefs_get_bnetdaddr(void) { return prefs_conf.bnetdaddr; } static int conf_set_bnetdaddr(const char* valstr) { return conf_set_str(&prefs_conf.bnetdaddr,valstr,NULL); } static int conf_setdef_bnetaddr(void) { return conf_set_str(&prefs_conf.bnetdaddr,NULL,BNETD_SERVER_LIST); } extern char const * prefs_get_realmname(void) { return prefs_conf.realmname; } static int conf_set_realmname(const char* valstr) { return conf_set_str(&prefs_conf.realmname,valstr,NULL); } static int conf_setdef_realmname(void) { return conf_set_str(&prefs_conf.realmname,NULL,DEFAULT_REALM_NAME); } extern unsigned int prefs_get_s2s_retryinterval(void) { return prefs_conf.s2s_retryinterval; } static int conf_set_s2s_retryinterval(const char* valstr) { return conf_set_int(&prefs_conf.s2s_retryinterval,valstr,0); } static int conf_setdef_s2s_retryinterval(void) { return conf_set_int(&prefs_conf.s2s_retryinterval,NULL,DEFAULT_S2S_RETRYINTERVAL); } extern unsigned int prefs_get_s2s_timeout(void) { return prefs_conf.s2s_timeout; } static int conf_set_s2s_timeout(const char* valstr) { return conf_set_int(&prefs_conf.s2s_timeout,valstr,0); } static int conf_setdef_s2s_timeout(void) { return conf_set_int(&prefs_conf.s2s_timeout,NULL,DEFAULT_S2S_TIMEOUT); } extern unsigned int prefs_get_sq_timeout(void) { return prefs_conf.sq_timeout; } static int conf_set_sq_timeout(const char* valstr) { return conf_set_int(&prefs_conf.sq_timeout,valstr,0); } static int conf_setdef_sq_timeout(void) { return conf_set_int(&prefs_conf.sq_timeout,NULL,DEFAULT_SQ_TIMEOUT); } extern unsigned int prefs_get_sq_checkinterval(void) { return prefs_conf.sq_checkinterval; } static int conf_set_sq_checkinterval(const char* valstr) { return conf_set_int(&prefs_conf.sq_checkinterval,valstr,0); } static int conf_setdef_sq_checkinterval(void) { return conf_set_int(&prefs_conf.sq_checkinterval,NULL,DEFAULT_SQ_CHECKINTERVAL); } extern unsigned int prefs_get_d2gs_checksum(void) { return prefs_conf.d2gs_checksum; } static int conf_set_d2gs_checksum(const char* valstr) { return conf_set_int(&prefs_conf.d2gs_checksum,valstr,0); } static int conf_setdef_d2gs_checksum(void) { return conf_set_int(&prefs_conf.d2gs_checksum,NULL,0); } extern unsigned int prefs_get_d2gs_version(void) { return prefs_conf.d2gs_version; } static int conf_set_d2gs_version(const char* valstr) { return conf_set_int(&prefs_conf.d2gs_version,valstr,0); } static int conf_setdef_d2gs_version(void) { return conf_set_int(&prefs_conf.d2gs_version,NULL,0); } extern unsigned int prefs_get_ladderlist_count(void) { return 0x10; } extern unsigned int prefs_get_d2ladder_refresh_interval(void) { return prefs_conf.ladder_refresh_interval; } static int conf_set_ladder_refresh_interval(const char* valstr) { return conf_set_int(&prefs_conf.ladder_refresh_interval,valstr,0); } static int conf_setdef_ladder_refresh_interval(void) { return conf_set_int(&prefs_conf.ladder_refresh_interval,NULL,3600); } extern unsigned int prefs_get_game_maxlifetime(void) { return prefs_conf.game_maxlifetime; } static int conf_set_game_maxlifetime(const char* valstr) { return conf_set_int(&prefs_conf.game_maxlifetime,valstr,0); } static int conf_setdef_game_maxlifetime(void) { return conf_set_int(&prefs_conf.game_maxlifetime,NULL,0); } extern char const * prefs_get_ladder_dir(void) { return prefs_conf.ladderdir; } static int conf_set_ladderdir(const char* valstr) { return conf_set_str(&prefs_conf.ladderdir,valstr,NULL); } static int conf_setdef_ladderdir(void) { return conf_set_str(&prefs_conf.ladderdir,NULL,D2CS_LADDER_DIR); } extern char const * d2cs_prefs_get_loglevels(void) { return prefs_conf.loglevels; } static int conf_set_loglevels(const char* valstr) { return conf_set_str(&prefs_conf.loglevels,valstr,NULL); } static int conf_setdef_loglevels(void) { return conf_set_str(&prefs_conf.loglevels,NULL,DEFAULT_LOG_LEVELS); } extern unsigned int prefs_allow_gamelist_showall(void) { return prefs_conf.gamelist_showall; } static int conf_set_gamelist_showall(const char* valstr) { return conf_set_bool(&prefs_conf.gamelist_showall,valstr,0); } static int conf_setdef_gamelist_showall(void) { return conf_set_bool(&prefs_conf.gamelist_showall,NULL,0); } extern unsigned int prefs_allow_gamelimit(void) { return prefs_conf.allow_gamelimit; } static int conf_set_allow_gamelimit(const char* valstr) { return conf_set_bool(&prefs_conf.allow_gamelimit,valstr,0); } static int conf_setdef_allow_gamelimit(void) { return conf_set_bool(&prefs_conf.allow_gamelimit,NULL,1); } extern unsigned int prefs_check_multilogin(void) { return prefs_conf.check_multilogin; } static int conf_set_check_multilogin(const char* valstr) { return conf_set_bool(&prefs_conf.check_multilogin,valstr,0); } static int conf_setdef_check_multilogin(void) { return conf_set_bool(&prefs_conf.check_multilogin,NULL,1); } extern char const * prefs_get_d2gs_password(void) { return prefs_conf.d2gs_password; } static int conf_set_d2gs_password(const char* valstr) { return conf_set_str(&prefs_conf.d2gs_password,valstr,NULL); } static int conf_setdef_d2gs_password(void) { return conf_set_str(&prefs_conf.d2gs_password,NULL,""); } extern unsigned int prefs_get_s2s_idletime(void) { return prefs_conf.s2s_idletime; } static int conf_set_s2s_idletime(const char* valstr) { return conf_set_int(&prefs_conf.s2s_idletime,valstr,0); } static int conf_setdef_s2s_idletime(void) { return conf_set_int(&prefs_conf.s2s_idletime,NULL,DEFAULT_S2S_IDLETIME); } extern unsigned int prefs_get_s2s_keepalive_interval(void) { return prefs_conf.s2s_keepalive_interval; } static int conf_set_s2s_keepalive_interval(const char* valstr) { return conf_set_int(&prefs_conf.s2s_keepalive_interval,valstr,0); } static int conf_setdef_s2s_keepalive_interval(void) { return conf_set_int(&prefs_conf.s2s_keepalive_interval,NULL,DEFAULT_S2S_KEEPALIVE_INTERVAL); } extern unsigned int prefs_get_timeout_checkinterval(void) { return prefs_conf.timeout_checkinterval; } static int conf_set_timeout_checkinterval(const char* valstr) { return conf_set_int(&prefs_conf.timeout_checkinterval,valstr,0); } static int conf_setdef_timeout_checkinterval(void) { return conf_set_int(&prefs_conf.timeout_checkinterval,NULL,DEFAULT_TIMEOUT_CHECKINTERVAL); } extern unsigned int prefs_get_max_game_idletime(void) { return prefs_conf.max_game_idletime; } static int conf_set_max_game_idletime(const char* valstr) { return conf_set_int(&prefs_conf.max_game_idletime,valstr,0); } static int conf_setdef_max_game_idletime(void) { return conf_set_int(&prefs_conf.max_game_idletime,NULL,MAX_GAME_IDLE_TIME); } extern unsigned int prefs_get_lod_realm(void) { return prefs_conf.lod_realm; } static int conf_set_lod_realm(const char* valstr) { return conf_set_int(&prefs_conf.lod_realm,valstr,0); } static int conf_setdef_lod_realm(void) { return conf_set_int(&prefs_conf.lod_realm,NULL,2); } extern unsigned int prefs_get_allow_convert(void) { return prefs_conf.allow_convert; } static int conf_set_allow_convert(const char* valstr) { return conf_set_bool(&prefs_conf.allow_convert,valstr,0); } static int conf_setdef_allow_convert(void) { return conf_set_bool(&prefs_conf.allow_convert,NULL,0); } extern char const * d2cs_prefs_get_transfile(void) { return prefs_conf.transfile; } static int conf_set_transfile(const char* valstr) { return conf_set_str(&prefs_conf.transfile,valstr,NULL); } static int conf_setdef_transfile(void) { return conf_set_str(&prefs_conf.transfile,NULL,D2CS_TRANS_FILE); } extern char const * prefs_get_d2cs_account_allowed_symbols(void) { return prefs_conf.account_allowed_symbols; } static int conf_set_account_allowed_symbols(const char* valstr) { return conf_set_str(&prefs_conf.account_allowed_symbols,valstr,NULL); } static int conf_setdef_account_allowed_symbols(void) { return conf_set_str(&prefs_conf.account_allowed_symbols,NULL,DEFAULT_ACC_ALLOWED_SYMBOLS); } extern unsigned int prefs_get_ladder_start_time(void) { return prefs_conf.ladder_start_time; } static int conf_set_ladder_start_time(const char* valstr) { return conf_set_timestr(&prefs_conf.ladder_start_time,valstr,0); } static int conf_setdef_ladder_start_time(void) { return conf_set_timestr(&prefs_conf.ladder_start_time,NULL,0); } extern unsigned int prefs_get_d2gs_restart_delay(void) { return prefs_conf.d2gs_restart_delay; } static int conf_set_d2gs_restart_delay(const char* valstr) { return conf_set_int(&prefs_conf.d2gs_restart_delay,valstr,0); } static int conf_setdef_d2gs_restart_delay(void) { return conf_set_int(&prefs_conf.d2gs_restart_delay,NULL,DEFAULT_D2GS_RESTART_DELAY); } extern unsigned int prefs_get_char_expire_time(void) { return prefs_conf.char_expire_day * 3600 * 24; } static int conf_set_char_expire_day(const char* valstr) { return conf_set_int(&prefs_conf.char_expire_day,valstr,0); } static int conf_setdef_char_expire_day(void) { return conf_set_int(&prefs_conf.char_expire_day,NULL,0); } extern char const * prefs_get_d2gsconffile(void) { return prefs_conf.d2gsconffile; } static int conf_set_d2gsconffile(const char* valstr) { return conf_set_str(&prefs_conf.d2gsconffile,valstr,NULL); } static int conf_setdef_d2gsconffile(void) { return conf_set_str(&prefs_conf.d2gsconffile,NULL,""); } extern char const * prefs_get_charlist_sort(void) { return prefs_conf.charlist_sort; } static int conf_set_charlist_sort(const char* valstr) { return conf_set_str(&prefs_conf.charlist_sort,valstr,NULL); } static int conf_setdef_charlist_sort(void) { return conf_set_str(&prefs_conf.charlist_sort,NULL,"none"); } extern char const * prefs_get_charlist_sort_order(void) { return prefs_conf.charlist_sort_order; } static int conf_set_charlist_sort_order(const char* valstr) { return conf_set_str(&prefs_conf.charlist_sort_order,valstr,NULL); } static int conf_setdef_charlist_sort_order(void) { return conf_set_str(&prefs_conf.charlist_sort_order,NULL,"ASC"); } extern unsigned int prefs_get_max_connections(void) { return prefs_conf.max_connections; } static int conf_set_max_connections(const char* valstr) { return conf_set_int(&prefs_conf.max_connections,valstr,0); } static int conf_setdef_max_connections(void) { return conf_set_int(&prefs_conf.max_connections,NULL,BNETD_MAX_SOCKETS); } extern char const * prefs_get_pidfile(void) { return prefs_conf.pidfile; } static int conf_set_pidfile(const char* valstr) { return conf_set_str(&prefs_conf.pidfile,valstr,NULL); } static int conf_setdef_pidfile(void) { return conf_set_str(&prefs_conf.pidfile,NULL,""); } pvpgn-1.8.5/src/d2cs/gamequeue.c0000644000175000017500000001112611151345317015407 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strcasecmp.h" #include "connection.h" #include "gamequeue.h" #include "handle_d2cs.h" #include "common/packet.h" #include "common/list.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" static t_list * gqlist_head=NULL; static unsigned int gqlist_seqno=0; extern t_list * gqlist(void) { return gqlist_head; } extern int gqlist_create(void) { gqlist_head=list_create(); return 0; } extern int gqlist_destroy(void) { t_gq * gq; BEGIN_LIST_TRAVERSE_DATA(gqlist_head,gq) { gq_destroy(gq,(t_elem **)curr_elem_); } END_LIST_TRAVERSE_DATA() if (list_destroy(gqlist_head)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error destroy game queue list"); return -1; } gqlist_head=NULL; return 0; } extern t_gq * gq_create(unsigned int clientid, t_packet * packet, char const * gamename) { t_gq * gq; gq=xmalloc(sizeof(t_gq)); gq->seqno=++gqlist_seqno; gq->clientid=clientid; gq->packet=packet; strncpy(gq->gamename, gamename, MAX_GAMENAME_LEN); if (packet) packet_add_ref(packet); list_append_data(gqlist_head,gq); return gq; } extern int gq_destroy(t_gq * gq, t_elem ** elem) { ASSERT(gq,-1); if (list_remove_data(gqlist_head,gq,elem)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error remove game queue from list"); return -1; } if (gq->packet) packet_del_ref(gq->packet); xfree(gq); return 0; } extern unsigned int gq_get_clientid(t_gq const * gq) { ASSERT(gq,0); return gq->clientid; } extern int gqlist_check_creategame(int number) { t_connection * c; t_gq * gq; int i=0; if (number <= 0) return -1; BEGIN_LIST_TRAVERSE_DATA(gqlist_head,gq) { c=d2cs_connlist_find_connection_by_sessionnum(gq->clientid); if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"client %d not found (gamename: %s)",gq->clientid,gq->gamename); gq_destroy(gq,&curr_elem_); continue; } else if (!conn_get_gamequeue(c)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game queue for client %s",d2cs_conn_get_account(c)); gq_destroy(gq,&curr_elem_); continue; } else { eventlog(eventlog_level_info,__FUNCTION__,"try create game %s for account %s",gq->gamename,d2cs_conn_get_account(c)); d2cs_handle_client_creategame(c,gq->packet); conn_set_gamequeue(c,NULL); gq_destroy(gq,&curr_elem_); i++; if(i >= number) break; } } END_LIST_TRAVERSE_DATA() return 0; } extern int gqlist_update_all_clients(void) { t_connection * c; t_gq * gq; unsigned int n; n=0; BEGIN_LIST_TRAVERSE_DATA(gqlist_head,gq) { c=d2cs_connlist_find_connection_by_sessionnum(gq->clientid); if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"client %d not found (gamename: %s)",gq->clientid,gq->gamename); gq_destroy(gq,&curr_elem_); continue; } else { n++; eventlog(eventlog_level_debug,__FUNCTION__,"update client %s position to %d",d2cs_conn_get_account(c),n); d2cs_send_client_creategamewait(c,n); } } END_LIST_TRAVERSE_DATA() if (n) eventlog(eventlog_level_info,__FUNCTION__,"total %d game queues",n); return 0; } extern unsigned int gqlist_get_gq_position(t_gq * gq) { t_gq * tmp; unsigned int pos; pos=0; BEGIN_LIST_TRAVERSE_DATA(gqlist_head,tmp) { pos++; if (tmp==gq) return pos; } END_LIST_TRAVERSE_DATA() return 0; } extern unsigned int gqlist_get_length(void) { return list_get_length(gqlist_head); } extern t_gq * gqlist_find_game(char const * gamename) { t_gq * gq; BEGIN_LIST_TRAVERSE_DATA(gqlist_head,gq) { if (!strcasecmp(gq->gamename,gamename)) return gq; } END_LIST_TRAVERSE_DATA() return NULL; } pvpgn-1.8.5/src/d2cs/net.h0000644000175000017500000000227611151345317014232 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_NET_H #define INCLUDED_NET_H extern int net_socket(int type); extern unsigned long int net_inet_addr(char const * host); extern int net_check_connected(int sock); extern int net_listen(unsigned int ip, unsigned int port, int type); extern int net_send_data(int sock, char * buff, int buffsize, int * pos, int * currsize); extern int net_recv_data(int sock, char * buff, int buffsize, int * pos, int * currsize); #endif pvpgn-1.8.5/src/d2cs/d2cs_protocol.h0000644000175000017500000002273211151345317016217 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2CS_PROTOCOL_H #define INCLUDED_D2CS_PROTOCOL_H #include "common/bn_type.h" typedef struct { bn_short size; bn_byte type; } t_d2cs_client_header; typedef struct { t_d2cs_client_header h; } t_d2cs_client_generic; #define CLIENT_D2CS_LOGINREQ 0x01 typedef struct { t_d2cs_client_header h; bn_int seqno; bn_int u1; bn_int bncs_addr1; bn_int sessionnum; bn_int sessionkey; /* always zero,self define */ bn_int cdkey_id; bn_int u5; bn_int clienttag; bn_int bnversion; bn_int bncs_addr2; bn_int u6; /* zero */ bn_int secret_hash[5]; /* account name */ } t_client_d2cs_loginreq; #define D2CS_CLIENT_LOGINREPLY 0x01 typedef struct { t_d2cs_client_header h; bn_int reply; } t_d2cs_client_loginreply; #define D2CS_CLIENT_LOGINREPLY_SUCCEED 0x00 #define D2CS_CLIENT_LOGINREPLY_BADPASS 0x0c #define CLIENT_D2CS_CREATECHARREQ 0x02 typedef struct { t_d2cs_client_header h; bn_short class; /* character class */ bn_short u1; /* always zero */ bn_short status; /* same as in .d2s file */ /* character name */ } t_client_d2cs_createcharreq; #define D2CS_CLIENT_CREATECHARREPLY 0x02 typedef struct { t_d2cs_client_header h; bn_int reply; } t_d2cs_client_createcharreply; #define D2CS_CLIENT_CREATECHARREPLY_SUCCEED 0x00 #define D2CS_CLIENT_CREATECHARREPLY_FAILED 0x01 #define D2CS_CLIENT_CREATECHARREPLY_ALREADY_EXIST 0x14 #define D2CS_CLIENT_CREATECHARREPLY_NAME_REJECT 0x15 #define CLIENT_D2CS_CREATEGAMEREQ 0x03 typedef struct { t_d2cs_client_header h; bn_short seqno; bn_int gameflag; /* just difficulty is set here */ bn_byte u1; /* always 1 */ bn_byte leveldiff; /* Only allow people of +/- n level to join */ bn_byte maxchar; /* Maximum number of chars allowed in game */ /* game name */ /* game pass */ /* game desc */ } t_client_d2cs_creategamereq; #define D2CS_CLIENT_CREATEGAMEREPLY 0x03 typedef struct { t_d2cs_client_header h; bn_short seqno; bn_short gameid; bn_short u1; /* always zero */ bn_int reply; } t_d2cs_client_creategamereply; #define D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED 0x00 #define D2CS_CLIENT_CREATEGAMEREPLY_FAILED 0x01 #define D2CS_CLIENT_CREATEGAMEREPLY_INVALID_NAME 0x1e #define D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST 0x1f #define D2CS_CLIENT_CREATEGAMEREPLY_SERVER_DOWN 0x20 #define D2CS_CLIENT_CREATEGAMEREPLY_NOT_AVAILABLE 0x32 #define D2CS_CLIENT_CREATEGAMEREPLY_U1 0x33 #define CLIENT_D2CS_JOINGAMEREQ 0x04 typedef struct { t_d2cs_client_header h; bn_short seqno; /* game name */ /* game pass */ } t_client_d2cs_joingamereq; #define D2CS_CLIENT_JOINGAMEREPLY 0x04 typedef struct { t_d2cs_client_header h; bn_short seqno; bn_short gameid; bn_short u1; /* always zero */ bn_int addr; bn_int token; bn_int reply; } t_d2cs_client_joingamereply; #define D2CS_CLIENT_JOINGAMEREPLY_SUCCEED 0x00 #define D2CS_CLIENT_JOINGAMEREPLY_BAD_PASS 0x29 #define D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST 0x2a #define D2CS_CLIENT_JOINGAMEREPLY_GAME_FULL 0x2b #define D2CS_CLIENT_JOINGAMEREPLY_LEVEL_LIMIT 0x2c #define D2CS_CLIENT_JOINGAMEREPLY_HARDCORE_SOFTCORE 0x71 #define D2CS_CLIENT_JOINGAMEREPLY_NORMAL_NIGHTMARE 0x73 #define D2CS_CLIENT_JOINGAMEREPLY_NIGHTMARE_HELL 0x74 #define D2CS_CLIENT_JOINGAMEREPLY_CLASSIC_EXPANSION 0x78 #define D2CS_CLIENT_JOINGAMEREPLY_EXPANSION_CLASSIC 0x79 #define D2CS_CLIENT_JOINGAMEREPLY_NORMAL_LADDER 0x7D #define D2CS_CLIENT_JOINGAMEREPLY_FAILED 0x01 #define CLIENT_D2CS_GAMELISTREQ 0x05 typedef struct { t_d2cs_client_header h; bn_short seqno; bn_int gameflag; /* only hardcore is set here */ /* bn_byte u1; string game name to search? */ } t_client_d2cs_gamelistreq; #define D2CS_CLIENT_GAMELISTREPLY 0x05 typedef struct { t_d2cs_client_header h; bn_short seqno; bn_int token; bn_byte currchar; /* current number of characters in game */ bn_int gameflag; /* 0x04 is always set here */ /* game name */ /* game desc */ } t_d2cs_client_gamelistreply; #define CLIENT_D2CS_GAMEINFOREQ 0x06 typedef struct { t_d2cs_client_header h; bn_short seqno; /* game name */ } t_client_d2cs_gameinforeq; #define D2CS_CLIENT_GAMEINFOREPLY 0x06 typedef struct { t_d2cs_client_header h; bn_short seqno; bn_int gameflag; bn_int etime; bn_byte charlevel; bn_byte leveldiff; bn_byte maxchar; bn_byte currchar; bn_byte class[16]; /* 16 character class */ bn_byte level[16]; /* 16 character level */ /* game description */ /* currchar number of character names */ } t_d2cs_client_gameinforeply; #define CLIENT_D2CS_CHARLOGINREQ 0x07 typedef struct { t_d2cs_client_header h; /* character name */ } t_client_d2cs_charloginreq; #define D2CS_CLIENT_CHARLOGINREPLY 0x07 typedef struct { t_d2cs_client_header h; bn_int reply; } t_d2cs_client_charloginreply; #define D2CS_CLIENT_CHARLOGINREPLY_SUCCEED 0x00 #define D2CS_CLIENT_CHARLOGINREPLY_FAILED 0x01 #define D2CS_CLIENT_CHARLOGINREPLY_NOT_FOUND 0x46 #define D2CS_CLIENT_CHARLOGINREPLY_EXPIRED 0x7b #define CLIENT_D2CS_DELETECHARREQ 0x0a typedef struct { t_d2cs_client_header h; bn_short u1; /* always zero */ /* character name */ } t_client_d2cs_deletecharreq; #define D2CS_CLIENT_DELETECHARREPLY 0x0a typedef struct { t_d2cs_client_header h; bn_short u1; /* always zero */ bn_int reply; } t_d2cs_client_deletecharreply; #define D2CS_CLIENT_DELETECHARREPLY_SUCCEED 0x00 #define D2CS_CLIENT_DELETECHARREPLY_FAILED 0x01 #define CLIENT_D2CS_LADDERREQ 0x11 typedef struct { t_d2cs_client_header h; bn_byte type; /* jadder type request */ bn_short start_pos; /* list ladder from what position */ } t_client_d2cs_ladderreq; #define D2CS_CLIENT_LADDERREPLY 0x11 typedef struct { t_d2cs_client_header h; bn_byte type; /* ladder type request */ bn_short total_len; /* total length of the ladder data */ bn_short curr_len; /* length of ladder data in this packet */ bn_short cont_len; /* length of ladder data in previous packets */ /* length here include the header but exclude this packet */ } t_d2cs_client_ladderreply; typedef struct { bn_short start_pos; /* start position of ladder */ bn_short u1; /* always zero */ bn_int count1; /* always 0x10 */ } t_d2cs_client_ladderheader; typedef struct { bn_int count2; /* 0x10 for first packet or 0x0 for continue */ } t_d2cs_client_ladderinfoheader; typedef struct { bn_int explow; bn_int exphigh; /* always zero */ bn_short status; bn_byte level; bn_byte u1; /* always zero */ char charname[16]; } t_d2cs_client_ladderinfo; #define LADDERSTATUS_FLAG_DEAD 0x10 #define LADDERSTATUS_FLAG_HARDCORE 0x20 #define LADDERSTATUS_FLAG_EXPANSION 0x40 #define LADDERSTATUS_FLAG_DIFFICULTY 0x0f00 #define CLIENT_D2CS_MOTDREQ 0x12 typedef struct { t_d2cs_client_header h; } t_client_d2cs_motdreq; #define D2CS_CLIENT_MOTDREPLY 0x12 typedef struct { t_d2cs_client_header h; bn_byte u1; /* message */ } t_d2cs_client_motdreply; #define CLIENT_D2CS_CANCELCREATEGAME 0x13 typedef struct { t_d2cs_client_header h; } t_client_d2cs_cancelcreategame; #define D2CS_CLIENT_CREATEGAMEWAIT 0x14 typedef struct { t_d2cs_client_header h; bn_int position; } t_d2cs_client_creategamewait; #define D2CS_CLIENT_CHARLADDERREQ 0x16 typedef struct { t_d2cs_client_header h; bn_int hardcore; bn_int expansion; /* character name */ } t_client_d2cs_charladderreq; /* use 0x11 LADDER reply for this request */ #define CLIENT_D2CS_CHARLISTREQ 0x17 typedef struct { t_d2cs_client_header h; bn_short maxchar; bn_short u1; } t_client_d2cs_charlistreq; #define D2CS_CLIENT_CHARLISTREPLY 0x17 typedef struct { t_d2cs_client_header h; bn_short maxchar; bn_short currchar; bn_short u1; /* always zero */ bn_short currchar2; /* character name */ /* character portrait blocks */ /* each block is 0x22 bytes static length */ } t_d2cs_client_charlistreply; #define CLIENT_D2CS_CONVERTCHARREQ 0x18 typedef struct { t_d2cs_client_header h; /* character name */ } t_client_d2cs_convertcharreq; #define D2CS_CLIENT_CONVERTCHARREPLY 0x18 typedef struct { t_d2cs_client_header h; bn_int reply; } t_d2cs_client_convertcharreply; #define D2CS_CLIENT_CONVERTCHARREPLY_SUCCEED 0x00 #define D2CS_CLIENT_CONVERTCHARREPLY_FAILED 0x01 #define CLIENT_D2CS_CHARLISTREQ_110 0x19 typedef struct { t_d2cs_client_header h; bn_short maxchar; bn_short u1; } t_client_d2cs_charlistreq_110; #define D2CS_CLIENT_CHARLISTREPLY_110 0x19 typedef struct { t_d2cs_client_header h; bn_short maxchar; bn_short currchar; bn_short u1; /* always zero */ bn_short currchar2; } t_d2cs_client_charlistreply_110; typedef struct { bn_int expire_time; /* character expire time (in seconds) */ /* character name */ /* character portrait blocks */ /* each block is 0x22 bytes static length */ } t_d2cs_client_chardata; #endif pvpgn-1.8.5/src/d2cs/s2s.c0000644000175000017500000001163311151345317014143 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memset.h" #include "compat/strdup.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include #include "compat/strerror.h" #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/psock.h" #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #include #include "compat/psock.h" #include "compat/strtoul.h" #include "connection.h" #include "bnetd.h" #include "net.h" #include "s2s.h" #include "common/fdwatch.h" #include "server.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" extern int s2s_check(void) { bnetd_check(); return 0; } extern int s2s_init(void) { bnetd_init(); return 0; } extern t_connection * s2s_create(char const * server, unsigned short def_port, t_conn_class class) { struct sockaddr_in addr, laddr; psock_t_socklen laddr_len; unsigned int ip; unsigned short port; int sock, connected; t_connection * c; char * p, * tserver; ASSERT(server,NULL); tserver=xstrdup(server); p=strchr(tserver,':'); if (p) { port=(unsigned short)strtoul(p+1,NULL,10); *p='\0'; } else { port=def_port; } if ((sock=net_socket(PSOCK_SOCK_STREAM))<0) { eventlog(eventlog_level_error,__FUNCTION__,"error creating s2s socket"); xfree(tserver); return NULL; } memset(&addr,0,sizeof(addr)); addr.sin_family = PSOCK_AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr= net_inet_addr(tserver); xfree(tserver); eventlog(eventlog_level_info,__FUNCTION__,"try make s2s connection to %s",server); if (psock_connect(sock,(struct sockaddr *)&addr,sizeof(addr))<0) { if (psock_errno()!=PSOCK_EWOULDBLOCK && psock_errno() != PSOCK_EINPROGRESS) { eventlog(eventlog_level_error,__FUNCTION__,"error connecting to %s (psock_connect: %s)",server,pstrerror(psock_errno())); psock_close(sock); return NULL; } connected=0; eventlog(eventlog_level_info,__FUNCTION__,"connection to s2s server %s is in progress",server); } else { connected=1; eventlog(eventlog_level_info,__FUNCTION__,"connected to s2s server %s",server); } laddr_len=sizeof(laddr); memset(&laddr,0,sizeof(laddr)); ip=port=0; if (psock_getsockname(sock,(struct sockaddr *)&laddr,&laddr_len)<0) { eventlog(eventlog_level_error,__FUNCTION__,"unable to get local socket info"); } else { if (laddr.sin_family != PSOCK_AF_INET) { eventlog(eventlog_level_error,__FUNCTION__,"got bad socket family %d",laddr.sin_family); } else { ip=ntohl(laddr.sin_addr.s_addr); port=ntohs(laddr.sin_port); } } if (!(c=d2cs_conn_create(sock,ip,port, ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port)))) { eventlog(eventlog_level_error,__FUNCTION__,"error create s2s connection"); psock_close(sock); return NULL; } if (connected) { if (conn_add_fd(c,fdwatch_type_read, d2cs_server_handle_tcp)<0) { eventlog(eventlog_level_error, __FUNCTION__, "error adding socket %d to fdwatch pool (max sockets?)",sock); d2cs_conn_set_state(c,conn_state_destroy); return NULL; } d2cs_conn_set_state(c,conn_state_init); } else { if (conn_add_fd(c, fdwatch_type_write, d2cs_server_handle_tcp)<0) { eventlog(eventlog_level_error, __FUNCTION__, "error adding socket %d to fdwatch pool (max sockets?)",sock); d2cs_conn_set_state(c,conn_state_destroy); return NULL; } d2cs_conn_set_state(c,conn_state_connecting); } d2cs_conn_set_class(c,class); return c; } extern int s2s_destroy(t_connection * c) { ASSERT(c,-1); switch (d2cs_conn_get_class(c)) { case conn_class_bnetd: bnetd_destroy(c); break; default: eventlog(eventlog_level_error,__FUNCTION__,"got bad s2s connection class %d",d2cs_conn_get_class(c)); return -1; } return 0; } pvpgn-1.8.5/src/d2cs/main.c0000644000175000017500000001466711151345317014372 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strdup.h" #include #include "compat/strerror.h" #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include "server.h" #include "game.h" #include "connection.h" #include "serverqueue.h" #include "d2gs.h" #include "prefs.h" #include "cmdline.h" #include "d2ladder.h" #include "version.h" #include "common/trans.h" #include "common/fdwatch.h" #include "common/eventlog.h" #ifdef WIN32 # include "win32/service.h" #endif #include "common/xalloc.h" #ifdef WIN32_GUI # include "win32/winmain.h" #endif #include "common/setup_after.h" char serviceLongName[] = "d2cs service"; char serviceName[] = "d2cs"; char serviceDescription[] = "Diablo 2 Character Server"; int g_ServiceStatus = -1; static int init(void); static int cleanup(void); static int config_init(int argc, char * * argv); static int config_cleanup(void); static int setup_daemon(void); static char * write_to_pidfile(void); #ifdef DO_DAEMONIZE static int setup_daemon(void) { int pid; if (chdir("/")<0) { eventlog(eventlog_level_error,__FUNCTION__,"can not change working directory to root directory (chdir: %s)",pstrerror(errno)); return -1; } close(STDIN_FILENO); close(STDOUT_FILENO); if (!cmdline_get_foreground()) { close(STDERR_FILENO); } switch ((pid = fork())) { case 0: break; case -1: eventlog(eventlog_level_error,__FUNCTION__,"error create child process (fork: %s)",pstrerror(errno)); return -1; default: return pid; } umask(0); setsid(); return 0; } #endif static char * write_to_pidfile(void) { char *pidfile = xstrdup(prefs_get_pidfile()); if (pidfile[0]=='\0') { xfree((void *)pidfile); /* avoid warning */ return NULL; } if (pidfile) { #ifdef HAVE_GETPID FILE * fp; if (!(fp = fopen(pidfile,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to open pid file \"%s\" for writing (fopen: %s)",pidfile,pstrerror(errno)); xfree((void *)pidfile); /* avoid warning */ return NULL; } else { fprintf(fp,"%u",(unsigned int)getpid()); if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close pid file \"%s\" after writing (fclose: %s)",pidfile,pstrerror(errno)); } #else eventlog(eventlog_level_warn,__FUNCTION__,"no getpid() system call, disable pid file in d2cs.conf"); xfree((void *)pidfile); /* avoid warning */ return NULL; #endif } return pidfile; } static int init(void) { d2cs_connlist_create(); d2cs_gamelist_create(); sqlist_create(); d2gslist_create(); gqlist_create(); d2ladder_init(); if(trans_load(d2cs_prefs_get_transfile(),TRANS_D2CS)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load trans list"); fdwatch_init(prefs_get_max_connections()); return 0; } static int cleanup(void) { d2ladder_destroy(); d2cs_connlist_destroy(); d2cs_gamelist_destroy(); sqlist_destroy(); d2gslist_destroy(); gqlist_destroy(); trans_unload(); fdwatch_close(); return 0; } static int config_init(int argc, char * * argv) { char const * levels; char * temp; char const * tok; int pid; if (cmdline_load(argc, argv) != 1) { return -1; } #ifdef DO_DAEMONIZE if ((!cmdline_get_foreground())) { if (!((pid = setup_daemon()) == 0)) { return pid; } } #endif if (d2cs_prefs_load(cmdline_get_preffile())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading configuration file %s",cmdline_get_preffile()); return -1; } eventlog_clear_level(); if ((levels = d2cs_prefs_get_loglevels())) { temp = xstrdup(levels); tok = strtok(temp,","); /* strtok modifies the string it is passed */ while (tok) { if (eventlog_add_level(tok)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add log level \"%s\"",tok); tok = strtok(NULL,","); } xfree(temp); } #ifdef DO_DAEMONIZE if (cmdline_get_foreground()) { eventlog_set(stderr); } else #endif { if (cmdline_get_logfile()) { if (eventlog_open(cmdline_get_logfile())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error open eventlog file %s",cmdline_get_logfile()); return -1; } } else { if (eventlog_open(d2cs_prefs_get_logfile())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error open eventlog file %s",d2cs_prefs_get_logfile()); return -1; } } } return 0; } static int config_cleanup(void) { d2cs_prefs_unload(); cmdline_unload(); return 0; } #ifdef WIN32_GUI extern int server_main(int argc, char * * argv) #else extern int main(int argc, char * * argv) #endif { int pid; char * pidfile; eventlog_set(stderr); if (!((pid = config_init(argc, argv)) == 0)) { // if (pid==1) pid=0; return pid; } pidfile = write_to_pidfile(); eventlog(eventlog_level_info,__FUNCTION__,D2CS_VERSION); if (init()<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to init"); return -1; } else { eventlog(eventlog_level_info,__FUNCTION__,"server initialized"); } if (d2cs_server_process()<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to run server"); return -1; } cleanup(); if (pidfile) { if (remove(pidfile)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove pid file \"%s\" (remove: %s)",pidfile,pstrerror(errno)); xfree((void *)pidfile); /* avoid warning */ } config_cleanup(); eventlog_close(); return 0; } pvpgn-1.8.5/src/d2cs/connection.c0000644000175000017500000004777611151345317015614 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/memcpy.h" #include "compat/strdup.h" #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/psock.h" #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_LIMITS_H # include #endif #include "compat/char_bit.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_ASSERT_H # include #endif #include "compat/psock.h" #include "compat/strcasecmp.h" #include "connection.h" #include "game.h" #include "gamequeue.h" #include "prefs.h" #include "d2gs.h" #include "net.h" #include "s2s.h" #include "handle_d2gs.h" #include "handle_d2cs.h" #include "handle_init.h" #include "handle_bnetd.h" #include "d2charfile.h" #include "common/fdwatch.h" #include "common/addr.h" #include "common/introtate.h" #include "common/network.h" #include "common/packet.h" #include "common/hashtable.h" #include "common/queue.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" static t_hashtable * connlist_head=NULL; static t_hashtable * conn_charname_list_head=NULL; static t_list * connlist_dead=NULL; static unsigned int total_connection=0; static int conn_handle_connecting(t_connection * c); static t_packet * conn_create_packet(t_connection * c); static int conn_handle_packet(t_connection * c, t_packet * packet); static int conn_handle_read(t_connection * c); static int conn_handle_write(t_connection * c); static unsigned int conn_charname_hash(char const * charname); static unsigned int conn_sessionnum_hash(unsigned int sessionnum); static unsigned int conn_sessionnum_hash(unsigned int sessionnum) { return sessionnum; } static unsigned int conn_charname_hash(char const * charname) { unsigned int hash; unsigned int i, len, pos; unsigned int ch; ASSERT(charname,0); len=strlen(charname); for (hash=0, i=0, pos=0; isessionnum==sessionnum) { hashtable_entry_release(curr); return c; } } return NULL; } extern t_connection * d2cs_connlist_find_connection_by_charname(char const * charname) { t_entry * curr; t_connection * c; unsigned int hash; hash=conn_charname_hash(charname); HASHTABLE_TRAVERSE_MATCHING(connlist_head,curr,hash) { if (!(c=entry_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection in list"); } else { if (!c->charname) continue; if (!strcmp_charname(c->charname,charname)) { hashtable_entry_release(curr); return c; } } } return NULL; } static t_packet * conn_create_packet(t_connection * c) { t_packet * packet; switch (c->class) { CASE(conn_class_init, packet=packet_create(packet_class_init)); CASE(conn_class_d2cs, packet=packet_create(packet_class_d2cs)); CASE(conn_class_d2gs, packet=packet_create(packet_class_d2gs)); CASE(conn_class_bnetd, packet=packet_create(packet_class_d2cs_bnetd)); default: eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d",c->class); return NULL; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"error create packet"); return NULL; } d2cs_conn_set_in_queue(c,packet); return packet; } static int conn_handle_connecting(t_connection * c) { int retval; if (net_check_connected(c->sock)<0) { eventlog(eventlog_level_warn,__FUNCTION__,"can not connect to %s",addr_num_to_addr_str(c->addr, c->port)); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"connected to %s",addr_num_to_addr_str(c->addr, c->port)); c->state=conn_state_init; /* this is a kind of hack to not update fd but updating breaks kqueue * and the clean fix would require a cache a userland copy of the kernel * kqueue fds, considering that it also doesnt brake anything else should do * for the moment fdwatch_update_fd(c->sock, fdwatch_type_read); */ switch (c->class) { case conn_class_bnetd: retval=handle_bnetd_init(c); break; default: eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d",c->class); return -1; } return retval; } static int conn_handle_packet(t_connection * c, t_packet * packet) { int retval; switch (c->class) { CASE (conn_class_init, retval=d2cs_handle_init_packet(c,packet)); CASE (conn_class_d2cs, retval=d2cs_handle_d2cs_packet(c,packet)); CASE (conn_class_d2gs, retval=handle_d2gs_packet(c,packet)); CASE (conn_class_bnetd, retval=handle_bnetd_packet(c,packet)); default: eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d (close connection)",c->class); retval=-1; break; } return retval; } static int conn_handle_read(t_connection * c) { t_packet * packet; int retval; packet = d2cs_conn_get_in_queue(c); if (!packet) { packet = conn_create_packet(c); if (!packet) return -1; c->insize=0; } switch (net_recv_packet(c->sock,packet,&c->insize)) { case -1: retval=-1; break; case 0: retval=0; break; case 1: c->insize=0; d2cs_conn_set_in_queue(c,NULL); retval=conn_handle_packet(c,packet); packet_del_ref(packet); break; default: retval=0; break; } return retval; } static int conn_handle_write(t_connection * c) { t_packet * packet; int retval; if (c->state==conn_state_connecting) { return conn_handle_connecting(c); } if (!(packet=conn_peek_outqueue(c))) return 0; switch (net_send_packet(c->sock, packet, &c->outsize)) { case -1: retval=-1; break; case 0: retval=0; break; case 1: c->outsize=0; packet=conn_pull_outqueue(c); packet_del_ref(packet); retval=0; break; default: retval = -1; } return retval; } extern int conn_handle_socket(t_connection * c) { time_t now; ASSERT(c,-1); now=time(NULL); if (c->socket_flag & SOCKET_FLAG_READ) { if (conn_handle_read(c)<0) return -1; c->last_active=now; } if (c->socket_flag & SOCKET_FLAG_WRITE) { if (conn_handle_write(c)<0) return -1; c->last_active=now; } c->socket_flag=0; return 0; } extern int connlist_check_timeout(void) { t_connection * c; time_t now; now=time(NULL); BEGIN_HASHTABLE_TRAVERSE_DATA(connlist_head, c) { switch (c->class) { case conn_class_d2cs: if (prefs_get_idletime() && (now - c->last_active > prefs_get_idletime())) { eventlog(eventlog_level_info,__FUNCTION__,"client %d idled too long time, destroy it",c->sessionnum); d2cs_conn_set_state(c,conn_state_destroy); } break; case conn_class_d2gs: if (prefs_get_s2s_idletime() && now - c->last_active > prefs_get_s2s_idletime()) { eventlog(eventlog_level_info,__FUNCTION__,"server %d timed out",c->sessionnum); d2cs_conn_set_state(c,conn_state_destroy); } break; case conn_class_bnetd: break; default: break; } } END_HASHTABLE_TRAVERSE_DATA() return 0; } extern t_connection * d2cs_conn_create(int sock, unsigned int local_addr, unsigned short local_port, unsigned int addr, unsigned short port) { static unsigned int sessionnum=1; t_connection * c; if (sock<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad socket"); return NULL; } c=xmalloc(sizeof(t_connection)); c->charname=NULL; c->account=NULL; c->sock=sock; c->fdw_idx = -1; c->socket_flag=0; c->local_addr=local_addr; c->local_port=local_port; c->addr=addr; c->port=port; c->class=conn_class_init; c->state=conn_state_init; c->sessionnum=sessionnum++; c->outqueue=NULL; c->inqueue=NULL; c->outsize=0; c->outsizep=0; c->insize=0; c->charinfo=NULL; c->d2gs_id=0; c->gamequeue=NULL; c->last_active=time(NULL); c->sessionnum_hash=conn_sessionnum_hash(c->sessionnum); c->bnetd_sessionnum=0; c->charname_hash=0; if (hashtable_insert_data(connlist_head, c, c->sessionnum_hash)<0) { xfree(c); eventlog(eventlog_level_error,__FUNCTION__,"error add connection to list"); return NULL; } total_connection++; eventlog(eventlog_level_info,__FUNCTION__,"created session=%d socket=%d (%d current connections)", c->sessionnum, sock, total_connection); return c; } extern int d2cs_conn_destroy(t_connection * c, t_elem ** curr) { t_elem * elem; ASSERT(c,-1); if (c->state==conn_state_destroying) return 0; if (hashtable_remove_data(connlist_head,c,c->sessionnum_hash)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error remove connection from list"); return -1; } c->state=conn_state_destroying; if (c->d2gs_id && c->class==conn_class_d2gs) { d2gs_deactive(d2gslist_find_gs(c->d2gs_id),c); } if (c->class==conn_class_bnetd) { s2s_destroy(c); } if (c->gamequeue) { gq_destroy(c->gamequeue,&elem); } if (c->account) xfree((void *)c->account); if (c->charinfo) xfree((void *)c->charinfo); if (c->charname) d2cs_conn_set_charname(c,NULL); if (c->inqueue) packet_del_ref(c->inqueue); queue_clear(&c->outqueue); if (connlist_dead) list_remove_data(connlist_dead, c, curr); fdwatch_del_fd(c->fdw_idx); psock_shutdown(c->sock,PSOCK_SHUT_RDWR); psock_close(c->sock); total_connection--; eventlog(eventlog_level_info,__FUNCTION__,"[%d] closed connection %d (%d left)",c->sock,c->sessionnum,total_connection); xfree(c); return 0; } extern int d2cs_conn_get_socket(t_connection const * c) { ASSERT(c,-1); return c->sock; } extern t_conn_state d2cs_conn_get_state(t_connection const * c) { ASSERT(c,conn_state_none); return c->state; } extern int d2cs_conn_set_state(t_connection * c, t_conn_state state) { t_elem * curr; ASSERT(c,-1); /* special case for destroying connections, add them to connlist_dead list */ if (state == conn_state_destroy && c->state != conn_state_destroy) { if (!connlist_dead) connlist_dead = list_create(); list_append_data(connlist_dead, c); } else if (state != conn_state_destroy && c->state == conn_state_destroy) { if (list_remove_data(connlist_dead, c, &curr)) { eventlog(eventlog_level_error, __FUNCTION__, "could not remove dead connection"); return -1; } } c->state=state; return 0; } extern t_conn_class d2cs_conn_get_class(t_connection const * c) { ASSERT(c,conn_class_none); return c->class; } extern int d2cs_conn_set_class(t_connection * c, t_conn_class class) { ASSERT(c,-1); c->class=class; return 0; } extern t_packet * d2cs_conn_get_in_queue(t_connection const * c) { ASSERT(c,NULL); return c->inqueue; } extern void d2cs_conn_set_in_queue(t_connection * c, t_packet *packet) { assert(c); c->inqueue = packet; } extern unsigned int d2cs_conn_get_out_size(t_connection const * c) { ASSERT(c,0); return c->outsize; } extern t_queue * * d2cs_conn_get_out_queue(t_connection const * c) { ASSERT(c,NULL); return (t_queue * *)&c->outqueue; } extern unsigned int d2cs_conn_get_in_size(t_connection const * c) { ASSERT(c,0); return c->insize; } extern int conn_push_outqueue(t_connection * c, t_packet * packet) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return -1; } if (!packet) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL packet"); return -1; } queue_push_packet((t_queue * *)&c->outqueue, packet); if (!c->outsizep++) fdwatch_update_fd(c->fdw_idx, fdwatch_type_read | fdwatch_type_write); return 0; } extern t_packet * conn_peek_outqueue(t_connection * c) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return NULL; } return queue_peek_packet((t_queue const * const *)&c->outqueue); } extern t_packet * conn_pull_outqueue(t_connection * c) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return NULL; } if (c->outsizep) { if (!(--c->outsizep)) fdwatch_update_fd(c->fdw_idx, fdwatch_type_read); return queue_pull_packet((t_queue * *)&c->outqueue); } return NULL; } extern int conn_add_socket_flag(t_connection * c, unsigned int flag) { ASSERT(c,-1); c->socket_flag |= flag; return 0; } extern int conn_process_packet(t_connection * c, t_packet * packet, t_packet_handle_table * table, unsigned int table_size) { unsigned int type; unsigned int size; ASSERT(c,-1); ASSERT(packet,-1); ASSERT(table,-1); type=packet_get_type(packet); size=packet_get_size(packet); if (type >= table_size || !table[type].size) { eventlog(eventlog_level_error,__FUNCTION__,"got bad packet type %d (class %d)",type,packet_get_class(packet)); return -1; } if (size < table[type].size) { eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size %d (type %d class %d)",size,type,packet_get_class(packet)); return -1; } if (!(c->state & table[type].state)) { eventlog(eventlog_level_error,__FUNCTION__,"connection %d state mismatch for packet type %d (class %d)",c->sessionnum, type,packet_get_class(packet)); return -1; } if (!table[type].handler) { eventlog(eventlog_level_error,__FUNCTION__,"missing handler for packet type %d (class %d)",type,packet_get_class(packet)); return -1; } return table[type].handler(c,packet); } extern int d2cs_conn_set_account(t_connection * c, char const * account) { ASSERT(c,-1); if (!account) { if (c->account) xfree((void *)c->account); c->account=NULL; } if (c->account) xfree((void *)c->account); c->account=xstrdup(account); return 0; } extern char const * d2cs_conn_get_account(t_connection const * c) { ASSERT(c,NULL); return c->account; } extern int d2cs_conn_set_charname(t_connection * c, char const * charname) { char const * temp; ASSERT(c,-1); temp=NULL; if (charname) temp=xstrdup(charname); if (c->charname) { if (hashtable_remove_data(conn_charname_list_head,c,c->charname_hash) <0) { eventlog(eventlog_level_error,__FUNCTION__,"error remove charname %s from list",charname); if (temp) xfree((void *)temp); return -1; } hashtable_purge(conn_charname_list_head); xfree((void *)c->charname); } if (charname) { c->charname=temp; c->charname_hash=conn_charname_hash(charname); if (hashtable_insert_data(conn_charname_list_head,c,c->charname_hash) <0) { eventlog(eventlog_level_error,__FUNCTION__,"error insert charname %s to list",charname); xfree((void *)c->charname); c->charname=NULL; return -1; } } else { c->charname=NULL; c->charname_hash=0; } return 0; } extern char const * d2cs_conn_get_charname(t_connection const * c) { ASSERT(c,NULL); return c->charname; } extern unsigned int d2cs_conn_get_sessionnum(t_connection const * c) { ASSERT(c,0); return c->sessionnum; } extern unsigned int conn_get_charinfo_ladder(t_connection const * c) { ASSERT(c,0); return d2charinfo_get_ladder(c->charinfo); } extern unsigned int conn_get_charinfo_expansion(t_connection const * c) { ASSERT(c,0); return d2charinfo_get_expansion(c->charinfo); } extern unsigned int conn_get_charinfo_hardcore(t_connection const * c) { ASSERT(c,0); return d2charinfo_get_hardcore(c->charinfo); } extern unsigned int conn_get_charinfo_dead(t_connection const * c) { ASSERT(c,0); return d2charinfo_get_dead(c->charinfo); } extern unsigned int conn_get_charinfo_difficulty(t_connection const * c) { ASSERT(c,0); return d2charinfo_get_difficulty(c->charinfo); } extern unsigned int conn_get_charinfo_level(t_connection const * c) { ASSERT(c,0); return d2charinfo_get_level(c->charinfo); } extern unsigned int conn_get_charinfo_class(t_connection const * c) { ASSERT(c,0); return d2charinfo_get_class(c->charinfo); } extern int conn_set_charinfo(t_connection * c, t_d2charinfo_summary const * charinfo) { ASSERT(c,-1); if (!charinfo) { if (c->charinfo) xfree((void *)c->charinfo); c->charinfo=NULL; return 0; } if (c->charinfo) xfree((void *)c->charinfo); c->charinfo=xmalloc(sizeof(t_d2charinfo_summary)); memcpy((void*)c->charinfo,charinfo,sizeof(t_d2charinfo_summary)); return 0; } extern int conn_set_d2gs_id(t_connection * c, unsigned int d2gs_id) { ASSERT(c,-1) c->d2gs_id=d2gs_id; return 0; } extern unsigned int conn_get_d2gs_id(t_connection const * c) { ASSERT(c,0) return c->d2gs_id; } extern unsigned int d2cs_conn_get_addr(t_connection const * c) { ASSERT(c,0); return c->addr; } extern unsigned short d2cs_conn_get_port(t_connection const * c) { ASSERT(c,0); return c->port; } extern t_gq * conn_get_gamequeue(t_connection const * c) { ASSERT(c,NULL); return c->gamequeue; } extern int conn_set_gamequeue(t_connection * c, t_gq * gq) { ASSERT(c,-1); c->gamequeue=gq; return 0; } extern int conn_set_bnetd_sessionnum(t_connection * c, unsigned int sessionnum) { ASSERT(c,-1); c->bnetd_sessionnum=sessionnum; return 0; } extern unsigned int conn_get_bnetd_sessionnum(t_connection const * c) { ASSERT(c,0); return c->bnetd_sessionnum; } extern int conn_add_fd(t_connection * c, t_fdwatch_type rw, fdwatch_handler handler) { assert(c); c->fdw_idx = fdwatch_add_fd(c->sock,rw,handler,c); return c->fdw_idx; } pvpgn-1.8.5/src/d2cs/handle_d2cs.h0000644000175000017500000000216011151345317015602 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_HANDLE_D2CS_H #define INCLUDED_HANDLE_D2CS_H #include "connection.h" #include "common/packet.h" extern int d2cs_handle_d2cs_packet(t_connection * c, t_packet * packet); extern int d2cs_handle_client_creategame(t_connection * c, t_packet * packet); extern int d2cs_send_client_creategamewait(t_connection * c, unsigned int position); #endif pvpgn-1.8.5/src/d2cs/handle_signal.h0000644000175000017500000000221711151345317016227 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_HANDLE_SIGNAL_H #define INCLUDED_HANDLE_SIGNAL_H #ifndef WIN32 extern int handle_signal_init(void); #else extern void signal_quit_wrapper(void); extern void signal_reload_config_wrapper(void); extern void signal_load_ladder_wrapper(void); extern void signal_exit_wrapper(void); extern void signal_restart_d2gs_wrapper(void); #endif extern int handle_signal(void); #endif pvpgn-1.8.5/src/d2cs/prefs.h0000644000175000017500000000702311151345317014556 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_PREFS_H #define INCLUDED_PREFS_H extern int d2cs_prefs_load(char const * filename); extern int prefs_reload(char const * filename); extern int d2cs_prefs_unload(void); extern char const * d2cs_prefs_get_transfile(void); extern char const * d2cs_prefs_get_logfile(void); extern char const * prefs_get_servaddrs(void); extern char const * prefs_get_charsave_dir(void); extern char const * prefs_get_charinfo_dir(void); extern char const * prefs_get_bak_charsave_dir(void); extern char const * prefs_get_bak_charinfo_dir(void); extern char const * prefs_get_charsave_newbie(void); extern char const * prefs_get_motd(void); extern char const * prefs_get_realmname(void); extern char const * prefs_get_d2gs_list(void); extern unsigned int prefs_get_maxchar(void); extern unsigned int prefs_get_list_purgeinterval(void); extern unsigned int prefs_get_maxgamelist(void); extern unsigned int prefs_allow_newchar(void); extern unsigned int prefs_get_gamequeue_checkinterval(void); extern unsigned int prefs_get_idletime(void); extern unsigned int d2cs_prefs_get_shutdown_delay(void); extern unsigned int d2cs_prefs_get_shutdown_decr(void); extern char const * prefs_get_bnetdaddr(void); extern unsigned int prefs_get_s2s_retryinterval(void); extern unsigned int prefs_get_s2s_timeout(void); extern unsigned int prefs_get_sq_timeout(void); extern unsigned int prefs_get_sq_checkinterval(void); extern unsigned int prefs_get_d2gs_checksum(void); extern unsigned int prefs_get_d2gs_version(void); extern unsigned int prefs_get_ladderlist_count(void); extern unsigned int prefs_get_d2ladder_refresh_interval(void); extern unsigned int prefs_get_game_maxlifetime(void); extern char const * prefs_get_ladder_dir(void); extern char const * d2cs_prefs_get_loglevels(void); extern unsigned int prefs_allow_gamelist_showall(void); extern unsigned int prefs_allow_gamelimit(void); extern unsigned int prefs_check_multilogin(void); extern char const * prefs_get_d2gs_password(void); extern unsigned int prefs_get_s2s_idletime(void); extern unsigned int prefs_get_s2s_keepalive_interval(void); extern unsigned int prefs_get_timeout_checkinterval(void); extern unsigned int prefs_get_max_game_idletime(void); extern unsigned int prefs_get_lod_realm(void); extern unsigned int prefs_get_allow_convert(void); extern char const * prefs_get_d2cs_account_allowed_symbols(void); extern unsigned int prefs_get_d2gs_restart_delay(void); extern unsigned int prefs_get_ladder_start_time(void); extern unsigned int prefs_get_char_expire_time(void); extern char const * prefs_get_d2gsconffile(void); extern char const * prefs_get_charlist_sort(void); extern char const * prefs_get_charlist_sort_order(void); extern unsigned int prefs_get_max_connections(void); extern char const * prefs_get_pidfile(void); #endif pvpgn-1.8.5/src/d2cs/d2charfile.h0000644000175000017500000001212711151345317015443 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2CHARFILE_H #define INCLUDED_D2CHARFILE_H /* only used in char convert */ #define D2CHARSAVE_VERSION_OFFSET 0x04 #define D2CHARSAVE_CHECKSUM_OFFSET 0x0C /* used in both save init and convert */ #define D2CHARSAVE_STATUS_OFFSET 0x18 /* newbie.save offset or old version */ #define D2CHARSAVE_STATUS_OFFSET_109 0x24 /* 1.09 or later version (1.10) */ /* only used for save init to newbie.save file */ #define D2CHARSAVE_CLASS_OFFSET 0x22 #define D2CHARSAVE_CHARNAME_OFFSET 0x08 /* unused */ #define D2CHARSAVE_LEVEL_OFFSET 0x24 #define D2CHAR_MAX_CLASS 0x06 #define D2CHARINFO_PORTRAIT_PADBYTE 0xff #define D2CHARINFO_PORTRAIT_HEADER 0x8084 #define D2CHARINFO_PORTRAIT_MASK 0x80 #define D2CHARINFO_STATUS_FLAG_INIT 0x01 #define D2CHARINFO_STATUS_FLAG_EXPANSION 0x20 #define D2CHARINFO_STATUS_FLAG_LADDER 0x40 #define D2CHARINFO_STATUS_FLAG_HARDCORE 0x04 #define D2CHARINFO_STATUS_FLAG_DEAD 0x08 #define D2CHARINFO_STATUS_FLAG_INIT_MASK (D2CHARINFO_STATUS_FLAG_INIT | \ D2CHARINFO_STATUS_FLAG_EXPANSION| D2CHARINFO_STATUS_FLAG_LADDER |D2CHARINFO_STATUS_FLAG_HARDCORE) #include "bit.h" #define charstatus_set_init(status,n) BIT_SET_CLR_FLAG(status, D2CHARINFO_STATUS_FLAG_INIT, n) #define charstatus_set_expansion(status,n) BIT_SET_CLR_FLAG(status, D2CHARINFO_STATUS_FLAG_EXPANSION, n) #define charstatus_set_ladder(status,n) BIT_SET_CLR_FLAG(status, D2CHARINFO_STATUS_FLAG_LADDER, n) #define charstatus_set_hardcore(status,n) BIT_SET_CLR_FLAG(status, D2CHARINFO_STATUS_FLAG_HARDCORE, n) #define charstatus_set_dead(status,n) BIT_SET_CLR_FLAG(status, D2CHARINFO_STATUS_FLAG_DEAD, n) #define charstatus_get_init(status) BIT_TST_FLAG(status, D2CHARINFO_STATUS_FLAG_INIT) #define charstatus_get_expansion(status) BIT_TST_FLAG(status, D2CHARINFO_STATUS_FLAG_EXPANSION) #define charstatus_get_ladder(status) BIT_TST_FLAG(status, D2CHARINFO_STATUS_FLAG_LADDER) #define charstatus_get_hardcore(status) BIT_TST_FLAG(status, D2CHARINFO_STATUS_FLAG_HARDCORE) #define charstatus_get_dead(status) BIT_TST_FLAG(status, D2CHARINFO_STATUS_FLAG_DEAD) #define charstatus_get_difficulty(status) ((( status >> 0x08) & 0x0f )/4) /* number of act = 4 */ #define charstatus_get_difficulty_expansion(status) ((( status >> 0x08) & 0x0f )/5) /* number of act = 5 */ #ifndef JUST_NEED_TYPES #include "d2cs_d2gs_character.h" extern int d2char_create(char const * account, char const * charname, unsigned char class, unsigned short status); extern int d2char_delete(char const * account, char const * charname); extern int d2char_get_summary(char const * account, char const * charname,t_d2charinfo_summary * charinfo); extern int d2char_get_portrait(char const * account, char const * filename, t_d2charinfo_portrait * portrait); extern int d2char_portrait_init(t_d2charinfo_portrait * portrait); extern int d2charinfo_load(char const * account, char const * charname, t_d2charinfo_file * data); extern int d2charinfo_check(t_d2charinfo_file * data); extern unsigned int d2charinfo_get_expansion(t_d2charinfo_summary const * charinfo); extern unsigned int d2charinfo_get_level(t_d2charinfo_summary const * charinfo); extern unsigned int d2charinfo_get_class(t_d2charinfo_summary const * charinfo); extern unsigned int d2charinfo_get_hardcore(t_d2charinfo_summary const * charinfo); extern unsigned int d2charinfo_get_ladder(t_d2charinfo_summary const * charinfo); extern unsigned int d2charinfo_get_dead(t_d2charinfo_summary const * charinfo); extern unsigned int d2charinfo_get_difficulty(t_d2charinfo_summary const * charinfo); extern int d2char_convert(char const * account, char const * charname); extern int d2char_find(char const * account, char const * charname); extern int d2char_get_savefile_name(char * filename,char const * charname); extern int d2char_get_infofile_name(char * filename,char const * account, char const * charname); extern int d2char_get_bak_savefile_name(char * filename,char const * charname); extern int d2char_get_bak_infofile_name(char * filename,char const * account, char const * charname); extern int d2char_get_infodir_name(char * filename,char const * account); extern int d2char_check_acctname(char const * name); extern int d2char_check_charname(char const * name); extern int file_write(char const * filename, void * data, unsigned int size); extern int file_read(char const * filename, void * data, unsigned int * size); #endif #endif pvpgn-1.8.5/src/d2cs/d2gs.h0000644000175000017500000000511411151345317014275 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2GS_H #define INCLUDED_D2GS_H #include "common/list.h" #include "connection.h" typedef enum { d2gs_state_none, d2gs_state_connected, d2gs_state_authed } t_d2gs_state; typedef struct d2gs { unsigned int ip; unsigned int id; unsigned int flag; unsigned int active; unsigned int token; t_d2gs_state state; unsigned int maxgame; unsigned int gamenum; t_connection * connection; } t_d2gs; #define D2GS_FLAG_VALID 0x01 extern t_list * d2gslist(void); extern int d2gslist_create(void); extern int d2gslist_destroy(void); extern int d2gslist_reload(char const * gslist); extern t_d2gs * d2gs_create(char const * ip); extern int d2gs_destroy(t_d2gs * gs,t_elem ** curr); extern t_d2gs * d2gslist_get_server_by_id(unsigned int id); extern t_d2gs * d2gslist_choose_server(void); extern t_d2gs * d2gslist_find_gs(unsigned int id); extern t_d2gs * d2gslist_find_gs_by_ip(unsigned int ip); extern unsigned int d2gs_get_id(t_d2gs const * gs); extern unsigned int d2gs_get_ip(t_d2gs const * gs); extern t_d2gs_state d2gs_get_state(t_d2gs const * gs); extern int d2gs_set_state(t_d2gs * gs, t_d2gs_state state); extern unsigned int d2gs_get_maxgame(t_d2gs const * gs); extern int d2gs_set_maxgame(t_d2gs * gs,unsigned int maxgame); extern unsigned int d2gs_get_gamenum(t_d2gs const * gs); extern int d2gs_add_gamenum(t_d2gs * gs,int number); extern unsigned int d2gs_get_token(t_d2gs const * gs); extern unsigned int d2gs_make_token(t_d2gs * gs); extern t_connection * d2gs_get_connection(t_d2gs const * gs); extern int d2gs_active(t_d2gs * gs, t_connection * c); extern int d2gs_deactive(t_d2gs * gs, t_connection * c); extern unsigned int d2gs_calc_checksum(t_connection * c); extern int d2gs_keepalive(void); extern int d2gs_restart_all_gs(void); #define D2GS_MAJOR_VERSION_MASK 0xffffff00 #endif pvpgn-1.8.5/src/d2cs/bnetd.c0000644000175000017500000000461711151345317014534 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "bnetd.h" #include "prefs.h" #include "s2s.h" #include "handle_bnetd.h" #include "connection.h" #include "common/eventlog.h" #include "common/setup_after.h" static t_connection * bnetd_connection=NULL; extern int bnetd_init(void) { return bnetd_check(); } extern int bnetd_check(void) { static unsigned int prev_connecting_checktime=0; if (bnetd_connection) { if (d2cs_conn_get_state(bnetd_connection)==conn_state_connecting) { if (time(NULL) - prev_connecting_checktime > prefs_get_s2s_timeout()) { eventlog(eventlog_level_warn,__FUNCTION__,"connection to bnetd s2s timeout"); d2cs_conn_set_state(bnetd_connection,conn_state_destroy); return -1; } } return 0; } if (!(bnetd_connection=s2s_create(prefs_get_bnetdaddr(),BNETD_SERV_PORT,conn_class_bnetd))) { return -1; } if (d2cs_conn_get_state(bnetd_connection)==conn_state_init) { handle_bnetd_init(bnetd_connection); } else { prev_connecting_checktime=time(NULL); } return 0; } extern t_connection * bnetd_conn(void) { return bnetd_connection; } extern int bnetd_set_connection(t_connection * c) { bnetd_connection=c; return 0; } extern int bnetd_destroy(t_connection * c) { if (bnetd_connection != c) { eventlog(eventlog_level_error,__FUNCTION__,"bnetd connection do not match"); return -1; } bnetd_connection=NULL; return 0; } pvpgn-1.8.5/src/d2cs/d2ladder.c0000644000175000017500000002000411151345317015105 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strcasecmp.h" #include "compat/memset.h" #include #include "compat/strerror.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "prefs.h" #include "d2charfile.h" #include "d2ladder.h" #include "d2cs_protocol.h" #include "common/tag.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" static t_d2ladder * ladder_data=NULL; static unsigned int max_ladder_type=0; static int d2ladderlist_create(unsigned int maxtype); static int d2ladder_create(unsigned int type, unsigned int len); static int d2ladder_append_ladder(unsigned int type, t_d2ladderfile_ladderinfo * info); static int d2ladder_readladder(void); extern int d2ladder_init(void) { if (d2ladder_readladder()<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to initialize ladder data"); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"ladder data initialized"); return 0; } static int d2ladder_readladder(void) { FILE * fp; t_d2ladderfile_ladderindex * ladderheader; t_d2ladderfile_ladderinfo * ladderinfo; char * ladderfile; t_d2ladderfile_header header; unsigned int i, n, temp, count, type, number; ladderfile=xmalloc(strlen(prefs_get_ladder_dir())+1+strlen(LADDER_FILE_PREFIX)+1+ strlen(CLIENTTAG_DIABLO2DV)+1); sprintf(ladderfile,"%s/%s.%s",prefs_get_ladder_dir(),LADDER_FILE_PREFIX,CLIENTTAG_DIABLO2DV); if (!(fp=fopen(ladderfile,"rb"))) { eventlog(eventlog_level_error,__FUNCTION__,"error opening ladder file \"%s\" for reading (fopen: %s)",ladderfile,pstrerror(errno)); xfree(ladderfile); return -1; } xfree(ladderfile); if (fread(&header,1,sizeof(header),fp)!=sizeof(header)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading ladder file"); fclose(fp); return -1; } max_ladder_type= bn_int_get(header.maxtype); if (d2ladderlist_create(max_ladder_type)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error create ladder list"); fclose(fp); return -1; } temp= max_ladder_type * sizeof(*ladderheader); ladderheader=xmalloc(temp); if (fread(ladderheader,1,temp,fp)!=temp) { eventlog(eventlog_level_error,__FUNCTION__,"error read ladder file"); xfree(ladderheader); fclose(fp); return -1; } for (i=0, count=0; i< max_ladder_type ; i++) { type=bn_int_get(ladderheader[i].type); number=bn_int_get(ladderheader[i].number); if (d2ladder_create(type,number)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error create ladder %d",type); continue; } fseek(fp,bn_int_get(ladderheader[i].offset),SEEK_SET); temp=number * sizeof(*ladderinfo); ladderinfo=xmalloc(temp); if (fread(ladderinfo,1,temp,fp)!=temp) { eventlog(eventlog_level_error,__FUNCTION__,"error read ladder file"); xfree(ladderinfo); continue; } for (n=0; n< number; n++) { d2ladder_append_ladder(type,ladderinfo+n); } xfree(ladderinfo); if (number) count++; } xfree(ladderheader); fclose(fp); eventlog(eventlog_level_info,__FUNCTION__,"ladder file loaded successfully (%d types %d maxtype)",count,max_ladder_type); return 0; } static int d2ladderlist_create(unsigned int maxtype) { ladder_data=xmalloc(maxtype * sizeof(*ladder_data)); memset(ladder_data,0, maxtype * sizeof(*ladder_data)); return 0; } extern int d2ladder_refresh(void) { d2ladder_destroy(); return d2ladder_readladder(); } static int d2ladder_create(unsigned int type, unsigned int len) { if (type>max_ladder_type) { eventlog(eventlog_level_error,__FUNCTION__,"ladder type %d exceed max ladder type %d",type,max_ladder_type); return -1; } ladder_data[type].info=xmalloc(sizeof(t_d2cs_client_ladderinfo) * len); ladder_data[type].len=len; ladder_data[type].type=type; ladder_data[type].curr_len=0; return 0; } static int d2ladder_append_ladder(unsigned int type, t_d2ladderfile_ladderinfo * info) { t_d2cs_client_ladderinfo * ladderinfo; unsigned short ladderstatus; unsigned short status; unsigned char class; if (!info) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL info"); return -1; } if (type > max_ladder_type) { eventlog(eventlog_level_error,__FUNCTION__,"ladder type %d exceed max ladder type %d",type,max_ladder_type); return -1; } if (!ladder_data[type].info) { eventlog(eventlog_level_error,__FUNCTION__,"ladder data info not initialized"); return -1; } if (ladder_data[type].curr_len >= ladder_data[type].len) { eventlog(eventlog_level_error,__FUNCTION__,"ladder data overflow %d > %d", ladder_data[type].curr_len, ladder_data[type].len); return -1; } status = bn_short_get(info->status); class = bn_byte_get(info->class); ladderstatus = (status & LADDERSTATUS_FLAG_DIFFICULTY); if (charstatus_get_hardcore(status)) { ladderstatus |= LADDERSTATUS_FLAG_HARDCORE; if (charstatus_get_dead(status)) { ladderstatus |= LADDERSTATUS_FLAG_DEAD; } } if (charstatus_get_expansion(status)) { ladderstatus |= LADDERSTATUS_FLAG_EXPANSION; ladderstatus |= min(class,D2CHAR_EXP_CLASS_MAX); } else { ladderstatus |= min(class,D2CHAR_CLASS_MAX); } ladderinfo=ladder_data[type].info+ladder_data[type].curr_len; bn_int_set(&ladderinfo->explow, bn_int_get(info->experience)); bn_int_set(&ladderinfo->exphigh,0); bn_short_set(&ladderinfo->status,ladderstatus); bn_byte_set(&ladderinfo->level, bn_int_get(info->level)); bn_byte_set(&ladderinfo->u1, 0); strncpy(ladderinfo->charname, info->charname, MAX_CHARNAME_LEN); ladder_data[type].curr_len++; return 0; } extern int d2ladder_destroy(void) { unsigned int i; if (ladder_data) { for (i=0; i< max_ladder_type; i++) { if (ladder_data[i].info) { xfree(ladder_data[i].info); ladder_data[i].info=NULL; } } xfree(ladder_data); ladder_data=NULL; } max_ladder_type=0; return 0; } extern int d2ladder_get_ladder(unsigned int * from, unsigned int * count, unsigned int type, t_d2cs_client_ladderinfo const * * info) { t_d2ladder * ladder; if (!ladder_data) return -1; ladder=ladder_data+type; if (!ladder->curr_len || !ladder->info) { eventlog(eventlog_level_warn,__FUNCTION__,"ladder type %d not found",type); return -1; } if (ladder->type != type) { eventlog(eventlog_level_error,__FUNCTION__,"got bad ladder data"); return -1; } if (ladder->curr_len < *count) { *from = 0; *count=ladder->curr_len; } else if (*from + *count> ladder->curr_len) { *from= ladder->curr_len - *count; } *info = ladder->info+ *from; return 0; } extern int d2ladder_find_character_pos(unsigned int type, char const * charname) { unsigned int i; t_d2ladder * ladder; if (!ladder_data) return -1; ladder=ladder_data+type; if (!ladder->curr_len || !ladder->info) { eventlog(eventlog_level_warn,__FUNCTION__,"ladder type %d not found",type); return -1; } if (ladder->type != type) { eventlog(eventlog_level_error,__FUNCTION__,"got bad ladder data"); return -1; } for (i=0; i< ladder->curr_len; i++) { if (!strcasecmp(ladder->info[i].charname,charname)) return i; } return -1; } pvpgn-1.8.5/src/d2cs/d2cs_d2gs_character.h0000644000175000017500000000477511151345317017240 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2001 faster (lqx@cic.tsinghua.edu.cn) * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2CS_D2GS_CHARACTER_H #define INCLUDED_D2CS_D2GS_CHARACTER_H #ifdef D2CS # include "common/bn_type.h" #endif #ifdef D2GS # include "bn_types.h" #pragma pack(push, character_h, 1) #endif #define D2CHARINFO_MAGICWORD 0x12345678 #define D2CHARINFO_VERSION 0x00010000 #define D2CHARINFO_PORTRAIT_PADSIZE 30 typedef struct { bn_int magicword; /* static for check */ bn_int version; /* charinfo file version */ bn_int create_time; /* character creation time */ bn_int last_time; /* character last access time */ bn_int checksum; bn_int total_play_time; /* total in game play time */ bn_int reserved[6]; unsigned char charname[MAX_CHARNAME_LEN]; unsigned char account[MAX_ACCTNAME_LEN]; unsigned char realmname[MAX_REALMNAME_LEN]; } t_d2charinfo_header; typedef struct { bn_int experience; bn_int charstatus; bn_int charlevel; bn_int charclass; } t_d2charinfo_summary; typedef struct { bn_short header; /* 0x84 0x80 */ bn_byte gfx[11]; bn_byte class; bn_byte color[11]; bn_byte level; bn_byte status; bn_byte u1[3]; bn_byte ladder; /* need not be 0xff and 0 to make character displayed as ladder character */ /* client only check this bit */ bn_byte u2[2]; bn_byte end; /* 0x00 */ } t_d2charinfo_portrait; typedef struct { t_d2charinfo_header header; t_d2charinfo_portrait portrait; bn_byte pad[D2CHARINFO_PORTRAIT_PADSIZE]; t_d2charinfo_summary summary; } t_d2charinfo_file; #ifdef D2GS #pragma pack(pop, character_h) #endif #endif pvpgn-1.8.5/src/d2cs/net.c0000644000175000017500000001610711151345317014223 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/memset.h" #include #include "compat/strerror.h" #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #ifdef HAVE_NETDB_H # include #endif #include "compat/psock.h" #include "net.h" #include "common/eventlog.h" #include "common/setup_after.h" /* FIXME: use addr.h code to do this and make a separate error * return path so that 255.255.255.255 isn't an error. */ extern unsigned long int net_inet_addr(char const * host) { struct hostent * hp; if (isdigit((int)host[0])) { return inet_addr(host); } else { hp=gethostbyname(host); if (!hp || !(hp->h_addr_list)) { return ~0UL; } return *(unsigned long *)hp->h_addr_list[0]; } } extern int net_socket(int type) { int sock; int val; int ipproto; if (type==PSOCK_SOCK_STREAM) { ipproto = PSOCK_IPPROTO_TCP; } else { ipproto = PSOCK_IPPROTO_UDP; } if ((sock=psock_socket(PSOCK_PF_INET, type, ipproto))<0) { eventlog(eventlog_level_error,__FUNCTION__,"error creating socket (psock_socket: %s)", pstrerror(psock_errno())); return -1; } val=1; if (psock_setsockopt(sock,PSOCK_SOL_SOCKET, PSOCK_SO_KEEPALIVE, &val, sizeof(val))<0) { eventlog(eventlog_level_error,__FUNCTION__,"error set socket option KEEPALIVE (psock_setsockopt: %s)",pstrerror(psock_errno())); } if (psock_ctl(sock,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error set socket mode to non-block (psock_ctl: %s)",pstrerror(psock_errno())); psock_close(sock); return -1; } return sock; } extern int net_check_connected(int sock) { int err; psock_t_socklen errlen; err = 0; errlen = sizeof(err); if (psock_getsockopt(sock,PSOCK_SOL_SOCKET, PSOCK_SO_ERROR, &err, &errlen)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error get socket option SO_ERROR (psock_getsockopt: %s)",pstrerror(psock_errno())); return -1; } if (errlen && err) return -1; return 0; } extern int net_listen(unsigned int ip, unsigned int port, int type) { int sock; int val; struct sockaddr_in addr; int ipproto; if (type==PSOCK_SOCK_STREAM) { ipproto = PSOCK_IPPROTO_TCP; } else { ipproto = PSOCK_IPPROTO_UDP; } if ((sock=psock_socket(PSOCK_PF_INET, type, ipproto))<0) { eventlog(eventlog_level_error,__FUNCTION__,"error create listen socket"); return -1; } val=1; if (psock_setsockopt(sock,PSOCK_SOL_SOCKET,PSOCK_SO_REUSEADDR,&val,sizeof(int))<0) { eventlog(eventlog_level_error,__FUNCTION__,"error set socket option SO_REUSEADDR"); } memset(&addr,0,sizeof(addr)); addr.sin_family=PSOCK_AF_INET; addr.sin_port=htons(port); addr.sin_addr.s_addr=htonl(ip); if (psock_bind(sock,(struct sockaddr *)&addr, sizeof(addr))<0) { eventlog(eventlog_level_error,__FUNCTION__,"error bind listen socket"); psock_close(sock); return -1; } if (psock_listen(sock,LISTEN_QUEUE)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error listen socket"); psock_close(sock); return -1; } return sock; } extern int net_send_data(int sock, char * buff, int buffsize, int * pos, int * currsize) { int nsend; ASSERT(buff,-1); ASSERT(pos,-1); if (*pos>buffsize) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] send buffer overflow pos=%d buffsize=%d",sock,*pos,buffsize); return -1; } if (*currsize>*pos) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] send buffer error currsize=%d pos=%d",sock,*currsize,*pos); return -1; } nsend=psock_send(sock,buff+*pos-*currsize,*currsize,0); if (nsend==0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] no data sent (close connection)",sock); return -1; } if (nsend<0) { if ( #ifdef PSOCK_EINTR psock_errno()==PSOCK_EINTR || #endif #ifdef PSOCK_EAGAIN psock_errno()==PSOCK_EAGAIN || #endif #ifdef PSOCK_EWOULDBLOCK psock_errno()==PSOCK_EWOULDBLOCK || #endif #ifdef PSOCK_NOBUFS psock_errno()==PSOCK_ENOBUFS || #endif #ifdef PSOCK_ENOMEM psock_errno()==ENOMEM || #endif 0) return 0; eventlog(eventlog_level_error,__FUNCTION__,"[%d] error sent data (closing connection) (psock_send: %s)",sock,pstrerror(psock_errno())); return -1; } *currsize -= nsend; return 1; } extern int net_recv_data(int sock, char * buff, int buffsize, int * pos, int * currsize) { int nrecv; ASSERT(buff,-1); ASSERT(pos,-1); if (*pos>buffsize) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] recv buffer overflow pos=%d buffsize=%d",sock,*pos,buffsize); return -1; } if (*currsize>*pos) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] recv buffer error currsize=%d pos=%d",sock,*currsize,*pos); return -1; } if (*pos==buffsize) { memmove(buff,buff+*pos,*currsize); *pos=0; } nrecv=psock_recv(sock,buff+*pos,buffsize-*pos,0); if (nrecv==0) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] remote host closed connection",sock); return -1; } if (nrecv<0) { if ( #ifdef PSOCK_EINTR psock_errno()==PSOCK_EINTR || #endif #ifdef PSOCK_EAGAIN psock_errno()==PSOCK_EAGAIN || #endif #ifdef PSOCK_EWOULDBLOCK psock_errno()==PSOCK_EWOULDBLOCK || #endif #ifdef PSOCK_ENOMEM psock_errno()==ENOMEM || #endif 0) return 0; if ( #ifdef PSOCK_ENOTCONN psock_errno()==PSOCK_ENOTCONN || #endif #ifdef PSOCK_ECONNRESET psock_errno()==PSOCK_ECONNRESET || #endif 0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] remote host closed connection (psock_recv: %s)",sock,pstrerror(psock_errno())); return -1; } eventlog(eventlog_level_error,__FUNCTION__,"[%d] recv error (closing connection) (psock_recv: %s)",sock,pstrerror(psock_errno())); return -1; } * currsize += nrecv; return 1; } pvpgn-1.8.5/src/d2cs/bit.h0000644000175000017500000000256311151345317014221 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_BIT_H #define INCLUDED_BIT_H #define BIT_POS(n) ( 1u << (n) ) #define BIT_SET_FLAG(n,f) ( (n) |= (f) ) #define BIT_CLR_FLAG(n,f) ( (n) &= ~(f) ) #define BIT_TST_FLAG(n,f) ( ((n) & (f)) ? 1: 0 ) #define BIT_SET_CLR_FLAG(n, f, v) ( (v)?(BIT_SET_FLAG(n,f)):(BIT_CLR_FLAG(n,f)) ) #define BIT_RANGE(n,m) ( BIT_POS((m)+1-(n)) - BIT_POS(n) ) #define BIT_LSHIFT(n,m) ( (n) << (m) ) #define BIT_RSHIFT(n,m) ( (n) >> (m) ) #define BIT_GET(n, m) ( ((n) >> (m)) & 1) #define BIT_GET_RANGE(n, m, l) ( ((n) >> (m)) & (1u << (l) -1)) #define BIT_GET_RANGE_MASK(n, m, mask) ( ((n) >> (m)) & (mask)) #endif pvpgn-1.8.5/src/d2cs/handle_init.h0000644000175000017500000000171411151345317015716 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_HANDLE_INIT_H #define INCLUDED_HANDLE_INIT_H #include "connection.h" #include "common/packet.h" extern int d2cs_handle_init_packet(t_connection * c, t_packet * packet); #endif pvpgn-1.8.5/src/d2cs/d2charfile.c0000644000175000017500000006314011151345317015437 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/memset.h" #include "compat/memcpy.h" #include #include "compat/strerror.h" #ifdef HAVE_UNISTD_H # include #endif #include "compat/access.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_STAT_H # include #endif #include "d2charfile.h" #include "prefs.h" #include "common/xstring.h" #include "common/bn_type.h" #include "common/eventlog.h" #include "common/d2char_checksum.h" #include "common/xalloc.h" #include "common/setup_after.h" static int d2charsave_init(void * buffer,char const * charname,unsigned char class,unsigned short status); static int d2charinfo_init(t_d2charinfo_file * chardata, char const * account, char const * charname, unsigned char class, unsigned short status); static int d2charsave_init(void * buffer,char const * charname,unsigned char class,unsigned short status) { ASSERT(buffer,-1); ASSERT(charname,-1); bn_byte_set((bn_byte *)((char *)buffer+D2CHARSAVE_CLASS_OFFSET), class); bn_short_set((bn_short *)((char *)buffer+D2CHARSAVE_STATUS_OFFSET),status); strncpy((char *)buffer+D2CHARSAVE_CHARNAME_OFFSET,charname,MAX_CHARNAME_LEN); return 0; } static int d2charinfo_init(t_d2charinfo_file * chardata, char const * account, char const * charname, unsigned char class, unsigned short status) { unsigned int i; time_t now; now=time(NULL); bn_int_set(&chardata->header.magicword,D2CHARINFO_MAGICWORD); bn_int_set(&chardata->header.version,D2CHARINFO_VERSION); bn_int_set(&chardata->header.create_time,now); bn_int_set(&chardata->header.last_time,now); bn_int_set(&chardata->header.total_play_time,0); memset(chardata->header.charname, 0,MAX_CHARNAME_LEN); strncpy(chardata->header.charname,charname,MAX_CHARNAME_LEN); memset(chardata->header.account, 0,MAX_ACCTNAME_LEN); strncpy(chardata->header.account,account,MAX_ACCTNAME_LEN); memset(chardata->header.realmname, 0,MAX_REALMNAME_LEN); strncpy(chardata->header.realmname,prefs_get_realmname(),MAX_REALMNAME_LEN); bn_int_set(&chardata->header.checksum,0); for (i=0; iheader.reserved); i++) { bn_int_set(&chardata->header.reserved[i],0); } bn_int_set(&chardata->summary.charlevel,1); bn_int_set(&chardata->summary.experience,0); bn_int_set(&chardata->summary.charclass,class); bn_int_set(&chardata->summary.charstatus,status); memset(chardata->portrait.gfx,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.gfx)); memset(chardata->portrait.color,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.color)); memset(chardata->portrait.u2,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.u2)); memset(chardata->portrait.u1,D2CHARINFO_PORTRAIT_MASK,sizeof(chardata->portrait.u1)); memset(chardata->pad,0,sizeof(chardata->pad)); bn_short_set(&chardata->portrait.header,D2CHARINFO_PORTRAIT_HEADER); bn_byte_set(&chardata->portrait.status,status|D2CHARINFO_PORTRAIT_MASK); bn_byte_set(&chardata->portrait.class,class+1); bn_byte_set(&chardata->portrait.level,1); if (charstatus_get_ladder(status)) bn_byte_set(&chardata->portrait.ladder, 1); else bn_byte_set(&chardata->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); bn_byte_set(&chardata->portrait.end,'\0'); memset(chardata->pad,0,sizeof(chardata->pad)); return 0; } extern int d2char_create(char const * account, char const * charname, unsigned char class, unsigned short status) { t_d2charinfo_file chardata; char * savefile, * infofile; char buffer[1024]; unsigned int size; int ladder_time, now; FILE * fp; ASSERT(account,-1); ASSERT(charname,-1); if (class>D2CHAR_MAX_CLASS) class=0; status &= D2CHARINFO_STATUS_FLAG_INIT_MASK; charstatus_set_init(status,1); /* We need to make sure we are creating the correct character (Classic or Expansion) for the type of game server we are running. If lod_realm = 1 then only Expansion characters can be created and if set to 0 then only Classic character can be created */ if (!(prefs_get_lod_realm() == 2)) { if (prefs_get_lod_realm() && ((status & 0x20) != 0x20)) { eventlog(eventlog_level_warn,__FUNCTION__,"This Realm is for LOD Characters Only"); return -1; } if (!prefs_get_lod_realm() && ((status & 0x20) != 0x0)) { eventlog(eventlog_level_warn,__FUNCTION__,"This Realm is for Classic Characters Only"); return -1; } } /* Once correct type of character is varified then continue with creation of character */ if (!prefs_allow_newchar()) { eventlog(eventlog_level_warn,__FUNCTION__,"creation of new character is disabled"); return -1; } if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } size=sizeof(buffer); if (file_read(prefs_get_charsave_newbie(), buffer, &size)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading newbie save file"); return -1; } if (size>=sizeof(buffer)) { eventlog(eventlog_level_error,__FUNCTION__,"newbie save file \"%s\" is corrupt (length %lu, expected <%lu)",prefs_get_charsave_newbie(),(unsigned long)size,(unsigned long)sizeof(buffer)); return -1; } savefile=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(savefile,charname); if ((fp=fopen(savefile,"rb"))) { eventlog(eventlog_level_warn,__FUNCTION__,"character save file \"%s\" for \"%s\" already exist",savefile,charname); fclose(fp); xfree(savefile); return -1; } infofile=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(infofile,account,charname); now = time(NULL); ladder_time = prefs_get_ladder_start_time(); if ((ladder_time > 0) && (now < ladder_time)) charstatus_set_ladder(status, 0); d2charsave_init(buffer,charname,class,status); d2charinfo_init(&chardata,account,charname,class,status); if (file_write(infofile,&chardata,sizeof(chardata))<0) { eventlog(eventlog_level_error,__FUNCTION__,"error writing info file \"%s\"",infofile); remove(infofile); xfree(infofile); xfree(savefile); return -1; } if (file_write(savefile,buffer,size)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error writing save file \"%s\"",savefile); remove(infofile); remove(savefile); xfree(savefile); xfree(infofile); return -1; } xfree(savefile); xfree(infofile); eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) class %d status 0x%X created",charname,account,class,status); return 0; } extern int d2char_find(char const * account, char const * charname) { char * file; FILE * fp; ASSERT(account,-1); ASSERT(charname,-1); file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); fp=fopen(file,"rb"); xfree(file); if (fp) { fclose(fp); return 0; } return -1; } extern int d2char_convert(char const * account, char const * charname) { FILE * fp; char * file; unsigned char buffer[MAX_SAVEFILE_SIZE]; unsigned int status_offset; unsigned char status; unsigned int charstatus; t_d2charinfo_file charinfo; unsigned int size; unsigned int version; unsigned int checksum; ASSERT(account,-1); ASSERT(charname,-1); /* Playing with a expanstion char on a classic realm will cause the game server to crash, therefore I recommed setting allow_convert = 0 in the d2cs.conf We need to do this to prevent creating classic char and converting to expantion on a classic realm. LOD Char must be created on LOD realm */ if (!prefs_get_allow_convert()) { eventlog(eventlog_level_info,__FUNCTION__,"Convert char has been disabled"); return -1; } /* Procedure is stopped here and returned if allow_convet = 0 in d2cs.conf */ if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to open charinfo file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); if (fread(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charinfo file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } charstatus=bn_int_get(charinfo.summary.charstatus); charstatus_set_expansion(charstatus,1); bn_int_set(&charinfo.summary.charstatus,charstatus); status=bn_byte_get(charinfo.portrait.status); charstatus_set_expansion(status,1); bn_byte_set(&charinfo.portrait.status,status); fseek(fp,0,SEEK_SET); /* FIXME: check return */ if (fwrite(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close charinfo file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno)); return -1; } file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); size=fread(buffer,1,sizeof(buffer),fp); if (!feof(fp)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET); if (version>=0x0000005C) { status_offset=D2CHARSAVE_STATUS_OFFSET_109; } else { status_offset=D2CHARSAVE_STATUS_OFFSET; } status=bn_byte_get(buffer+status_offset); charstatus_set_expansion(status,1); bn_byte_set((bn_byte *)(buffer+status_offset),status); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ if (version>=0x0000005C) { checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET); bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ } fseek(fp,0,SEEK_SET); /* FIXME: check return */ if (fwrite(buffer,1,size,fp)!=size) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close charsave file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno)); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) converted to expansion",charname,account); return 0; } extern int d2char_delete(char const * account, char const * charname) { char * file; ASSERT(account,-1); ASSERT(charname,-1); if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } /* charsave file */ file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); if (remove(file)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to delete charinfo file \"%s\" (remove: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); /* charinfo file */ file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (remove(file)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to delete charsave file \"%s\" (remove: %s)",file,pstrerror(errno)); } xfree(file); /* bak charsave file */ file=xmalloc(strlen(prefs_get_bak_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_bak_infofile_name(file,account,charname); if (access(file, F_OK) == 0) { if (remove(file)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to delete bak charinfo file \"%s\" (remove: %s)",file,pstrerror(errno)); } } xfree(file); /* bak charinfo file */ file=xmalloc(strlen(prefs_get_bak_charsave_dir())+1+strlen(charname)+1); d2char_get_bak_savefile_name(file,charname); if (access(file, F_OK) == 0) { if (remove(file)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to delete bak charsave file \"%s\" (remove: %s)",file,pstrerror(errno)); } } xfree(file); eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) deleted",charname,account); return 0; } extern int d2char_get_summary(char const * account, char const * charname,t_d2charinfo_summary * charinfo) { t_d2charinfo_file data; ASSERT(account,-1); ASSERT(charname,-1); ASSERT(charinfo,-1); if (d2charinfo_load(account, charname, &data)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading character %s(*%s)",charname,account); return -1; } memcpy(charinfo,&data.summary,sizeof(data.summary)); eventlog(eventlog_level_info,__FUNCTION__,"character %s difficulty %d expansion %d hardcore %d dead %d loaded",charname, d2charinfo_get_difficulty(charinfo), d2charinfo_get_expansion(charinfo), d2charinfo_get_hardcore(charinfo),d2charinfo_get_dead(charinfo)); return 0; } extern int d2charinfo_load(char const * account, char const * charname, t_d2charinfo_file * data) { char * file; int size, ladder_time; if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); size=sizeof(t_d2charinfo_file); if (file_read(file,data,&size)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading character file %s",file); xfree(file); return -1; } if (size!=sizeof(t_d2charinfo_file)) { eventlog(eventlog_level_error,__FUNCTION__,"got bad charinfo file %s (length %d)",charname,size); xfree(file); return -1; } d2char_portrait_init(&data->portrait); if (d2charinfo_check(data) < 0) { xfree(file); return -1; } if (!(charstatus_get_ladder(bn_int_get(data->summary.charstatus)))) { bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); xfree(file); return 0; } ladder_time = prefs_get_ladder_start_time(); if ((ladder_time > 0) && bn_int_get(data->header.create_time) < ladder_time) { char buffer[MAX_SAVEFILE_SIZE]; unsigned int status_offset; unsigned char status; unsigned int charstatus; unsigned int size; unsigned int version; unsigned int checksum; FILE * fp; eventlog(eventlog_level_info,__FUNCTION__,"%s(*%s) was created in old ladder season, set to non-ladder", charname, account); if (!(fp=fopen(file,"wb"))) { eventlog(eventlog_level_error,__FUNCTION__,"charinfo file \"%s\" does not exist for account \"%s\"",file,account); xfree(file); return 0; } xfree(file); charstatus = bn_int_get(data->summary.charstatus); charstatus_set_ladder(charstatus, 0); bn_int_set(&data->summary.charstatus, charstatus); status=bn_byte_get(data->portrait.status); charstatus_set_ladder(status,0); bn_byte_set(&data->portrait.status,status); bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); if (fwrite(data,1,sizeof(*data),fp)!=sizeof(*data)) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } fclose(fp); file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return 0; } xfree(file); size=fread(buffer,1,sizeof(buffer),fp); if (!feof(fp)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET); if (version>=0x5C) { status_offset=D2CHARSAVE_STATUS_OFFSET_109; } else { status_offset=D2CHARSAVE_STATUS_OFFSET; } status=bn_byte_get(buffer+status_offset); charstatus_set_ladder(status,0); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ bn_byte_set((bn_byte *)(buffer+status_offset),status); if (version>=0x5C) { checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET); bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum); } fseek(fp,0,SEEK_SET); if (fwrite(buffer,1,size,fp)!=size) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } fclose(fp); } else { bn_byte_set(&data->portrait.ladder, 1); xfree(file); } return 0; } extern int d2charinfo_check(t_d2charinfo_file * data) { ASSERT(data,-1); if (bn_int_get(data->header.magicword) != D2CHARINFO_MAGICWORD) { eventlog(eventlog_level_error,__FUNCTION__,"info data check failed (header 0x%08X)",bn_int_get(data->header.magicword)); return -1; } if (bn_int_get(data->header.version) != D2CHARINFO_VERSION) { eventlog(eventlog_level_error,__FUNCTION__,"info data check failed (version 0x%08X)",bn_int_get(data->header.version)); return -1; } return 0; } extern int d2char_portrait_init(t_d2charinfo_portrait * portrait) { unsigned int i; unsigned char * p; p=(unsigned char *)portrait; for (i=0; i= MIN_NAME_LEN || i<= MAX_CHARNAME_LEN) return 0; return -1; } extern int d2char_check_acctname(char const * name) { unsigned int i; unsigned char ch; if (!name) return -1; if (!isalnum((int)name[0])) return -1; for (i=1; i<=MAX_CHARNAME_LEN; i++) { ch=name[i]; if (ch=='\0') break; if (isalnum(ch)) continue; if (strchr(prefs_get_d2cs_account_allowed_symbols(),ch)) continue; return -1; } if (i >= MIN_NAME_LEN || i<= MAX_ACCTNAME_LEN) return 0; return -1; } extern int d2char_get_savefile_name(char * filename, char const * charname) { char tmpchar[MAX_CHARNAME_LEN]; ASSERT(filename,-1); ASSERT(charname,-1); strncpy(tmpchar,charname,sizeof(tmpchar)); tmpchar[sizeof(tmpchar)-1]='\0'; strtolower(tmpchar); sprintf(filename,"%s/%s",prefs_get_charsave_dir(),tmpchar); return 0; } extern int d2char_get_bak_savefile_name(char * filename, char const * charname) { char tmpchar[MAX_CHARNAME_LEN]; ASSERT(filename,-1); ASSERT(charname,-1); strncpy(tmpchar,charname,sizeof(tmpchar)); tmpchar[sizeof(tmpchar)-1]='\0'; strtolower(tmpchar); sprintf(filename,"%s/%s",prefs_get_bak_charsave_dir(),tmpchar); return 0; } extern int d2char_get_infodir_name(char * filename, char const * account) { char tmpacct[MAX_ACCTNAME_LEN]; ASSERT(filename,-1); ASSERT(account,-1); strncpy(tmpacct,account,sizeof(tmpacct)); tmpacct[sizeof(tmpacct)-1]='\0'; strtolower(tmpacct); sprintf(filename,"%s/%s",prefs_get_charinfo_dir(),tmpacct); return 0; } extern int d2char_get_infofile_name(char * filename, char const * account, char const * charname) { char tmpchar[MAX_CHARNAME_LEN]; char tmpacct[MAX_ACCTNAME_LEN]; ASSERT(filename,-1); ASSERT(account,-1); ASSERT(charname,-1); strncpy(tmpchar,charname,sizeof(tmpchar)); tmpchar[sizeof(tmpchar)-1]='\0'; strtolower(tmpchar); strncpy(tmpacct,account,sizeof(tmpacct)); tmpchar[sizeof(tmpacct)-1]='\0'; strtolower(tmpacct); sprintf(filename,"%s/%s/%s",prefs_get_charinfo_dir(),tmpacct,tmpchar); return 0; } extern int d2char_get_bak_infofile_name(char * filename, char const * account, char const * charname) { char tmpchar[MAX_CHARNAME_LEN]; char tmpacct[MAX_ACCTNAME_LEN]; ASSERT(filename,-1); ASSERT(account,-1); ASSERT(charname,-1); strncpy(tmpchar,charname,sizeof(tmpchar)); tmpchar[sizeof(tmpchar)-1]='\0'; strtolower(tmpchar); strncpy(tmpacct,account,sizeof(tmpacct)); tmpchar[sizeof(tmpacct)-1]='\0'; strtolower(tmpacct); sprintf(filename,"%s/%s/%s",prefs_get_bak_charinfo_dir(),tmpacct,tmpchar); return 0; } extern unsigned int d2charinfo_get_ladder(t_d2charinfo_summary const * charinfo) { ASSERT(charinfo,0); return charstatus_get_ladder(bn_int_get(charinfo->charstatus)); } extern unsigned int d2charinfo_get_expansion(t_d2charinfo_summary const * charinfo) { ASSERT(charinfo,0); return charstatus_get_expansion(bn_int_get(charinfo->charstatus)); } extern unsigned int d2charinfo_get_level(t_d2charinfo_summary const * charinfo) { ASSERT(charinfo,0); return bn_int_get(charinfo->charlevel); } extern unsigned int d2charinfo_get_class(t_d2charinfo_summary const * charinfo) { ASSERT(charinfo,0); return bn_int_get(charinfo->charclass); } extern unsigned int d2charinfo_get_hardcore(t_d2charinfo_summary const * charinfo) { ASSERT(charinfo,0); return charstatus_get_hardcore(bn_int_get(charinfo->charstatus)); } extern unsigned int d2charinfo_get_dead(t_d2charinfo_summary const * charinfo) { ASSERT(charinfo,0); return charstatus_get_dead(bn_int_get(charinfo->charstatus)); } extern unsigned int d2charinfo_get_difficulty(t_d2charinfo_summary const * charinfo) { unsigned int difficulty; ASSERT(charinfo,0); if (d2charinfo_get_expansion(charinfo)) { difficulty=charstatus_get_difficulty_expansion(bn_int_get(charinfo->charstatus)); } else { difficulty=charstatus_get_difficulty(bn_int_get(charinfo->charstatus)); } if (difficulty>2) difficulty=2; return difficulty; } /* those functions should move to util.c */ extern int file_read(char const * filename, void * data, unsigned int * size) { FILE * fp; unsigned int n; ASSERT(filename,-1); ASSERT(data,-1); ASSERT(size,-1); if (!(fp=fopen(filename,"rb"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return -1; } fseek(fp,0,SEEK_END); /* FIXME: check return value */ n=ftell(fp); n=min(*size,n); rewind(fp); /* FIXME: check return value */ if (fread(data,1,n,fp)!=n) { eventlog(eventlog_level_error,__FUNCTION__,"error reading file \"%s\" (fread: %s)",filename,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno)); return -1; } *size=n; return 0; } extern int file_write(char const * filename, void * data, unsigned int size) { FILE * fp; ASSERT(filename,-1); ASSERT(data,-1); ASSERT(size,-1); if (!(fp=fopen(filename,"wb"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for writing (fopen: %s)",filename,pstrerror(errno)); return -1; } if (fwrite(data,1,size,fp)!=size) { eventlog(eventlog_level_error,__FUNCTION__,"error writing file \"%s\" (fwrite: %s)",filename,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after writing (fclose: %s)",filename,pstrerror(errno)); return -1; } return 0; } pvpgn-1.8.5/src/d2cs/s2s.h0000644000175000017500000000203711151345317014146 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_S2S_H #define INCLUDED_S2S_H #include "connection.h" extern int s2s_init(void); extern int s2s_check(void); extern t_connection * s2s_create(char const * server, unsigned short def_port, t_conn_class class); extern int s2s_destroy(t_connection * s2s); #endif pvpgn-1.8.5/src/d2cs/setup.h0000644000175000017500000001064511151345317014603 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2CS_SETUP_H #define INCLUDED_D2CS_SETUP_H /* FIXME: what is this for? */ #ifndef D2CS # define D2CS #endif #ifndef min # define min(a,b) (((a)>(b))?(b):(a)) #endif #ifndef max # define max(a,b) (((a)>(b))?(a):(b)) #endif #define tf(a) ((a)?1:0) #define strcmp_charname strcasecmp #define strncmp_charname strncasencmp #define BEGIN_LIST_TRAVERSE_DATA(list,data) \ {\ t_elem * curr_elem_;\ for (curr_elem_=list_get_first(list); curr_elem_ && (data=elem_get_data(curr_elem_)); \ curr_elem_=elem_get_next(list,curr_elem_)) #define END_LIST_TRAVERSE_DATA() \ } #define BEGIN_LIST_TRAVERSE_DATA_CONST(list,data)\ {\ t_elem const * curr_elem_;\ for (curr_elem_=list_get_first_const(list); curr_elem_ && (data=elem_get_data(curr_elem_)); \ curr_elem_=elem_get_next_const(list,curr_elem_)) #define END_LIST_TRAVERSE_DATA_CONST() \ } #define BEGIN_HASHTABLE_TRAVERSE_DATA(hashtable,data)\ {\ t_entry * curr_entry_;\ for (curr_entry_=hashtable_get_first(hashtable); curr_entry_ && (data=entry_get_data(curr_entry_));\ curr_entry_=entry_get_next(curr_entry_)) #define END_HASHTABLE_TRAVERSE_DATA() \ } #define BEGIN_HASHTABLE_TRAVERSE_MATCHING_DATA(hashtable,data,hash)\ {\ t_entry * curr_entry_;\ for (curr_entry_=hashtable_get_first_matching(hashtable,hash); \ curr_entry_ && (data=entry_get_data(curr_entry_)); \ curr_entry_ = entry_get_next_matching(curr_entry_)) #define END_HASHTABLE_TRAVERSE_DATA() \ } #define CASE(condition,func) case condition:\ func;\ break;\ #define ASSERT(var,retval) if (!var) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL " #var); return retval; } #define DECLARE_PACKET_HANDLER(handler) static int handler(t_connection *, t_packet *); #define NELEMS(s) sizeof(s)/sizeof(s[0]) #define MAX_SAVEFILE_SIZE 32 * 1024 #define MAX_CHARNAME_LEN 16 #define MAX_GAMENAME_LEN 16 #define MAX_GAMEPASS_LEN 16 #define MAX_GAMEDESC_LEN 32 #define MAX_ACCTNAME_LEN 16 #define MAX_REALMNAME_LEN 32 #define MIN_NAME_LEN 2 #define MAX_CHAR_PER_GAME 8 #define D2CS_SERVER_PORT 6113 #define MAX_GAME_IDLE_TIME 0 #define DEFAULT_S2S_RETRYINTERVAL 60 #define DEFAULT_S2S_TIMEOUT 60 #define DEFAULT_SQ_CHECKINTERVAL 300 #define DEFAULT_SQ_TIMEOUT 300 #define DEFAULT_REALM_NAME "D2CS" #define DEFAULT_SHUTDOWN_DELAY 300 #define DEFAULT_SHUTDOWN_DECR 60 #define DEFAULT_S2S_IDLETIME 300 #define DEFAULT_S2S_KEEPALIVE_INTERVAL 60 #define DEFAULT_TIMEOUT_CHECKINTERVAL 60 #define DEFAULT_ACC_ALLOWED_SYMBOLS "-_[]" #define DEFAULT_D2GS_RESTART_DELAY 300 #define MAJOR_VERSION_EQUAL(v1,v2,mask) (((v1) & (mask)) == ((v2) & (mask))) #ifndef D2CS_DEFAULT_CONF_FILE # define D2CS_DEFAULT_CONF_FILE "conf/d2cs.conf" #endif #define DEFAULT_LOG_FILE "/usr/local/var/d2cs.log" #define DEFAULT_LOG_LEVELS "info,warn,error" #define DEFAULT_MEMLOG_FILE "/tmp/d2cs-mem.log" #define D2CS_SERVER_ADDRS "0.0.0.0" #define D2GS_SERVER_LIST "192.168.0.1" #define BNETD_SERVER_LIST "192.168.0.1" #define MAX_D2GAME_NUMBER 30 #define MAX_CHAR_PER_ACCT 8 // MAX_MAX_CHAR_PER_ACCT is needed cause D2 client can at worst case only handle 18 chars #define MAX_MAX_CHAR_PER_ACCT 18 #define MAX_CLIENT_IDLETIME 30 * 60 #define D2CS_CHARINFO_DIR "/usr/local/var/charinfo" #define D2CS_CHARSAVE_DIR "/usr/local/var/charsave" #define D2CS_BAK_CHARINFO_DIR "/usr/local/var/bak/charinfo" #define D2CS_BAK_CHARSAVE_DIR "/usr/local/var/bak/charsave" #define D2CS_CHARSAVE_NEWBIE "/usr/local/var/files/newbie.save" #define D2CS_TRANS_FILE "/usr/local/etc/address_translation.conf" #define D2CS_LADDER_DIR "/usr/local/var/ladders" #define D2CS_MOTD "No MOTD yet" #define LIST_PURGE_INTERVAL 300 #define GAMEQUEUE_CHECK_INTERVAL 60 #define MAX_GAME_LIST 20 #endif pvpgn-1.8.5/src/d2cs/server.c0000644000175000017500000002207511151345317014744 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/memset.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/psock.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #include "compat/psock.h" #include "d2gs.h" #include "net.h" #include "s2s.h" #include "gamequeue.h" #include "game.h" #include "connection.h" #include "serverqueue.h" #include "common/fdwatch.h" #include "server.h" #include "prefs.h" #include "d2ladder.h" #include "handle_signal.h" #include "common/addr.h" #include "common/list.h" #include "common/hashtable.h" #include "common/eventlog.h" #ifdef WIN32 # include /* for kbhit() and getch() */ #endif #include "common/setup_after.h" static int server_listen(void); static int server_accept(int sock); static int server_handle_timed_event(void); static int server_handle_socket(void); static int server_loop(void); static int server_cleanup(void); t_addrlist * server_listen_addrs; extern int g_ServiceStatus; static int server_listen(void) { t_addr * curr_laddr; t_addr_data laddr_data; int sock; if (!(server_listen_addrs=addrlist_create(prefs_get_servaddrs(),INADDR_ANY,D2CS_SERVER_PORT))) { eventlog(eventlog_level_error,__FUNCTION__,"error create listening address list"); return -1; } BEGIN_LIST_TRAVERSE_DATA(server_listen_addrs,curr_laddr) { sock=net_listen(addr_get_ip(curr_laddr),addr_get_port(curr_laddr),PSOCK_SOCK_STREAM); if (sock<0) { eventlog(eventlog_level_error,__FUNCTION__,"error listen socket"); return -1; } if (psock_ctl(sock,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error set listen socket in non-blocking mode"); } laddr_data.i = sock; addr_set_data(curr_laddr,laddr_data); if (fdwatch_add_fd(sock, fdwatch_type_read, d2cs_server_handle_accept, curr_laddr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error adding socket %d to fdwatch pool (max sockets?)",sock); psock_close(sock); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"listen on %s", addr_num_to_addr_str(addr_get_ip(curr_laddr),addr_get_port(curr_laddr))); } END_LIST_TRAVERSE_DATA() return 0; } static int server_accept(int sock) { int csock; struct sockaddr_in caddr, raddr; psock_t_socklen caddr_len, raddr_len; int val; unsigned int ip; unsigned short port; t_connection *cc; caddr_len=sizeof(caddr); memset(&caddr,0,sizeof(caddr)); csock=psock_accept(sock,(struct sockaddr *)&caddr,&caddr_len); if (csock<0) { eventlog(eventlog_level_error,__FUNCTION__,"error accept new connection"); return -1; } else eventlog(eventlog_level_info,__FUNCTION__,"accept connection from %s",inet_ntoa(caddr.sin_addr)); val=1; if (psock_setsockopt(csock, PSOCK_SOL_SOCKET, PSOCK_SO_KEEPALIVE, &val,sizeof(val))<0) { eventlog(eventlog_level_warn,__FUNCTION__,"error set sock option keep alive"); } if (psock_ctl(csock, PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error set socket to non-blocking mode"); psock_close(csock); return -1; } raddr_len=sizeof(raddr); memset(&raddr,0,sizeof(raddr)); ip=port=0; if (psock_getsockname(csock,(struct sockaddr *)&raddr,&raddr_len)<0) { eventlog(eventlog_level_warn,__FUNCTION__,"unable to get local socket info"); } else { if (raddr.sin_family!=PSOCK_AF_INET) { eventlog(eventlog_level_warn,__FUNCTION__,"got bad socket family %d",raddr.sin_family); } else { ip=ntohl(raddr.sin_addr.s_addr); port=ntohs(raddr.sin_port); } } if (!(cc = d2cs_conn_create(csock,ip,port,ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)))) { eventlog(eventlog_level_error,__FUNCTION__,"error create new connection"); psock_close(csock); return -1; } if (conn_add_fd(cc, fdwatch_type_read, d2cs_server_handle_tcp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error adding socket %d to fdwatch pool (max sockets?)",csock); d2cs_conn_set_state(cc,conn_state_destroy); return -1; } return 0; } static int server_handle_timed_event(void) { static time_t prev_list_purgetime=0; static time_t prev_gamequeue_checktime=0; static time_t prev_s2s_checktime=0; static time_t prev_sq_checktime=0; static time_t prev_d2ladder_refresh_time=0; static time_t prev_s2s_keepalive_time=0; static time_t prev_timeout_checktime; time_t now; now=time(NULL); if (now-prev_list_purgetime>(signed)prefs_get_list_purgeinterval()) { hashtable_purge(d2cs_connlist()); d2cs_gamelist_check_voidgame(); prev_list_purgetime=now; } if (now-prev_gamequeue_checktime>(signed)prefs_get_gamequeue_checkinterval()) { gqlist_update_all_clients(); prev_gamequeue_checktime=now; } if (now-prev_s2s_checktime>(signed)prefs_get_s2s_retryinterval()) { s2s_check(); prev_s2s_checktime=now; } if (now-prev_sq_checktime>(signed)prefs_get_sq_checkinterval()) { sqlist_check_timeout(); prev_sq_checktime=now; } if (now-prev_d2ladder_refresh_time>(signed)prefs_get_d2ladder_refresh_interval()) { d2ladder_refresh(); prev_d2ladder_refresh_time=now; } if (now-prev_s2s_keepalive_time>(signed)prefs_get_s2s_keepalive_interval()) { d2gs_keepalive(); prev_s2s_keepalive_time=now; } if (now-prev_timeout_checktime>(signed)prefs_get_timeout_checkinterval()) { connlist_check_timeout(); prev_timeout_checktime=now; } return 0; } extern int d2cs_server_handle_accept(void *data, t_fdwatch_type rw) { int sock; sock = addr_get_data((t_addr *)data).i; server_accept(sock); return 0; } extern int d2cs_server_handle_tcp(void *data, t_fdwatch_type rw) { t_connection *c = (t_connection *)data; if (rw & fdwatch_type_read) conn_add_socket_flag(c,SOCKET_FLAG_READ); if (rw & fdwatch_type_write) conn_add_socket_flag(c,SOCKET_FLAG_WRITE); if (conn_handle_socket(c)<0) d2cs_conn_set_state(c, conn_state_destroy); return 0; } static int server_handle_socket(void) { switch (fdwatch(BNETD_POLL_INTERVAL)) { case -1: if ( #ifdef PSOCK_EINTR psock_errno()!=PSOCK_EINTR && #endif 1) { eventlog(eventlog_level_error,__FUNCTION__,"select failed (select: %s)",pstrerror(psock_errno())); return -1; } /* fall through */ case 0: return 0; default: break; } fdwatch_handle(); return 0; } static int server_loop(void) { unsigned int count; count=0; while (1) { #ifdef WIN32 if (g_ServiceStatus<0 && kbhit() && getch()=='q') signal_quit_wrapper(); if (g_ServiceStatus == 0) signal_quit_wrapper(); while (g_ServiceStatus == 2) Sleep(1000); #endif if (handle_signal()<0) break; if (++count>=(1000/BNETD_POLL_INTERVAL)) { server_handle_timed_event(); count=0; } server_handle_socket(); d2cs_connlist_reap(); } return 0; } static int server_cleanup(void) { t_addr * curr_laddr; int sock; BEGIN_LIST_TRAVERSE_DATA(server_listen_addrs,curr_laddr) { sock=addr_get_data(curr_laddr).i; psock_close(sock); } END_LIST_TRAVERSE_DATA() addrlist_destroy(server_listen_addrs); return 0; } extern int d2cs_server_process(void) { #ifndef WIN32 handle_signal_init(); #endif if (psock_init()<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to init network"); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"network initialized"); if (s2s_init()<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to init s2s connection"); return -1; } if (server_listen()<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to setup listen socket"); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"entering server loop"); server_loop(); eventlog(eventlog_level_info,__FUNCTION__,"exit from server loop,cleanup"); server_cleanup(); return 0; } pvpgn-1.8.5/src/d2cs/game.h0000644000175000017500000001365011151345317014353 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_GAME_H #define INCLUDED_GAME_H #include "d2gs.h" #include "connection.h" #include "bit.h" typedef struct { unsigned char class; unsigned char level; char const * charname; } t_game_charinfo; typedef struct { unsigned int id; char const * name; char const * pass; char const * desc; int create_time; int lastaccess_time; unsigned int created; unsigned int gameflag; unsigned int charlevel; unsigned int leveldiff; unsigned int d2gs_gameid; unsigned int maxchar; unsigned int currchar; t_list * charlist; t_d2gs * d2gs; } t_game; #define D2_GAMEFLAG_BETA 0x00000001 #define D2_GAMEFLAG_RELEASE 0x00000002 #define D2_GAMEFLAG_TEMPLATE 0x00000008 #define D2_GAMEFLAG_SINGLE 0x00000010 #define D2_GAMEFLAG_HARDCORE 0x00000800 #define D2_GAMEFLAG_EXPANSION 0x00100000 #define D2_GAMEFLAG_LADDER 0x00200000 #define gameflag_get_difficulty(gameflag) ( (gameflag >> 0x0C) & 0x07 ) #define gameflag_get_expansion(gameflag) BIT_TST_FLAG(gameflag, D2_GAMEFLAG_EXPANSION) #define gameflag_get_ladder(gameflag) BIT_TST_FLAG(gameflag, D2_GAMEFLAG_LADDER) #define gameflag_get_hardcore(gameflag) BIT_TST_FLAG(gameflag, D2_GAMEFLAG_HARDCORE) #define gameflag_get_beta(gameflag) BIT_TST_FLAG(gameflag, D2_GAMEFLAG_BETA) /* true if the game is a beta version with limitations */ #define gameflag_get_release(gameflag) BIT_TST_FLAG(gameflag, D2_GAMEFLAG_RELEASE) /* this bit must always not be zero */ #define gameflag_get_single(gameflag) BIT_TST_FLAG(gameflag, D2_GAMEFLAG_SINGLE) /* true if the game is single mode without party */ #define gameflag_get_template(gameflag) BIT_TST_FLAG(gameflag, D2_GAMEFLAG_TEMPLATE) /* true if use template settings */ #define gameflag_set_difficulty(gameflag,n) ( gameflag |= ((n & 0x07) << 0x0C) ) #define gameflag_set_expansion(gameflag,n) BIT_SET_CLR_FLAG(gameflag, D2_GAMEFLAG_EXPANSION, n) #define gameflag_set_ladder(gameflag,n) BIT_SET_CLR_FLAG(gameflag, D2_GAMEFLAG_LADDER, n) #define gameflag_set_hardcore(gameflag,n) BIT_SET_CLR_FLAG(gameflag, D2_GAMEFLAG_HARDCORE, n) #define gameflag_create(l,e,h,d) (0x04|(e?D2_GAMEFLAG_EXPANSION:0) | (h?D2_GAMEFLAG_HARDCORE:0) | ((d & 0x07) << 0x0c) | (l?D2_GAMEFLAG_LADDER:0)) extern t_list * d2cs_gamelist(void); extern int d2cs_gamelist_destroy(void); extern int d2cs_gamelist_create(void); extern t_game * d2cs_gamelist_find_game(char const * gamename); extern t_game * gamelist_find_game_by_id(unsigned int id); extern t_game * gamelist_find_game_by_d2gs_and_id(unsigned int d2gs_id, unsigned int d2gs_gameid); extern void d2cs_gamelist_check_voidgame(void); extern t_game * d2cs_game_create(char const * gamename, char const * gamepass, char const * gamedesc, unsigned int gameflag); extern int game_destroy(t_game * game, t_elem ** elem); extern int game_add_character(t_game * game, char const * charname, unsigned char class, unsigned char level); extern int game_del_character(t_game * game, char const * charname); extern t_d2gs * game_get_d2gs(t_game const * game); extern int game_set_d2gs(t_game * game, t_d2gs * gs); extern int game_set_d2gs_gameid(t_game * game, unsigned int gameid); extern unsigned int game_get_d2gs_gameid(t_game const * game); extern int game_set_id(t_game * game, unsigned int id); extern unsigned int d2cs_game_get_id(t_game const * game); extern int game_set_created(t_game * game, unsigned int created); extern unsigned int game_get_created(t_game const * game); extern int game_set_leveldiff(t_game * game, unsigned int leveldiff); extern int game_set_charlevel(t_game * game, unsigned int charlevel); extern unsigned int game_get_charlevel(t_game const * game); extern unsigned int game_get_leveldiff(t_game const * game); extern unsigned int game_get_maxlevel(t_game const * game); extern unsigned int game_get_minlevel(t_game const * game); extern int game_set_gameflag_ladder(t_game * game, unsigned int ladder); extern int game_set_gameflag_expansion(t_game * game, unsigned int expansion); extern int game_set_gameflag_hardcore(t_game * game, unsigned int hardcore); extern int game_set_gameflag_difficulty(t_game * game, unsigned int difficulty); extern unsigned int game_get_gameflag_ladder(t_game const * game); extern unsigned int game_get_gameflag_expansion(t_game const * game); extern unsigned int game_get_gameflag_hardcore(t_game const * game); extern unsigned int game_get_gameflag_difficulty(t_game const * game); extern int game_set_maxchar(t_game * game, unsigned int maxchar); extern unsigned int game_get_maxchar(t_game const * game); extern unsigned int game_get_currchar(t_game const * game); extern char const * d2cs_game_get_name(t_game const * game); extern char const * d2cs_game_get_pass(t_game const * game); extern char const * game_get_desc(t_game const * game); extern unsigned int game_get_gameflag(t_game const * game); extern int d2cs_game_get_create_time(t_game const * game); extern int game_set_create_time(t_game * game,int create_time); extern t_list * game_get_charlist(t_game const * game); extern t_game * gamelist_find_character(char const * charname); extern unsigned int gamelist_get_totalgame(void); extern t_elem const * gamelist_get_curr_elem(void); extern void gamelist_set_curr_elem(t_elem const * elem); #endif pvpgn-1.8.5/src/d2cs/bnetd.h0000644000175000017500000000207111151345317014531 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_BNETD_H #define INCLUDED_BNETD_H #include "s2s.h" extern int bnetd_init(void); extern int bnetd_check(void); extern t_connection * bnetd_conn(void); extern int bnetd_destroy(t_connection * c); extern int bnetd_set_connection(t_connection * c); extern int bnetd_keepalive(void); #endif pvpgn-1.8.5/src/d2cs/d2cs_bnetd_protocol.h0000644000175000017500000000521511151345317017370 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2CS_BNETD_PROTOCOL_H #define INCLUDED_D2CS_BNETD_PROTOCOL_H #include "common/bn_type.h" typedef struct { bn_short size; bn_short type; bn_int seqno; /* seqno, set by the sender */ } t_d2cs_bnetd_header; typedef struct { t_d2cs_bnetd_header h; } t_d2cs_bnetd_generic; #define BNETD_D2CS_AUTHREQ 0x01 typedef struct { t_d2cs_bnetd_header h; bn_int sessionnum; } t_bnetd_d2cs_authreq; #define D2CS_BNETD_AUTHREPLY 0x02 typedef struct { t_d2cs_bnetd_header h; bn_int version; /* realm name */ } t_d2cs_bnetd_authreply; #define BNETD_D2CS_AUTHREPLY 0x02 typedef struct { t_d2cs_bnetd_header h; bn_int reply; } t_bnetd_d2cs_authreply; #define BNETD_D2CS_AUTHREPLY_SUCCEED 0x00 #define BNETD_D2CS_AUTHREPLY_BAD_VERSION 0x01 #define D2CS_BNETD_ACCOUNTLOGINREQ 0x10 typedef struct { t_d2cs_bnetd_header h; bn_int seqno; bn_int sessionnum; bn_int sessionkey; bn_int secret_hash[5]; /* account name */ } t_d2cs_bnetd_accountloginreq; #define BNETD_D2CS_ACCOUNTLOGINREPLY 0x10 typedef struct { t_d2cs_bnetd_header h; bn_int reply; } t_bnetd_d2cs_accountloginreply; #define BNETD_D2CS_ACCOUNTLOGINREPLY_SUCCEED 0x00 #define BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED 0x01 #define D2CS_BNETD_CHARLOGINREQ 0x11 typedef struct { t_d2cs_bnetd_header h; bn_int sessionnum; /* character name */ /* character portrait */ } t_d2cs_bnetd_charloginreq; #define BNETD_D2CS_CHARLOGINREPLY 0x11 typedef struct { t_d2cs_bnetd_header h; bn_int reply; } t_bnetd_d2cs_charloginreply; #define BNETD_D2CS_CHARLOGINREPLY_SUCCEED 0x00 #define BNETD_D2CS_CHARLOGINREPLY_FAILED 0x01 #define BNETD_D2CS_GAMEINFOREQ 0x12 typedef struct { t_d2cs_bnetd_header h; /* gamename */ } t_bnetd_d2cs_gameinforeq; #define D2CS_BNETD_GAMEINFOREPLY 0x12 typedef struct { t_d2cs_bnetd_header h; bn_byte difficulty; /* gamename */ } t_d2cs_bnetd_gameinforeply; #endif pvpgn-1.8.5/src/d2cs/handle_bnetd.h0000644000175000017500000000177211151345317016053 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_HANDLE_BNETD_H #define INCLUDED_HANDLE_BNETD_H #include "connection.h" #include "common/packet.h" extern int handle_bnetd_packet(t_connection * c, t_packet * packet); extern int handle_bnetd_init(t_connection * c); #endif pvpgn-1.8.5/src/d2cs/handle_signal.c0000644000175000017500000001410711151345317016223 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "setup.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strdup.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef DO_POSIXSIG # include # include "compat/signal.h" #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include "d2gs.h" #include "game.h" #include "prefs.h" #include "d2ladder.h" #include "cmdline.h" #include "handle_signal.h" #include "common/trans.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" static void on_signal(int s); static volatile struct { unsigned char do_quit; unsigned char cancel_quit; unsigned char reload_config; unsigned char reload_ladder; unsigned char restart_d2gs; unsigned int exit_time; } signal_data ={ 0, 0, 0, 0, 0, 0 }; extern int handle_signal(void) { time_t now; char const * levels; char * temp; char const * tok; if (signal_data.cancel_quit) { signal_data.cancel_quit=0; if (!signal_data.exit_time) { eventlog(eventlog_level_info,__FUNCTION__,"there is no previous shutdown to be canceled"); } else { signal_data.exit_time=0; eventlog(eventlog_level_info,__FUNCTION__,"shutdown was canceled due to signal"); } } if (signal_data.do_quit) { signal_data.do_quit=0; now=time(NULL); if (!signal_data.exit_time) { signal_data.exit_time=now+d2cs_prefs_get_shutdown_delay(); } else { signal_data.exit_time-=d2cs_prefs_get_shutdown_decr(); } eventlog(eventlog_level_info,__FUNCTION__,"the server is going to shutdown in %lu minutes",(signal_data.exit_time-now)/60); } if (signal_data.exit_time) { now=time(NULL); if (now >= (signed)signal_data.exit_time) { signal_data.exit_time=0; eventlog(eventlog_level_info,__FUNCTION__,"shutdown server due to signal"); return -1; } } if (signal_data.reload_config) { signal_data.reload_config=0; eventlog(eventlog_level_info,__FUNCTION__,"reloading configuartion file due to signal"); if (prefs_reload(cmdline_get_preffile())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error reload configuration file,exitting"); return -1; } if (d2gslist_reload(prefs_get_d2gs_list())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error reloading game server list,exitting"); return -1; } if (trans_reload(d2cs_prefs_get_transfile(),TRANS_D2CS)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not reload trans list"); } eventlog_clear_level(); if ((levels = d2cs_prefs_get_loglevels())) { temp = xstrdup(levels); tok = strtok(temp,","); /* strtok modifies the string it is passed */ while (tok) { if (eventlog_add_level(tok)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add log level \"%s\"",tok); tok = strtok(NULL,","); } xfree(temp); } #ifdef DO_DAEMONIZE if (!cmdline_get_foreground()) #endif eventlog_open(d2cs_prefs_get_logfile()); } if (signal_data.reload_ladder) { signal_data.reload_ladder=0; eventlog(eventlog_level_info,__FUNCTION__,"reloading ladder data due to signal"); d2ladder_refresh(); } if (signal_data.restart_d2gs) { signal_data.restart_d2gs=0; eventlog(eventlog_level_info,__FUNCTION__,"restarting all game servers due to signal"); d2gs_restart_all_gs(); } return 0; } #ifdef WIN32 extern void signal_quit_wrapper(void) { signal_data.do_quit=1; } extern void signal_reload_config_wrapper(void) { signal_data.reload_config = 1; } extern void signal_load_ladder_wrapper(void) { signal_data.reload_ladder = 1; } extern void signal_exit_wrapper(void) { signal_data.exit_time = 1; } extern void signal_restart_d2gs_wrapper(void) { signal_data.restart_d2gs = 1; } #else extern int handle_signal_init(void) { signal(SIGINT,on_signal); signal(SIGTERM,on_signal); signal(SIGABRT,on_signal); signal(SIGHUP,on_signal); signal(SIGUSR1,on_signal); signal(SIGUSR2,on_signal); signal(SIGPIPE,on_signal); return 0; } static void on_signal(int s) { switch (s) { case SIGINT: eventlog(eventlog_level_debug,__FUNCTION__,"sigint received"); signal_data.do_quit=1; break; case SIGTERM: eventlog(eventlog_level_debug,__FUNCTION__,"sigint received"); signal_data.do_quit=1; break; case SIGABRT: eventlog(eventlog_level_debug,__FUNCTION__,"sigabrt received"); signal_data.cancel_quit=1; break; case SIGHUP: eventlog(eventlog_level_debug,__FUNCTION__,"sighup received"); signal_data.reload_config=1; break; case SIGUSR1: eventlog(eventlog_level_debug,__FUNCTION__,"sigusr1 received"); signal_data.reload_ladder=1; break; case SIGUSR2: eventlog(eventlog_level_debug,__FUNCTION__,"sigusr2 received"); signal_data.restart_d2gs=1; break; case SIGPIPE: eventlog(eventlog_level_debug,__FUNCTION__,"sigpipe received"); break; } signal(s,on_signal); } #endif pvpgn-1.8.5/src/d2cs/server.h0000644000175000017500000000177511151345317014755 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SERVER_H #define INCLUDED_SERVER_H #include "common/fdwatch.h" extern int d2cs_server_process(void); extern int d2cs_server_handle_tcp(void*,t_fdwatch_type); extern int d2cs_server_handle_accept(void*,t_fdwatch_type); #endif pvpgn-1.8.5/src/d2cs/cmdline.h0000644000175000017500000000231411151345317015050 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * Copyright (C) 2005 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __D2CS_CMDLINE_H_PROTOS__ #define __D2CS_CMDLINE_H_PROTOS__ extern int cmdline_load(int argc, char * * argv); extern void cmdline_unload(void); /* options exported by cmdline */ #ifdef DO_DAEMONIZE extern int cmdline_get_foreground(void); #endif extern const char* cmdline_get_preffile(void); extern const char* cmdline_get_logfile(void); #endif /* __D2CS_CMDLINE_H_PROTOS__ */ pvpgn-1.8.5/src/d2cs/d2cs_d2gs_protocol.h0000644000175000017500000001132311151345317017130 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2001 faster (lqx@cic.tsinghua.edu.cn) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2CS_D2GS_PROTOCOL_H #define INCLUDED_D2CS_D2GS_PROTOCOL_H /* * there is only little comments in this header file * check the documents for more details */ /* include your own header files here */ #ifdef D2CS # include "common/bn_type.h" #endif #ifdef D2GS # include "bn_types.h" #pragma pack(push, pack01, 1) #endif typedef struct { bn_short size; bn_short type; bn_int seqno; /* seqno, set by the sender */ } t_d2cs_d2gs_header; typedef struct { t_d2cs_d2gs_header h; } t_d2cs_d2gs_generic; #define D2CS_D2GS_AUTHREQ 0x10 typedef struct { t_d2cs_d2gs_header h; bn_int sessionnum; bn_int signlen; /* realm name */ /* key check sum, maybe 128 bytes */ } t_d2cs_d2gs_authreq; #define D2GS_D2CS_AUTHREPLY 0x11 typedef struct { t_d2cs_d2gs_header h; bn_int version; bn_int checksum; bn_int randnum; bn_int signlen; bn_basic sign[128]; } t_d2gs_d2cs_authreply; #define D2CS_D2GS_AUTHREPLY 0x11 typedef struct { t_d2cs_d2gs_header h; bn_int reply; } t_d2cs_d2gs_authreply; #define D2CS_D2GS_AUTHREPLY_SUCCEED 0x00 #define D2CS_D2GS_AUTHREPLY_BAD_VERSION 0x01 #define D2CS_D2GS_AUTHREPLY_BAD_CHECKSUM 0x02 #define D2GS_D2CS_SETGSINFO 0x12 typedef struct { t_d2cs_d2gs_header h; bn_int maxgame; bn_int gameflag; } t_d2gs_d2cs_setgsinfo; #define D2CS_D2GS_SETGSINFO 0x12 typedef struct { t_d2cs_d2gs_header h; bn_int maxgame; bn_int gameflag; } t_d2cs_d2gs_setgsinfo; #define D2CS_D2GS_ECHOREQ 0x13 typedef struct { t_d2cs_d2gs_header h; } t_d2cs_d2gs_echoreq; #define D2GS_D2CS_ECHOREPLY 0x13 typedef struct { t_d2cs_d2gs_header h; } t_d2gs_d2cs_echoreply; #define D2CS_D2GS_CONTROL 0x14 typedef struct { t_d2cs_d2gs_header h; bn_int cmd; bn_int value; } t_d2cs_d2gs_control; #define D2CS_D2GS_CONTROL_CMD_RESTART 0x01 #define D2CS_D2GS_CONTROL_CMD_SHUTDOWN 0x02 #define D2CS_D2GS_CONTROL_VALUE_DEFAULT 0x00 #define D2CS_D2GS_SETINITINFO 0x15 typedef struct { t_d2cs_d2gs_header h; bn_int time; bn_int gs_id; bn_int ac_version; /* ac_checksum */ } t_d2cs_d2gs_setinitinfo; #define D2CS_D2GS_SETCONFFILE 0x16 typedef struct { t_d2cs_d2gs_header h; bn_int size; bn_int reserved1; /* conf file (null terminated string) */ } t_d2cs_d2gs_setconffile; #define D2CS_D2GS_CREATEGAMEREQ 0x20 typedef struct { t_d2cs_d2gs_header h; bn_byte ladder; bn_byte expansion; bn_byte difficulty; bn_byte hardcore; /* gamename */ /* gamepass */ /* gamedesc */ /* create by acctname */ /* create by charname */ /* create by ip address(string) */ } t_d2cs_d2gs_creategamereq; #define D2GAME_DIFFICULTY_NORMAL 0 #define D2GAME_DIFFICULTY_NIGHTMARE 1 #define D2GAME_DIFFICULTY_HELL 2 #define D2GS_D2CS_CREATEGAMEREPLY 0x20 typedef struct { t_d2cs_d2gs_header h; bn_int result; bn_int gameid; } t_d2gs_d2cs_creategamereply; #define D2GS_D2CS_CREATEGAME_SUCCEED 0 #define D2GS_D2CS_CREATEGAME_FAILED 1 #define D2CS_D2GS_JOINGAMEREQ 0x21 typedef struct { t_d2cs_d2gs_header h; bn_int gameid; bn_int token; /* character name */ /* account name */ /* client ip address(string) */ } t_d2cs_d2gs_joingamereq; #define D2GS_D2CS_JOINGAMEREPLY 0x21 typedef struct { t_d2cs_d2gs_header h; bn_int result; bn_int gameid; } t_d2gs_d2cs_joingamereply; #define D2GS_D2CS_JOINGAME_SUCCEED 0 #define D2GS_D2CS_JOINGAME_FAILED 1 #define D2GS_D2CS_JOINGAME_GAME_FULL 2 #define D2GS_D2CS_UPDATEGAMEINFO 0x22 typedef struct { t_d2cs_d2gs_header h; bn_int flag; bn_int gameid; bn_int charlevel; bn_int charclass; /* charname */ } t_d2gs_d2cs_updategameinfo; #define D2GS_D2CS_UPDATEGAMEINFO_FLAG_UPDATE 0 #define D2GS_D2CS_UPDATEGAMEINFO_FLAG_ENTER 1 #define D2GS_D2CS_UPDATEGAMEINFO_FLAG_LEAVE 2 #define D2GS_D2CS_CLOSEGAME 0x23 typedef struct { t_d2cs_d2gs_header h; bn_int gameid; } t_d2gs_d2cs_closegame; #ifdef D2GS #pragma pack(pop, pack01) #endif #endif pvpgn-1.8.5/src/d2cs/d2ladder.h0000644000175000017500000000263511151345317015124 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2001 sousou (liupeng.cs@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2LADDER_H #define INCLUDED_D2LADDER_H #include "common/bn_type.h" #include "d2cs_protocol.h" #include "d2cs_d2dbs_ladder.h" typedef struct { unsigned int type; unsigned int len; unsigned int curr_len; t_d2cs_client_ladderinfo * info; } t_d2ladder; extern int d2ladder_init(void); extern int d2ladder_refresh(void); extern int d2ladder_destroy(void); extern int d2ladder_get_ladder(unsigned int * from, unsigned int * count, unsigned int type, t_d2cs_client_ladderinfo const * * info); extern int d2ladder_find_character_pos(unsigned int type, char const * charname); #endif pvpgn-1.8.5/src/config.h.in0000644000175000017500000002502511151346340014455 0ustar aaronaaron/* config.h.in. Generated automatically from configure.in by autoheader. */ /* Define if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE #undef _ALL_SOURCE #endif /* Define if the closedir function returns void instead of int. */ #undef CLOSEDIR_VOID /* Define to empty if the keyword does not work. */ #undef const /* Define if you don't have vprintf but do have _doprnt. */ #undef HAVE_DOPRNT /* Define if you have a working `mmap' system call. */ #undef HAVE_MMAP /* Define if you have the strftime function. */ #undef HAVE_STRFTIME /* Define if you have the vprintf function. */ #undef HAVE_VPRINTF /* Define as __inline if that's what the C compiler calls it. */ #undef inline /* Define if on MINIX. */ #undef _MINIX /* Define to `long' if doesn't define. */ #undef off_t /* Define to `int' if doesn't define. */ #undef pid_t /* Define if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define if you need to in order for stat and other things to work. */ #undef _POSIX_SOURCE /* Define as the return type of signal handlers (int or void). */ #undef RETSIGTYPE /* Define if the `setpgrp' function takes no argument. */ #undef SETPGRP_VOID /* Define to `unsigned' if doesn't define. */ #undef size_t /* Define if the `S_IS*' macros in do not work properly. */ #undef STAT_MACROS_BROKEN /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define if your declares struct tm. */ #undef TM_IN_SYS_TIME /* The number of bytes in a signed char. */ #undef SIZEOF_SIGNED_CHAR /* The number of bytes in a signed int. */ #undef SIZEOF_SIGNED_INT /* The number of bytes in a signed long. */ #undef SIZEOF_SIGNED_LONG /* The number of bytes in a signed long long. */ #undef SIZEOF_SIGNED_LONG_LONG /* The number of bytes in a signed short. */ #undef SIZEOF_SIGNED_SHORT /* The number of bytes in a unsigned char. */ #undef SIZEOF_UNSIGNED_CHAR /* The number of bytes in a unsigned int. */ #undef SIZEOF_UNSIGNED_INT /* The number of bytes in a unsigned long. */ #undef SIZEOF_UNSIGNED_LONG /* The number of bytes in a unsigned long long. */ #undef SIZEOF_UNSIGNED_LONG_LONG /* The number of bytes in a unsigned short. */ #undef SIZEOF_UNSIGNED_SHORT /* Define if you have the _mkdir function. */ #undef HAVE__MKDIR /* Define if you have the _snprintf function. */ #undef HAVE__SNPRINTF /* Define if you have the _vsnprintf function. */ #undef HAVE__VSNPRINTF /* Define if you have the bcopy function. */ #undef HAVE_BCOPY /* Define if you have the chdir function. */ #undef HAVE_CHDIR /* Define if you have the difftime function. */ #undef HAVE_DIFFTIME /* Define if you have the epoll_create function. */ #undef HAVE_EPOLL_CREATE /* Define if you have the fork function. */ #undef HAVE_FORK /* Define if you have the ftime function. */ #undef HAVE_FTIME /* Define if you have the getenv function. */ #undef HAVE_GETENV /* Define if you have the getgid function. */ #undef HAVE_GETGID /* Define if you have the getgrnam function. */ #undef HAVE_GETGRNAM /* Define if you have the gethostbyname function. */ #undef HAVE_GETHOSTBYNAME /* Define if you have the gethostname function. */ #undef HAVE_GETHOSTNAME /* Define if you have the getlogin function. */ #undef HAVE_GETLOGIN /* Define if you have the getopt function. */ #undef HAVE_GETOPT /* Define if you have the getpagesize function. */ #undef HAVE_GETPAGESIZE /* Define if you have the getpid function. */ #undef HAVE_GETPID /* Define if you have the getpwnam function. */ #undef HAVE_GETPWNAM /* Define if you have the getrlimit function. */ #undef HAVE_GETRLIMIT /* Define if you have the getservbyname function. */ #undef HAVE_GETSERVBYNAME /* Define if you have the gettimeofday function. */ #undef HAVE_GETTIMEOFDAY /* Define if you have the getuid function. */ #undef HAVE_GETUID /* Define if you have the index function. */ #undef HAVE_INDEX /* Define if you have the inet_aton function. */ #undef HAVE_INET_ATON /* Define if you have the inet_ntoa function. */ #undef HAVE_INET_NTOA /* Define if you have the ioctl function. */ #undef HAVE_IOCTL /* Define if you have the kqueue function. */ #undef HAVE_KQUEUE /* Define if you have the memcpy function. */ #undef HAVE_MEMCPY /* Define if you have the memmove function. */ #undef HAVE_MEMMOVE /* Define if you have the memset function. */ #undef HAVE_MEMSET /* Define if you have the mkdir function. */ #undef HAVE_MKDIR /* Define if you have the mktime function. */ #undef HAVE_MKTIME /* Define if you have the pipe function. */ #undef HAVE_PIPE /* Define if you have the poll function. */ #undef HAVE_POLL /* Define if you have the pow function. */ #undef HAVE_POW /* Define if you have the recv function. */ #undef HAVE_RECV /* Define if you have the recvfrom function. */ #undef HAVE_RECVFROM /* Define if you have the rindex function. */ #undef HAVE_RINDEX /* Define if you have the select function. */ #undef HAVE_SELECT /* Define if you have the send function. */ #undef HAVE_SEND /* Define if you have the sendto function. */ #undef HAVE_SENDTO /* Define if you have the setgid function. */ #undef HAVE_SETGID /* Define if you have the setitimer function. */ #undef HAVE_SETITIMER /* Define if you have the setpgid function. */ #undef HAVE_SETPGID /* Define if you have the setpgrp function. */ #undef HAVE_SETPGRP /* Define if you have the setsid function. */ #undef HAVE_SETSID /* Define if you have the setuid function. */ #undef HAVE_SETUID /* Define if you have the sigaction function. */ #undef HAVE_SIGACTION /* Define if you have the sigaddset function. */ #undef HAVE_SIGADDSET /* Define if you have the sigprocmask function. */ #undef HAVE_SIGPROCMASK /* Define if you have the snprintf function. */ #undef HAVE_SNPRINTF /* Define if you have the socket function. */ #undef HAVE_SOCKET /* Define if you have the strcasecmp function. */ #undef HAVE_STRCASECMP /* Define if you have the strchr function. */ #undef HAVE_STRCHR /* Define if you have the strdup function. */ #undef HAVE_STRDUP /* Define if you have the strerror function. */ #undef HAVE_STRERROR /* Define if you have the stricmp function. */ #undef HAVE_STRICMP /* Define if you have the strncasecmp function. */ #undef HAVE_STRNCASECMP /* Define if you have the strnicmp function. */ #undef HAVE_STRNICMP /* Define if you have the strrchr function. */ #undef HAVE_STRRCHR /* Define if you have the strsep function. */ #undef HAVE_STRSEP /* Define if you have the strtoul function. */ #undef HAVE_STRTOUL /* Define if you have the uname function. */ #undef HAVE_UNAME /* Define if you have the vsnprintf function. */ #undef HAVE_VSNPRINTF /* Define if you have the wait function. */ #undef HAVE_WAIT /* Define if you have the waitpid function. */ #undef HAVE_WAITPID /* Define if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define if you have the header file. */ #undef HAVE_ASSERT_H /* Define if you have the header file. */ #undef HAVE_DIR_H /* Define if you have the header file. */ #undef HAVE_DIRECT_H /* Define if you have the header file. */ #undef HAVE_DIRENT_H /* Define if you have the header file. */ #undef HAVE_FCNTL_H /* Define if you have the header file. */ #undef HAVE_GRP_H /* Define if you have the header file. */ #undef HAVE_LIMITS_H /* Define if you have the header file. */ #undef HAVE_MALLOC_H /* Define if you have the header file. */ #undef HAVE_MEMORY_H /* Define if you have the header file. */ #undef HAVE_NDIR_H /* Define if you have the header file. */ #undef HAVE_NETDB_H /* Define if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define if you have the header file. */ #undef HAVE_POLL_H /* Define if you have the header file. */ #undef HAVE_PWD_H /* Define if you have the header file. */ #undef HAVE_SQLITE3_H /* Define if you have the header file. */ #undef HAVE_STDARG_H /* Define if you have the header file. */ #undef HAVE_STDDEF_H /* Define if you have the header file. */ #undef HAVE_STDINT_H /* Define if you have the header file. */ #undef HAVE_STRING_H /* Define if you have the header file. */ #undef HAVE_STRINGS_H /* Define if you have the header file. */ #undef HAVE_STROPTS_H /* Define if you have the header file. */ #undef HAVE_SYS_DIR_H /* Define if you have the header file. */ #undef HAVE_SYS_EPOLL_H /* Define if you have the header file. */ #undef HAVE_SYS_EVENT_H /* Define if you have the header file. */ #undef HAVE_SYS_FILE_H /* Define if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define if you have the header file. */ #undef HAVE_SYS_MMAN_H /* Define if you have the header file. */ #undef HAVE_SYS_NDIR_H /* Define if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define if you have the header file. */ #undef HAVE_SYS_POLL_H /* Define if you have the header file. */ #undef HAVE_SYS_RESOURCE_H /* Define if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define if you have the header file. */ #undef HAVE_SYS_STROPTS_H /* Define if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define if you have the header file. */ #undef HAVE_SYS_TIMEB_H /* Define if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define if you have the header file. */ #undef HAVE_SYS_UTSNAME_H /* Define if you have the header file. */ #undef HAVE_SYS_WAIT_H /* Define if you have the header file. */ #undef HAVE_TERMIOS_H /* Define if you have the header file. */ #undef HAVE_TIME_H /* Define if you have the header file. */ #undef HAVE_UNISTD_H /* Define if you have the header file. */ #undef HAVE_VARARGS_H /* Define if mkdir takes only one argument. */ #undef MKDIR_TAKES_ONE_ARG pvpgn-1.8.5/src/Makefile.in0000644000175000017500000006654011151345317014511 0ustar aaronaaron# # Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) # Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ mandir = @mandir@ confdir = @sysconfdir@ sharedir = @localstatedir@ filesdir = @localstatedir@/files usersdir = @localstatedir@/users userscdbdir = @localstatedir@/userscdb clandir = @localstatedir@/clans teamdir = @localstatedir@/teams bnmaildir = @localstatedir@/bnmail reportsdir = @localstatedir@/reports chanlogsdir = @localstatedir@/chanlogs charinfodir = @localstatedir@/charinfo charsavedir = @localstatedir@/charsave ladderdir = @localstatedir@/ladders statusdir = @localstatedir@/status bak_charsavedir = @localstatedir@/bak/charsave bak_charinfodir = @localstatedir@/bak/charinfo SRC_SRCDIR = @srcdir@ SRC_BINDIR = @srcdir@/../bin SRC_SBINDIR = @srcdir@/../sbin SRC_MANDIR = @srcdir@/../man SRC_CONFDIR = @srcdir@/../conf SRC_SHAREDIR = @srcdir@/../files SRC_SCRIPTDIR = @srcdir@/../scripts SRC_ACDIR = ${SRC_SRCDIR}/autoconf SRC_BNETDDIR = ${SRC_SRCDIR}/bnetd SRC_D2CSDIR = ${SRC_SRCDIR}/d2cs SRC_D2DBSDIR = ${SRC_SRCDIR}/d2dbs SRC_BNIUTILSDIR = ${SRC_SRCDIR}/bniutils SRC_BNPASSDIR = ${SRC_SRCDIR}/bnpass SRC_BNTRACKDDIR = ${SRC_SRCDIR}/bntrackd SRC_CLIENTDIR = ${SRC_SRCDIR}/client SRC_COMMONDIR = ${SRC_SRCDIR}/common SRC_COMPATDIR = ${SRC_SRCDIR}/compat SRC_DEBUGDIR = ${SRC_SRCDIR}/debug SRC_CDBDIR = ${SRC_SRCDIR}/tinycdb SRC_ZLIBDIR = ${SRC_SRCDIR}/zlib SRC_WIN32DIR = ${SRC_SRCDIR}/win32 RMF = rm -f RMDIR = rmdir ECHO = echo SED = sed INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_DIRS = @INSTALL@ -d -m 755 # CC set by configure # CFLAGS set by configure CPPFLAGS = @DEFS@ @DEFINES@ -DBNETD_DEFAULT_CONF_FILE=\"${confdir}/bnetd.conf\" -DD2CS_DEFAULT_CONF_FILE=\"${confdir}/d2cs.conf\" -DD2DBS_DEFAULT_CONF_FILE=\"${confdir}/d2dbs.conf\" -I"${SRC_SRCDIR}" @CPPFLAGS@ COMPILE = @CC@ @CFLAGS@ ${CPPFLAGS} -fno-strict-aliasing -c #PREPROCESS = @CPP@ ${CPPFLAGS} LINK = @CC@ @CFLAGS@ @LDFLAGS@ LINK_LIBS = @LIBS@ PARTS = bnetd bniutils bnpass bnpcap bnproxy bntrackd client common compat d2cs d2dbs tinycdb zlib win32 ifeq (@enable_bnetd@,no) bnetd_SBIN = bnetd_CONFS = bnetd_OBJECTS = else bnetd_SBIN = ${SRC_SBINDIR}/bnetd bnetd_CONFS = bnetd.conf ad.conf channel.conf realm.conf autoupdate.conf \ bnetd_default_user.plain bnetd_default_user.cdb \ versioncheck.conf bnmotd.txt bnissue.txt bnmaps.conf \ bnxplevel.conf bnxpcalc.conf news.txt command_groups.conf \ bnban.conf bnhelp.conf bnalias.conf anongame_infos.conf \ tournament.conf topics.conf sql_DB_layout.conf sql_DB_layout2.conf \ address_translation.conf supportfile.conf bnetd_OBJECTS = ${SRC_BNETDDIR}/main.o \ ${SRC_BNETDDIR}/server.o \ ${SRC_BNETDDIR}/connection.o \ ${SRC_BNETDDIR}/message.o \ ${SRC_BNETDDIR}/handle_init.o \ ${SRC_BNETDDIR}/handle_bnet.o \ ${SRC_BNETDDIR}/handle_file.o \ ${SRC_BNETDDIR}/handle_bot.o \ ${SRC_BNETDDIR}/handle_telnet.o \ ${SRC_BNETDDIR}/handle_irc.o \ ${SRC_BNETDDIR}/handle_udp.o \ ${SRC_BNETDDIR}/channel.o \ ${SRC_BNETDDIR}/channel_conv.o \ ${SRC_BNETDDIR}/game.o \ ${SRC_BNETDDIR}/anongame.o \ ${SRC_BNETDDIR}/command.o \ ${SRC_BNETDDIR}/account.o \ ${SRC_BNETDDIR}/account_wrap.o \ ${SRC_BNETDDIR}/prefs.o \ ${SRC_BNETDDIR}/tick.o \ ${SRC_BNETDDIR}/file.o \ ${SRC_BNETDDIR}/watch.o \ ${SRC_BNETDDIR}/ladder.o \ ${SRC_BNETDDIR}/ladder_calc.o \ ${SRC_BNETDDIR}/adbanner.o \ ${SRC_BNETDDIR}/timer.o \ ${SRC_BNETDDIR}/tracker.o \ ${SRC_BNETDDIR}/ipban.o \ ${SRC_BNETDDIR}/game_conv.o \ ${SRC_BNETDDIR}/autoupdate.o \ ${SRC_BNETDDIR}/helpfile.o \ ${SRC_BNETDDIR}/mail.o \ ${SRC_BNETDDIR}/anongame_infos.o \ ${SRC_BNETDDIR}/anongame_gameresult.o \ ${SRC_BNETDDIR}/storage.o \ ${SRC_BNETDDIR}/storage_file.o \ ${SRC_BNETDDIR}/file_plain.o \ ${SRC_BNETDDIR}/file_cdb.o \ ${SRC_BNETDDIR}/storage_sql.o \ ${SRC_BNETDDIR}/storage_sql2.o \ ${SRC_BNETDDIR}/sql_dbcreator.o \ ${SRC_BNETDDIR}/sql_common.o \ ${SRC_BNETDDIR}/sql_pgsql.o \ ${SRC_BNETDDIR}/sql_mysql.o \ ${SRC_BNETDDIR}/sql_sqlite3.o \ ${SRC_BNETDDIR}/sql_odbc.o \ ${SRC_BNETDDIR}/runprog.o \ ${SRC_BNETDDIR}/realm.o \ ${SRC_BNETDDIR}/character.o \ ${SRC_BNETDDIR}/udptest_send.o \ ${SRC_BNETDDIR}/versioncheck.o \ ${SRC_BNETDDIR}/handle_d2cs.o \ ${SRC_BNETDDIR}/news.o \ ${SRC_BNETDDIR}/irc.o \ ${SRC_BNETDDIR}/alias_command.o \ ${SRC_BNETDDIR}/command_groups.o \ ${SRC_BNETDDIR}/output.o \ ${SRC_BNETDDIR}/handle_anongame.o \ ${SRC_BNETDDIR}/tournament.o \ ${SRC_BNETDDIR}/anongame_maplists.o\ ${SRC_BNETDDIR}/clan.o\ ${SRC_BNETDDIR}/team.o\ ${SRC_BNETDDIR}/topic.o\ ${SRC_BNETDDIR}/friends.o\ ${SRC_BNETDDIR}/ladder_binary.o \ ${SRC_BNETDDIR}/support.o \ ${SRC_BNETDDIR}/attrgroup.o \ ${SRC_BNETDDIR}/attrlayer.o \ ${SRC_BNETDDIR}/cmdline.o \ ${SRC_COMMONDIR}/tag.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/bn_type.o \ ${SRC_COMMONDIR}/packet.o \ ${SRC_COMMONDIR}/queue.o \ ${SRC_COMMONDIR}/util.o \ ${SRC_COMMONDIR}/network.o \ ${SRC_COMMONDIR}/list.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/bnettime.o \ ${SRC_COMMONDIR}/bnethash.o \ ${SRC_COMMONDIR}/bnethashconv.o \ ${SRC_COMMONDIR}/addr.o \ ${SRC_COMMONDIR}/hashtable.o \ ${SRC_COMMONDIR}/give_up_root_privileges.o \ ${SRC_COMMONDIR}/token.o \ ${SRC_COMMONDIR}/proginfo.o \ ${SRC_COMMONDIR}/rlimit.o \ ${SRC_COMMONDIR}/fdwatch.o\ ${SRC_COMMONDIR}/fdwatch_select.o\ ${SRC_COMMONDIR}/fdwatch_poll.o\ ${SRC_COMMONDIR}/fdwatch_kqueue.o\ ${SRC_COMMONDIR}/fdwatch_epoll.o\ ${SRC_COMMONDIR}/trans.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMMONDIR}/rcm.o \ ${SRC_COMMONDIR}/conf.o \ ${SRC_COMMONDIR}/asnprintf.o \ ${SRC_COMMONDIR}/xstr.o \ ${SRC_COMPATDIR}/pdir.o \ ${SRC_COMPATDIR}/inet_aton.o \ ${SRC_COMPATDIR}/inet_ntoa.o \ ${SRC_COMPATDIR}/strdup.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/strtoul.o \ ${SRC_COMPATDIR}/strftime.o \ ${SRC_COMPATDIR}/strcasecmp.o \ ${SRC_COMPATDIR}/strncasecmp.o \ ${SRC_COMPATDIR}/strsep.o \ ${SRC_COMPATDIR}/psock.o \ ${SRC_COMPATDIR}/uname.o \ ${SRC_COMPATDIR}/gettimeofday.o \ ${SRC_COMPATDIR}/difftime.o \ ${SRC_COMPATDIR}/memset.o \ ${SRC_COMPATDIR}/memcpy.o \ ${SRC_COMPATDIR}/mmap.o \ ${SRC_CDBDIR}/cdb_init.o \ ${SRC_CDBDIR}/cdb_find.o \ ${SRC_CDBDIR}/cdb_findnext.o \ ${SRC_CDBDIR}/cdb_seek.o \ ${SRC_CDBDIR}/cdb_seq.o \ ${SRC_CDBDIR}/cdb_unpack.o \ ${SRC_CDBDIR}/cdb_make_add.o \ ${SRC_CDBDIR}/cdb_make_put.o \ ${SRC_CDBDIR}/cdb_make_find.o \ ${SRC_CDBDIR}/cdb_make.o \ ${SRC_CDBDIR}/cdb_hash.o \ ${SRC_ZLIBDIR}/pvpgn_adler32.o \ ${SRC_ZLIBDIR}/pvpgn_deflate.o \ ${SRC_ZLIBDIR}/pvpgn_trees.o \ ${SRC_ZLIBDIR}/pvpgn_zutil.o \ ${SRC_WIN32DIR}/service.o endif ifeq (@enable_d2cs@,no) d2cs_SBIN = d2cs_CONFS = d2cs_OBJECTS = else d2cs_SBIN = ${SRC_SBINDIR}/d2cs d2cs_CONFS = d2cs.conf d2server.ini address_translation.conf d2cs_OBJECTS = ${SRC_D2CSDIR}/main.o \ ${SRC_D2CSDIR}/d2gs.o \ ${SRC_D2CSDIR}/handle_d2gs.o \ ${SRC_D2CSDIR}/serverqueue.o \ ${SRC_D2CSDIR}/connection.o \ ${SRC_D2CSDIR}/game.o \ ${SRC_D2CSDIR}/server.o \ ${SRC_D2CSDIR}/handle_init.o \ ${SRC_D2CSDIR}/handle_d2cs.o \ ${SRC_D2CSDIR}/d2charfile.o \ ${SRC_D2CSDIR}/d2charlist.o \ ${SRC_D2CSDIR}/gamequeue.o \ ${SRC_D2CSDIR}/prefs.o \ ${SRC_D2CSDIR}/cmdline.o \ ${SRC_D2CSDIR}/bnetd.o \ ${SRC_D2CSDIR}/handle_bnetd.o \ ${SRC_D2CSDIR}/s2s.o \ ${SRC_D2CSDIR}/net.o \ ${SRC_D2CSDIR}/d2ladder.o \ ${SRC_D2CSDIR}/handle_signal.o \ ${SRC_COMMONDIR}/xstring.o \ ${SRC_COMMONDIR}/conf.o \ ${SRC_COMMONDIR}/hashtable.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/list.o \ ${SRC_COMMONDIR}/packet.o \ ${SRC_COMMONDIR}/bn_type.o \ ${SRC_COMMONDIR}/addr.o \ ${SRC_COMMONDIR}/util.o \ ${SRC_COMMONDIR}/queue.o \ ${SRC_COMMONDIR}/network.o \ ${SRC_COMMONDIR}/rlimit.o \ ${SRC_COMMONDIR}/fdwatch.o\ ${SRC_COMMONDIR}/fdwatch_select.o\ ${SRC_COMMONDIR}/fdwatch_poll.o\ ${SRC_COMMONDIR}/fdwatch_kqueue.o\ ${SRC_COMMONDIR}/fdwatch_epoll.o\ ${SRC_COMMONDIR}/d2char_checksum.o\ ${SRC_COMMONDIR}/trans.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/inet_aton.o \ ${SRC_COMPATDIR}/inet_ntoa.o \ ${SRC_COMPATDIR}/strdup.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/strtoul.o \ ${SRC_COMPATDIR}/strftime.o \ ${SRC_COMPATDIR}/strcasecmp.o \ ${SRC_COMPATDIR}/strncasecmp.o \ ${SRC_COMPATDIR}/strsep.o \ ${SRC_COMPATDIR}/psock.o \ ${SRC_COMPATDIR}/uname.o \ ${SRC_COMPATDIR}/gettimeofday.o \ ${SRC_COMPATDIR}/difftime.o \ ${SRC_COMPATDIR}/pdir.o \ ${SRC_COMPATDIR}/memset.o \ ${SRC_COMPATDIR}/memcpy.o \ ${SRC_COMPATDIR}/memmove.o \ ${SRC_WIN32DIR}/service.o endif ifeq (@enable_d2dbs@,no) d2dbs_SBIN = d2dbs_CONFS = d2dbs_OBJECTS = else d2dbs_SBIN = ${SRC_SBINDIR}/d2dbs d2dbs_CONFS = d2dbs.conf d2dbs_OBJECTS = ${SRC_D2DBSDIR}/main.o \ ${SRC_D2DBSDIR}/charlock.o \ ${SRC_D2DBSDIR}/d2ladder.o \ ${SRC_D2DBSDIR}/dbserver.o \ ${SRC_D2DBSDIR}/dbspacket.o \ ${SRC_D2DBSDIR}/cmdline.o \ ${SRC_D2DBSDIR}/prefs.o \ ${SRC_D2DBSDIR}/handle_signal.o \ ${SRC_D2DBSDIR}/dbsdupecheck.o \ ${SRC_COMMONDIR}/xstring.o \ ${SRC_COMMONDIR}/conf.o \ ${SRC_COMMONDIR}/list.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/bn_type.o \ ${SRC_COMMONDIR}/util.o \ ${SRC_COMMONDIR}/addr.o \ ${SRC_COMMONDIR}/d2char_checksum.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMMONDIR}/network.o \ ${SRC_COMMONDIR}/packet.o \ ${SRC_COMPATDIR}/inet_aton.o \ ${SRC_COMPATDIR}/psock.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/strsep.o \ ${SRC_WIN32DIR}/service.o endif sbnetd_SBIN = ${SRC_SBINDIR}/sbnetd sbnetd_OBJECTS = ${SRC_DEBUGDIR}/sbnetd.o \ ${SRC_COMPATDIR}/strerror.o bntrackd_SBIN = ${SRC_SBINDIR}/bntrackd bntrackd_OBJECTS= ${SRC_BNTRACKDDIR}/bntrackd.o \ ${SRC_COMMONDIR}/util.o \ ${SRC_COMMONDIR}/list.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMMONDIR}/bn_type.o \ ${SRC_COMPATDIR}/inet_ntoa.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/psock.o \ ${SRC_COMPATDIR}/memset.o bnchat_BIN = ${SRC_BINDIR}/bnchat bnchat_OBJECTS = ${SRC_CLIENTDIR}/bnchat.o \ ${SRC_CLIENTDIR}/client.o \ ${SRC_CLIENTDIR}/client_connect.o \ ${SRC_CLIENTDIR}/udptest.o \ ${SRC_COMMONDIR}/packet.o \ ${SRC_COMMONDIR}/queue.o \ ${SRC_COMMONDIR}/bn_type.o \ ${SRC_COMMONDIR}/network.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/bnethash.o \ ${SRC_COMMONDIR}/bnethashconv.o \ ${SRC_COMMONDIR}/util.o \ ${SRC_COMMONDIR}/bnettime.o \ ${SRC_COMMONDIR}/proginfo.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/inet_ntoa.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/psock.o \ ${SRC_COMPATDIR}/gettimeofday.o \ ${SRC_COMPATDIR}/vsnprintf.o \ ${SRC_COMPATDIR}/memset.o bnpass_BIN = ${SRC_BINDIR}/bnpass bnpass_OBJECTS = ${SRC_BNPASSDIR}/bnpass.o \ ${SRC_COMMONDIR}/bnethash.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMPATDIR}/strerror.o bnftp_BIN = ${SRC_BINDIR}/bnftp bnftp_OBJECTS = ${SRC_CLIENTDIR}/bnftp.o \ ${SRC_CLIENTDIR}/client.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/packet.o \ ${SRC_COMMONDIR}/queue.o \ ${SRC_COMMONDIR}/bn_type.o \ ${SRC_COMMONDIR}/network.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/bnettime.o \ ${SRC_COMMONDIR}/util.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/inet_ntoa.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/strftime.o \ ${SRC_COMPATDIR}/psock.o \ ${SRC_COMPATDIR}/gettimeofday.o bnbot_BIN = ${SRC_BINDIR}/bnbot bnbot_OBJECTS = ${SRC_CLIENTDIR}/bnbot.o \ ${SRC_CLIENTDIR}/client.o \ ${SRC_COMMONDIR}/packet.o \ ${SRC_COMMONDIR}/bn_type.o \ ${SRC_COMMONDIR}/network.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/util.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/inet_ntoa.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/psock.o bnstat_BIN = ${SRC_BINDIR}/bnstat bnstat_OBJECTS = ${SRC_CLIENTDIR}/bnstat.o \ ${SRC_CLIENTDIR}/client.o \ ${SRC_CLIENTDIR}/client_connect.o \ ${SRC_CLIENTDIR}/udptest.o \ ${SRC_COMMONDIR}/packet.o \ ${SRC_COMMONDIR}/queue.o \ ${SRC_COMMONDIR}/bn_type.o \ ${SRC_COMMONDIR}/network.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/bnethash.o \ ${SRC_COMMONDIR}/bnethashconv.o \ ${SRC_COMMONDIR}/util.o \ ${SRC_COMMONDIR}/bnettime.o \ ${SRC_COMMONDIR}/proginfo.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/inet_ntoa.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/strftime.o \ ${SRC_COMPATDIR}/psock.o \ ${SRC_COMPATDIR}/gettimeofday.o \ ${SRC_COMPATDIR}/memset.o bnilist_BIN = ${SRC_BINDIR}/bnilist bnilist_OBJECTS = ${SRC_BNIUTILSDIR}/bnilist.o \ ${SRC_BNIUTILSDIR}/fileio.o \ ${SRC_BNIUTILSDIR}/tga.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/memcpy.o bni2tga_BIN = ${SRC_BINDIR}/bni2tga bni2tga_OBJECTS = ${SRC_BNIUTILSDIR}/bni2tga.o \ ${SRC_BNIUTILSDIR}/fileio.o \ ${SRC_COMPATDIR}/strerror.o bniextract_BIN = ${SRC_BINDIR}/bniextract bniextract_OBJECTS= ${SRC_BNIUTILSDIR}/bniextract.o \ ${SRC_BNIUTILSDIR}/fileio.o \ ${SRC_BNIUTILSDIR}/tga.o \ ${SRC_BNIUTILSDIR}/bni.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/memcpy.o bnibuild_BIN = ${SRC_BINDIR}/bnibuild bnibuild_OBJECTS= ${SRC_BNIUTILSDIR}/bnibuild.o \ ${SRC_BNIUTILSDIR}/fileio.o \ ${SRC_BNIUTILSDIR}/tga.o \ ${SRC_BNIUTILSDIR}/bni.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/memcpy.o tgainfo_BIN = ${SRC_BINDIR}/tgainfo tgainfo_OBJECTS = ${SRC_BNIUTILSDIR}/tgainfo.o \ ${SRC_BNIUTILSDIR}/fileio.o \ ${SRC_BNIUTILSDIR}/tga.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/memcpy.o timetest_BIN = ${SRC_BINDIR}/timetest timetest_OBJECTS = ${SRC_DEBUGDIR}/timetest.o \ ${SRC_COMMONDIR}/bn_type.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/bnettime.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/gettimeofday.o listtest_BIN = ${SRC_BINDIR}/listtest listtest_OBJECTS = ${SRC_DEBUGDIR}/listtest.o \ ${SRC_COMMONDIR}/list.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/strdup.o hashtabletest_BIN = ${SRC_BINDIR}/hashtabletest hashtabletest_OBJECTS = ${SRC_DEBUGDIR}/hashtabletest.o \ ${SRC_COMMONDIR}/hashtable.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/strdup.o addrtest_BIN = ${SRC_BINDIR}/addrtest addrtest_OBJECTS = ${SRC_DEBUGDIR}/addrtest.o \ ${SRC_COMMONDIR}/addr.o \ ${SRC_COMMONDIR}/util.o \ ${SRC_COMMONDIR}/list.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/inet_aton.o \ ${SRC_COMPATDIR}/inet_ntoa.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/psock.o \ ${SRC_COMPATDIR}/memset.o \ ${SRC_COMPATDIR}/memcpy.o \ ${SRC_COMPATDIR}/strdup.o cdb_BIN = ${SRC_BINDIR}/bncdb cdb_OBJECTS = ${SRC_CDBDIR}/cdb.o \ ${SRC_CDBDIR}/cdb_init.o \ ${SRC_CDBDIR}/cdb_find.o \ ${SRC_CDBDIR}/cdb_findnext.o \ ${SRC_CDBDIR}/cdb_seek.o \ ${SRC_CDBDIR}/cdb_seq.o \ ${SRC_CDBDIR}/cdb_unpack.o \ ${SRC_CDBDIR}/cdb_make_add.o \ ${SRC_CDBDIR}/cdb_make_put.o \ ${SRC_CDBDIR}/cdb_make_find.o \ ${SRC_CDBDIR}/cdb_make.o \ ${SRC_CDBDIR}/cdb_hash.o \ ${SRC_COMMONDIR}/eventlog.o \ ${SRC_COMMONDIR}/hexdump.o \ ${SRC_COMMONDIR}/xalloc.o \ ${SRC_COMPATDIR}/mmap.o \ ${SRC_COMPATDIR}/strerror.o \ ${SRC_COMPATDIR}/getopt.o OBJECTS = ${bnetd_OBJECTS} ${d2cs_OBJECTS} ${d2dbs_OBJECTS} ${bntrackd_OBJECTS} ${bnchat_OBJECTS} ${bnpass_OBJECTS} ${bnbot_OBJECTS} ${bnftp_OBJECTS} ${bnstat_OBJECTS} ${bnilist_OBJECTS} ${bni2tga_OBJECTS} ${bniextract_OBJECTS} ${bnibuild_OBJECTS} ${tgainfo_OBJECTS} ${timetest_OBJECTS} ${listtest_OBJECTS} ${hashtabletest_OBJECTS} ${addrtest_OBJECTS} ${cdb_OBJECTS} SBINS = ${bnetd_SBIN} ${bntrackd_SBIN} ${d2cs_SBIN} ${d2dbs_SBIN} BINS = ${bnchat_BIN} ${bnpass_BIN} ${bnftp_BIN} ${bnbot_BIN} ${bnstat_BIN} ${bnilist_BIN} ${bni2tga_BIN} ${bniextract_BIN} ${bnibuild_BIN} ${tgainfo_BIN} ${cdb_BIN} MAN1S = bnetd.1 bntrackd.1 bnchat.1 bnpass.1 bnbot.1 bnftp.1 bnstat.1 bnetd.1 bni2tga.1 bnibuild.1 bniextract.1 bnilist.1 tgainfo.1 MAN5S = bnetd.conf.5 bntext.5 bnmotd.txt.5 bnissue.txt.5 bnnews.txt.5 CONFS = ${bnetd_CONFS} ${d2cs_CONFS} ${d2dbs_CONFS} SHARES = ad000001.smk ad000001.mng ad000004.mng \ tos.txt \ newbie.save \ termsofservice-default.txt termsofservice-enUS.txt \ chathelp-war3-default.txt chathelp-war3-enUS.txt \ chathelp-war3-frFR.txt chathelp-war3-zhCN.txt chathelp-war3-ruRU.txt \ newaccount-default.txt newaccount-enUS.txt OTHERRM = ${sbnetd_OBJECTS} ${sbnetd_SBIN} ${timetest_BIN} ${listtest_BIN} ${hashtabletest_BIN} ${addrtest_BIN} ${cdb_BIN} ${SRC_ACDIR}/ansi2knr ${SRC_ACDIR}/ansi2knr.o @ANSI2KNR_TMP@ DIRS = ${SRC_BINDIR} ${SRC_SBINDIR} # common dependencies can't be expressed this way portably... #${OBJECTS}: ${SRC_SRCDIR}/Makefile ${SRC_SRCDIR}/config.h ${SRC_COMMONDIR}/version.h ${SRC_COMMONDIR}/setup_before.h ${SRC_COMMONDIR}/setup_after.h ${SRC_ACDIR}/ansi2knr .PHONY: all all: .dep @ANSI2KNR_DEP@ config ${SBINS} ${BINS} ${SRC_CONFDIR}/bnetd.conf ${SRC_CONFDIR}/d2cs.conf ${SRC_CONFDIR}/d2dbs.conf .PHONY: clean clean: -${RMF} core -${RMF} ${OBJECTS} -${RMF} ${SBINS} -${RMF} ${BINS} -${RMF} ${OTHERRM} .PHONY: distclean distclean: clean -${RMF} ${SRC_CONFDIR}/bnetd.conf -${RMF} ${SRC_CONFDIR}/d2cs.conf -${RMF} ${SRC_CONFDIR}/d2dbs.conf -${RMF} ${SRC_SRCDIR}/config.cache ${SRC_SRCDIR}/config.log -${RMF} ${SRC_SRCDIR}/config.status -${RMF} ${SRC_SRCDIR}/Makefile ${SRC_SRCDIR}/config.h -${RMDIR} ${DIRS} .PHONY: cvsclean cvsclean: distclean -${RMF} ${SRC_SRCDIR}/configure ${SRC_SRCDIR}/config.h.in .PHONY: clean-compile clean-compile: clean all .PHONY: config config: .dep ${SRC_SRCDIR}/Makefile ${SRC_SRCDIR}/config.h ${SRC_SRCDIR}/configure: ${SRC_SRCDIR}/configure.in @${ECHO} "The configure script is out of date; rebuilding..." cd ${SRC_SRCDIR} && autoconf @${ECHO} >> ${SRC_SRCDIR}/config.h.in @${ECHO} >> $@ ${SRC_SRCDIR}/config.h.in: ${SRC_SRCDIR}/configure.in @${ECHO} "The config.h.in header is out of date; rebuilding..." cd ${SRC_SRCDIR} && autoheader @${ECHO} >> $@ @${ECHO} >> ${SRC_SRCDIR}/configure ${SRC_SRCDIR}/config.status: ${SRC_SRCDIR}/configure @${ECHO} "The config.status script is out of date; rechecking..." ${SRC_SRCDIR}/config.status --recheck @${ECHO} >> $@ ${SRC_SRCDIR}/config.h: ${SRC_SRCDIR}/config.h.in ${SRC_SRCDIR}/config.status @${ECHO} "The config.h header is out of date; rewriting..." ${SRC_SRCDIR}/config.status @${ECHO} >> ${SRC_SRCDIR}/Makefile @${ECHO} >> $@ ${SRC_SRCDIR}/Makefile: ${SRC_SRCDIR}/Makefile.in ${SRC_SRCDIR}/config.status @${ECHO} "The Makefile is out of date; rewriting..." ${SRC_SRCDIR}/config.status @${ECHO} >> ${SRC_SRCDIR}/config.h @${ECHO} >> $@ ${SRC_BINDIR}: ${INSTALL_DIRS} $@ ${SRC_SBINDIR}: ${INSTALL_DIRS} $@ .PHONY: bnetd bnetd: .dep ${bnetd_SBIN} .PHONY: install install: .dep install-sbin install-bin install-man install-conf install-share .PHONY: install-bnetd install-bnetd: ${bnetd_SBIN} ${INSTALL_DIRS} ${DESTDIR}/${sbindir} @list='${bnetd_SBIN}'; for p in $$list; do \ if test -f $$p; then \ ${ECHO} " ${INSTALL_PROGRAM} $$p ${DESTDIR}/${sbindir}"; \ ${INSTALL_PROGRAM} $$p ${DESTDIR}/${sbindir}; \ else :; fi; \ done .PHONY: install-sbin install-sbin: ${SBINS} ${INSTALL_DIRS} ${DESTDIR}/${sbindir} @list='${SBINS}'; for p in $$list; do \ if test -f $$p; then \ ${ECHO} " ${INSTALL_PROGRAM} $$p ${DESTDIR}/${sbindir}"; \ ${INSTALL_PROGRAM} $$p ${DESTDIR}/${sbindir}; \ else :; fi; \ done .PHONY: install-bin install-bin: ${BINS} ${INSTALL_DIRS} ${DESTDIR}/${bindir} @list='${BINS}'; for p in $$list; do \ if test -f $$p; then \ ${ECHO} " ${INSTALL_PROGRAM} $$p ${DESTDIR}/${bindir}"; \ ${INSTALL_PROGRAM} $$p ${DESTDIR}/${bindir}; \ else :; fi; \ done .PHONY: install-man install-man: ${INSTALL_DIRS} ${DESTDIR}/${mandir} ${DESTDIR}/${mandir}/man1 ${DESTDIR}/${mandir}/man5 @list='${MAN1S}'; for p in $$list; do \ if test -f ${SRC_MANDIR}/$$p; then \ ${ECHO} " ${INSTALL_DATA} ${SRC_MANDIR}/$$p ${DESTDIR}/${mandir}/man1"; \ ${INSTALL_DATA} ${SRC_MANDIR}/$$p ${DESTDIR}/${mandir}/man1; \ else :; fi; \ done @list='${MAN5S}'; for p in $$list; do \ if test -f ${SRC_MANDIR}/$$p; then \ ${ECHO} " ${INSTALL_DATA} ${SRC_MANDIR}/$$p ${DESTDIR}/${mandir}/man5"; \ ${INSTALL_DATA} ${SRC_MANDIR}/$$p ${DESTDIR}/${mandir}/man5; \ else :; fi; \ done .PHONY: install-conf install-conf: ${SRC_CONFDIR}/bnetd.conf ${SRC_CONFDIR}/d2cs.conf ${SRC_CONFDIR}/d2dbs.conf ${INSTALL_DIRS} ${DESTDIR}/${confdir} @list='${CONFS}'; for p in $$list; do \ if test -f ${SRC_CONFDIR}/$$p; then \ ${ECHO} " ${INSTALL_DATA} ${SRC_CONFDIR}/$$p ${DESTDIR}/${confdir}"; \ ${INSTALL_DATA} ${SRC_CONFDIR}/$$p ${DESTDIR}/${confdir}; \ else :; fi; \ done .PHONY: install-share install-share: ${INSTALL_DIRS} ${DESTDIR}/${sharedir} ${DESTDIR}/${filesdir} ${DESTDIR}/${usersdir} ${DESTDIR}/${userscdbdir} ${DESTDIR}/${bnmaildir} ${DESTDIR}/${reportsdir} \ ${DESTDIR}/${chanlogsdir} ${DESTDIR}/${charinfodir} ${DESTDIR}/${charsavedir} ${DESTDIR}/${bak_charsavedir} \ ${DESTDIR}/${bak_charinfodir} ${DESTDIR}/${ladderdir} ${DESTDIR}/${statusdir} \ ${DESTDIR}/${clandir} ${DESTDIR}/${teamdir} @list='${SHARES}'; for p in $$list; do \ if test -f ${SRC_SHAREDIR}/$$p; then \ ${ECHO} " ${INSTALL_DATA} ${SRC_SHAREDIR}/$$p ${DESTDIR}/${filesdir}"; \ ${INSTALL_DATA} ${SRC_SHAREDIR}/$$p ${DESTDIR}/${filesdir}; \ else :; fi; \ done chmod u+x ${SRC_SCRIPTDIR}/tos.sh ${SRC_SCRIPTDIR}/tos.sh ${DESTDIR}/${filesdir} .PHONY: uninstall uninstall: uninstall-sbin uninstall-bin uninstall-man uninstall-conf uninstall-share .PHONY: uninstall-sbin uninstall-sbin: @list='${SBINS}'; for p in $$list; do \ ${ECHO} " ${RMF} ${sbindir}/$$p"; \ ${RMF} ${sbindir}/$$p; \ done .PHONY: uninstall-bin uninstall-bin: @list='${BINS}'; for p in $$list; do \ ${ECHO} " ${RMF} ${bindir}/$$p"; \ ${RMF} ${bindir}/$$p; \ done .PHONY: uninstall-man uninstall-man: @list='${MAN1S}'; for p in $$list; do \ ${ECHO} " ${RMF} ${mandir}/man1/$$p"; \ ${RMF} ${mandir}/man1/$$p; \ done @list='${MAN5S}'; for p in $$list; do \ ${ECHO} " ${RMF} ${mandir}/man5/$$p"; \ ${RMF} ${mandir}/man5/$$p; \ done .PHONY: uninstall-conf uninstall-conf: @list='${CONFS}'; for p in $$list; do \ ${ECHO} " ${RMF} ${confdir}/$$p"; \ ${RMF} ${confdir}/$$p; \ done .PHONY: uninstall-share uninstall-share: @list='${SHARES}'; for p in $$list; do \ ${ECHO} " ${RMF} ${sharedir}/$$p"; \ ${RMF} ${sharedir}/$$p; \ done ${SRC_CONFDIR}/bnetd.conf: ${SRC_CONFDIR}/bnetd.conf.in ${SRC_SRCDIR}/config.status @${RMF} $@ ${SED} -e "s@/usr/local/var/@${sharedir}/@g" -e "s@/usr/local/etc/@${confdir}/@g" ${SRC_CONFDIR}/bnetd.conf.in > $@ ${SRC_CONFDIR}/d2cs.conf: ${SRC_CONFDIR}/d2cs.conf.in ${SRC_SRCDIR}/config.status @${RMF} $@ ${SED} -e "s@/usr/local/var/@${sharedir}/@g" -e "s@/usr/local/etc/@${confdir}/@g" ${SRC_CONFDIR}/d2cs.conf.in > $@ ${SRC_CONFDIR}/d2dbs.conf: ${SRC_CONFDIR}/d2dbs.conf.in ${SRC_SRCDIR}/config.status @${RMF} $@ ${SED} -e "s@/usr/local/var/@${sharedir}/@g" -e "s@/usr/local/etc/@${confdir}/@g" ${SRC_CONFDIR}/d2dbs.conf.in > $@ ${SRC_ACDIR}/ansi2knr: ${SRC_ACDIR}/ansi2knr.o @${RMF} $@ ${LINK} ${SRC_ACDIR}/ansi2knr.o ${LINK_LIBS} -o $@ ${SRC_ACDIR}/ansi2knr.o: ${SRC_ACDIR}/ansi2knr.c @${RMF} $@ ${COMPILE} ${SRC_ACDIR}/ansi2knr.c -o $@ SHOWHEADER: @echo @echo "Using compile command: ${COMPILE}" @echo .c.o: @${RMF} $@ @echo "Compiling $*.c" @@COMPILEANSI1@ @@COMPILEANSI2@ @@COMPILEANSI3@ .dep: ${MAKE} dep dep: @${RMF} .dep @for a in ${PARTS}; do \ echo Dependency check: $$a; \ ${COMPILE} -MM `ls $$a/*.c` | sed -e "s@\(.*\)\.o:\(.*\)@$$a\/\1\.o:\2@g" 1>>.dep; \ done ${bnetd_SBIN}: SHOWHEADER ${bnetd_OBJECTS} @${INSTALL_DIRS} ${SRC_SBINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bnetd_OBJECTS} ${LINK_LIBS} -o $@ ${d2cs_SBIN}: SHOWHEADER ${d2cs_OBJECTS} @${INSTALL_DIRS} ${SRC_SBINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${d2cs_OBJECTS} ${LINK_LIBS} -o $@ ${d2dbs_SBIN}: SHOWHEADER ${d2dbs_OBJECTS} @${INSTALL_DIRS} ${SRC_SBINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${d2dbs_OBJECTS} ${LINK_LIBS} -o $@ ${sbnetd_SBIN}: SHOWHEADER ${sbnetd_OBJECTS} @${INSTALL_DIRS} ${SRC_SBINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${sbnetd_OBJECTS} ${LINK_LIBS} -o $@ ${bntrackd_SBIN}: SHOWHEADER ${bntrackd_OBJECTS} @${INSTALL_DIRS} ${SRC_SBINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bntrackd_OBJECTS} ${LINK_LIBS} -o $@ ${bnchat_BIN}: SHOWHEADER ${bnchat_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bnchat_OBJECTS} ${LINK_LIBS} -o $@ ${bnpass_BIN}: SHOWHEADER ${bnpass_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bnpass_OBJECTS} ${LINK_LIBS} -o $@ ${bnftp_BIN}: SHOWHEADER ${bnftp_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bnftp_OBJECTS} ${LINK_LIBS} -o $@ ${bnbot_BIN}: SHOWHEADER ${bnbot_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bnbot_OBJECTS} ${LINK_LIBS} -o $@ ${bnstat_BIN}: SHOWHEADER ${bnstat_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bnstat_OBJECTS} ${LINK_LIBS} -o $@ ${bnilist_BIN}: SHOWHEADER ${bnilist_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bnilist_OBJECTS} ${LINK_LIBS} -o $@ ${bni2tga_BIN}: SHOWHEADER ${bni2tga_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bni2tga_OBJECTS} ${LINK_LIBS} -o $@ ${bniextract_BIN}: SHOWHEADER ${bniextract_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bniextract_OBJECTS} ${LINK_LIBS} -o $@ ${bnibuild_BIN}: SHOWHEADER ${bnibuild_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${bnibuild_OBJECTS} ${LINK_LIBS} -o $@ ${tgainfo_BIN}: SHOWHEADER ${tgainfo_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${tgainfo_OBJECTS} ${LINK_LIBS} -o $@ ${timetest_BIN}: SHOWHEADER ${timetest_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${timetest_OBJECTS} ${LINK_LIBS} -o $@ ${listtest_BIN}: SHOWHEADER ${listtest_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${listtest_OBJECTS} ${LINK_LIBS} -o $@ ${hashtabletest_BIN}: SHOWHEADER ${hashtabletest_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${hashtabletest_OBJECTS} ${LINK_LIBS} -o $@ ${addrtest_BIN}: SHOWHEADER ${addrtest_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${addrtest_OBJECTS} ${LINK_LIBS} -o $@ ${cdb_BIN}: SHOWHEADER ${cdb_OBJECTS} @${INSTALL_DIRS} ${SRC_BINDIR} @${RMF} $@ @echo "Linking $@" @${LINK} ${cdb_OBJECTS} ${LINK_LIBS} -o $@ ifneq ($(wildcard .dep),) include .dep endif # Tell versions (3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pvpgn-1.8.5/src/configure.in0000644000175000017500000004005211151345317014743 0ustar aaronaaron# # Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) # Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # Process this file with autoconf to produce a configure script. AC_INIT(bnetd/handle_bnet.c) AC_CONFIG_HEADER(config.h) AUTOCONF_CONFIG_DIR="autoconf" AC_CONFIG_AUX_DIR(${AUTOCONF_CONFIG_DIR}) builtin(include,autoconf/ccstdc.m4) builtin(include,autoconf/mkdir.m4) AC_CANONICAL_SYSTEM # Checks for programs. AC_PROG_CC AC_PROG_INSTALL # Checks compiler. AC_PROG_CPP # Checks for systems. AC_AIX AC_ISC_POSIX AC_MINIX # Custom checks. zwarnflags="" AC_ARG_WITH(warn, [ --with-warn enable compiler warnings], [zwarnflags="-pedantic -Wall -W -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wunreachable-code -Winline -Wpacked -Wno-sign-compare"]) zlangflags="" AC_ARG_WITH(ansi, [ --with-ansi use ANSI C mode], [zlangflags="-ansi -pedantic"]) extra_include="" AC_ARG_WITH(includes, [ --with-includes=DIR search include DIR for header files], [ case "x$withval" in x/*|x.*) AC_MSG_RESULT([adding ${withval} to include search path]) if test ! -d ${withval}; then AC_MSG_RESULT([Warning: directory ${withval} does not exist]) fi extra_include="${extra_include} -I${withval}" ;; *) AC_MSG_RESULT([not adding any includes]) ;; esac]) extra_lib_dir="" AC_ARG_WITH(libraries, [ --with-libraries=DIR search library DIR for libraries], [ case "x${withval}" in x/*|x.*) AC_MSG_RESULT([adding ${withval} to library search path]) if test ! -d ${withval}; then AC_MSG_RESULT([Warning: directory ${withval} does not exist]) fi extra_lib_dir="${extra_lib_dir} -L${withval}" ;; *) AC_MSG_RESULT([not adding any libs]) ;; esac]) extra_lib="" AC_ARG_WITH(efence, [ --with-efence link with Electric Fence to find memory problems], [extra_lib="${extra_lib} -lefence"]) AC_ARG_WITH(mysql, [ --with-mysql include MySQL user accounts support]) AC_ARG_WITH(pgsql, [ --with-pgsql include PostgreSQL user accounts support]) AC_ARG_WITH(mssql, [ --with-mssql include MSSQL user accounts support (requires FreeTDS includes/libs)]) AC_ARG_WITH(sqlite3, [ --with-sqlite3 include SQLite3 user accounts support ]) AC_ARG_WITH(odbc, [ --with-odbc include ODBC user accounts support ]) extra_define="" dnl Enable poll() AC_ARG_ENABLE(poll, [ --enable-poll Enable poll() instead of select(). Normally poll is preferred over select, but configure knows poll is broken on some platforms. If you think you are smarter than the configure script, you may enable poll with this option. --disable-poll Disable the use of poll().], [ case "$enableval" in yes) echo "Forcing poll() to be enabled" ac_cv_func_poll='yes' ;; no) echo "Forcing poll() to be disabled" ac_cv_func_poll='no' ;; esac ]) dnl Shamesly stolen from squid 2.3 configure.in dnl This has to be before AC_CHECK_FUNCS # Disable poll() on certain platforms. Override by setting ac_cv_func_poll # when running configure. if test -z "$ac_cv_func_poll"; then case "$host" in [alpha-dec-osf3.*]) # John Kay (jkay@nlanr.net) 19970818 echo "disabling poll for $host..." ac_cv_func_poll='no' ;; [*-hp-hpux*.*]) # Duane Wessels echo "disabling poll for $host..." ac_cv_func_poll='no' ;; [*-linux-*]) # Henrik Nordstrom (hno@hem.passagen.se) 19980817 # poll is problematic on Linux. We disable it # by default until Linux gets it right. rev=`uname -r | awk -F. '{printf "%03d%03d",$1,$2}'` if test $rev -lt 002002; then echo "disabling poll for $host < 2.2..." ac_cv_func_poll='no' fi ;; [powerpc-ibm-aix4.1.*]) # Mike Laster (mlaster@metavillage.com) 19981021 echo "disabling poll for $host..." ac_cv_func_poll='no' ;; [*-pc-sco3.2*]) # Robert Side # Mon, 18 Jan 1999 17:48:00 GMT echo "disabling poll for $host..." ac_cv_func_poll='no' ;; esac fi # disable parts of the build process AC_ARG_ENABLE(bnetd, [ --enable-bnetd Enable building of bnetd server (default) --disable-bnetd Disable building of bnetd server]) AC_ARG_ENABLE(d2cs, [ --enable-d2cs Enable building of d2cs server (default) --disable-d2cs Disable building of d2cs server]) AC_ARG_ENABLE(d2dbs, [ --enable-d2dbs Enable building of d2dbs server (default) --disable-d2dbs Disable building of d2dbs server]) LDFLAGS="${LDFLAGS} ${extra_lib_dir}" LIBS="${LIBS} ${extra_lib}" CFLAGS="${CFLAGS} ${zlangflags} ${zwarnflags}" DEFINES="${DEFINES} ${extra_define}" CPPFLAGS="${CPPFLAGS} ${extra_include}" # This is our invention so we have to substitute it ourselves # autoconf uses DEFS AC_SUBST(DEFINES) AC_SUBST(enable_bnetd) AC_SUBST(enable_d2cs) AC_SUBST(enable_d2dbs) # Checks for compiler quirks. AC_PROG_GCC_TRADITIONAL AM_PROG_CC_STDC AC_C_CONST AC_C_INLINE #AC_EXEEXT # Checks for libraries. AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"]) AC_CHECK_LIB(z, compress, [LIBS="$LIBS -lz"]) mysql_include_path="" dnl Detecting mysql paths if test "$with_mysql" = "yes" ; then AC_MSG_CHECKING([for mysql include path]) mysql_try_includes="/usr/include /usr/include/mysql /usr/local/include /usr/local/include/mysql /usr/local/mysql/include /usr/local/mysql/include/mysql" for i in `echo ${mysql_try_includes}`; do if test -f "${i}/mysql.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" mysql_include_path=${i} break fi done if test -n "$mysql_include_path" ; then AC_MSG_RESULT([found in $mysql_include_path]) else AC_MSG_ERROR([not found, please install the MySQL headers]) fi fi mysql_lib_path="" if test "$with_mysql" = "yes" ; then AC_CHECK_LIB(mysqlclient, mysql_init , [DEFINES="${DEFINES} -DWITH_SQL_MYSQL" ; LIBS="${LIBS} -lmysqlclient"], [ AC_MSG_CHECKING([for mysql lib path]) mysql_try_libs="/usr/lib /usr/lib/mysql /usr/local/lib /usr/local/lib/mysql /usr/local/mysql/lib /usr/local/mysql/lib/mysql" found="" for i in `echo ${mysql_try_libs}`; do if test -f "${i}/libmysqlclient.so" -o -f "${i}/libmysqlclient.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" AC_CHECK_LIB(mysqlclient, mysql_close , [DEFINES="${DEFINES} -DWITH_SQL_MYSQL" ; LIBS="${LIBS} -lmysqlclient" ; mysql_lib_path="${i}"], [LDFLAGS="${save_ldflags}"]) break fi done if test -n "$mysql_lib_path" ; then AC_MSG_RESULT([found in $mysql_lib_path]) else AC_MSG_ERROR([not found, please install the MySQL libraries]) fi ]) fi pgsql_include_path="" dnl Detecting pgsql paths if test "$with_pgsql" = "yes" ; then AC_MSG_CHECKING([for pgsql include path]) pgsql_try_includes="/usr/include /usr/include/pgsql /usr/local/include /usr/local/include/pgsql /usr/local/pgsql/include" for i in `echo ${pgsql_try_includes}`; do if test -f "${i}/libpq-fe.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" pgsql_include_path=${i} break fi done if test -n "$pgsql_include_path" ; then AC_MSG_RESULT([found in $pgsql_include_path]) else AC_MSG_ERROR([not found, please install the PostgreSQL includes]) fi fi pgsql_lib_path="" if test "$with_pgsql" = "yes" ; then AC_CHECK_LIB(pq, PQsetdbLogin , [DEFINES="${DEFINES} -DWITH_SQL_PGSQL" ; LIBS="${LIBS} -lpq"], [ AC_MSG_CHECKING([for pgsql lib path]) pgsql_try_libs="/usr/lib /usr/lib/pgsql /usr/local/lib /usr/local/lib/pgsql /usr/local/pgsql/lib" for i in `echo ${pgsql_try_libs}`; do if test -f "${i}/libpq.so" -o -f "${i}/libpq.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" AC_CHECK_LIB(pq, PQfinish , [DEFINES="${DEFINES} -DWITH_SQL_PGSQL" ; LIBS="${LIBS} -lpq" ; pgsql_lib_path="${i}"], [LDFLAGS="${save_ldflags}"]) break fi done if test -n "$pgsql_lib_path" ; then AC_MSG_RESULT([found in $pgsql_lib_path]) else AC_MSG_ERROR([not found, please install the PostgreSQL libraries]) fi ]) fi mssql_include_path="" dnl Detecting mssql paths if test "$with_mssql" = "yes" ; then AC_MSG_CHECKING([for mssql/FreeTDS include path]) mssql_try_includes="/usr/include /usr/include/freetds /usr/local/include /usr/local/include/freetds /usr/local/freetds/include" for i in `echo ${mssql_try_includes}`; do if test -f "${i}/sqlfront.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" mssql_include_path=${i} break fi done if test -n "$mssql_include_path" ; then AC_MSG_RESULT([found in $mssql_include_path]) else AC_MSG_ERROR([not found, please install the FreeTDS includes]) fi fi mssql_lib_path="" if test "$with_mssql" = "yes" ; then AC_CHECK_LIB(sybdb, dbinit, [DEFINES="${DEFINES} -DWITH_SQL_MSSQL" ; LIBS="${LIBS} -lsybdb"], [ AC_MSG_CHECKING([for mssql/FreeTDS lib path]) mssql_try_libs="/usr/lib /usr/lib/freetds /usr/local/lib /usr/local/lib/freetds /usr/local/freetds/lib" for i in `echo ${mssql_try_libs}`; do if test -f "${i}/libsybdb.so" -o -f "${i}/libsybdb.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" AC_CHECK_LIB(sybdb, dbclose, [DEFINES="${DEFINES} -DWITH_SQL_MSSQL" ; LIBS="${LIBS} -lsybdb" ; mssql_lib_path="${i}"], [LDFLAGS="${save_ldflags}"]) break fi done if test -n "$mssql_lib_path" ; then AC_MSG_RESULT([found in $mssql_lib_path]) else AC_MSG_ERROR([not found, please install the FreeTDS libraries]) fi ]) fi sqlite3_include_path="" dnl Detecting sqlite3 paths if test "$with_sqlite3" = "yes" ; then AC_MSG_CHECKING([for SQLite3 include path]) sqlite3_try_includes="/usr/include /usr/include/sqlite3 /usr/local/include /usr/local/include/sqlite3 /usr/local/sqlite3/include" for i in `echo ${sqlite3_try_includes}`; do if test -f "${i}/sqlite3.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" sqlite3_include_path=${i} break fi done if test -n "$sqlite3_include_path" ; then AC_MSG_RESULT([found in $sqlite3_include_path]) else AC_MSG_ERROR([not found, please install the SQLite3 includes]) fi fi sqlite3_lib_path="" if test "$with_sqlite3" = "yes" ; then AC_CHECK_LIB(sqlite3, sqlite3_open, [DEFINES="${DEFINES} -DWITH_SQL_SQLITE3" ; LIBS="${LIBS} -lsqlite3"], [ AC_MSG_CHECKING([for SQLite3 lib path]) sqlite3_try_libs="/usr/lib /usr/lib/sqlite3 /usr/local/lib /usr/local/lib/sqlite3 /usr/local/sqlite3/lib" for i in `echo ${sqlite3_try_libs}`; do if test -f "${i}/libsqlite3.so" -o -f "${i}/libsqlite3.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" AC_CHECK_LIB(sqlite3, sqlite3_close, [DEFINES="${DEFINES} -DWITH_SQL_SQLITE3" ; LIBS="${LIBS} -lsqlite3" ; sqlite3_lib_path="${i}"], [LDFLAGS="${save_ldflags}"]) break fi done if test -n "$sqlite3_lib_path" ; then AC_MSG_RESULT([found in $sqlite3_lib_path]) else AC_MSG_ERROR([not found, please install the SQLite3 libraries]) fi ]) fi odbc_include_path="" dnl Detecting odbc paths if test "$with_odbc" = "yes" ; then AC_MSG_CHECKING([for odbc include path]) odbc_try_includes="/usr/include /usr/include/odbc /usr/local/include /usr/local/include/odbc /usr/local/odbc/include" for i in `echo ${odbc_try_includes}`; do if test -f "${i}/sqlext.h" ; then CPPFLAGS="${CPPFLAGS} -I${i}" odbc_include_path=${i} break fi done if test -n "$odbc_include_path" ; then AC_MSG_RESULT([found in $odbc_include_path]) else AC_MSG_ERROR([not found, please install the odbc includes]) fi fi odbc_lib_path="" if test "$with_odbc" = "yes" ; then AC_CHECK_LIB(odbc, SQLConnect, [DEFINES="${DEFINES} -DWITH_SQL_ODBC" ; LIBS="${LIBS} -lodbc"], [ AC_MSG_CHECKING([for odbc lib path]) odbc_try_libs="/usr/lib /usr/lib/odbc /usr/local/lib /usr/local/lib/odbc /usr/local/odbc/lib" for i in `echo ${odbc_try_libs}`; do if test -f "${i}/libodbc.so" -o -f "${i}/libodbc.a" ; then save_ldflags="${LDFLAGS}" LDFLAGS="${LDFLAGS} -L${i}" AC_CHECK_LIB(odbc, SQLDisconnect, [DEFINES="${DEFINES} -DWITH_SQL_ODBC" ; LIBS="${LIBS} -lodbc" ; odbc_lib_path="${i}"], [LDFLAGS="${save_ldflags}"]) break fi done if test -n "$odbc_lib_path" ; then AC_MSG_RESULT([found in $odbc_lib_path]) else AC_MSG_ERROR([not found, please install the odbc libraries]) fi ]) fi AC_CHECK_LIB(nsl, gethostbyname, [LIBS="$LIBS -lnsl"]) AC_CHECK_LIB(socket, socket, [LIBS="$LIBS -lsocket"]) AC_CHECK_LIB(resolv, inet_aton, [LIBS="$LIBS -lresolv"]) dnl BeOS BONE... AC_CHECK_LIB(bind, __inet_aton, [LIBS="$LIBS -lbind"]) case "$host" in [*-beos*]) if test "$ac_cv_lib_bind___inet_aton" = "yes"; then dnl force things, AC_CHECK_FUNC will never get the mangled versions anyway. echo "Forcing inet_aton() and inet_ntoa() to be enabled" ac_cv_func_inet_aton='yes' ac_cv_func_inet_ntoa='yes' fi ;; esac AC_CHECK_LIB(wsock32, _libwsock32_a_iname, [LIBS="$LIBS -lwsock32"]) # Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC AC_HEADER_TIME AC_HEADER_STAT AC_CHECK_HEADERS([\ fcntl.h \ sys/time.h \ time.h \ sys/select.h \ string.h \ strings.h \ unistd.h \ stdarg.h \ varargs.h \ malloc.h \ sys/utsname.h \ sys/timeb.h \ sys/socket.h \ sys/param.h \ netinet/in.h \ arpa/inet.h \ netdb.h \ termios.h \ stddef.h \ memory.h \ sys/types.h \ sys/wait.h \ sys/ioctl.h \ stdint.h \ sys/file.h \ limits.h \ poll.h \ sys/poll.h \ stropts.h \ sys/stropts.h \ sys/stat.h \ pwd.h \ grp.h \ dir.h \ direct.h \ sys/mman.h \ sys/event.h \ sys/epoll.h \ sys/resource.h \ assert.h \ sqlite3.h \ ]) # Checks for typedefs and structures AC_STRUCT_TM AC_TYPE_PID_T AC_TYPE_SIGNAL AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_CHECK_SIZEOF(unsigned char, 1) AC_CHECK_SIZEOF(unsigned short, 2) AC_CHECK_SIZEOF(unsigned int, 4) AC_CHECK_SIZEOF(unsigned long, 4) AC_CHECK_SIZEOF(unsigned long long, 0) AC_CHECK_SIZEOF(signed char, 1) AC_CHECK_SIZEOF(signed short, 2) AC_CHECK_SIZEOF(signed int, 4) AC_CHECK_SIZEOF(signed long, 4) AC_CHECK_SIZEOF(signed long long, 0) # Checks for library functions. AC_FUNC_MMAP AC_FUNC_STRFTIME AC_FUNC_VPRINTF AC_FUNC_CLOSEDIR_VOID AC_FUNC_MKDIR_ARGS AC_CHECK_FUNCS(gethostname gettimeofday select socket strdup strtoul strerror inet_aton inet_ntoa uname recv send recvfrom sendto uname fork getpid sigaction sigprocmask sigaddset setpgid setpgrp ftime strcasecmp strncasecmp stricmp strnicmp chdir difftime strchr strrchr index rindex memcpy memset memmove bcopy wait waitpid pipe getenv ioctl setsid mktime poll gethostbyname getservbyname getlogin pow getpwnam getgrnam getuid getgid setuid setgid mkdir _mkdir strsep getopt kqueue setitimer epoll_create getrlimit vsnprintf _vsnprintf snprintf _snprintf) if test X$ac_cv_func_setpgrp = X"yes"; then AC_FUNC_SETPGRP fi if test X"${am_cv_prog_cc_stdc}" = X"no"; then COMPILEANSI1='${PREPROCESS} $< | sed '"'"'s/^# *\([0-9][0-9]*\) *\([^ ]*[a-z][^ ]*\) *.*$$/#line \1 \2/'"'"' | ${SRC_ACDIR}/ansi2knr > ${SRC_SRCDIR}/.ansi2knr_tmp.c' COMPILEANSI2='${COMPILE} ${SRC_SRCDIR}/.ansi2knr_tmp.c -o $@' COMPILEANSI3='@${RMF} ${SRC_SRCDIR}/.ansi2knr_tmp.c' ANSI2KNR_TMP='${SRC_SRCDIR}/.ansi2knr_tmp.c' ANSI2KNR_DEP='${SRC_ACDIR}/ansi2knr' else COMPILEANSI1='${COMPILE} $< -o $@' COMPILEANSI2='@:' COMPILEANSI3='@:' ANSI2KNR_TMP='' ANSI2KNR_DEP='' fi AC_SUBST(COMPILEANSI1) AC_SUBST(COMPILEANSI2) AC_SUBST(COMPILEANSI3) AC_SUBST(ANSI2KNR_TMP) AC_SUBST(ANSI2KNR_DEP) AC_OUTPUT(Makefile) pvpgn-1.8.5/src/bnpcap/0000755000175000017500000000000011151345372013675 5ustar aaronaaronpvpgn-1.8.5/src/bnpcap/.cvsignore0000644000175000017500000000001111151345317015664 0ustar aaronaarontcpdumps pvpgn-1.8.5/src/bnpcap/Makefile0000644000175000017500000000066111151345317015337 0ustar aaronaaronCC=gcc CFLAGS=-g -O -W -Wall -DHAVE_CONFIG_H -I.. LDFLAGS= LINK_LIBS=-lpcap LINK=$(CC) $(LDFLAGS) COMPILE=$(CC) $(CFLAGS) -c BNPCAP_OBJS = bnpcap.o\ ../common/hexdump.o\ ../common/list.o\ ../common/eventlog.o\ ../common/packet.o\ ../common/bn_type.o\ ../common/util.o all: bnpcap bnpcap: $(BNPCAP_OBJS) $(LINK) -o bnpcap $(BNPCAP_OBJS) $(LINK_LIBS) .c.o: ${COMPILE} $< -o $@ clean: rm -f bnpcap $(BNPCAP_OBJS) pvpgn-1.8.5/src/bnpcap/bnpcap.c0000644000175000017500000005700511151345317015312 0ustar aaronaaron/* * Copyright (C) 2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #include #include #include #include #include #include "compat/strerror.h" #include "compat/getopt.h" #include "common/init_protocol.h" #include "common/bnet_protocol.h" #include "common/udp_protocol.h" #include "common/packet.h" #include "common/eventlog.h" #include "common/hexdump.h" #include "common/list.h" #include "common/version.h" #include "common/util.h" #include "common/setup_after.h" /* FIXME: everywhere: add checks for NULL pointers */ char *filename = NULL; pcap_t *pc; char ebuf[PCAP_ERRBUF_SIZE]; int bnpcap_dodebug = 0; int bnpcap_beverbose = 0; unsigned int listen_port = 6112; /********************* CONNECTIONS ********************/ typedef enum { tcp_state_none, tcp_state_syn, tcp_state_ack, tcp_state_ok } t_tcp_state; typedef struct { /* It's IPV4 */ unsigned int ip; unsigned short port; } t_bnpcap_addr; /* To track connections ... */ typedef struct { t_bnpcap_addr client; t_bnpcap_addr server; t_packet_class class; t_tcp_state tcpstate; int incomplete; int clientoff; t_packet *clientpkt; int serveroff; t_packet *serverpkt; t_list * packets; } t_bnpcap_conn; typedef struct { t_packet_dir dir; struct timeval tv; unsigned int id; t_packet *p; } t_bnpcap_packet; t_list * conns; t_list * udppackets; struct timeval packettime; static unsigned int current_packet_id = 1; /*********************** HEADERS **********************/ /* FIXME: don't assume that's always true */ typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; /************************** TCP ***********************/ typedef struct { u16 sport; u16 dport; u32 seqno; u32 ackno; u16 stuff; /* Data offset, various flags */ u16 window; u16 checksum; u16 urgp; /* Urgent Pointer (if URG flag set) */ /* options */ } t_tcp_header_raw; typedef struct { unsigned short sport; unsigned short dport; unsigned int seqno; unsigned int ackno; unsigned char doffset; unsigned short flags; #define TCP_URG 0x20 /* Urgent pointer field significant */ #define TCP_ACK 0x10 /* Acknowlegdement field significant */ #define TCP_PSH 0x08 /* Push function */ #define TCP_RST 0x04 /* Reset connection */ #define TCP_SYN 0x02 /* Synchronize sequence numbers */ #define TCP_FIN 0x01 /* No more data from sender (finish) */ unsigned short window; unsigned short checksum; unsigned short urgp; /* options */ } t_tcp_header; /******************************** UDP ************************/ typedef struct { u16 sport; u16 dport; u16 len; u16 checksum; } t_ip_udp_header_raw; typedef struct { unsigned short sport; unsigned short dport; unsigned short len; unsigned short checksum; } t_ip_udp_header; /******************************** IP *************************/ typedef struct { u8 versionihl; u8 tos; u16 len; u16 id; u16 flagsoffset; u8 ttl; u8 protocol; u16 checksum; u32 src; u32 dst; /* options */ } t_ip_header_raw; typedef struct { unsigned char version; unsigned char ihl; unsigned char tos; unsigned short len; unsigned short id; unsigned char flags; #define IP_DF 0x02 /* 1 == Don't fragment */ #define IP_MF 0x01 /* 1 == More fragments */ unsigned short offset; unsigned char ttl; unsigned char protocol; unsigned short checksum; unsigned int src; unsigned int dst; /* options */ } t_ip_header; /******************************* ETHERNET *****************************/ typedef struct { u8 dst[6]; /* Ethernet hardware address */ u8 src[6]; /* Ethernet hardware address */ u16 type; /* Ethernet_II: protocol type */ /* FIXME: Ethernet [802.2|802.3|SNAP]: maybe something else (eg. length) */ } t_ether_raw; /************************************************************************/ /************************* CONNECTION FUNCTIONS *************************/ static t_bnpcap_conn * bnpcap_conn_new(t_bnpcap_addr const *s, t_bnpcap_addr const *d) { t_bnpcap_conn * c; c = (t_bnpcap_conn *) malloc(sizeof(t_bnpcap_conn)); /* avoid warning */ if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno)); return NULL; } if (d->port==listen_port || d->port==6200) { /* FIXME: That's dirty: We assume the server is on port 6112 */ memcpy(&c->client,s,sizeof(t_bnpcap_addr)); memcpy(&c->server,d,sizeof(t_bnpcap_addr)); } else { memcpy(&c->client,d,sizeof(t_bnpcap_addr)); memcpy(&c->server,s,sizeof(t_bnpcap_addr)); } c->class = packet_class_init; c->packets = list_create(); c->incomplete = 0; c->tcpstate = tcp_state_none; c->clientoff = 0; c->clientpkt = NULL; c->serveroff = 0; c->serverpkt = NULL; return c; } static void bnpcap_conn_set_class(t_bnpcap_conn *c, t_packet_class class) { c->class = class; } static t_packet_class bnpcap_conn_get_class(t_bnpcap_conn *c) { return c->class; } static t_bnpcap_conn * bnpcap_conn_find(t_bnpcap_addr const *s, t_bnpcap_addr const *d) { t_elem * curr; LIST_TRAVERSE(conns,curr) { t_bnpcap_conn *c; c = elem_get_data(curr); if (((c->client.ip==s->ip)&&(c->client.port==s->port))&& ((c->server.ip==d->ip)&&(c->server.port==d->port))) { return c; } else if (((c->client.ip==d->ip)&&(c->client.port==d->port))&& ((c->server.ip==s->ip)&&(c->server.port==s->port))) { return c; } } return NULL; } static t_packet_dir bnpcap_conn_get_dir(t_bnpcap_conn const * c, t_bnpcap_addr const *s, t_bnpcap_addr const *d) { if (((c->client.ip==s->ip)&&(c->client.port==s->port))&& ((c->server.ip==d->ip)&&(c->server.port==d->port))) return packet_dir_from_client; else return packet_dir_from_server; } static int bnpcap_conn_add_packet(t_bnpcap_conn *c, t_bnpcap_packet *bp) { eventlog(eventlog_level_debug,__FUNCTION__,"id=%u ",bp->id); list_append_data(c->packets,bp); packet_add_ref(bp->p); return 0; } static int bnpcap_conn_packet(unsigned int sip, unsigned short sport, unsigned int dip, unsigned short dport, unsigned char const * data, unsigned int len) { t_bnpcap_addr s; t_bnpcap_addr d; t_bnpcap_conn *c; t_bnpcap_packet *bp; s.ip = sip; s.port = sport; d.ip = dip; d.port = dport; if ((c = bnpcap_conn_find(&s,&d))) { eventlog(eventlog_level_debug,__FUNCTION__,"adding packet to existing connection"); if (c->tcpstate==tcp_state_ack) { c->tcpstate = tcp_state_ok; } else if (c->tcpstate==tcp_state_syn) { c->incomplete = 1; /* ACK missing */ c->tcpstate = tcp_state_ok; } } else { eventlog(eventlog_level_debug,__FUNCTION__,"adding packet to incomplete connection"); c = bnpcap_conn_new(&s,&d); bnpcap_conn_set_class(c,packet_class_raw); /* we don't know the init sequence */ c->incomplete = 1; c->tcpstate = tcp_state_ok; list_append_data(conns,c); } if (c->tcpstate!=tcp_state_ok) { eventlog(eventlog_level_warn,__FUNCTION__,"connection got packet in wrong state!"); } if (bnpcap_conn_get_class(c) == packet_class_init) { if (len>1) { eventlog(eventlog_level_warn,__FUNCTION__,"init packet larger than 1 byte"); } switch (data[0]) { case CLIENT_INITCONN_CLASS_BNET: bnpcap_conn_set_class(c,packet_class_bnet); break; case CLIENT_INITCONN_CLASS_FILE: bnpcap_conn_set_class(c,packet_class_file); break; case 0xf7: // W3 matchmaking hack eventlog(eventlog_level_info,__FUNCTION__,"matchmaking packet"); bnpcap_conn_set_class(c,packet_class_bnet); break; default: bnpcap_conn_set_class(c,packet_class_raw); } } else { t_packet *p; unsigned int off; unsigned char const *datap = data; int always_complete = 0; if (bnpcap_conn_get_class(c) == packet_class_raw) always_complete = 1; /* There is no size field */ if (bnpcap_conn_get_class(c) == packet_class_file) always_complete = 1; /* Size field isn't always there */ if (always_complete) { /* packet is always complete */ eventlog(eventlog_level_debug,__FUNCTION__,"packet is always complete (class=%d)",bnpcap_conn_get_class(c)); bp = (t_bnpcap_packet *) malloc(sizeof(t_bnpcap_packet)); /* avoid warning */ if (!bp) { eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno)); return -1; } bp->dir = bnpcap_conn_get_dir(c,&s,&d); bp->p = packet_create(bnpcap_conn_get_class(c)); bp->id = current_packet_id++; if (!bp->p) { eventlog(eventlog_level_error,__FUNCTION__,"packet_create failed"); return -1; } memcpy(&bp->tv,&packettime,sizeof(struct timeval)); packet_set_size(bp->p,len); memcpy(packet_get_raw_data(bp->p,0),data,len); bnpcap_conn_add_packet(c,bp); if ((packet_get_class(bp->p)==packet_class_file)&&(packet_get_type(bp->p)==SERVER_FILE_REPLY)) { eventlog(eventlog_level_debug,__FUNCTION__,"file transfer initiated (setting to raw)"); bnpcap_conn_set_class(c,packet_class_raw); } } else { /* read out saved state */ if (bnpcap_conn_get_dir(c,&s,&d)==packet_dir_from_client) { p = c->clientpkt; off = c->clientoff; } else { p = c->serverpkt; off = c->serveroff; } while ((datap-data)<(signed)len) { if (!p) { eventlog(eventlog_level_debug,__FUNCTION__,"creating new packet"); p = packet_create(bnpcap_conn_get_class(c)); if (!p) { eventlog(eventlog_level_error,__FUNCTION__,"packet_create failed"); return -1; } packet_set_size(p,packet_get_header_size(p)); /* set it to the minimum for now */ off = 0; } if (off < packet_get_header_size(p)) { unsigned int l = (packet_get_header_size(p)-off); /* (len-(datap-data)) : remaining bytes in buffer */ if ((len-(datap-data)) < l) l = (len-(datap-data)); eventlog(eventlog_level_debug,__FUNCTION__,"filling up header (adding %d to %d to get %d)",l,off,packet_get_header_size(p)); memcpy(packet_get_raw_data(p,off),datap,l); datap = datap + l; off = off + l; } else { unsigned int l = (packet_get_size(p)-off); if ((len-(datap-data)) < l) l = (len-(datap-data)); eventlog(eventlog_level_debug,__FUNCTION__,"filling up packet (0x%04x:%s) (adding %d to %d to get %d)",packet_get_type(p),packet_get_type_str(p,bnpcap_conn_get_dir(c,&s,&d)),l,off,packet_get_size(p)); memcpy(packet_get_raw_data(p,off),datap,l); datap = datap + l; off = off + l; } if ((off>=packet_get_header_size(p))&&(off>=packet_get_size(p))) { /* packet is complete */ eventlog(eventlog_level_debug,__FUNCTION__,"packet is complete"); bp = (t_bnpcap_packet *) malloc(sizeof(t_bnpcap_packet)); /* avoid warning */ if (!bp) { eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno)); return -1; } if ((off != packet_get_size(p))&&(bnpcap_dodebug)) { eventlog(eventlog_level_warn,__FUNCTION__,"packet size differs (%d != %d) (offset=0x%04x)",off,packet_get_size(p),datap-data); hexdump(stderr,data,len); /* memcpy(packet_get_raw_data(p,0),data,packet_get_size(p)); */ } bp->dir = bnpcap_conn_get_dir(c,&s,&d); bp->p = p; bp->id = current_packet_id++; memcpy(&bp->tv,&packettime,sizeof(struct timeval)); bnpcap_conn_add_packet(c,bp); if (packet_get_size(p)==0) datap = data + len; /* if size is invalid, drop the rest of the stream packet */ p = NULL; off = 0; } } /* while */ /* write back saved state */ if ((off>0)&&(bnpcap_dodebug)) { eventlog(eventlog_level_debug,__FUNCTION__,"saving %d bytes in packet buffer (p=0x%08lx)",off,(long)p); } if (bnpcap_conn_get_dir(c,&s,&d)==packet_dir_from_client) { c->clientpkt = p; c->clientoff = off; } else { c->serverpkt = p; c->serveroff = off; } } /* !always_complete */ return 0; } return 0; } /************************************************************************/ /******************************** LAYERS ********************************/ /********************************* TCP **********************************/ static int bnpcap_tcp2tcp(t_tcp_header * d, t_tcp_header_raw const * s) { d->sport = htons(s->sport); d->dport = htons(s->dport); d->seqno = htonl(s->seqno); d->ackno = htonl(s->ackno); d->doffset = (htons(s->stuff) & 0xF000) >> 12; d->flags = (htons(s->stuff) & 0x0FFF); d->window = htons(s->window); d->checksum = htons(s->checksum); d->urgp = htons(s->urgp); return 0; } static int bnpcap_process_tcp(t_ip_header const * ip, unsigned char const *data, unsigned int len) { t_tcp_header_raw const *raw; t_tcp_header h; raw = (t_tcp_header_raw const *) data; /* avoid warning */ bnpcap_tcp2tcp(&h,raw); if (h.doffset < 5) { eventlog(eventlog_level_warn,__FUNCTION__,"tcp header too small (%u 32-bit words)",h.doffset); return 1; } else { char fstr[32] = ""; if (h.flags & TCP_URG) strcat(fstr,"U"); if (h.flags & TCP_ACK) strcat(fstr,"A"); if (h.flags & TCP_PSH) strcat(fstr,"P"); if (h.flags & TCP_RST) strcat(fstr,"R"); if (h.flags & TCP_SYN) strcat(fstr,"S"); if (h.flags & TCP_FIN) strcat(fstr,"F"); eventlog(eventlog_level_debug,__FUNCTION__,"tcp: sport=%u dport=%u seqno=0x%08x ackno=0x%08x window=0x%08x len=%d (%s)",h.sport,h.dport,h.seqno,h.ackno,h.window,((signed)len-(h.doffset*4)),fstr); if (((signed)len-(h.doffset*4))<=0) { eventlog(eventlog_level_info,__FUNCTION__,"empty packet (%d)",((signed)len-(h.doffset*4))); /* handle sync packets */ if (h.flags & TCP_SYN) { t_bnpcap_addr s,d; s.ip=ip->src; s.port=h.sport; d.ip=ip->dst; d.port=h.dport; if (h.flags & TCP_ACK) { t_bnpcap_conn *c = bnpcap_conn_find(&s,&d); if (c) { if (c->tcpstate==tcp_state_syn) c->tcpstate=tcp_state_ack; } } else { if (!bnpcap_conn_find(&s,&d)) { t_bnpcap_conn *c; c = bnpcap_conn_new(&s,&d); c->tcpstate = tcp_state_syn; list_append_data(conns,c); eventlog(eventlog_level_debug,__FUNCTION__,"created new connection with SYN"); } else { eventlog(eventlog_level_debug,__FUNCTION__,"got SYN in connection"); } } } } else if (((h.sport!=listen_port)&&(h.dport!=listen_port)) && ((h.sport!=6200)&&(h.dport!=6200))) { eventlog(eventlog_level_info,__FUNCTION__,"other packet (%d)",((signed)len-(h.doffset*4))); } else { eventlog(eventlog_level_info,__FUNCTION__,"valid packet (%d)",((signed)len-(h.doffset*4))); bnpcap_conn_packet(ip->src,h.sport,ip->dst,h.dport,data+(h.doffset*4),len-(h.doffset*4)); } return 0; } } /************************************ UDP ********************************/ static int bnpcap_udp2udp(t_ip_udp_header *d, t_ip_udp_header_raw const *s) { d->sport = ntohs(s->sport); d->dport = ntohs(s->dport); d->len = ntohs(s->len); d->checksum = ntohs(s->checksum); return 0; } static int bnpcap_process_udp(unsigned char const *data, unsigned int len) { t_ip_udp_header_raw const *raw; t_ip_udp_header h; t_bnpcap_packet *bp; raw = (t_ip_udp_header_raw const *) data; /* avoid warning */ bnpcap_udp2udp(&h,raw); bp = (t_bnpcap_packet *) malloc(sizeof(t_bnpcap_packet)); /* avoid warning */ if (!bp) { eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno)); return -1; } if (h.dport==listen_port || h.dport==6200) { bp->dir = packet_dir_from_client; } else { bp->dir = packet_dir_from_server; } eventlog(eventlog_level_debug,__FUNCTION__,"sport=%u dport=%u len=%u(%d)",h.sport,h.dport,h.len,len); bp->id = current_packet_id++; memcpy(&bp->tv,&packettime,sizeof(struct timeval)); bp->p = packet_create(packet_class_udp); if (!bp->p) { eventlog(eventlog_level_error,__FUNCTION__,"packet_create failed"); return -1; } packet_set_size(bp->p,h.len-sizeof(t_ip_udp_header_raw)); memcpy(packet_get_raw_data(bp->p,0),data+sizeof(t_ip_udp_header_raw),h.len-sizeof(t_ip_udp_header_raw)); eventlog(eventlog_level_error,__FUNCTION__,"id=%u ",bp->id); list_append_data(udppackets,bp); return 0; } /************************************ IP *********************************/ static int bnpcap_ip2ip(t_ip_header * d, t_ip_header_raw const * s) { d->version = ((s->versionihl & 0xf0) >> 4); d->ihl = s->versionihl & 0x0f; d->tos = s->tos; d->len = ntohs(s->len); d->id = ntohs(s->id); d->offset = ntohl(s->flagsoffset); d->flags = ((d->offset & 0xE000)>>13); d->offset = ((d->offset & 0x1FFF)); d->ttl = s->ttl; d->protocol = s->protocol; d->checksum = ntohs(s->checksum); d->src = ntohl(s->src); d->dst = ntohl(s->dst); return 0; } static int bnpcap_process_ip(unsigned char const *data, unsigned int len) { /* FIXME: handle IP fragmentation */ /* FIXME: use identification field to pass the datagram in the right order */ t_ip_header_raw const *raw; t_ip_header h; raw = (t_ip_header_raw const *) data; /* avoid warning */ bnpcap_ip2ip(&h,raw); if (h.version != 4) { eventlog(eventlog_level_warn,__FUNCTION__,"ip version %u not supported (ihl=%u, raw=0x%02x)",h.version,h.ihl,raw->versionihl); return 1; } else if (h.ihl < 5) { /* an IP header must be at least 5 words */ eventlog(eventlog_level_warn,__FUNCTION__,"ip header to small (%u 32-bit words)",h.ihl); return 1; } else if (h.len > len) { eventlog(eventlog_level_warn,__FUNCTION__,"ip len larger than packet (%d > %d)",h.len,len); return 1; } else { char fstr[32] = ""; if (h.flags & IP_DF) strcat(fstr,"D"); if (h.flags & IP_MF) strcat(fstr,"M"); eventlog(eventlog_level_debug,__FUNCTION__,"ip: len=%u(%u) src=%08x dst=%08x protocol=%u offset=0x%08x id=0x%08x (%s)",h.len,len,h.src,h.dst,h.protocol,h.offset,h.id,fstr); if (h.protocol==6) { /* This is TCP */ return bnpcap_process_tcp(&h,data+(h.ihl*4),h.len-(h.ihl*4)); } else if (h.protocol==17) { /* This is UDP */ return bnpcap_process_udp(data+(h.ihl*4),h.len-(h.ihl*4)); } } return 0; } /************************************* ETHERNET ******************************/ static int bnpcap_process_ether(unsigned char const *data, unsigned int len) { /* Well, first parse the ethernet header (I hope you use Ethernet_II :) ... */ t_ether_raw const *raw; raw = (t_ether_raw const *) data; /* avoid warning */ if (ntohs(raw->type)==0x0800) { /* This is IP */ return bnpcap_process_ip(data+sizeof(t_ether_raw),len-sizeof(t_ether_raw)); } else { eventlog(eventlog_level_warn,__FUNCTION__,"unsupported protocol 0x%04x",ntohs(raw->type)); return 1; } } /* If you want to use other hardware protocols like PPP add them here ... */ /**************************** PACKET/PCAP *********************************/ static void bnpcap_process_packet(u_char * private, const struct pcap_pkthdr * p, u_char const * data) { unsigned int pl = p->len; if(private) private = NULL; // hack to eliminate compiler warning memcpy(&packettime,&p->ts,sizeof(struct timeval)); eventlog(eventlog_level_debug,__FUNCTION__,"packet: len=%d caplen=%d",p->len,p->caplen); /* FIXME: check if it's ethernet */ bnpcap_process_ether(data,pl); } /**************************************************************************/ static void bnpcap_usage(void) { printf("BNPCAP - A tool to convert pcap battle.net dumps to a human-readable format.\n"); printf("Version " PVPGN_VERSION " --- Copyright (c) 2001 Marco Ziech (mmz@gmx.net)\n"); printf("This software makes use of libpcap.\n\n"); printf("Usage: bnpcap [-d] [-v] [-p PORT] \n"); printf(" -d Print out debugging information\n"); printf(" -v Be more verbose\n"); printf(" -p PORT Specify port to process (Default: 6112)\n\n"); } /******************************* MAIN *************************************/ int main (int argc, char **argv) { t_elem * currconn; t_elem * currudp; int c; while ((c=getopt(argc,argv,"dvp:"))!=-1) { switch (c) { case 'p': str_to_uint(optarg, &listen_port); break; case 'd': bnpcap_dodebug = 1; break; case 'v': bnpcap_beverbose = 1; break; case '?': printf("unrecognized option '%c'\n",optopt); break; default: printf("getopt returned \'%c\'\n",c); } } if (optind < argc) { filename = argv[optind]; } else { bnpcap_usage(); return 1; } pc = pcap_open_offline(filename,ebuf); if (!pc) { fprintf(stderr,"pcap_open_offline: %s\n",ebuf); return -1; } eventlog_set(stderr); eventlog_clear_level(); if (bnpcap_dodebug) eventlog_add_level("debug"); if (bnpcap_beverbose||bnpcap_dodebug) eventlog_add_level("info"); eventlog_add_level("warn"); eventlog_add_level("error"); eventlog_add_level("fatal"); conns = list_create(); udppackets = list_create(); pcap_dispatch(pc,0,bnpcap_process_packet,NULL); printf("### This packet dump was created by bnpcap.\n"); LIST_TRAVERSE(conns,currconn) { t_bnpcap_conn *c; char cstr[64]; char sstr[64]; t_elem * currpacket; c = elem_get_data(currconn); snprintf(cstr,64,"%u.%u.%u.%u:%u",((c->client.ip & 0xFF000000)>>24),((c->client.ip & 0x00FF0000)>>16),((c->client.ip & 0x0000FF00)>>8),((c->client.ip & 0x000000FF)),c->client.port); snprintf(sstr,64,"%u.%u.%u.%u:%u",((c->server.ip & 0xFF000000)>>24),((c->server.ip & 0x00FF0000)>>16),((c->server.ip & 0x0000FF00)>>8),((c->server.ip & 0x000000FF)),c->server.port); printf("## %s connection: client=%s server=%s\n",(c->incomplete?"incomplete":"complete"),cstr,sstr); LIST_TRAVERSE(c->packets,currpacket) { t_bnpcap_packet * bp; bp = elem_get_data(currpacket); printf("# %u packet from %s: type=0x%04x(%s) length=%d class=%s\n",bp->id/*bp->tv.tv_sec*/,(bp->dir==packet_dir_from_client?"client":"server"),packet_get_type(bp->p),packet_get_type_str(bp->p,bp->dir),packet_get_size(bp->p),packet_get_class_str(bp->p)); hexdump(stdout,packet_get_raw_data(bp->p,0),packet_get_size(bp->p)); printf("\n"); } } printf("## udp packets\n"); LIST_TRAVERSE(udppackets,currudp) { t_bnpcap_packet *bp; bp = elem_get_data(currudp); printf("# %u packet from %s: type=0x%04x(%s) length=%d class=%s\n",bp->id/*bp->tv.tv_sec*/,(bp->dir==packet_dir_from_client?"client":"server"),packet_get_type(bp->p),packet_get_type_str(bp->p,bp->dir),packet_get_size(bp->p),packet_get_class_str(bp->p)); hexdump(stdout,packet_get_raw_data(bp->p,0),packet_get_size(bp->p)); printf("\n"); } pcap_close(pc); return 0; } pvpgn-1.8.5/src/autogen.sh0000644000175000017500000000003711151345317014427 0ustar aaronaaron#!/bin/sh autoconf autoheader pvpgn-1.8.5/src/bnpass/0000755000175000017500000000000011151345372013720 5ustar aaronaaronpvpgn-1.8.5/src/bnpass/bnpass.c0000644000175000017500000000674111151345317015361 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #include #include "compat/exitstatus.h" #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "common/eventlog.h" #include "common/bnethash.h" #include "common/version.h" #include "common/setup_after.h" static void usage(char const * progname) { fprintf(stderr, "usage: %s [] [--] []\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n",progname); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { char const * pass=NULL; int a; int forcepass=0; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a #include #include #include #include "d2cs_resource.h" #include "common/eventlog.h" #include "d2cs/version.h" #include "d2cs/handle_signal.h" #include "service.h" #include "winmain.h" #include "common/setup_after.h" #define WM_SHELLNOTIFY (WM_USER+1) extern int server_main(int argc, char *argv[]); /* d2cs main function in d2cs/main.c */ static void d2cs(void * dummy); /* thread function for d2cs */ static void guiAddText(const char *str, COLORREF clr); static void KillTrayIcon(HWND hwnd); static int OnShellNotify(HWND hwnd, int uID, int uMessage); static void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify); static BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct); static void OnClose(HWND hwnd); static void OnSize(HWND hwnd, UINT state, int cx, int cy); LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL CALLBACK DlgProcAbout(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); HWND ghwndConsole; /* hwnd for eventlog output */ static int gui_run = TRUE; /* default state: run gui */ static int d2cs_run = TRUE; /* default state: run d2cs */ static int d2cs_running = FALSE; /* currect state: not running */ int fprintf(FILE *stream, const char *format, ...) { va_list args; va_start(args, format); if(stream == stderr || stream == stdout) return gui_lvprintf(eventlog_level_error, format, args); else return vfprintf(stream, format, args); } static void KillTrayIcon(HWND hwnd) { NOTIFYICONDATA dta; dta.cbSize = sizeof(NOTIFYICONDATA); dta.hWnd = hwnd; dta.uID = ID_TRAY; dta.uFlags = 0; Shell_NotifyIcon(NIM_DELETE, &dta); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG msg; /* if running as a service skip starting the GUI and go straight to starting d2cs */ if (__argc==2 && strcmp(__argv[1],"--service")==0) { Win32_ServiceRun(); return 1; } LoadLibrary("RichEd20.dll"); wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(LPVOID); wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ID_ICON1)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszMenuName = MAKEINTRESOURCE(ID_MENU); wc.lpszClassName = "BnetWndClass"; if(!RegisterClassEx( &wc )) RegisterClass((LPWNDCLASS)&wc.style); hwnd = CreateWindow(TEXT("BnetWndClass"),"Diablo II Character Server", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, LoadMenu(hInstance, MAKEINTRESOURCE(ID_MENU)), hInstance,NULL); if(hwnd) { ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); } while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage( &msg ); DispatchMessage( &msg ); if(!d2cs_running && d2cs_run && gui_run) { d2cs_running = TRUE; _beginthread(d2cs, 0, NULL); } if(!gui_run && !d2cs_running) { KillTrayIcon(hwnd); exit(0); } } return ((int) msg.wParam); } LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { HANDLE_MSG(hwnd, WM_CREATE, OnCreate); HANDLE_MSG(hwnd, WM_SIZE, OnSize); HANDLE_MSG(hwnd, WM_COMMAND, OnCommand); HANDLE_MSG(hwnd, WM_CLOSE, OnClose); case WM_SHELLNOTIFY: return OnShellNotify(hwnd, wParam, lParam); } return DefWindowProc(hwnd, uMsg, wParam, lParam); } static BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) { ghwndConsole = CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, NULL, WS_CHILD|WS_VISIBLE|ES_READONLY|ES_MULTILINE| WS_VSCROLL|WS_HSCROLL|ES_NOHIDESEL, 0, 0, 0, 0, hwnd, 0, 0, NULL); if(!ghwndConsole) return FALSE; return TRUE; } static void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { switch (id) { case ID_RESTORE: OnShellNotify(hwnd, ID_TRAY, WM_LBUTTONDBLCLK); break; case ID_START_D2CS: fprintf(stderr,"Sending Start Signal to d2cs\n"); d2cs_run = TRUE; break; case ID_SHUTDOWN_D2CS: fprintf(stderr,"Sending Shutdown Signal to d2cs\n"); d2cs_run = FALSE; signal_quit_wrapper(); break; case ID_RESTART_D2CS: fprintf(stderr,"Sending Restart Signal To d2cs\n"); d2cs_run = TRUE; signal_quit_wrapper(); break; case ID_EDITCONFIG_D2CS: ShellExecute(NULL, "open", "notepad.exe", "conf\\d2cs.conf", NULL, SW_SHOW ); break; case ID_LOADCONFIG_D2CS: fprintf(stderr,"Sending Reload Config Signal To d2cs\n"); signal_reload_config_wrapper(); break; case ID_LADDER_LOAD: fprintf(stderr,"Sending Reload Ladder Signal To d2cs\n"); signal_load_ladder_wrapper(); break; case ID_RESTART_D2GS: fprintf(stderr,"Sending Restart d2gs Signal To d2cs\n"); signal_restart_d2gs_wrapper(); break; case ID_EXIT: OnClose(hwnd); break; case ID_CLEAR: SendMessage(ghwndConsole, WM_SETTEXT, 0, 0); break; case ID_ABOUT: DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_ABOUT_BOX), hwnd, (DLGPROC)DlgProcAbout); break; } } static int OnShellNotify(HWND hwnd, int uID, int uMessage) { if(uID == ID_TRAY) { if(uMessage == WM_LBUTTONDBLCLK) { if(!IsWindowVisible(hwnd)) ShowWindow(hwnd, SW_RESTORE); SetForegroundWindow(hwnd); } } return 0; } static void OnClose(HWND hwnd) { fprintf(stderr,"Sending Exit Signal To d2cs\n"); gui_run = FALSE; d2cs_run = FALSE; signal_exit_wrapper(); } static void OnSize(HWND hwnd, UINT state, int cx, int cy) { NOTIFYICONDATA dta; if( state == SIZE_MINIMIZED ) { dta.cbSize = sizeof(NOTIFYICONDATA); dta.hWnd = hwnd; dta.uID = ID_TRAY; dta.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; dta.uCallbackMessage = WM_SHELLNOTIFY; dta.hIcon = LoadIcon(GetWindowInstance(hwnd), MAKEINTRESOURCE(ID_ICON1)); strcpy(dta.szTip, "D2CS Version"); strcat(dta.szTip, " "); strcat(dta.szTip, D2CS_VERSION_STRING); Shell_NotifyIcon(NIM_ADD, &dta); ShowWindow(hwnd, SW_HIDE); return; } MoveWindow(ghwndConsole, 0, 0, cx, cy, TRUE); } BOOL CALLBACK DlgProcAbout(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CLOSE: EndDialog(hwnd, TRUE); return TRUE; case WM_INITDIALOG: return TRUE; case WM_COMMAND: switch ((int)wParam) { case IDOK: EndDialog(hwnd, TRUE); return TRUE; } } return FALSE; } extern int gui_lprintf(t_eventlog_level l, const char *format, ...) { va_list arglist; va_start(arglist, format); return gui_lvprintf(l, format, arglist); } extern int gui_lvprintf(t_eventlog_level l, const char *format, va_list arglist) { char buff[4096]; int result; COLORREF clr; result = vsprintf(buff, format, arglist); switch(l) { case eventlog_level_none: clr = RGB(0, 0, 0); break; case eventlog_level_trace: clr = RGB(255, 0, 255); break; case eventlog_level_debug: clr = RGB(0, 0, 255); break; case eventlog_level_info: clr = RGB(0, 0, 0); break; case eventlog_level_warn: clr = RGB(255, 128, 64); break; case eventlog_level_error: clr = RGB(255, 0, 0); break; case eventlog_level_fatal: clr = RGB(255, 0, 0); break; default: clr = RGB(0, 0, 0); } guiAddText(buff, clr); return result; } static void guiAddText(const char *str, COLORREF clr) { int start_lines, text_length, end_lines; CHARRANGE cr; CHARRANGE ds; CHARFORMAT fmt; text_length = SendMessage(ghwndConsole, WM_GETTEXTLENGTH, 0, 0); if (text_length > 30000) { ds.cpMin = 0; ds.cpMax = text_length - 30000; SendMessage(ghwndConsole, EM_EXSETSEL, 0, (LPARAM)&ds); SendMessage(ghwndConsole, EM_REPLACESEL, FALSE, 0); } cr.cpMin = text_length; cr.cpMax = text_length; SendMessage(ghwndConsole, EM_EXSETSEL, 0, (LPARAM)&cr); fmt.cbSize = sizeof(CHARFORMAT); fmt.dwMask = CFM_COLOR|CFM_FACE|CFM_SIZE|CFM_BOLD|CFM_ITALIC|CFM_STRIKEOUT|CFM_UNDERLINE; fmt.yHeight = 160; fmt.dwEffects = 0; fmt.crTextColor = clr; strcpy(fmt.szFaceName,"Courier New"); SendMessage(ghwndConsole, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt); SendMessage(ghwndConsole, EM_REPLACESEL, FALSE, (LPARAM)str); } #define EXIT_ERROR -1 #define EXIT_OK 0 #define EXIT_SERVICE 1 static void d2cs(void * dummy) { switch (server_main(__argc, __argv)) { case EXIT_SERVICE: gui_run = FALSE; /* close gui */ case EXIT_ERROR: d2cs_run = FALSE; /* don't restart */ case EXIT_OK: ; /* do nothing */ } fprintf(stderr,"Server Stopped\n"); d2cs_running = FALSE; } #endif pvpgn-1.8.5/src/win32/d2dbs_resource.h0000644000175000017500000000056511151345317016457 0ustar aaronaaron#define ID_TRAY 4 #define ID_RESTORE 5 #define ID_EXIT 6 #define ID_ABOUT_BOX 101 #define ID_ICON1 102 #define ID_MENU 103 #define ID_START_D2DBS 40001 #define ID_SHUTDOWN_D2DBS 40002 #define ID_RESTART_D2DBS 40003 #define ID_EDITCONFIG_D2DBS 40004 #define ID_LOADCONFIG_D2DBS 40005 #define ID_LADDER_SAVE 40006 #define ID_CLEAR 40007 #define ID_ABOUT 40008 pvpgn-1.8.5/src/win32/service.c0000644000175000017500000001372511151345317015207 0ustar aaronaaron /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef WIN32 #include #include #include #if !defined(WINADVAPI) #if !defined(_ADVAPI32_) #define WINADVAPI DECLSPEC_IMPORT #else #define WINADVAPI #endif #endif extern char serviceLongName[]; extern char serviceName[]; extern char serviceDescription[]; extern int g_ServiceStatus; #ifdef WIN32_GUI extern int server_main(int argc, char *argv[]); #else extern int main(int argc, char *argv[]); #endif SERVICE_STATUS serviceStatus; SERVICE_STATUS_HANDLE serviceStatusHandle = 0; typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID); void Win32_ServiceInstall() { SERVICE_DESCRIPTION sdBuf; CSD_T ChangeServiceDescription; HANDLE advapi32; SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE); if (serviceControlManager) { char path[_MAX_PATH + 10]; if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0) { SC_HANDLE service; strcat(path, " --service"); service = CreateService(serviceControlManager, serviceName, serviceLongName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path, 0, 0, 0, 0, 0); if (service) { sdBuf.lpDescription = serviceDescription; if (!(advapi32 = GetModuleHandle("ADVAPI32.DLL"))) { CloseServiceHandle(service); CloseServiceHandle(serviceControlManager); return; } ; if (!(ChangeServiceDescription = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A"))) { CloseServiceHandle(service); CloseServiceHandle(serviceControlManager); return; } ChangeServiceDescription( service, // handle to service SERVICE_CONFIG_DESCRIPTION, // change: description &sdBuf); CloseServiceHandle(service); } } CloseServiceHandle(serviceControlManager); } } void Win32_ServiceUninstall() { SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); if (serviceControlManager) { SC_HANDLE service = OpenService(serviceControlManager, serviceName, SERVICE_QUERY_STATUS | DELETE); if (service) { SERVICE_STATUS serviceStatus; if (QueryServiceStatus(service, &serviceStatus)) { if (serviceStatus.dwCurrentState == SERVICE_STOPPED) DeleteService(service); } //DeleteService(service); CloseServiceHandle(service); } CloseServiceHandle(serviceControlManager); } } void WINAPI ServiceControlHandler(DWORD controlCode) { switch (controlCode) { case SERVICE_CONTROL_INTERROGATE: break; case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(serviceStatusHandle, &serviceStatus); g_ServiceStatus = 0; return; case SERVICE_CONTROL_PAUSE: g_ServiceStatus = 2; serviceStatus.dwCurrentState = SERVICE_PAUSED; SetServiceStatus(serviceStatusHandle, &serviceStatus); break; case SERVICE_CONTROL_CONTINUE: serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(serviceStatusHandle, &serviceStatus); g_ServiceStatus = 1; break; default: if ( controlCode >= 128 && controlCode <= 255 ) // user defined control code break; else // unrecognized control code break; } SetServiceStatus(serviceStatusHandle, &serviceStatus); } void WINAPI ServiceMain(DWORD argc, char *argv[]) { // initialise service status serviceStatus.dwServiceType = SERVICE_WIN32; serviceStatus.dwCurrentState = SERVICE_START_PENDING; serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; serviceStatus.dwWin32ExitCode = NO_ERROR; serviceStatus.dwServiceSpecificExitCode = NO_ERROR; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler); if ( serviceStatusHandle ) { char path[_MAX_PATH + 1]; int i, last_slash = 0; GetModuleFileName(0, path, sizeof(path)/sizeof(path[0])); for (i = 0; i < strlen(path); i++) { if (path[i] == '\\') last_slash = i; } path[last_slash] = 0; // service is starting serviceStatus.dwCurrentState = SERVICE_START_PENDING; SetServiceStatus(serviceStatusHandle, &serviceStatus); // do initialisation here SetCurrentDirectory(path); // running serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus( serviceStatusHandle, &serviceStatus ); //////////////////////// // service main cycle // //////////////////////// g_ServiceStatus = 1; argc = 1; #ifdef WIN32_GUI server_main(argc, argv); #else main(argc, argv); #endif // service was stopped serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(serviceStatusHandle, &serviceStatus); // do cleanup here // service is now stopped serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); serviceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(serviceStatusHandle, &serviceStatus); } } void Win32_ServiceRun() { SERVICE_TABLE_ENTRY serviceTable[] = { { serviceName, ServiceMain }, { 0, 0 } }; if (!StartServiceCtrlDispatcher(serviceTable)) { } } #endif pvpgn-1.8.5/src/win32/d2cs_resource.h0000644000175000017500000000062011151345317016304 0ustar aaronaaron#define ID_TRAY 4 #define ID_RESTORE 5 #define ID_EXIT 6 #define ID_ABOUT_BOX 101 #define ID_ICON1 102 #define ID_MENU 103 #define ID_START_D2CS 40001 #define ID_SHUTDOWN_D2CS 40002 #define ID_RESTART_D2CS 40003 #define ID_EDITCONFIG_D2CS 40004 #define ID_LOADCONFIG_D2CS 40005 #define ID_LADDER_LOAD 40006 #define ID_RESTART_D2GS 40007 #define ID_CLEAR 40008 #define ID_ABOUT 40009 pvpgn-1.8.5/src/win32/winmain.h0000644000175000017500000000215511151345317015211 0ustar aaronaaron/* * Copyright (C) 2001 Erik Latoshek [forester] (laterk@inbox.lv) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __WINMAIN_H__ #define __WINMAIN_H__ #include #include "common/eventlog.h" extern int gui_printf(const char *format, ...); extern void guiOnUpdateUserList(void); extern int gui_lvprintf(t_eventlog_level l, const char *format, va_list arglist); extern int gui_lprintf(t_eventlog_level l, const char *format, ...); #endif pvpgn-1.8.5/src/win32/service.h0000644000175000017500000000151311151345317015204 0ustar aaronaaron /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef WIN32 void Win32_ServiceInstall(void); void Win32_ServiceUninstall(void); void Win32_ServiceRun(void); #endif pvpgn-1.8.5/src/win32/d2dbs_winmain.c0000644000175000017500000002513011151345317016260 0ustar aaronaaron/* * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef WIN32_GUI #include "common/setup_before.h" #include #include #include #include #include "d2dbs_resource.h" #include "common/eventlog.h" #include "d2dbs/version.h" #include "d2dbs/handle_signal.h" #include "service.h" #include "winmain.h" #include "common/setup_after.h" #define WM_SHELLNOTIFY (WM_USER+1) extern int server_main(int argc, char *argv[]); /* d2dbs main function in d2dbs/main.c */ static void d2dbs(void * dummy); /* thread function for d2dbs */ static void guiAddText(const char *str, COLORREF clr); static void KillTrayIcon(HWND hwnd); static int OnShellNotify(HWND hwnd, int uID, int uMessage); static void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify); static BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct); static void OnClose(HWND hwnd); static void OnSize(HWND hwnd, UINT state, int cx, int cy); LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL CALLBACK DlgProcAbout(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); HWND ghwndConsole; /* hwnd for eventlog output */ static int gui_run = TRUE; /* default state: run gui */ static int d2dbs_run = TRUE; /* default state: run d2dbs */ static int d2dbs_running = FALSE; /* currect state: not running */ int fprintf(FILE *stream, const char *format, ...) { va_list args; va_start(args, format); if(stream == stderr || stream == stdout) return gui_lvprintf(eventlog_level_error, format, args); else return vfprintf(stream, format, args); } static void KillTrayIcon(HWND hwnd) { NOTIFYICONDATA dta; dta.cbSize = sizeof(NOTIFYICONDATA); dta.hWnd = hwnd; dta.uID = ID_TRAY; dta.uFlags = 0; Shell_NotifyIcon(NIM_DELETE, &dta); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG msg; /* if running as a service skip starting the GUI and go straight to starting d2dbs */ if (__argc==2 && strcmp(__argv[1],"--service")==0) { Win32_ServiceRun(); return 1; } LoadLibrary("RichEd20.dll"); wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(LPVOID); wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ID_ICON1)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszMenuName = MAKEINTRESOURCE(ID_MENU); wc.lpszClassName = "BnetWndClass"; if(!RegisterClassEx( &wc )) RegisterClass((LPWNDCLASS)&wc.style); hwnd = CreateWindow(TEXT("BnetWndClass"),"Diablo II DataBase Server", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, NULL, LoadMenu(hInstance, MAKEINTRESOURCE(ID_MENU)), hInstance,NULL); if(hwnd) { ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); } while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage( &msg ); DispatchMessage( &msg ); if(!d2dbs_running && d2dbs_run && gui_run) { d2dbs_running = TRUE; _beginthread(d2dbs, 0, NULL); } if(!gui_run && !d2dbs_running) { KillTrayIcon(hwnd); exit(0); } } return ((int) msg.wParam); } LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { HANDLE_MSG(hwnd, WM_CREATE, OnCreate); HANDLE_MSG(hwnd, WM_SIZE, OnSize); HANDLE_MSG(hwnd, WM_COMMAND, OnCommand); HANDLE_MSG(hwnd, WM_CLOSE, OnClose); case WM_SHELLNOTIFY: return OnShellNotify(hwnd, wParam, lParam); } return DefWindowProc(hwnd, uMsg, wParam, lParam); } static BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) { ghwndConsole = CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, NULL, WS_CHILD|WS_VISIBLE|ES_READONLY|ES_MULTILINE| WS_VSCROLL|WS_HSCROLL|ES_NOHIDESEL, 0, 0, 0, 0, hwnd, 0, 0, NULL); if(!ghwndConsole) return FALSE; return TRUE; } static void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { switch (id) { case ID_RESTORE: OnShellNotify(hwnd, ID_TRAY, WM_LBUTTONDBLCLK); break; case ID_START_D2DBS: fprintf(stderr,"Sending Start Signal to d2dbs\n"); d2dbs_run = TRUE; break; case ID_SHUTDOWN_D2DBS: fprintf(stderr,"Sending Shutdown Signal to d2dbs\n"); d2dbs_run = FALSE; d2dbs_signal_quit_wrapper(); break; case ID_RESTART_D2DBS: fprintf(stderr,"Sending Restart Signal To d2dbs\n"); d2dbs_run = TRUE; d2dbs_signal_quit_wrapper(); break; case ID_EDITCONFIG_D2DBS: ShellExecute(NULL, "open", "notepad.exe", "conf\\d2dbs.conf", NULL, SW_SHOW ); break; case ID_LOADCONFIG_D2DBS: fprintf(stderr,"Sending Reload Config Signal To d2dbs\n"); d2dbs_signal_reload_config_wrapper(); break; case ID_LADDER_SAVE: fprintf(stderr,"Sending Save Ladder Signal To d2dbs\n"); d2dbs_signal_save_ladder_wrapper(); break; case ID_EXIT: OnClose(hwnd); break; case ID_CLEAR: SendMessage(ghwndConsole, WM_SETTEXT, 0, 0); break; case ID_ABOUT: DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_ABOUT_BOX), hwnd, (DLGPROC)DlgProcAbout); break; } } static int OnShellNotify(HWND hwnd, int uID, int uMessage) { if(uID == ID_TRAY) { if(uMessage == WM_LBUTTONDBLCLK) { if(!IsWindowVisible(hwnd)) ShowWindow(hwnd, SW_RESTORE); SetForegroundWindow(hwnd); } } return 0; } static void OnClose(HWND hwnd) { fprintf(stderr,"Sending Exit Signal To d2dbs\n"); gui_run = FALSE; d2dbs_run = FALSE; d2dbs_signal_exit_wrapper(); } static void OnSize(HWND hwnd, UINT state, int cx, int cy) { NOTIFYICONDATA dta; if( state == SIZE_MINIMIZED ) { dta.cbSize = sizeof(NOTIFYICONDATA); dta.hWnd = hwnd; dta.uID = ID_TRAY; dta.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; dta.uCallbackMessage = WM_SHELLNOTIFY; dta.hIcon = LoadIcon(GetWindowInstance(hwnd), MAKEINTRESOURCE(ID_ICON1)); strcpy(dta.szTip, "D2DBS Version"); strcat(dta.szTip, " "); strcat(dta.szTip, D2DBS_VERSION_NUMBER); Shell_NotifyIcon(NIM_ADD, &dta); ShowWindow(hwnd, SW_HIDE); return; } MoveWindow(ghwndConsole, 0, 0, cx, cy, TRUE); } BOOL CALLBACK DlgProcAbout(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CLOSE: EndDialog(hwnd, TRUE); return TRUE; case WM_INITDIALOG: return TRUE; case WM_COMMAND: switch ((int)wParam) { case IDOK: EndDialog(hwnd, TRUE); return TRUE; } } return FALSE; } extern int gui_lprintf(t_eventlog_level l, const char *format, ...) { va_list arglist; va_start(arglist, format); return gui_lvprintf(l, format, arglist); } extern int gui_lvprintf(t_eventlog_level l, const char *format, va_list arglist) { char buff[4096]; int result; COLORREF clr; result = vsprintf(buff, format, arglist); switch(l) { case eventlog_level_none: clr = RGB(0, 0, 0); break; case eventlog_level_trace: clr = RGB(255, 0, 255); break; case eventlog_level_debug: clr = RGB(0, 0, 255); break; case eventlog_level_info: clr = RGB(0, 0, 0); break; case eventlog_level_warn: clr = RGB(255, 128, 64); break; case eventlog_level_error: clr = RGB(255, 0, 0); break; case eventlog_level_fatal: clr = RGB(255, 0, 0); break; default: clr = RGB(0, 0, 0); } guiAddText(buff, clr); return result; } static void guiAddText(const char *str, COLORREF clr) { int start_lines, text_length, end_lines; CHARRANGE cr; CHARRANGE ds; CHARFORMAT fmt; text_length = SendMessage(ghwndConsole, WM_GETTEXTLENGTH, 0, 0); if (text_length > 30000) { ds.cpMin = 0; ds.cpMax = text_length - 30000; SendMessage(ghwndConsole, EM_EXSETSEL, 0, (LPARAM)&ds); SendMessage(ghwndConsole, EM_REPLACESEL, FALSE, 0); } cr.cpMin = text_length; cr.cpMax = text_length; SendMessage(ghwndConsole, EM_EXSETSEL, 0, (LPARAM)&cr); fmt.cbSize = sizeof(CHARFORMAT); fmt.dwMask = CFM_COLOR|CFM_FACE|CFM_SIZE|CFM_BOLD|CFM_ITALIC|CFM_STRIKEOUT|CFM_UNDERLINE; fmt.yHeight = 160; fmt.dwEffects = 0; fmt.crTextColor = clr; strcpy(fmt.szFaceName,"Courier New"); SendMessage(ghwndConsole, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt); SendMessage(ghwndConsole, EM_REPLACESEL, FALSE, (LPARAM)str); } #define EXIT_ERROR -1 #define EXIT_OK 0 #define EXIT_SERVICE 1 static void d2dbs(void * dummy) { switch (server_main(__argc, __argv)) { case EXIT_SERVICE: gui_run = FALSE; /* close gui */ case EXIT_ERROR: d2dbs_run = FALSE; /* don't restart */ case EXIT_OK: ; /* do nothing */ } fprintf(stderr,"Server Stopped\n"); d2dbs_running = FALSE; } #endif pvpgn-1.8.5/src/win32/winmain.c0000644000175000017500000005266511151345317015217 0ustar aaronaaron/* * Copyright (C) 2001 Erik Latoshek [forester] (laterk@inbox.lv) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef WIN32_GUI #pragma warning(disable : 4047) #include "common/setup_before.h" #include #include #include #include #include #include #include #include #include #include "bnetd/connection.h" #include "bnetd/account.h" #include "bnetd/account_wrap.h" #include "bnetd/ipban.h" #include "bnetd/message.h" #include "bnetd/server.h" #include "common/addr.h" #include "common/eventlog.h" #include "common/list.h" #include "common/version.h" #include "resource.h" #include "winmain.h" #include "common/setup_after.h" #define WM_SHELLNOTIFY (WM_USER+1) extern int server_main(int, char*[]); static void guiThread(void*); static void guiAddText(const char *, COLORREF); static void guiAddText_user(const char *, COLORREF); static void guiDEAD(char*); static void guiMoveWindow(HWND, RECT*); static void guiClearLogWindow(void); static void guiKillTrayIcon(void); long PASCAL guiWndProc(HWND, UINT, WPARAM, LPARAM); static void guiOnCommand(HWND, int, HWND, UINT); static void guiOnMenuSelect(HWND, HMENU, int, HMENU, UINT); static int guiOnShellNotify(int, int); static BOOL guiOnCreate(HWND, LPCREATESTRUCT); static void guiOnClose(HWND); static void guiOnSize(HWND, UINT, int, int); static void guiOnPaint(HWND); static void guiOnCaptureChanged(HWND); static BOOL guiOnSetCursor(HWND, HWND, UINT, UINT); static void guiOnMouseMove(HWND, int, int, UINT); static void guiOnLButtonDown(HWND, BOOL, int, int, UINT); static void guiOnLButtonUp(HWND, int, int, UINT); static void guiOnServerConfig (void); static void guiOnAbout (HWND); static void guiOnUpdates (void); static void guiOnAnnounce (HWND); static void guiOnUserStatusChange (HWND); BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); BOOL CALLBACK AnnDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); BOOL CALLBACK KickDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); #define MODE_HDIVIDE 1 #define MODE_VDIVIDE 1 struct gui_struc { HWND hwnd; HMENU hmenuTray; HWND hwndConsole; HWND hwndUsers; HWND hwndUserCount; HWND hwndUserEditButton; HWND hwndTree; int y_ratio; int x_ratio; HANDLE event_ready; BOOL main_finished; int mode; char szDefaultStatus[128]; RECT rectHDivider, rectVDivider, rectConsole, rectUsers, rectConsoleEdge, rectUsersEdge; WPARAM wParam; LPARAM lParam; }; static struct gui_struc gui; char selected_item[255]; int fprintf(FILE *stream, const char *format, ...) { va_list args; va_start(args, format); if(stream == stderr || stream == stdout) return gui_lvprintf(eventlog_level_error, format, args); else return vfprintf(stream, format, args); } int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE reserved, LPSTR lpCmdLine, int nCmdShow) { int result; gui.main_finished = FALSE; gui.event_ready = CreateEvent(NULL, FALSE, FALSE, NULL); _beginthread( guiThread, 0, (void*)hInstance); WaitForSingleObject(gui.event_ready, INFINITE); result = server_main(__argc ,__argv); gui.main_finished = TRUE; eventlog(eventlog_level_debug,__FUNCTION__,"server exited ( return : %i )", result); WaitForSingleObject(gui.event_ready, INFINITE); return 0; } static void guiThread(void *param) { WNDCLASSEX wc; MSG msg; LoadLibrary("RichEd20.dll"); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW|CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)guiWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = (HINSTANCE)param; wc.hIcon = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_ICON1)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = 0; wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); wc.lpszClassName = "BnetdWndClass"; wc.hIconSm = NULL; if(!RegisterClassEx( &wc )) guiDEAD("cant register WNDCLASS"); gui.hwnd = CreateWindowEx( 0, wc.lpszClassName, "The Player -vs- Player Gaming Network Server", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, (HINSTANCE)param, NULL); if(!gui.hwnd) guiDEAD("cant create window"); ShowWindow(gui.hwnd, SW_SHOW); SetEvent(gui.event_ready); while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } long PASCAL guiWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { gui.wParam = wParam; gui.lParam = lParam; switch(message) { HANDLE_MSG(hwnd, WM_CREATE, guiOnCreate); HANDLE_MSG(hwnd, WM_COMMAND, guiOnCommand); HANDLE_MSG(hwnd, WM_MENUSELECT, guiOnMenuSelect); HANDLE_MSG(hwnd, WM_SIZE, guiOnSize); HANDLE_MSG(hwnd, WM_CLOSE, guiOnClose); HANDLE_MSG(hwnd, WM_PAINT, guiOnPaint); HANDLE_MSG(hwnd, WM_SETCURSOR, guiOnSetCursor); HANDLE_MSG(hwnd, WM_LBUTTONDOWN, guiOnLButtonDown); HANDLE_MSG(hwnd, WM_LBUTTONUP, guiOnLButtonUp); HANDLE_MSG(hwnd, WM_MOUSEMOVE, guiOnMouseMove); case WM_CAPTURECHANGED: guiOnCaptureChanged((HWND)lParam); return 0; case WM_SHELLNOTIFY: return guiOnShellNotify(wParam, lParam); } return DefWindowProc(hwnd, message, wParam, lParam); } static BOOL guiOnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) { gui.hwndConsole = CreateWindowEx( 0, RICHEDIT_CLASS, NULL, WS_CHILD|WS_VISIBLE|ES_READONLY|ES_MULTILINE|WS_VSCROLL|WS_HSCROLL|ES_NOHIDESEL, 0, 0, 0, 0, hwnd, 0, 0, NULL); if(!gui.hwndConsole) return FALSE; gui.hwndUsers = CreateWindowEx( WS_EX_CLIENTEDGE, "LISTBOX", NULL, WS_CHILD|WS_VISIBLE|LBS_STANDARD|LBS_NOINTEGRALHEIGHT, 0, 0, 0, 0, hwnd, 0, 0, NULL); if(!gui.hwndUsers) return FALSE; //amadeo: temp. button for useredit until rightcklick is working.... gui.hwndUserEditButton = CreateWindow( "button", "Edit User Status", WS_CHILD | WS_VISIBLE | ES_LEFT, 0, 0, 0, 0, hwnd, (HMENU) 881, 0, NULL) ; if(!gui.hwndUserEditButton) return FALSE; gui.hwndUserCount = CreateWindowEx( WS_EX_CLIENTEDGE, "edit", " 0 user(s) online:", WS_CHILD|WS_VISIBLE|ES_CENTER|ES_READONLY, 0, 0, 0, 0, hwnd, 0, 0, NULL); if(!gui.hwndUserCount) return FALSE; SendMessage(gui.hwndUserCount, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); SendMessage(gui.hwndUsers, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); SendMessage(gui.hwndUserEditButton, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); BringWindowToTop(gui.hwndUsers); strcpy( gui.szDefaultStatus, "Void" ); gui.y_ratio = (100<<10)/100; gui.x_ratio = (0<<10)/100; return TRUE; } static void guiOnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { if( id == IDM_EXIT ) guiOnClose(hwnd); else if( id == IDM_SAVE ) server_save_wraper(); else if( id == IDM_RESTART ) server_restart_wraper(); else if( id == IDM_SHUTDOWN ) server_quit_wraper(); else if( id == IDM_CLEAR ) guiClearLogWindow(); else if( id == IDM_RESTORE ) guiOnShellNotify(IDI_TRAY, WM_LBUTTONDBLCLK); else if(id == IDM_USERLIST) guiOnUpdateUserList(); else if(id == IDM_SERVERCONFIG) guiOnServerConfig (); else if(id == IDM_ABOUT) guiOnAbout (hwnd); else if(id == ID_HELP_CHECKFORUPDATES) guiOnUpdates (); else if(id == IDM_ANN) guiOnAnnounce (hwnd); else if(id == ID_USERACTIONS_KICKUSER) guiOnUserStatusChange(hwnd); else if(id == 881) guiOnUserStatusChange(hwnd); } static void guiOnMenuSelect(HWND hwnd, HMENU hmenu, int item, HMENU hmenuPopup, UINT flags) { // char str[256]; //by greini /*if( item == 0 || flags == -1) SetWindowText( gui.hwndStatus, gui.szDefaultStatus ); else { LoadString( GetWindowInstance(hwnd), item, str, sizeof(str) ); if( str[0] ) SetWindowText( gui.hwndStatus, str ); }*/ } static int guiOnShellNotify(int uID, int uMessage) { if(uID == IDI_TRAY) { if(uMessage == WM_LBUTTONDBLCLK) { if( !IsWindowVisible(gui.hwnd) ) ShowWindow(gui.hwnd, SW_RESTORE); SetForegroundWindow(gui.hwnd); } else if(uMessage == WM_RBUTTONDOWN) { POINT cp; GetCursorPos(&cp); SetForegroundWindow(gui.hwnd); TrackPopupMenu(gui.hmenuTray, TPM_LEFTALIGN|TPM_LEFTBUTTON, cp.x, cp.y, 0, gui.hwnd, NULL); } } return 0; } static void guiOnPaint(HWND hwnd) { PAINTSTRUCT ps; HDC dc; dc = BeginPaint(hwnd, &ps); DrawEdge(dc, &gui.rectHDivider, BDR_SUNKEN, BF_MIDDLE); DrawEdge(dc, &gui.rectConsoleEdge, BDR_SUNKEN, BF_RECT); DrawEdge(dc, &gui.rectUsersEdge, BDR_SUNKEN, BF_RECT); EndPaint(hwnd, &ps); UpdateWindow(gui.hwndConsole); UpdateWindow(gui.hwndUsers); UpdateWindow(gui.hwndUserCount); UpdateWindow(gui.hwndUserEditButton); } static void guiOnClose(HWND hwnd) { guiKillTrayIcon(); if( !gui.main_finished ) { eventlog(eventlog_level_debug,__FUNCTION__,"GUI wants server dead..."); exit(0); } else { eventlog(eventlog_level_debug,__FUNCTION__,"GUI wants to exit..."); SetEvent(gui.event_ready); } } static void guiOnSize(HWND hwnd, UINT state, int cx, int cy) { int cy_console, cy_edge, cx_edge, cy_frame, cy_status; if( state == SIZE_MINIMIZED ) { NOTIFYICONDATA dta; dta.cbSize = sizeof(NOTIFYICONDATA); dta.hWnd = hwnd; dta.uID = IDI_TRAY; dta.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; dta.uCallbackMessage = WM_SHELLNOTIFY; dta.hIcon = LoadIcon(GetWindowInstance(hwnd), MAKEINTRESOURCE(IDI_ICON1)); strcpy(dta.szTip, "PvPGN"); strcat(dta.szTip, " "); strcat(dta.szTip, PVPGN_VERSION); Shell_NotifyIcon(NIM_ADD, &dta); ShowWindow(hwnd, SW_HIDE); return; } if (state == SIZE_RESTORED) { NOTIFYICONDATA dta; dta.hWnd = hwnd; dta.uID = IDI_TRAY; Shell_NotifyIcon(NIM_DELETE,&dta); } cy_status = 0; cy_edge = GetSystemMetrics(SM_CYEDGE); cx_edge = GetSystemMetrics(SM_CXEDGE); cy_frame = (cy_edge<<1) + GetSystemMetrics(SM_CYBORDER) + 1; cy_console = ((cy-cy_status-cy_frame-cy_edge*2)*gui.y_ratio)>>10; gui.rectConsoleEdge.left = 0; gui.rectConsoleEdge.right = cx -140; gui.rectConsoleEdge.top = 0; gui.rectConsoleEdge.bottom = cy - cy_status; gui.rectConsole.left = cx_edge; gui.rectConsole.right = cx - 140 -cx_edge; gui.rectConsole.top = cy_edge; gui.rectConsole.bottom = cy - cy_status; gui.rectUsersEdge.left = cx - 140; gui.rectUsersEdge.top = 18; gui.rectUsersEdge.right = cx; gui.rectUsersEdge.bottom = cy - cy_status - 10; gui.rectUsers.left = cx -138; gui.rectUsers.right = cx ; gui.rectUsers.top = 18 + cy_edge; gui.rectUsers.bottom = cy - cy_status -20 ; guiMoveWindow(gui.hwndConsole, &gui.rectConsole); guiMoveWindow(gui.hwndUsers, &gui.rectUsers); MoveWindow(gui.hwndUserCount, cx - 140, 0, 140, 18, TRUE); MoveWindow(gui.hwndUserEditButton, cx - 140, cy - cy_status -20, 140, 20, TRUE); } static BOOL guiOnSetCursor(HWND hwnd, HWND hwndCursor, UINT codeHitTest, UINT msg) { POINT p; if(hwnd == hwndCursor && codeHitTest == HTCLIENT) { GetCursorPos(&p); ScreenToClient(hwnd, &p); if(PtInRect(&gui.rectHDivider, p)) SetCursor(LoadCursor(0, IDC_SIZENS)); return TRUE; } return FORWARD_WM_SETCURSOR(hwnd, hwndCursor, codeHitTest, msg, DefWindowProc); } static void guiOnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags) { POINT p; p.x = x; p.y = y; if( PtInRect(&gui.rectHDivider, p) ) { SetCapture(hwnd); gui.mode |= MODE_HDIVIDE; } } static void guiOnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags) { ReleaseCapture(); gui.mode &= ~(MODE_HDIVIDE|MODE_VDIVIDE); } static void guiOnCaptureChanged(HWND hwndNewCapture) { gui.mode &= ~(MODE_HDIVIDE|MODE_VDIVIDE); } static void guiOnMouseMove(HWND hwnd, int x, int y, UINT keyFlags) { int offset, cy_console, cy_users; RECT r; if( gui.mode & MODE_HDIVIDE ) { offset = y - gui.rectHDivider.top; if( !offset ) return; cy_console = gui.rectConsole.bottom - gui.rectConsole.top; cy_users = gui.rectUsers.bottom - gui.rectUsers.top; if( cy_console + offset <= 0) offset = -cy_console; else if( cy_users - offset <= 0) offset = cy_users; cy_console += offset; cy_users -= offset; if( cy_console + cy_users == 0 ) return; gui.y_ratio = (cy_console<<10) / (cy_console + cy_users); GetClientRect(hwnd, &r); guiOnSize(hwnd, 0, r.right, r.bottom); InvalidateRect(hwnd, NULL, FALSE); } } extern int gui_printf(const char *format, ...) { va_list arglist; va_start(arglist, format); return gui_lvprintf(eventlog_level_error, format, arglist); } extern int gui_lprintf(t_eventlog_level l, const char *format, ...) { va_list arglist; va_start(arglist, format); return gui_lvprintf(l, format, arglist); } extern int gui_lvprintf(t_eventlog_level l, const char *format, va_list arglist) { char buff[4096]; int result; COLORREF clr; result = vsprintf(buff, format, arglist); switch(l) { case eventlog_level_none: clr = RGB(0, 0, 0); break; case eventlog_level_trace: clr = RGB(255, 0, 255); break; case eventlog_level_debug: clr = RGB(0, 0, 255); break; case eventlog_level_info: clr = RGB(0, 0, 0); break; case eventlog_level_warn: clr = RGB(255, 128, 64); break; case eventlog_level_error: clr = RGB(255, 0, 0); break; case eventlog_level_fatal: clr = RGB(255, 0, 0); break; default: clr = RGB(0, 0, 0); } guiAddText(buff, clr); return result; } static void guiOnUpdates () { ShellExecute(NULL, "open", "pvpgn.berlios.de", NULL, NULL, SW_SHOW ); } static void guiOnAnnounce (HWND hwnd) { DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ANN), hwnd, (DLGPROC)AnnDlgProc); } static void guiOnUserStatusChange (HWND hwnd) { int index; index = SendMessage(gui.hwndUsers, LB_GETCURSEL, 0, 0); SendMessage(gui.hwndUsers, LB_GETTEXT, index, (LPARAM)selected_item); DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_KICKUSER), hwnd, (DLGPROC)KickDlgProc); SendMessage(gui.hwndUsers, LB_SETCURSEL, -1, 0); } static void guiOnAbout (HWND hwnd) { DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ABOUT), hwnd, (DLGPROC)AboutDlgProc); } static void guiOnServerConfig() { ShellExecute(NULL, "open", "notepad.exe", "conf\\bnetd.conf", NULL, SW_SHOW ); } extern void guiOnUpdateUserList() { t_connection * c; t_elem const * curr; t_account * acc; char UserCount[80]; SendMessage(gui.hwndUsers, LB_RESETCONTENT, 0, 0); LIST_TRAVERSE_CONST(connlist(),curr) { if (!(c = elem_get_data(curr))) continue; if (!(acc = conn_get_account(c))) continue; SendMessage(gui.hwndUsers, LB_ADDSTRING, 0, (LPARAM)account_get_name(acc)); } sprintf(UserCount, "%d", connlist_login_get_length()); strcat (UserCount, " user(s) online:"); SendMessage(gui.hwndUserCount,WM_SETTEXT,0,(LPARAM)UserCount); } static void guiAddText(const char *str, COLORREF clr) { int start_lines, text_length, end_lines; CHARRANGE cr; CHARRANGE ds; CHARFORMAT fmt; text_length = SendMessage(gui.hwndConsole, WM_GETTEXTLENGTH, 0, 0); if ( text_length >30000 ) { ds.cpMin = 0; ds.cpMax = text_length - 30000; SendMessage(gui.hwndConsole, EM_EXSETSEL, 0, (LPARAM)&ds); SendMessage(gui.hwndConsole, EM_REPLACESEL, FALSE, 0); } cr.cpMin = text_length; cr.cpMax = text_length; SendMessage(gui.hwndConsole, EM_EXSETSEL, 0, (LPARAM)&cr); fmt.cbSize = sizeof(CHARFORMAT); fmt.dwMask = CFM_COLOR|CFM_FACE|CFM_SIZE|CFM_BOLD|CFM_ITALIC|CFM_STRIKEOUT|CFM_UNDERLINE; fmt.yHeight = 160; fmt.dwEffects = 0; fmt.crTextColor = clr; strcpy(fmt.szFaceName,"Courier New"); SendMessage(gui.hwndConsole, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt); SendMessage(gui.hwndConsole, EM_REPLACESEL, FALSE, (LPARAM)str); } static void guiDEAD(char *message) { char *nl; char errorStr[4096]; char *msgLastError; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msgLastError, 0, NULL); nl = strchr(msgLastError, '\r'); if(nl) *nl = 0; sprintf(errorStr, "%s\nGetLastError() = '%s'\n", message, msgLastError); LocalFree(msgLastError); MessageBox(0, errorStr, "guiDEAD", MB_ICONSTOP|MB_OK); exit(1); } static void guiMoveWindow(HWND hwnd, RECT* r) { MoveWindow(hwnd, r->left, r->top, r->right-r->left, r->bottom-r->top, TRUE); } static void guiClearLogWindow(void) { SendMessage(gui.hwndConsole, WM_SETTEXT, 0, 0); } static void guiKillTrayIcon(void) { NOTIFYICONDATA dta; dta.cbSize = sizeof(NOTIFYICONDATA); dta.hWnd = gui.hwnd; dta.uID = IDI_TRAY; dta.uFlags = 0; Shell_NotifyIcon(NIM_DELETE, &dta); } BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch(Message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: EndDialog(hwnd, IDOK); break; } break; default: return FALSE; } return TRUE; } BOOL CALLBACK AnnDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { t_message *message; switch(Message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: { int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_EDIT1)); if(len > 0) { char* buf; buf = (char*)GlobalAlloc(GPTR, len + 1); GetDlgItemText(hwnd, IDC_EDIT1, buf, len + 1); if ((message = message_create(message_type_error,NULL,NULL,buf))) { message_send_all(message); message_destroy(message); } GlobalFree((HANDLE)buf); SetDlgItemText(hwnd, IDC_EDIT1, ""); } else { MessageBox(hwnd, "You didn't enter anything!", "Warning", MB_OK); } break; } } break; case WM_CLOSE: EndDialog(hwnd, IDOK); break; default: return FALSE; } return TRUE; } BOOL CALLBACK KickDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch(Message) { case WM_INITDIALOG: if (selected_item[0]!= 0) { SetDlgItemText(hwnd, IDC_EDITKICK, selected_item); } return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_KICK_EXECUTE: { t_connection * conngui; t_account * accountgui; BOOL messageq; BOOL kickq; char temp[60]; char ipadr[110]; messageq = FALSE; kickq = FALSE; GetDlgItemText(hwnd, IDC_EDITKICK, selected_item, 32); conngui = connlist_find_connection_by_accountname(selected_item); accountgui = accountlist_find_account(selected_item); if (conngui == NULL) { strcat(selected_item," could not be found in Userlist!"); MessageBox(hwnd,selected_item,"ERROR", MB_OK); } else { HWND hButton = GetDlgItem(hwnd, IDC_CHECKBAN); HWND hButton1 = GetDlgItem(hwnd, IDC_CHECKKICK); HWND hButton2 = GetDlgItem(hwnd, IDC_CHECKADMIN); HWND hButton3 = GetDlgItem(hwnd, IDC_CHECKMOD); HWND hButton4 = GetDlgItem(hwnd, IDC_CHECKANN); if (SendMessage(hButton2 , BM_GETCHECK, 0, 0)==BST_CHECKED) { account_set_admin(accountgui); account_set_command_groups(accountgui, 255); messageq = TRUE; } if (SendMessage(hButton3 , BM_GETCHECK, 0, 0)==BST_CHECKED) { account_set_auth_operator(accountgui,NULL,1); messageq = TRUE; } if (SendMessage(hButton4 , BM_GETCHECK, 0, 0)==BST_CHECKED) { account_set_strattr(accountgui,"BNET\\auth\\announce","true"); messageq = TRUE; } if (SendMessage(hButton , BM_GETCHECK, 0, 0)==BST_CHECKED) { unsigned int i_GUI; strcpy (temp, addr_num_to_addr_str(conn_get_addr(conngui), 0)); for (i_GUI=0; temp[i_GUI]!=':'; i_GUI++) ipadr[i_GUI]=temp[i_GUI]; ipadr[i_GUI]= 0; strcpy(temp," a "); strcat(temp,ipadr); handle_ipban_command(NULL,temp); temp[0] = 0; strcpy(temp," has been added to IpBanList"); strcat(ipadr,temp); if (messageq == TRUE) { strcat(ipadr," and UserStatus changed"); MessageBox(hwnd,ipadr,"ipBan & StatusChange", MB_OK); messageq = FALSE; kickq = FALSE; } else MessageBox(hwnd,ipadr,"ipBan", MB_OK); } if (SendMessage(hButton1 , BM_GETCHECK, 0, 0)==BST_CHECKED) { conn_set_state(conngui,conn_state_destroy); kickq = TRUE; } if ((messageq == TRUE)&&(kickq == TRUE)) { strcat (selected_item,"has been kicked and Status has changed"); MessageBox(hwnd,selected_item,"UserKick & StatusChange", MB_OK); } if ((kickq == TRUE)&&(messageq == FALSE)) { strcat (selected_item," has been kicked from the server"); MessageBox(hwnd,selected_item,"UserKick", MB_OK); } if ((kickq == FALSE)&&(messageq == TRUE)) { strcat (selected_item,"'s Status has been changed"); MessageBox(hwnd,selected_item,"StatusChange", MB_OK); } selected_item[0] = 0; } break; } } break; case WM_CLOSE: EndDialog(hwnd, IDC_EDITKICK); break; default: return FALSE; } return TRUE; } #endif pvpgn-1.8.5/src/win32/configwin.h0000644000175000017500000003023111151345317015526 0ustar aaronaaron/* ../include/config.h.win32 Generated by hand from ../include/config.h.in. */ /* ../include/config.h.in. Generated automatically from configure.in by autoheader. */ #ifdef __BORLANDC__ # define __FUNCTION__ __FUNC__ #endif /* Define if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* #undef _ALL_SOURCE */ #endif /* Define if the closedir function returns void instead of int. */ /* #undef CLOSEDIR_VOID */ /* Define to empty if the keyword does not work. */ /* #undef const */ /* Define if you don't have vprintf but do have _doprnt. */ /* #undef HAVE_DOPRNT */ /* Define if you have the strftime function. */ #define HAVE_STRFTIME 1 /* Define if you have the vprintf function. */ #define HAVE_VPRINTF 1 /* Define if you have the _vsnprintf function. */ #define HAVE__VSNPRINTF 1 /* Define if you have the _snprintf function. */ #define HAVE__SNPRINTF 1 /* Define if on MINIX. */ /* #undef _MINIX */ /* Define to `long' if doesn't define. */ /* #undef off_t */ /* Define to `int' if doesn't define. */ /* #undef pid_t */ /* Define if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define if you need to in order for stat and other things to work. */ /* #undef _POSIX_SOURCE */ /* Define as the return type of signal handlers (int or void). */ #define RETSIGTYPE void /* Define if the `setpgrp' function takes no argument. */ /* #undef SETPGRP_VOID */ /* Define to `unsigned' if doesn't define. */ /* #undef size_t */ /* Define if the `S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if you can safely include both and . */ /* #undef TIME_WITH_SYS_TIME */ /* MinGW can safely include both headers, but conflicts with compat/gettimeofday.h */ /* Define if your declares struct tm. */ /* #undef TM_IN_SYS_TIME */ /* The number of bytes in a unsigned char. */ #define SIZEOF_UNSIGNED_CHAR 1 /* The number of bytes in a signed char. */ #define SIZEOF_SIGNED_CHAR 1 /* The number of bytes in a unsigned int. */ #define SIZEOF_UNSIGNED_INT 4 /* The number of bytes in a signed int. */ #define SIZEOF_SIGNED_INT 4 /* The number of bytes in a unsigned long. */ #define SIZEOF_UNSIGNED_LONG 4 /* The number of bytes in a signed long. */ #define SIZEOF_SIGNED_LONG 4 /* The number of bytes in a unsigned long long. */ /* Borland doesn't do ull, but VC++ and MinGW do */ #ifdef __BORLANDC__ # define SIZEOF_UNSIGNED_LONG_LONG 0 #else # define SIZEOF_UNSIGNED_LONG_LONG 8 #endif /* The number of bytes in a signed long long. */ /* Borland doesn't do ll, but VC++ and MinGW do */ #ifdef __BORLANDC__ # define SIZEOF_SIGNED_LONG_LONG 0 #else # define SIZEOF_SIGNED_LONG_LONG 8 #endif /* The number of bytes in a unsigned short. */ #define SIZEOF_UNSIGNED_SHORT 2 /* The number of bytes in a signed short. */ #define SIZEOF_SIGNED_SHORT 2 /* Define if you have the _mkdir function. */ #define HAVE__MKDIR 1 /* Define if you have the bcopy function. */ /* #undef HAVE_BCOPY */ /* Define if you have the chdir function. */ #ifdef __MINGW32__ # define HAVE_CHDIR 1 #endif /* Define if you have the difftime function. */ #define HAVE_DIFFTIME 1 /* Define if you have the fork function. */ /* #undef HAVE_FORK */ /* Define if you have the ftime function. */ #define HAVE_FTIME 1 /* Define if you have the getenv function. */ #define HAVE_GETENV 1 /* Define if you have the getgid function. */ /* #undef HAVE_GETGID */ /* Define if you have the getgrnam function. */ /* #undef HAVE_GETGRNAM */ /* Define if you have the gethostbyname function. */ #define HAVE_GETHOSTBYNAME 1 /* Define if you have the gethostname function. */ #define HAVE_GETHOSTNAME 1 /* Define if you have the getlogin function. */ /* #undef HAVE_GETLOGIN */ /* Define if you have the getopt function. */ #ifdef __MINGW32__ # define HAVE_GETOPT 1 #endif /* Define if you have the getpid function. */ #ifdef __MINGW32__ # define HAVE_GETPID 1 #endif /* Define if you have the getpwnam function. */ /* #undef HAVE_GETPWNAM */ /* Define if you have the getrlimit function. */ /* #undef HAVE_GETRLIMIT */ /* Define if you have the getservbyname function. */ #define HAVE_GETSERVBYNAME 1 /* Define if you have the gettimeofday function. */ /* #undef HAVE_GETTIMEOFDAY */ /* Define if you have the getuid function. */ /* #undef HAVE_GETUID */ /* Define if you have the index function. */ /* #undef HAVE_INDEX */ /* Define if you have the inet_aton function. */ /* #undef HAVE_INET_ATON */ /* Define if you have the inet_ntoa function. */ #define HAVE_INET_NTOA 1 /* Define if you have the header file. */ #ifdef __MINGW32__ # define HAVE_INTTYPES_H 1 #endif /* Define if you have the ioctl function. */ /* #undef HAVE_IOCTL */ /* Define if you have the kqueue function. */ /* #undef HAVE_KQUEUE */ /* Define if you have the memcpy function. */ #define HAVE_MEMCPY 1 /* Define if you have the memmove function. */ #define HAVE_MEMMOVE 1 /* Define if you have the memset function. */ #define HAVE_MEMSET 1 /* Define if you have the mkdir function. */ #define HAVE_MKDIR 1 /* Define if you have the mktime function. */ #define HAVE_MKTIME 1 /* Define if you have the pipe function. */ /* #undef HAVE_PIPE */ /* Define if you have the poll function. */ /* #undef HAVE_POLL */ /* Define if you have the pow function. */ #define HAVE_POW 1 /* Define if you have the recv function. */ #define HAVE_RECV 1 /* Define if you have the recvfrom function. */ #define HAVE_RECVFROM 1 /* Define if you have the rindex function. */ /* #undef HAVE_RINDEX */ /* Define if you have the select function. */ #define HAVE_SELECT 1 /* Define if you have the send function. */ #define HAVE_SEND 1 /* Define if you have the sendto function. */ #define HAVE_SENDTO 1 /* Define if you have the setgid function. */ /* #undef HAVE_SETGID */ /* Define if you have the setpgid function. */ /* #undef HAVE_SETPGID */ /* Define if you have the setpgrp function. */ /* #undef HAVE_SETPGRP */ /* Define if you have the setsid function. */ /* #undef HAVE_SETSID */ /* Define if you have the setuid function. */ /* #undef HAVE_SETUID */ /* Define if you have the sigaction function. */ /* #undef HAVE_SIGACTION */ /* Define if you have the sigaddset function. */ /* #undef HAVE_SIGADDSET */ /* Define if you have the sigprocmask function. */ /* #undef HAVE_SIGPROCMASK */ /* Define if you have the socket function. */ #define HAVE_SOCKET 1 /* Define if you have the strcasecmp function. */ #ifdef __MINGW32__ #define HAVE_STRCASECMP 1 #endif /* Define if you have the strchr function. */ #define HAVE_STRCHR 1 /* Define if you have the strsep function. */ /* #undef HAVE_STRSEP */ /* Define if you have the strdup function. */ #define HAVE_STRDUP 1 /* Define if you have the strerror function. */ #define HAVE_STRERROR 1 /* Define if you have the stricmp function. */ #define HAVE_STRICMP 1 /* Define if you have the strncasecmp function. */ #ifdef __MINGW32__ # define HAVE_STRNCASECMP 1 #endif /* Define if you have the strnicmp function. */ #define HAVE_STRNICMP 1 /* Define if you have the strrchr function. */ #define HAVE_STRRCHR 1 /* Define if you have the strtoul function. */ #define HAVE_STRTOUL 1 /* Define if you have the uname function. */ /* #undef HAVE_UNAME */ /* Define if you have the wait function. */ /* #undef HAVE_WAIT */ /* Define if you have the waitpid function. */ /* #undef HAVE_WAITPID */ /* Define if you have the header file. */ /* #undef HAVE_ARPA_INET_H */ /* Define if you have the header file. */ #if defined(__BORLANDC__) || defined(__MINGW32__) # define HAVE_DIR_H 1 #endif /* Define if you have the header file. */ #ifndef __BORLAMDC__ # define HAVE_DIRECT_H 1 #endif /* Define if you have the header file. */ /* #undef HAVE_DIRENT_H */ #ifdef __MINGW32__ # define HAVE_DIRENT_H 1 #endif /* Define if you have the epoll_create function. */ /* #undef HAVE_EPOLL_CREATE */ /* Define if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define if you have the header file. */ /* #undef HAVE_GRP_H */ /* Define if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define if you have the header file. */ #define HAVE_MALLOC_H 1 /* Define if you have the header file. */ #ifdef __MINGW32__ # define HAVE_MEMORY_H 1 #endif /* Define if you have a working mmap system call. */ /* #undef HAVE_MMAP */ /* Define if you have the header file. */ /* #undef HAVE_NDIR_H */ /* Define if you have the header file. */ /* #undef HAVE_NETDB_H */ /* Define if you have the header file. */ /* #undef HAVE_NETINET_IN_H */ /* Define if you have the header file. */ /* #undef HAVE_POLL_H */ /* Define if you have the header file. */ /* #undef HAVE_PWD_H */ /* Define if you have the setitimer function. */ /* #undef HAVE_SETITIMER */ /* Define if you have the snprintf function. */ #ifdef __MINGW32__ #define HAVE_SNPRINTF 1 #endif /* Define if you have the header file. */ #define HAVE_STDARG_H 1 /* Define if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define if you have the header file. */ #ifdef __MINGW32__ # define HAVE_STDINT_H 1 #endif /* Define if you have the header file. */ #ifdef __MINGW32__ #define HAVE_STDLIB_H 1 #endif /* Define if you have the header file. */ #define HAVE_STRING_H 1 /* Define if you have the header file. */ #ifdef __MINGW32__ # define HAVE_STRINGS_H 1 #endif /* Define if you have the header file. */ /* #undef HAVE_STROPTS_H */ /* Define if you have the strrchr function */ #ifdef __MINGW32__ #define HAVE_STRRCHR 1 #endif /* Define if you have the header file. */ /* #undef HAVE_SYS_DIR_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_EPOLL_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_EVENT_H */ /* Define if you have the header file. */ #ifdef __MINGW32__ # define HAVE_SYS_FILE_H 1 #endif /* Define if you have the header file. */ /* #undef HAVE_SYS_IOCTL_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_MMAN_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_NDIR_H */ /* Define if you have the header file. */ #ifdef __MINGW32__ # define HAVE_SYS_PARAM_H 1 #endif /* Define if you have the header file. */ /* #undef HAVE_SYS_POLL_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_RESOURCE_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_SELECT_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_SOCKET_H */ /* Define if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define if you have the header file. */ /* #undef HAVE_SYS_STROPTS_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_TIME_H */ /* MinGW has this header, but confilcts with compat/gettimeofday.h */ /* Define if you have the header file. */ #define HAVE_SYS_TIMEB_H 1 /* Define if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define if you have the header file. */ /* #undef HAVE_SYS_UTSNAME_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_WAIT_H */ /* Define if you have the header file. */ /* #undef HAVE_TERMIOS_H */ /* Define if mkdir takes only one argument. */ #define MKDIR_TAKES_ONE_ARG 1 /* Define if you have the header file. */ #define HAVE_VARARGS_H 1 /* Define if you have the header file. */ #ifdef __MINGW32__ # define HAVE_UNISTD_H 1 #endif /* Define if you support inline */ #define inline __inline /* Define if you support assertions */ #define HAVE_ASSERT_H 1 /* Define if you have the header file. */ #define HAVE_TIME_H 1 pvpgn-1.8.5/src/win32/console_resource.rc0000644000175000017500000000030111151345317017264 0ustar aaronaaron#include "console_resource.h" #define APSTUDIO_READONLY_SYMBOLS #ifndef __BORLANDC__ #include "afxres.h" #endif /* Icon */ ID_ICON1 ICON DISCARDABLE "win32/logo01.ico" pvpgn-1.8.5/src/win32/logo01.ico0000644000175000017500000003464611151345317015205 0ustar aaronaaronhF ¨®00¨V00¨þ( @7pM¥&fËC ?pSzª‘´ÕxÄŒ­Ñ„µÚH¸ì3¬Ö…Øÿ >~J¨6yÍJt"KQœ¬a¦ËZÃÚ -M%I’!2< Eƒ'9'< s£PLI0\!•~ÿÿÿÛÜÝÞßàáâãäåæç ÌÍÎÏÐÑÒÓÔÕÖר JÚ¾¿ÀÁÂÃÄÅÆÇÈÉÊ J ±²³´µ¶·¸¹º»¼½ ” ¢£¤¥¦§¨©ª«¬­® ¯°•–—˜™š›œžŸ ¡ v †‡ˆ‰Š‹ŒŽ‘’ “”wxyz{|}~€‚ƒ … ijklmnopqrstu v Z[\]^_`abcdef ghKLMNOPQRSTUVW -Y<=>?@ABCDEFGH J./0123456789: ; !"#$%&'()*+ ,-  ( @€7pM¥&fËC ?pSzª‘´ÕxÄŒ­Ñ„µÚH¸ì3¬Ö…Øÿ >~J¨6yÍJt"KQœ¬a¦ËZÃÚ -M%I’!2< Eƒ'9'< s£PLI0\!•~ÿÿÿÖÖ×רØÙÙÚÚÛÛÜÜÝÝÞÞßßààááââ ÖÖ×רØÙÙÚÚÛÛÜÜÝÝÞÞßßààááââ ÈÈÉÉÊÊËËÌÌÍÍÎÎÏÏÐÐÑÑÒÒÓÓÔÔ IIÕÕÈÈÉÉÊÊËËÌÌÍÍÎÎÏÏÐÐÑÑÒÒÓÓÔÔ IIÕÕ»»¼¼½½¾¾¿¿ÀÀÁÁÂÂÃÃÄÄÅÅÆÆÇÇ II »»¼¼½½¾¾¿¿ÀÀÁÁÂÂÃÃÄÄÅÅÆÆÇÇ II ®®¯¯°°±±²²³³´´µµ¶¶··¸¸¹¹ºº ‘‘ ®®¯¯°°±±²²³³´´µµ¶¶··¸¸¹¹ºº ‘‘ ŸŸ  ¡¡¢¢££¤¤¥¥¦¦§§¨¨©©ªª«« ¬¬­­ŸŸ  ¡¡¢¢££¤¤¥¥¦¦§§¨¨©©ªª«« ¬¬­­’’““””••––——˜˜™™šš››œœžž tt ’’““””••––——˜˜™™šš››œœžž tt ƒƒ„„……††‡‡ˆˆ‰‰ŠŠ‹‹ŒŒŽŽ ‘‘ƒƒ„„……††‡‡ˆˆ‰‰ŠŠ‹‹ŒŒŽŽ ‘‘uuvvwwxxyyzz{{||}}~~€€ ‚‚ uuvvwwxxyyzz{{||}}~~€€ ‚‚ gghhiijjkkllmmnnooppqqrrss tt gghhiijjkkllmmnnooppqqrrss tt XXYYZZ[[\\]]^^__``aabbccdd eeffXXYYZZ[[\\]]^^__``aabbccdd eeffJJKKLLMMNNOOPPQQRRSSTTUUVV --WWJJKKLLMMNNOOPPQQRRSSTTUUVV --WW<<==>>??@@AABBCCDDEEFFGGHH II<<==>>??@@AABBCCDDEEFFGGHH II..//00112233445566778899:: ;;..//00112233445566778899:: ;; !!""##$$%%&&''(())**++ ,,-- !!""##$$%%&&''(())**++ ,,--    ??003333000000003300000000000000(0`€         #%& ("+$-$.$0#1 2346 :!;"<%>'@)A+F,H.L0N0O6LLBd7o8s=wEvNyVx\jaRfIjCm@o>oG.- *.! *üÎ_U 8®8786­+{G,)‚Š+zL0/‚|A)!F. )eýa]2223883¬,"$ ( }P0…ƒ, <$!H>!QÍÎ_W2336­73ÜYYYYYY+H *G' ‚‡(){(.†Gto´ï^178o·­­­ÓYYYYYY)G $,|‘/'+||„‹/Lkg´éP%9Ýø¯n¸«æécYY!@"+ .‹|*+>‹‡’{t½¼Û·!;éÿÿziÿý­ç®bYY+/   ƒ|**/Ž‹‚eÊÖÝtoïüÿp¾ÿüð­æódYY -G |{..‡™—Õñ°t[";èôÿ(0ýñøí®ææ®YYYH.  G= G=•˜—kï]]\1§îÿ:Æîô÷ðçæ­­YYY-  -I'Š0‹˜—„ÁÓa\ $:äÿþ)ñëõöõÛ­­æ- 0< !ŠG?••gÆË_U!F¥êÿŽ,,æãøüúÔèñëY  z ‹?*Š•–OdÂÅ^ '<âÿÿŽƒ€âãñüüûøÿóYYYU ! Š@y–kgeeÕ_ 0Šþÿí¦¢£âäîñõÑÿðñYYYY  zx'‹˜„ÎÎ˾òa!C£÷ßÛÜ¢¦ââëëëûôïðYYY! " *yz˜tÄÍÌÂÕc+€õàãù÷²¢ââäíìÑíéïYYYY% $ HI!‹—E\e½Ê½¿d/†Ýàéø÷ð²âââäéÒÞèëYYY%"$ HIz[ºÂfeÄUD¨¨ªÛÑóîãââààëרëæY#$"% J„‹ƒihLNÖa ;ñ¨´¶Äùóæâ輦ªªíëæ$ ! ).„‹•-ptNQºd)ƒß¤ogiÄõëèí»Ž‹§ëíç%" ! %„‰(tNQUMÖc…ªtttfÔïñÙ¼µŽ¤ëçëYYYYYY$"!H(PUÙª±ÀÇÀirð𿼼¾ÂîèìYYYYYY&$"# /OïµÞ±ÈËÓÑÕ·í¹¼¼¾×Ú®¬YY'!"   P´ÑÚØÐûûÐÑÒéµµµ»ñ¸¬©YY""// ll´´¿ÌÌÍÑÐúíµ±±¸ñ·mµYY GŽlkkqvIIzxkÑùí³±±±×ظ¹YYY&•”$$Hw‚plllw/““žÕømòí²±ª°Ûïh×YYYz!–%EA('“rpkkp/„$%GJImÚ§¨©ÞîÛØ° E„„/“C yqpik "-j»ÃÐÑôÚ¨¨ªîïï×Ù-'““‘‰‰œ™xi¿0f½Àrt½ÐúòÝ©ªèìëêñðYYYYYY „‘’“’’›™™œŠ³ÃÆÀÀjK*KM¾ÑôÛªàèèíéñóYYYYYY%ƒˆ‰““™˜wkrÀÊÓ˽I*rsuÖòêªíäÞÚ×ÖóYY€„B†‰““™@oŽžÇÊËËiwkiÌüÔõòìªúíçÙÖÙïYYY@ˆ‰“’‹ŸšŸ´²³ÊÓ˽Lr¾ûþüøõìªÿóèÛÕ×ñYYY$$†E‡ˆ‘‰™½i³ÀÀÓÒÓÃpKkÒÑýûõì©ÿüíÝÕÔöYYYBC†?‡ˆ’‘²mk³ÇÇËÑÑÒÔ½ofÍÐýûÑí«ÿëÞ°ÛÔöYYYYY?††}ˆ‰”¡ƒØ>i³ÀÇÊÐÐÐʾigÌÏýúøííó䯯°ÍúYYYYY,D~~-Š•È²Òp³²ÀÈÒÐÐÐÌÀheËÏýûøòíì寯ÜÍõ/}@€†~” žÓÐÕl³²ÇËÐÐúÐÔ´rrËÏüÑרÛìæ¯¯ÙÌóA}B‚€™²²Çûjk³ÀÉÒÓÊÁÀoLPrÅÍû¿kk×í鯸¿ÅõYYYYYY@D@~D‰ž²²Çû>k³ÀÁ¼iËÎnu*(¼ÆÆÆÄssÕØê¯¹¾ÂöYYYYYYCEƒ}CžÙ²ÇúHlkr*t¶µÂPO&ÇÆÈÉÊÔËm,Úí¸¹¾ÂôYYYCB†„B‹Ÿ±²ÉÒIpu+ ÂIÊËÆÈÈÇÉÌÒÙì𸹹ÂóYYYB?……~‘¤²²ÙÀIvH *+qkKÕÏÉÆÆÆÆÈÄËòíô¹¹¿ÄöYYY@~€†‡²¡Ù´Owxi³¾Œ˜ÑÐÊÆÁÁÆÃÅÆÕêëë°¸ÚÅôYYY|~…Š žžnr,uvypÀûúÌÇÂÃÃÆÃÅØÚèêëݯÙÙóYYYYYY|~~„Љž¡–MpnmÆÏÏÎËÆÁÂÂÃÃÉÆØÛÞíî®°ÙØõYYYYYY?B~…‹‰›ŸŸ~–‚*K“likÉÊÃÃÃÃÅÊËÕ××ÛÞçâ«°ÙÚö$~~Љœ™™€–“|–J’»ÃÄÃÄÄÌÏÐÐÑÑÕÛÞáâ«ÙÜÛöÿÿ€€€€ƒƒƒƒƒÁÀÀàÀÀÁÇ€€€€ƒƒƒƒƒ€€€€€€€€€€€€€€€À€€€€(0`€"">*6^*P );laÈ'QŽ4W)QnƒGO`"=m :d2Y.L$8%3)@2Q 1('#1$/=¾Ùè§ÆÒvaE-0! 3C)Š^E¶•-šj‘S¨f$£L%¸&F#B„2a(H"E*&M‹S£+D'K1J[:D,T"LB:h(>!35d0U",$1&8(5Vex¼éû…~`\L;% 6\g] q. ¦{©b ‰'(­~%J- 7A !D„&8N&2!6Q6!PœH–*J&6$7$Cl52"=e>r&3&*2A•·É˜½ÄuaD88%& 8d r0n6Kª¦TŠ7X¾Æ999999999999999999"+F$sV¥!Q¡X¹!DvAYpn‹°b‰¯\²æO™½'$ )"/ HcSÆï¹þþÞþû!VzN‚ŸÎþýµùö¼·Mëæ=ÕÇFˆe999999*G)R- $%5"4  &N’B~,:-A/U%[¯!U¨![¸H†Teƒ©Î|»æT·å3Yg#%' %cˆpÙøªïþîûþ aƒq µÒöù³íþwáóº­<êÝ‚ðì<“w999999!-O!4_ ( G€$Cw"-0S3RP¡ \ÀX¼+Z°€°Ö}ËøO¦Ë7Vc=?> -HdMÇý‹Üúüþý/?;T½ï÷}ÝúšÓäcáì6ÄÀ.ãÜBíç6µ„999999999"6e1V&    7[@q!20ZD’@vZÀ[¿!XÀHm•qÉõLQE\O?BA8#&&# >C$ŒÌkÔúþþü%Ue %y¯ÍjÙý‹Üý—ÙèxÙèKËÉ1ÖÒ%̲Ê­999999999+Q    1L%C`%-"=R§5Q$V© ZÁWÃ#M—sšÇ‡»Å›€WEB:*-*(7Qz=ÃýøüþÌèú&?!(yßùRÑüãý•ÕìŽÝè`ÊÑ1ÊÇÌÅ$ØÜ+L ) 8P$El".1P°4Y#Q£Y¾XÁ*;P[f|™»{¨ÂdZI(,- )< Fp*¦ö÷þýÐùþb±U“Sоö/ÈýØü³æþ¹àì±ÕçžÒòºòù‡çú999999999$4;  --R¯;w!*LY¶UÅKn–iz”akƒapƒ|¶Ôj]F %7Vg¤ÖéÿÆîúcÃõ*ÝkÌwǸû5ÌÿlÖþÞøàü˜Ë߯öýyÎò×ü999999999999'-     'Dr1Ly$#9!V®[Æ-U–š°Õ¹ØŒ©É•´†Åê{^"2 Bjv¸˜ÞôB³î\µÜZžç$má‚ã¶ø'Áû[ÑþY×ûZÃø«ÙåŠÎçqÑøw×û9999999992! 1  )>)Fq'4""F|Wº [¾?Qh‚¢Å•µØŽ²Ø~™À€»Ûšˆq ,ETˆØþ3›ð:»ö£åú™ØîJ…Ýpݲû³ù<ÈüfËù]Âø˜ÐàcÄæUÄînÕþ999999999999 : '7 "8T&Af+ 6"R¥XÃ6f?AKQb€hŽÄ„©Õj‹°rš»ŠŒ} 4S aŸW¬æ0¥ïTÃõÜòžàöuÎóN‡Ö¬ö«ùºü>À÷W¼ðŒÆàC»ãPÆõUÍý999999999<,6* #8T#@_#*$JW¶#Y·&%)==C_‚´{œÃNjŠVj†¥µ-/)%>h4‘׿. ä]±ßÌâ†ØëlØø8¾ø¨ý­ú)´í+­ð[Ãôt²ÌiÊÖPÍûCÌþ99947*: & ,@a* P—"V±H–#!',\u¦[w–9J]6FTz½àw]#/ Lw|Íý%Ý=†·W“²|³Ä¡Óä‚áïFÌø#¸ûMÅùe‹¤0„Ø6šâ'šÔcÏòTÓÿHÌû$ 9 +5" &<"3N'Q”#U§VÀ*M" 'Ia…ATm1@R'4Db™¹ƒ} (@ V“?¯ë$z¶:g…L{‘W‰œ³Ã‹ßê[ÒóOÅøfÈ÷e”¥$fª `§ ŒÔZÐödÚýOÊì :0(1 (9J•M®">!$7Kg2@S(2?&.90GVwÁß[fp`$šÖ)n¡9Uj=[h4[iEw†€¾ÌpÕôÔôdµÚf¤X«%a°"xÃPÓþJÃÎ[ÒÓ999999999999999999$ 712 "  "9_%@ $##09O&/< )6"-%i«Ì‘™–i²4›ã>‘Ëf–ÆxªÓp¨¾[ˆŸ7dyyÖïuÏô` ¿c¦bަk•©u§¸lÛúRÍÇ_ËÉ999999999999999999;8 /4 ")N&&'%%+6 &1$/"+=NpÈíL¬MªïIÎ|¥Ï…¯Ò»Ú•ÀÝ{³ÍP°iÊõ`—¶c¦d¦n—­pÁäe¿Ý9»»$¨«999999"; 63 % +, ) *# $k'!W½U¾ 79#;i0Dv!H8_ŠDhDhAh-Qu)\'R¾L¾j©‰ÆêjËìA‹Ä<Æ?—ÕL¢×]¹ÜtÆè\‰špºË999999999'Dy/VÊ L*b7o%8 #NS¾ 7O|;[„Kj‘Jo•Eaƒ'T@˜7 3 ?;\(D`$Bh=vb²á*ŠÐ-Õ,“ÙGªàkÆè`·àk²Ó[¤Ä 3e"O´&Xº"J•E™2SRÀ /j!+Gp2X…@_†X{£Gi"2.#.QNrŸdˆ¶~žÇ ¾à–»áŽËó^©Ý+Ž×)Ý›ènÊým×þrÖùn¶Øi¯Ð+L '#AP¼S½P·M¯V´K«%b½aÇ"\²-O{Ut›j½!4I(7KeˆgÅq”¿FZ|;Opi„ ¤Æß©ÐðÌòRªÝ#’à—âR¾ú`ÇûUÏöXÍì}Ïù{Îò999999999999999999  ( D™M¶N¸P¾Q¹P¸%`ÍcÍ!bÑ#bÄR¥_Â{È€¢Íp“Êl–ÆOn›-A`*>6Kb5?Wx“¬˜Èì‰Ðö]¹ì"™ä+§îNÇòO¼ôeÇéWÉè}Ëé…×ú999999999999999999 "AŠ@#G’K¨F®O¾R»^ÌYÅY´1OƒLnš5Q}nšÑªÛ³ÞŠ®ÖnŒ²&@a*;)DZyB\v6Orw´Û†Îô[ÀñžèeÅöBÄùI·ócÀárÆâ{Â݇Øý999999CŒB™5tCžG¯O¿R»!`Î9s1^‘!]°+c³2d¶wžÒ‚¬Ü‰®ÙŠ®Ö]{ /JkJke{ž‹²Î³Øô„·ÙÊòÈîaÆ÷è§êýfÅúL¼ðf¿ÚyÄÚhÄÛqÚû999999999 !=Œ8yA“F¦J­O½Rº"S©&fÃ"eÐ-h¾CtºI|ÌT¾‚¬ÝŒ±Û†­ÙlŒ°-?\=Xk·¬ÏéÊåö»ß÷Ñô‘Çñ_Ëú ˜Ý×ñþˆ×úUÂí]¹Ô¿ÒtÀÛÙý999999999$$$  7 6E 6dE¡F¦O¸K°(cÆ(]¼*XÓ~ˆ«Ts¯bˆÂr˜ÑošÔˆ¯Ü¶âŒ²Ý} ÌEa‡-BcJh”’µß™ÀâÀàóªÔóÆî`Ëö•ÜÏóù­ãùdÊîM³Ð|¾Ò„¾Ó“Þö999999999""""?m0qG ƒKªN¯T»1qÒD–mÞ=rQx®bŠÅl”ÎuׄªÚš·ãž¾â™¸ã„¬Üo’º_}ŸVq’®ÕžºÜÂßó©Ïï›ÇðiËöhÉï†àù;ÌõC§ÑC©ÌN®Ë•¸Ä¥Õí999999999999999 -I 0h:…DŽ?Š'LP°'eÅW¼|£ÚR‚ÊŽ·ç6UˆX½`‹Èg”Ð|£Ú²ß¡Àâ¤Ã䜾ä³Üs˜ÀWwšKgƒ‰§Ð›¸ÛÉßö«ÊìœÌìƒÊúeÏù`Õû>ÒùE¨ÆJ§Ã[±Ç›¶½×ï.Z=;rBŠG?€"U½2nÇ1eÊ±à›½ì|«äCb•Z‚ÀbŽËx ×ˆ¬Ýœºá¥Äå§Æç›¼ã…¯ÜZ„±@\zC_zŠ¨Ñ»Þ¾Ùô–¹àv´ân°Ûa¼é]ÈöBÎüD©ÁU§¾e±Â²·†Ùõ9n9~8oC‘;ˆB”,[ÈI|ÍJÐz©å®ÐîJs©GiŸ`‡Ål”Φב³Þ‰°Ü‚©ÖvÊn•ÉGc†+@[(5K>Z|‚£Ì”´Ø¬Éëj“ÀKn–DlŽpºßbÅñTÉùF©½Z¦»o®½{°ºŽÚþ999999999999999999;q6g:x9‰5gL¬4fËWŒÕUŒ×w¢Ù¯Ïé>kGiŸ`‡Äs•Éu—Ãe‚§a£Ž©È›¶Ô?a“4Jf+=%=gˆ°yŸÎ¢Îu£Îx¢Ç2Uw6XsÉái¿ç]ÆñI¤¹`¨·oªµx­¶“Øÿ9999999999999999996n4bD•8„4jQ´4eÌc–ÖRÔt›Þ§Åí$:dDb•Gi›=V~ ,>ANdC•µZ‘¹œ¢+6J);R!Y2Io(<]#1)D+E4TIo¤.Eh*W²·Þ—¼Ü‚¥Î|¡ÎzžÌy Í|žÏ€£Ï}¡È‰®ÕÆëdÍöÒö_¨½`¡³e¬¼}­¹’Õý9999999997u?„CŒG K¢ SµG€×*[³;qÆ_™ÛK{º*9P/Fl.Fm;`¯Ht´W‚¿p‘¹/Y¡ZƘ»ç¥Ãà†§ÔyËw›Éw›ÉyË{ŸÈ£Ëy¢Ïz¯ÕZÊòQÏ÷\ÔöWªÈW¡¶b³Éw¯ÈŒÕý999999999@€>†A‰Hœ"Oª!S³2kÏ*cÁ*c½6d«;[{1H5Np2Im)Dx3S‰8^«+]¶p™Ý²ÎæªÈ厳Õt™ÑxÉ{žÊ{žÊ{œÍ€žÈx£Êp­×d¸ÞPÈöWËóZÐ÷N­ÎM§Âd±Çb°Ó‡×ü999999999999999999@€<ƒ?‡D˜"OªM­,eÉ'lÏ1f±!TÂ$[´#%1/@[4Xˆ7b© #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strchr.h" #include #include "compat/strerror.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #include "common/bn_type.h" #include "common/queue.h" #include "connection.h" #include "common/packet.h" #include "common/file_protocol.h" #include "common/eventlog.h" #include "prefs.h" #include "common/bnettime.h" #include "common/util.h" #include "common/xalloc.h" #include "file.h" #include "common/setup_after.h" static char const * file_get_info(char const * rawname, unsigned int * len, bn_long * modtime); static char * file_find_default(const char *rawname) { /* Add new default files here */ const char * defaultfiles[]={"termsofservice-",".txt", "newaccount-",".txt", "chathelp-war3-",".txt", "matchmaking-war3-",".dat", "tos_",".txt", "tos-unicode_", ".txt", NULL,NULL}; const char ** pattern, **extension; char *filename = NULL; for (pattern = defaultfiles, extension = defaultfiles + 1; *pattern; pattern+=2, extension+=2) if (!strncmp(rawname, *pattern,strlen(*pattern))) { /* Check if there is a default file available for this kind of file */ filename = (char*)xmalloc(strlen(prefs_get_filedir()) + 1 + strlen(*pattern) + 7 + strlen(*extension) + 1); strcpy(filename, prefs_get_filedir()); strcat(filename, "/"); strcat(filename, *pattern); strcat(filename, "default"); strcat(filename, *extension); break; } return filename; } static char const * file_get_info(char const * rawname, unsigned int * len, bn_long * modtime) { char *filename; struct stat sfile; t_bnettime bt; if (!rawname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL rawname"); return NULL; } if (!len) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL len"); return NULL; } if (!modtime) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL modtime"); return NULL; } if (strchr(rawname,'/') || strchr(rawname,'\\')) { eventlog(eventlog_level_warn,__FUNCTION__,"got rawname containing '/' or '\\' \"%s\"",rawname); return NULL; } filename = buildpath(prefs_get_filedir(), rawname); if (stat(filename,&sfile)<0) { /* if it doesn't exist, try to replace with default file */ xfree((void*)filename); filename = file_find_default(rawname); if (!filename) return NULL; /* no default version */ if (stat(filename,&sfile)<0) { /* try again */ /* FIXME: check for lower-case version of filename */ xfree(filename); return NULL; } } *len = (unsigned int)sfile.st_size; bt = time_to_bnettime(sfile.st_mtime,0); bnettime_to_bn_long(bt,modtime); return filename; } extern int file_to_mod_time(char const * rawname, bn_long * modtime) { char const * filename; unsigned int len; if (!rawname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL rawname"); return -1; } if (!modtime) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL modtime"); return -1; } if (!(filename = file_get_info(rawname, &len, modtime))) return -1; xfree((void *)filename); /* avoid warning */ return 0; } /* Send a file. If the file doesn't exist we still need to respond * to the file request. This will set filelen to 0 and send the server * reply message and the client will be happy and not hang. */ extern int file_send(t_connection * c, char const * rawname, unsigned int adid, unsigned int etag, unsigned int startoffset, int need_header) { char const * filename; t_packet * rpacket; FILE * fp; unsigned int filelen; int nbytes; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!rawname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL rawname"); return -1; } if (!(rpacket = packet_create(packet_class_file))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create file packet"); return -1; } packet_set_size(rpacket,sizeof(t_server_file_reply)); packet_set_type(rpacket,SERVER_FILE_REPLY); if ((filename = file_get_info(rawname,&filelen,&rpacket->u.server_file_reply.timestamp))) { if (!(fp = fopen(filename,"rb"))) { /* FIXME: check for lower-case version of filename */ eventlog(eventlog_level_error,__FUNCTION__,"stat() succeeded yet could not open file \"%s\" for reading (fclose: %s)",filename,pstrerror(errno)); filelen = 0; } xfree((void *)filename); /* avoid warning */ } else { fp = NULL; filelen = 0; bn_long_set_a_b(&rpacket->u.server_file_reply.timestamp,0,0); } if (fp) { if (startoffset%u)",conn_get_socket(c),startoffset,filelen); /* Keep the real filesize. Battle.net does it the same way ... */ fclose(fp); fp = NULL; } } if (need_header) { /* send the header from the server with the rawname and length. */ bn_int_set(&rpacket->u.server_file_reply.filelen,filelen); bn_int_set(&rpacket->u.server_file_reply.adid,adid); bn_int_set(&rpacket->u.server_file_reply.extensiontag,etag); /* rpacket->u.server_file_reply.timestamp is set above */ packet_append_string(rpacket,rawname); conn_push_outqueue(c,rpacket); } packet_del_ref(rpacket); /* Now send the data. Since it may be longer than a packet; we use * the raw packet class. */ if (!fp) { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] sending no data for file \"%s\"",conn_get_socket(c),rawname); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"[%d] sending file \"%s\" of length %d",conn_get_socket(c),rawname,filelen); for (;;) { if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create raw packet"); if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (fclose: %s)",rawname,pstrerror(errno)); return -1; } if ((nbytes = fread(packet_get_raw_data_build(rpacket,0),1,MAX_PACKET_SIZE,fp))<(int)MAX_PACKET_SIZE) { if (nbytes>0) /* send out last portion */ { packet_set_size(rpacket,nbytes); conn_push_outqueue(c,rpacket); } packet_del_ref(rpacket); if (ferror(fp)) eventlog(eventlog_level_error,__FUNCTION__,"read failed before EOF on file \"%s\" (fread: %s)",rawname,pstrerror(errno)); break; } packet_set_size(rpacket,nbytes); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (fclose: %s)",rawname,pstrerror(errno)); return 0; } pvpgn-1.8.5/src/bnetd/handle_telnet.c0000644000175000017500000002542311151345317016505 0ustar aaronaaron/* * Copyright (C) 2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strdup.h" #include #include "common/packet.h" #include "common/tag.h" #include "message.h" #include "common/eventlog.h" #include "command.h" #include "account.h" #include "account_wrap.h" #include "connection.h" #include "channel.h" #include "common/queue.h" #include "common/bnethash.h" #include "common/bnethashconv.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/list.h" #include "common/xalloc.h" #include "handle_telnet.h" #include "common/setup_after.h" extern int handle_telnet_packet(t_connection * c, t_packet const * const packet) { t_packet * rpacket; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c)); return -1; } if (packet_get_class(packet)!=packet_class_raw) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet)); return -1; } { char const * const linestr=packet_get_str_const(packet,0,MAX_MESSAGE_LEN); if (packet_get_size(packet)<2) /* empty line */ return 0; if (!linestr) { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] line too long",conn_get_socket(c)); return 0; } switch (conn_get_state(c)) { case conn_state_connected: conn_add_flags(c,MF_PLUG); conn_set_clienttag(c,CLIENTTAG_BNCHATBOT_UINT); { char const * temp=linestr; if (temp[0]=='\004') /* FIXME: no echo, ignore for now (we always do no echo) */ temp = &temp[1]; if (temp[0]=='\0') /* empty line */ { conn_set_state(c,conn_state_bot_username); /* don't look for ^D or reset tag and flags */ break; } conn_set_state(c,conn_state_bot_password); if (conn_set_loggeduser(c,temp)<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),temp); { char const * const msg="\r\nPassword: "; if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } #if 0 /* don't echo */ packet_append_ntstring(rpacket,conn_get_loggeduser(c)); #endif packet_append_ntstring(rpacket,msg); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } break; case conn_state_bot_username: conn_set_state(c,conn_state_bot_password); if (conn_set_loggeduser(c,linestr)<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),linestr); { char const * const temp="\r\nPassword: "; if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } #if 0 /* don't echo */ packet_append_ntstring(rpacket,linestr); #endif packet_append_ntstring(rpacket,temp); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } break; case conn_state_bot_password: { char const * const tempa="\r\nLogin failed.\r\n\r\nUsername: "; char const * const tempb="\r\nAccount has no bot access.\r\n\r\nUsername: "; char const * const loggeduser=conn_get_loggeduser(c); t_account * account; char const * oldstrhash1; t_hash trypasshash1; t_hash oldpasshash1; char * testpass; if (!loggeduser) /* error earlier in login */ { /* no log message... */ conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (connlist_find_connection_by_accountname(loggeduser)) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (already logged in)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (!(account = accountlist_find_account(loggeduser))) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (bad account)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if ((oldstrhash1 = account_get_pass(account))) { if (hash_set_str(&oldpasshash1,oldstrhash1)<0) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (corrupted passhash1?)",conn_get_socket(c),account_get_name(account)); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } testpass = xstrdup(linestr); { unsigned int i; for (i=0; i #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include "compat/strcasecmp.h" #include #include "compat/strerror.h" #ifdef HAVE_UNISTD_H # include #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/difftime.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_ASSERT_H # include #endif #include "common/eventlog.h" #include "prefs.h" #include "connection.h" #include "account.h" #include "account_wrap.h" #include "ladder.h" #include "ladder_calc.h" #include "common/bnettime.h" #include "common/util.h" #include "common/elist.h" #include "common/tag.h" #include "common/addr.h" #include "common/xalloc.h" #include "realm.h" #include "watch.h" #include "game_conv.h" #include "game.h" #include "server.h" #include "compat/uint.h" #include "compat/rename.h" #include "common/setup_after.h" DECLARE_ELIST_INIT(gamelist_head); static int glist_length=0; static int totalcount=0; static void game_choose_host(t_game * game); static void game_destroy(t_game * game); static int game_report(t_game * game); static void game_choose_host(t_game * game) { unsigned int i; if (game->count<1) { eventlog(eventlog_level_error,__FUNCTION__,"game has had no connections?!"); return; } if (!game->connections) { eventlog(eventlog_level_error,__FUNCTION__,"game has NULL connections array"); return; } for (i=0; icount; i++) if (game->connections[i]) { game->owner = game->connections[i]; game->addr = conn_get_game_addr(game->connections[i]); game->port = conn_get_game_port(game->connections[i]); return; } eventlog(eventlog_level_warn,__FUNCTION__,"no valid connections found"); } extern char const * game_type_get_str(t_game_type type) { switch (type) { case game_type_none: return "NONE"; case game_type_melee: return "melee"; case game_type_topvbot: return "top vs bottom"; case game_type_ffa: return "free for all"; case game_type_oneonone: return "one on one"; case game_type_ctf: return "capture the flag"; case game_type_greed: return "greed"; case game_type_slaughter: return "slaughter"; case game_type_sdeath: return "sudden death"; case game_type_ladder: return "ladder"; case game_type_ironman: return "ironman"; case game_type_mapset: return "mapset"; case game_type_teammelee: return "team melee"; case game_type_teamffa: return "team free for all"; case game_type_teamctf: return "team capture the flag"; case game_type_pgl: return "PGL"; case game_type_diablo: return "Diablo"; case game_type_diablo2open: return "Diablo II (open)"; case game_type_diablo2closed: return "Diablo II (closed)"; case game_type_all: default: return "UNKNOWN"; } } extern char const * game_status_get_str(t_game_status status) { switch (status) { case game_status_started: return "started"; case game_status_full: return "full"; case game_status_open: return "open"; case game_status_done: return "done"; case game_status_loaded: return "loaded"; default: return "UNKNOWN"; } } extern char const * game_result_get_str(t_game_result result) { switch (result) { case game_result_none: return "NONE"; case game_result_win: return "WIN"; case game_result_loss: return "LOSS"; case game_result_draw: return "DRAW"; case game_result_disconnect: return "DISCONNECT"; case game_result_observer: return "OBSERVER"; default: return "UNKNOWN"; } } extern char const * game_option_get_str(t_game_option option) { switch (option) { case game_option_melee_normal: return "normal"; case game_option_ffa_normal: return "normal"; case game_option_oneonone_normal: return "normal"; case game_option_ctf_normal: return "normal"; case game_option_greed_10000: return "10000 minerals"; case game_option_greed_7500: return "7500 minerals"; case game_option_greed_5000: return "5000 minerals"; case game_option_greed_2500: return "2500 minerals"; case game_option_slaughter_60: return "60 minutes"; case game_option_slaughter_45: return "45 minutes"; case game_option_slaughter_30: return "30 minutes"; case game_option_slaughter_15: return "15 minutes"; case game_option_sdeath_normal: return "normal"; case game_option_ladder_countasloss: return "count as loss"; case game_option_ladder_nopenalty: return "no penalty"; case game_option_mapset_normal: return "normal"; case game_option_teammelee_4: return "4 teams"; case game_option_teammelee_3: return "3 teams"; case game_option_teammelee_2: return "2 teams"; case game_option_teamffa_4: return "4 teams"; case game_option_teamffa_3: return "3 teams"; case game_option_teamffa_2: return "2 teams"; case game_option_teamctf_4: return "4 teams"; case game_option_teamctf_3: return "3 teams"; case game_option_teamctf_2: return "2 teams"; case game_option_topvbot_7: return "7 vs all"; case game_option_topvbot_6: return "6 vs all"; case game_option_topvbot_5: return "5 vs all"; case game_option_topvbot_4: return "4 vs all"; case game_option_topvbot_3: return "3 vs all"; case game_option_topvbot_2: return "2 vs all"; case game_option_topvbot_1: return "1 vs all"; case game_option_none: return "none"; default: return "UNKNOWN"; } } extern char const * game_maptype_get_str(t_game_maptype maptype) { switch (maptype) { case game_maptype_selfmade: return "Self-Made"; case game_maptype_blizzard: return "Blizzard"; case game_maptype_ladder: return "Ladder"; case game_maptype_pgl: return "PGL"; case game_maptype_kbk: return "KBK"; case game_maptype_compusa: return "CompUSA"; default: return "Unknown"; } } extern char const * game_tileset_get_str(t_game_tileset tileset) { switch (tileset) { case game_tileset_badlands: return "Badlands"; case game_tileset_space: return "Space"; case game_tileset_installation: return "Installation"; case game_tileset_ashworld: return "Ash World"; case game_tileset_jungle: return "Jungle"; case game_tileset_desert: return "Desert"; case game_tileset_ice: return "Ice"; case game_tileset_twilight: return "Twilight"; default: return "Unknown"; } } extern char const * game_speed_get_str(t_game_speed speed) { switch (speed) { case game_speed_slowest: return "slowest"; case game_speed_slower: return "slower"; case game_speed_slow: return "slow"; case game_speed_normal: return "normal"; case game_speed_fast: return "fast"; case game_speed_faster: return "faster"; case game_speed_fastest: return "fastest"; default: return "unknown"; } } extern char const * game_difficulty_get_str(t_game_difficulty difficulty) { switch (difficulty) { case game_difficulty_normal: return "normal"; case game_difficulty_nightmare: return "nightmare"; case game_difficulty_hell: return "hell"; case game_difficulty_hardcore_normal: return "hardcore normal"; case game_difficulty_hardcore_nightmare: return "hardcore nightmare"; case game_difficulty_hardcore_hell: return "hardcore hell"; default: return "unknown"; } } extern t_game * game_create(char const * name, char const * pass, char const * info, t_game_type type, int startver, t_clienttag clienttag, unsigned long gameversion) { t_game * game; if (!name) { eventlog(eventlog_level_info,__FUNCTION__,"got NULL game name"); return NULL; } if (!pass) { eventlog(eventlog_level_info,__FUNCTION__,"got NULL game pass"); return NULL; } if (!info) { eventlog(eventlog_level_info,__FUNCTION__,"got NULL game info"); return NULL; } if (gamelist_find_game(name, clienttag, game_type_all)) { eventlog(eventlog_level_info,__FUNCTION__,"game \"%s\" not created because it already exists",name); return NULL; /* already have a game by that name */ } game = xmalloc(sizeof(t_game)); game->name = xstrdup(name); game->pass = xstrdup(pass); game->info = xstrdup(info); if (!(game->clienttag = clienttag)) { eventlog(eventlog_level_error,__FUNCTION__,"got UNKNOWN clienttag"); xfree((void *)game->info); /* avoid warning */ xfree((void *)game->pass); /* avoid warning */ xfree((void *)game->name); /* avoid warning */ xfree(game); return NULL; } game->type = type; game->addr = 0; /* will be set by first player */ game->port = 0; /* will be set by first player */ game->version = gameversion; game->startver = startver; /* start packet version */ game->status = game_status_open; game->realm = 0; game->realmname = NULL; game->id = ++totalcount; game->mapname = NULL; game->ref = 0; game->count = 0; game->owner = NULL; game->connections = NULL; game->players = NULL; game->results = NULL; game->reported_results = NULL; game->report_heads = NULL; game->report_bodies = NULL; game->create_time = now; game->start_time = (time_t)0; game->lastaccess_time = now; game->option = game_option_none; game->maptype = game_maptype_none; game->tileset = game_tileset_none; game->speed = game_speed_none; game->mapsize_x = 0; game->mapsize_y = 0; game->maxplayers = 0; game->bad = 0; game->description = NULL; game->flag = strcmp(pass,"") ? game_flag_private : game_flag_none; game->difficulty = game_difficulty_none; game_parse_info(game,info); elist_add(&gamelist_head,&game->glist_link); glist_length++; eventlog(eventlog_level_info,__FUNCTION__,"game \"%s\" (pass \"%s\") type %hu(%s) startver %d created",name,pass,(unsigned short)type,game_type_get_str(game->type),startver); return game; } static void game_destroy(t_game * game) { unsigned int i; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return; } elist_del(&game->glist_link); glist_length--; if (game->realmname) { realm_add_game_number(realmlist_find_realm(game->realmname),-1); } eventlog(eventlog_level_debug,__FUNCTION__,"game \"%s\" (count=%u ref=%u) removed from list...",game_get_name(game),game->count,game->ref); for (i=0; icount; i++) { if (game->report_bodies && game->report_bodies[i]) xfree((void *)game->report_bodies[i]); /* avoid warning */ if (game->report_heads && game->report_heads[i]) xfree((void *)game->report_heads[i]); /* avoid warning */ if (game->reported_results && game->reported_results[i]) xfree((void *)game->reported_results[i]); } if (game->realmname) xfree((void *)game->realmname); /* avoid warining */ if (game->report_bodies) xfree((void *)game->report_bodies); /* avoid warning */ if (game->report_heads) xfree((void *)game->report_heads); /* avoid warning */ if (game->results) xfree((void *)game->results); /* avoid warning */ if (game->reported_results) xfree((void *)game->reported_results); if (game->connections) xfree((void *)game->connections); /* avoid warning */ if (game->players) xfree((void *)game->players); /* avoid warning */ if (game->mapname) xfree((void *)game->mapname); /* avoid warning */ if (game->description) xfree((void *)game->description); /* avoid warning */ xfree((void *)game->info); /* avoid warning */ xfree((void *)game->pass); /* avoid warning */ if (game->name) xfree((void *)game->name); /* avoid warning */ xfree((void *)game); /* avoid warning */ eventlog(eventlog_level_info,__FUNCTION__,"game deleted"); return; } static int game_evaluate_results(t_game * game) { unsigned int i,j; unsigned int wins, losses, draws, disconnects, reports; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!game->results) { eventlog(eventlog_level_error,__FUNCTION__,"results array is NULL"); return -1; } if (!game->reported_results) { eventlog(eventlog_level_error,__FUNCTION__,"reported_results array is NULL"); return -1; } for (i=0;icount;i++) { wins = losses = draws = disconnects = reports = 0; for (j=0;jcount;j++) { if (game->reported_results[j]) { switch (game->reported_results[j][i]) { case game_result_win: wins++; reports++; break; case game_result_loss: losses++; reports++; break; case game_result_draw: draws++; reports++; break; case game_result_disconnect: disconnects++; reports++; break; default: break; } } } eventlog(eventlog_level_debug,__FUNCTION__,"wins: %u losses: %u draws: %u disconnects: %u",wins,losses,draws,disconnects); //now decide what result we give if (!(reports)) // no results at all - game canceled before starting { game->results[i] = game_result_none; eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"none\" to player %d",i); } else if ((disconnects>=draws) && (disconnects>=losses) && (disconnects>=wins)) { game->results[i] = game_result_disconnect; //consider disconnects the worst case... eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"disconnect\" to player %d",i); } else if ((losses>=wins) && (losses>=draws)) { game->results[i]=game_result_loss; //losses are also bad... eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"loss\" to player %d",i); } else if ((draws>=wins)) { game->results[i]=game_result_draw; eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"draw\" to player %d",i); } else if (wins) { game->results[i]=game_result_win; eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"win\" to player %d",i); } } return 0; } static int game_match_type(t_game_type type,const char *gametypes) { char *p, *q; int res; if (!gametypes || !gametypes[0]) return 0; gametypes = p = xstrdup(gametypes); res = 0; do { q = strchr(p,','); if (q) *q = '\0'; if (!strcasecmp(p,"topvbot")) { if (type == game_type_topvbot) { res = 1; break; } } else if (!strcasecmp(p,"melee")) { if (type == game_type_melee) { res = 1; break; } } else if (!strcasecmp(p,"ffa")) { if (type == game_type_ffa) { res = 1; break; } } else if (!strcasecmp(p,"oneonone")) { if (type == game_type_oneonone) { res = 1; break; } } if (q) p = q + 1; } while(q); free((void*)gametypes); return res; } static int game_report(t_game * game) { FILE * fp; char * realname; char * tempname; unsigned int i; unsigned int realcount; t_ladder_info * ladder_info=NULL; int discisloss; char clienttag_str[5]; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!game->clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got UNKNOWN clienttag"); return -1; } if (!game->players) { eventlog(eventlog_level_error,__FUNCTION__,"player array is NULL"); return -1; } if (!game->reported_results) { eventlog(eventlog_level_error,__FUNCTION__,"reported_results array is NULL"); return -1; } if (!game->results) { eventlog(eventlog_level_error,__FUNCTION__,"results array is NULL"); return -1; } if (prefs_get_discisloss()==1 || game->option==game_option_ladder_countasloss) discisloss = 1; else discisloss = 0; if (game->clienttag==CLIENTTAG_WARCRAFT3_UINT || game->clienttag==CLIENTTAG_WAR3XP_UINT) // war3 game reporting is done elsewhere, so we can skip this function return 0; if (game->clienttag==CLIENTTAG_DIABLOSHR_UINT || game->clienttag==CLIENTTAG_DIABLORTL_UINT || game->clienttag==CLIENTTAG_DIABLO2ST_UINT || game->clienttag==CLIENTTAG_DIABLO2DV_UINT || game->clienttag==CLIENTTAG_DIABLO2XP_UINT) { if (prefs_get_report_diablo_games() == 1) /* diablo games have transient players and no reported winners/losers */ realcount = 0; else { eventlog(eventlog_level_info,__FUNCTION__,"diablo gamereport disabled: ignoring game"); return 0; } } else { game_evaluate_results(game); // evaluate results from the reported results /* "compact" the game; move all the real players to the top... */ realcount = 0; for (i=0; icount; i++) { if (!game->players[i]) { eventlog(eventlog_level_error,__FUNCTION__,"player slot %u has NULL account",i); continue; } if (game->results[i]!=game_result_none) { game->players[realcount] = game->players[i]; game->results[realcount] = game->results[i]; game->report_heads[realcount] = game->report_heads[i]; game->report_bodies[realcount] = game->report_bodies[i]; realcount++; } } /* then nuke duplicate players after the real players */ for (i=realcount; icount; i++) { game->players[i] = NULL; game->results[i] = game_result_none; game->report_heads[i] = NULL; game->report_bodies[i] = NULL; } if (realcount<1) { eventlog(eventlog_level_info,__FUNCTION__,"ignoring game"); return -1; } } eventlog(eventlog_level_debug,__FUNCTION__,"realcount=%d count=%u",realcount,game->count); if (realcount>=1 && !game->bad) { if (game_is_ladder(game) ) { t_ladder_id id; if (game_get_type(game)==game_type_ironman) id = ladder_id_ironman; else id = ladder_id_normal; for (i=0; iresults[i]); ladder_init_account(game->players[i],game->clienttag,id); switch (game->results[i]) { case game_result_win: account_inc_ladder_wins(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_win)); break; case game_result_loss: account_inc_ladder_losses(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_loss)); break; case game_result_draw: account_inc_ladder_draws(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_draw)); break; case game_result_disconnect: if (discisloss) { account_inc_ladder_losses(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_loss)); } else { /* FIXME: do the first disconnect only stuff like below */ account_inc_ladder_disconnects(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_disconnect)); } break; default: eventlog(eventlog_level_error,__FUNCTION__,"bad ladder game realplayer results[%u] = %u",i,game->results[i]); account_inc_ladder_disconnects(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_disconnect)); } account_set_ladder_last_time(game->players[i],game->clienttag,id,bnettime()); } ladder_info = xmalloc(sizeof(t_ladder_info)*realcount); if (ladder_update(game->clienttag,id, realcount,game->players,game->results,ladder_info, discisloss?ladder_option_disconnectisloss:ladder_option_none)<0) { eventlog(eventlog_level_info,__FUNCTION__,"unable to update ladder stats"); xfree(ladder_info); ladder_info = NULL; } } else { int disc_set=0; for (i=0; iresults[i]) { case game_result_win: account_inc_normal_wins(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_win)); break; case game_result_loss: account_inc_normal_losses(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_loss)); break; case game_result_draw: account_inc_normal_draws(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_draw)); break; case game_result_disconnect: if (discisloss) { account_inc_normal_losses(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_loss)); } else { /* FIXME: Is the missing player always the first one in this array? It seems like it should be the person that created the game */ if (!disc_set) { account_inc_normal_disconnects(game->players[i],game->clienttag); disc_set = 1; } account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_disconnect)); } break; default: eventlog(eventlog_level_error,__FUNCTION__,"bad normal game realplayer results[%u] = %u",i,game->results[i]); /* FIXME: Jung-woo fixed this here but we should find out what value results[i] has... and why "discisloss" isn't set above in game_result_disconnect */ #if 0 /* commented out for loose disconnect policy */ /* account_inc_normal_disconnects(game->players[i],game->clienttag); */ #endif account_inc_normal_disconnects(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_disconnect)); } account_set_normal_last_time(game->players[i],game->clienttag,bnettime()); } } } if (game_get_type(game)!=game_type_ladder && prefs_get_report_all_games()!=1) { eventlog(eventlog_level_debug,__FUNCTION__,"not reporting normal games"); return 0; } { struct tm * tmval; char dstr[64]; if (!(tmval = localtime(&now))) dstr[0] = '\0'; else sprintf(dstr,"%04d%02d%02d%02d%02d%02d", 1900+tmval->tm_year, tmval->tm_mon+1, tmval->tm_mday, tmval->tm_hour, tmval->tm_min, tmval->tm_sec); tempname = xmalloc(strlen(prefs_get_reportdir())+1+1+5+1+2+1+strlen(dstr)+1+6+1); sprintf(tempname,"%s/_bnetd-gr_%s_%06u",prefs_get_reportdir(),dstr,game->id); realname = xmalloc(strlen(prefs_get_reportdir())+1+2+1+strlen(dstr)+1+6+1); sprintf(realname,"%s/gr_%s_%06u",prefs_get_reportdir(),dstr,game->id); } if (!(fp = fopen(tempname,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open report file \"%s\" for writing (fopen: %s)",tempname,pstrerror(errno)); if (ladder_info) xfree(ladder_info); xfree(realname); xfree(tempname); return -1; } if (game->bad) fprintf(fp,"[ game results ignored due to inconsistencies ]\n\n"); fprintf(fp,"name=\"%s\" id="GAMEID_FORMAT"\n", game_get_name(game), game->id); fprintf(fp,"clienttag=%4s type=\"%s\" option=\"%s\"\n", tag_uint_to_str(clienttag_str,game->clienttag), game_type_get_str(game->type), game_option_get_str(game->option)); { struct tm * gametime; char timetemp[GAME_TIME_MAXLEN]; if (!(gametime = localtime(&game->create_time))) strcpy(timetemp,"?"); else strftime(timetemp,sizeof(timetemp),GAME_TIME_FORMAT,gametime); fprintf(fp,"created=\"%s\" ",timetemp); if (!(gametime = localtime(&game->start_time))) strcpy(timetemp,"?"); else strftime(timetemp,sizeof(timetemp),GAME_TIME_FORMAT,gametime); fprintf(fp,"started=\"%s\" ",timetemp); if (!(gametime = localtime(&now))) strcpy(timetemp,"?"); else strftime(timetemp,sizeof(timetemp),GAME_TIME_FORMAT,gametime); fprintf(fp,"ended=\"%s\"\n",timetemp); } { char const * mapname; if (!(mapname = game_get_mapname(game))) mapname = "?"; fprintf(fp,"mapfile=\"%s\" mapauth=\"%s\" mapsize=%ux%u tileset=\"%s\"\n", mapname, game_maptype_get_str(game_get_maptype(game)), game_get_mapsize_x(game),game_get_mapsize_y(game), game_tileset_get_str(game_get_tileset(game))); } fprintf(fp,"joins=%u maxplayers=%u\n", game_get_count(game), game_get_maxplayers(game)); if (!prefs_get_hide_addr()) fprintf(fp,"host=%s\n",addr_num_to_addr_str(game_get_addr(game),game_get_port(game))); fprintf(fp,"\n\n"); if (game->clienttag==CLIENTTAG_DIABLORTL_UINT) for (i=0; icount; i++) fprintf(fp,"%-16s JOINED\n",account_get_name(game->players[i])); else if (ladder_info) for (i=0; iplayers[i]), game_result_get_str(game->results[i]), ladder_info[i].oldrating, ladder_info[i].oldrank, ladder_info[i].prob*100.0, ladder_info[i].k, ladder_info[i].adj); else for (i=0; iplayers[i]), game_result_get_str(game->results[i])); fprintf(fp,"\n\n"); if (ladder_info) xfree(ladder_info); for (i=0; ireport_heads[i]) fprintf(fp,"%s\n",game->report_heads[i]); else fprintf(fp,"[ game report header not available for player %u (\"%s\") ]\n",i+1,account_get_name(game->players[i])); if (game->report_bodies[i]) fprintf(fp,"%s\n",game->report_bodies[i]); else fprintf(fp,"[ game report body not available for player %u (\"%s\") ]\n\n",i+1,account_get_name(game->players[i])); } fprintf(fp,"\n\n"); if (game->clienttag==CLIENTTAG_STARCRAFT_UINT || game->clienttag==CLIENTTAG_SHAREWARE_UINT || game->clienttag==CLIENTTAG_BROODWARS_UINT || game->clienttag==CLIENTTAG_WARCIIBNE_UINT) { for (i=0; iplayers[i]), account_get_normal_wins(game->players[i],game->clienttag), account_get_normal_losses(game->players[i],game->clienttag), account_get_normal_disconnects(game->players[i],game->clienttag), account_get_normal_draws(game->players[i],game->clienttag)); } if (game->clienttag==CLIENTTAG_STARCRAFT_UINT || game->clienttag==CLIENTTAG_BROODWARS_UINT || game->clienttag==CLIENTTAG_WARCIIBNE_UINT) { fprintf(fp,"\n"); for (i=0; iplayers[i]), account_get_ladder_wins(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_losses(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_disconnects(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_rating(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_rank(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_draws(game->players[i],game->clienttag,ladder_id_normal)); } if (game->clienttag==CLIENTTAG_WARCIIBNE_UINT) { fprintf(fp,"\n"); for (i=0; iplayers[i]), account_get_ladder_wins(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_losses(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_disconnects(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_rating(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_rank(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_draws(game->players[i],game->clienttag,ladder_id_ironman)); } fprintf(fp,"\nThis game lasted %lu minutes (elapsed).\n",((unsigned long int)difftime(now,game->start_time))/60); if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close report file \"%s\" after writing (fclose: %s)",tempname,pstrerror(errno)); xfree(realname); xfree(tempname); return -1; } if (p_rename(tempname,realname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not rename report file to \"%s\" (rename: %s)",realname,pstrerror(errno)); xfree(realname); xfree(tempname); return -1; } eventlog(eventlog_level_debug,__FUNCTION__,"game report saved as \"%s\"",realname); xfree(realname); xfree(tempname); return 0; } extern unsigned int game_get_id(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->id; } extern char const * game_get_name(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } return game->name ? game->name : "BNet"; } extern t_game_type game_get_type(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->type; } extern t_game_maptype game_get_maptype(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return game_maptype_none; } return game->maptype; } extern int game_set_maptype(t_game * game, t_game_maptype maptype) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } game->maptype = maptype; return 0; } extern t_game_tileset game_get_tileset(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return game_tileset_none; } return game->tileset; } extern int game_set_tileset(t_game * game, t_game_tileset tileset) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } game->tileset = tileset; return 0; } extern t_game_speed game_get_speed(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return game_speed_none; } return game->speed; } extern int game_set_speed(t_game * game, t_game_speed speed) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } game->speed = speed; return 0; } extern unsigned int game_get_mapsize_x(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->mapsize_x; } extern int game_set_mapsize_x(t_game * game, unsigned int x) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } game->mapsize_x = x; return 0; } extern unsigned int game_get_mapsize_y(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->mapsize_y; } extern int game_set_mapsize_y(t_game * game, unsigned int y) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } game->mapsize_y = y; return 0; } extern unsigned int game_get_maxplayers(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->maxplayers; } extern int game_set_maxplayers(t_game * game, unsigned int maxplayers) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } game->maxplayers = maxplayers; return 0; } extern unsigned int game_get_difficulty(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->difficulty; } extern int game_set_difficulty(t_game * game, unsigned int difficulty) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } game->difficulty = difficulty; return 0; } extern char const * game_get_description(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } return game->description; } extern int game_set_description(t_game * game, char const * description) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!description) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL description"); return -1; } if (game->description != NULL) xfree((void *)game->description); game->description = xstrdup(description); return 0; } extern char const * game_get_pass(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } return game->pass; } extern char const * game_get_info(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } return game->info; } extern int game_get_startver(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->startver; } extern unsigned long game_get_version(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->version; } extern unsigned int game_get_ref(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->ref; } extern unsigned int game_get_count(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->count; } extern void game_set_status(t_game * game, t_game_status status) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return; } // [quetzal] 20020829 - this should prevent invalid status changes // its like started game cant become open and so on if (game->status == game_status_started && (status == game_status_open || status == game_status_full || status == game_status_loaded)) { eventlog(eventlog_level_error, "game_set_status", "attempting to set status '%s' (%d) to started game", game_status_get_str(status), status); return; } if (game->status == game_status_done && status != game_status_done) { eventlog(eventlog_level_error, "game_set_status", "attempting to set status '%s' (%d) to done game", game_status_get_str(status), status); return; } if (status==game_status_started && game->start_time==(time_t)0) game->start_time = now; game->status = status; } extern t_game_status game_get_status(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->status; } extern unsigned int game_get_addr(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->addr; /* host byte order */ } extern unsigned short game_get_port(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->port; /* host byte order */ } extern unsigned int game_get_latency(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } if (game->ref<1) { eventlog(eventlog_level_error,__FUNCTION__,"game \"%s\" has no players",game_get_name(game)); return 0; } if (!game->players) { eventlog(eventlog_level_error,__FUNCTION__,"game \"%s\" has NULL players array (ref=%u)",game_get_name(game),game->ref); return 0; } if (!game->players[0]) { eventlog(eventlog_level_error,__FUNCTION__,"game \"%s\" has NULL players[0] entry (ref=%u)",game_get_name(game),game->ref); return 0; } return 0; /* conn_get_latency(game->players[0]); */ } extern t_connection * game_get_player_conn(t_game const * game, unsigned int i) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } if (game->ref<1) { eventlog(eventlog_level_error,__FUNCTION__,"game \"%s\" has no players",game_get_name(game)); return NULL; } if (!game->players) { eventlog(eventlog_level_error,__FUNCTION__,"game \"%s\" has NULL player array (ref=%u)",game_get_name(game),game->ref); return NULL; } if (!game->players[i]) { eventlog(eventlog_level_error,__FUNCTION__,"game \"%s\" has NULL players[i] entry (ref=%u)",game_get_name(game),game->ref); return NULL; } return game->connections[i]; } extern t_clienttag game_get_clienttag(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->clienttag; } extern int game_add_player(t_game * game, char const * pass, int startver, t_connection * c) { t_connection * * tempc; t_account * * tempp; t_game_result * tempr; t_game_result ** temprr; char const * * temprh; char const * * temprb; unsigned int i = 0; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!pass) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL password"); return -1; } if (startver!=STARTVER_UNKNOWN && startver!=STARTVER_GW1 && startver!=STARTVER_GW3 && startver!=STARTVER_GW4 && startver!=STARTVER_REALM1) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game startver %d",startver); return -1; } if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (game->type==game_type_ladder && account_get_normal_wins(conn_get_account(c),conn_get_clienttag(c))<10) /* if () ... */ { eventlog(eventlog_level_error,__FUNCTION__,"can not join ladder game without 10 normal wins"); return -1; } { t_clienttag gt; if (!(gt = game_get_clienttag(game))) { eventlog(eventlog_level_error,__FUNCTION__,"could not get clienttag for game"); return -1; } } if (game->pass[0]!='\0' && strcasecmp(game->pass,pass)!=0) { eventlog(eventlog_level_debug,__FUNCTION__,"game \"%s\" password mismatch \"%s\"!=\"%s\"",game_get_name(game),game->pass,pass); return -1; } if (game->connections && (game->count > 0)) { for (i=0; icount; i++) { if (game->connections[i] == NULL) { game->connections[i] = c; game->players[i] = conn_get_account(c); game->results[i] = game_result_none; game->reported_results[i] = NULL; game->report_heads[i] = NULL; game->report_bodies[i] = NULL; game->ref++; game->lastaccess_time = now; break; } } } if ((i == game->count) || (game->count == 0)) { if (!game->connections) /* some realloc()s are broken */ tempc = xmalloc((game->count+1)*sizeof(t_connection *)); else tempc = xrealloc(game->connections,(game->count+1)*sizeof(t_connection *)); game->connections = tempc; if (!game->players) /* some realloc()s are broken */ tempp = xmalloc((game->count+1)*sizeof(t_account *)); else tempp = xrealloc(game->players,(game->count+1)*sizeof(t_account *)); game->players = tempp; if (!game->results) /* some realloc()s are broken */ tempr = xmalloc((game->count+1)*sizeof(t_game_result)); else tempr = xrealloc(game->results,(game->count+1)*sizeof(t_game_result)); game->results = tempr; if (!game->reported_results) temprr = xmalloc((game->count+1)*sizeof(t_game_result *)); else temprr = xrealloc(game->reported_results,(game->count+1)*sizeof(t_game_result *)); game->reported_results = temprr; if (!game->report_heads) /* some xrealloc()s are broken */ temprh = xmalloc((game->count+1)*sizeof(char const *)); else temprh = xrealloc((void *)game->report_heads,(game->count+1)*sizeof(char const *)); /* avoid compiler warning */ game->report_heads = temprh; if (!game->report_bodies) /* some xrealloc()s are broken */ temprb = xmalloc((game->count+1)*sizeof(char const *)); else temprb = xrealloc((void *)game->report_bodies,(game->count+1)*sizeof(char const *)); /* avoid compiler warning */ game->report_bodies = temprb; game->connections[game->count] = c; game->players[game->count] = conn_get_account(c); game->results[game->count] = game_result_none; game->reported_results[game->count] = NULL; game->report_heads[game->count] = NULL; game->report_bodies[game->count] = NULL; game->count++; game->ref++; game->lastaccess_time = now; } // end of "if ((i == game->count) || (game->count == 0))" if (game->startver!=startver && startver!=STARTVER_UNKNOWN) /* with join startver ALWAYS unknown [KWS] */ eventlog(eventlog_level_error,__FUNCTION__,"player \"%s\" client \"%s\" startver %u joining game startver %u (count=%u ref=%u)",account_get_name(conn_get_account(c)),clienttag_uint_to_str(conn_get_clienttag(c)),startver,game->startver,game->count,game->ref); game_choose_host(game); return 0; } extern int game_del_player(t_game * game, t_connection * c) { char const * tname; unsigned int i; t_account * account; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!game->players) { eventlog(eventlog_level_error,__FUNCTION__,"player array is NULL"); return -1; } if (!game->reported_results) { eventlog(eventlog_level_error,__FUNCTION__,"reported results array is NULL"); return -1; } account = conn_get_account(c); if(conn_get_leavegamewhisper_ack(c)==0) { watchlist_notify_event(conn_get_account(c),NULL,conn_get_clienttag(c),watch_event_leavegame); conn_set_leavegamewhisper_ack(c,1); //1 = already whispered. We reset this each time user joins a channel } eventlog(eventlog_level_debug,__FUNCTION__,"game \"%s\" has ref=%u, count=%u; trying to remove player \"%s\"",game_get_name(game),game->ref,game->count,account_get_name(account)); for (i=0; icount; i++) if (game->players[i]==account && game->connections[i]) { eventlog(eventlog_level_debug,__FUNCTION__,"removing player #%u \"%s\" from \"%s\", %u players left",i,(tname = account_get_name(account)),game_get_name(game),game->ref-1); game->connections[i] = NULL; if (!(game->reported_results[i])) eventlog(eventlog_level_debug,__FUNCTION__,"player \"%s\" left without reporting (valid) results",tname); eventlog(eventlog_level_debug,__FUNCTION__,"player deleted... (ref=%u)",game->ref); if (game->ref<2) { eventlog(eventlog_level_debug,__FUNCTION__,"no more players, reporting game"); game_report(game); eventlog(eventlog_level_debug,__FUNCTION__,"no more players, destroying game"); game_destroy(game); return 0; } game->ref--; game->lastaccess_time = now; game_choose_host(game); return 0; } eventlog(eventlog_level_error,__FUNCTION__,"player \"%s\" was not in the game",account_get_name(account)); return -1; } extern t_account * game_get_player(t_game * game, unsigned int i) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } if (!(icount)) { eventlog(eventlog_level_error,__FUNCTION__,"requested illegal player id %u",i); return NULL; } return game->players[i]; } extern int game_set_report(t_game * game, t_account * account, char const * rephead, char const * repbody) { unsigned int pos; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!game->players) { eventlog(eventlog_level_error,__FUNCTION__,"player array is NULL"); return -1; } if (!game->report_heads) { eventlog(eventlog_level_error,__FUNCTION__,"report_heads array is NULL"); return -1; } if (!game->report_bodies) { eventlog(eventlog_level_error,__FUNCTION__,"report_bodies array is NULL"); return -1; } if (!rephead) { eventlog(eventlog_level_error,__FUNCTION__,"report head is NULL"); return -1; } if (!repbody) { eventlog(eventlog_level_error,__FUNCTION__,"report body is NULL"); return -1; } { unsigned int i; pos = game->count; for (i=0; icount; i++) if (game->players[i]==account) pos = i; } if (pos==game->count) { eventlog(eventlog_level_error,__FUNCTION__,"could not find player \"%s\" to set result",account_get_name(account)); return -1; } game->report_heads[pos] = xstrdup(rephead); game->report_bodies[pos] = xstrdup(repbody); return 0; } extern int game_set_reported_results(t_game * game, t_account * account, t_game_result * results) { unsigned int i,j; t_game_result result; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!results) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL results"); return -1; } if (!game->players) { eventlog(eventlog_level_error,__FUNCTION__,"player array is NULL"); return -1; } if (!game->reported_results) { eventlog(eventlog_level_error,__FUNCTION__,"reported_results array is NULL"); return -1; } for (i=0;icount;i++) { if ((game->players[i]==account)) break; } if (i==game->count) { eventlog(eventlog_level_error,__FUNCTION__,"could not find player \"%s\" to set reported results",account_get_name(account)); return -1; } if (game->reported_results[i]) { eventlog(eventlog_level_error,__FUNCTION__,"player \"%s\" allready reported results - skipping this report",account_get_name(account)); return -1; } for (j=0;jcount;j++) { result = results[j]; switch(result) { case game_result_win: case game_result_loss: case game_result_draw: case game_result_observer: case game_result_disconnect: break; case game_result_none: case game_result_playing: if (i != j) break; /* accept none/playing only from "others" */ default: /* result is invalid */ if (i!=j) { eventlog(eventlog_level_error,__FUNCTION__,"ignoring bad reported result %u for player \"%s\"",(unsigned int)result,account_get_name(game->players[j])); results[i]=game_result_none; } else { eventlog(eventlog_level_error,__FUNCTION__,"got bad reported result %u for self - skipping results",(unsigned int)result); return -1; } } } game->reported_results[i] = results; return 0; } extern int game_set_self_report(t_game * game, t_account * account, t_game_result result) { unsigned int i; t_game_result * results; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!game->players) { eventlog(eventlog_level_error,__FUNCTION__,"player array is NULL"); return -1; } if (!game->reported_results) { eventlog(eventlog_level_error,__FUNCTION__,"reported_results array is NULL"); return -1; } results = xmalloc(sizeof(t_game_result)*game->count); for (i=0;icount;i++) { if ((game->players[i]==account)) results[i]= result; else results[i]= game_result_none; } game_set_reported_results(game,account,results); return 0; } extern t_game_result * game_get_reported_results(t_game * game, t_account * account) { unsigned int i; if (!(game)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } if (!(account)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } if (!(game->players)) { eventlog(eventlog_level_error,__FUNCTION__,"player array is NULL"); return NULL; } if (!(game->reported_results)) { eventlog(eventlog_level_error,__FUNCTION__,"reported_results array is NULL"); return NULL; } for (i=0;icount;i++) { if ((game->players[i]==account)) break; } if (i==game->count) { eventlog(eventlog_level_error,__FUNCTION__,"could not find player \"%s\" to set reported results",account_get_name(account)); return NULL; } if (!(game->reported_results[i])) { eventlog(eventlog_level_error,__FUNCTION__,"player \"%s\" has not reported any results",account_get_name(account)); return NULL; } return game->reported_results[i]; } extern char const * game_get_mapname(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } return game->mapname; } extern int game_set_mapname(t_game * game, char const * mapname) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!mapname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL mapname"); return -1; } if (game->mapname != NULL) xfree((void *)game->mapname); game->mapname = xstrdup(mapname); return 0; } extern t_connection * game_get_owner(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } return game->owner; } extern time_t game_get_create_time(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return (time_t)0; } return game->create_time; } extern time_t game_get_start_time(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return (time_t)0; } return game->start_time; } extern int game_set_option(t_game * game, t_game_option option) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } game->option = option; return 0; } extern t_game_option game_get_option(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return game_option_none; } return game->option; } extern int gamelist_create(void) { elist_init(&gamelist_head); glist_length = 0; return 0; } extern int gamelist_destroy(void) { /* FIXME: if called with active games, games are not freed */ elist_init(&gamelist_head); glist_length = 0; return 0; } extern int gamelist_get_length(void) { return glist_length; } extern t_game * gamelist_find_game(char const * name, t_clienttag ctag, t_game_type type) { t_elist *curr; t_game *game; elist_for_each(curr,&gamelist_head) { game = elist_entry(curr,t_game,glist_link); if ((type==game_type_all || game->type==type) && ctag == game->clienttag && game->name && !strcasecmp(name,game->name)) return game; } return NULL; } extern t_game * gamelist_find_game_byid(unsigned int id) { t_elist *curr; t_game *game; elist_for_each(curr,&gamelist_head) { game = elist_entry(curr,t_game,glist_link); if (game->id==id) return game; } return NULL; } extern void gamelist_traverse(t_glist_func cb, void *data) { t_elist *curr; elist_for_each(curr,&gamelist_head) { if (cb(elist_entry(curr,t_game,glist_link),data)<0) return; } } extern int gamelist_total_games(void) { return totalcount; } extern int game_set_realm(t_game * game, unsigned int realm) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } game->realm = realm; return 0; } extern unsigned int game_get_realm(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->realm; } extern int game_set_realmname(t_game * game, char const * realmname) { char const * temp; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (realmname) temp=xstrdup(realmname); else temp=NULL; if (game->realmname) xfree((void *)game->realmname); /* avoid warning */ game->realmname = temp; return 0; } extern char const * game_get_realmname(t_game const * game) { if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } return game->realmname; } extern void gamelist_check_voidgame(void) { t_elist *curr, *save; t_game *game; elist_for_each_safe(curr,&gamelist_head,save) { game = elist_entry(curr,t_game,glist_link); if (!game->realm) continue; if (game->ref >= 1) continue; if ((now - game->lastaccess_time) > MAX_GAME_EMPTY_TIME) game_destroy(game); } } extern void game_set_flag(t_game * game, t_game_flag flag) { if (!game) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL game"); return; } game->flag = flag; } extern t_game_flag game_get_flag(t_game const * game) { if (!game) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL game"); return 0; } return game->flag; } extern int game_get_count_by_clienttag(t_clienttag ct) { t_game *game; t_elist *curr; int clienttaggames = 0; if (!ct) { eventlog(eventlog_level_error, __FUNCTION__, "got UNKNOWN clienttag"); return 0; } /* Get number of games for client tag specific */ elist_for_each(curr,&gamelist_head) { game = elist_entry(curr,t_game,glist_link); if(game_get_clienttag(game)==ct) clienttaggames++; } return clienttaggames; } static int game_match_name(const char *name, const char *prefix) { /* the easy cases */ if (!name || !*name) return 1; if (!prefix || !*prefix) return 1; if (!strncmp(name,prefix,strlen(prefix))) return 1; return 0; } extern int game_is_ladder(t_game *game) { assert(game); /* all normal ladder games are still counted as ladder games */ if (game->type == game_type_ladder || game->type == game_type_ironman) return 1; /* addition game types are also checked against gamename prefix if set */ if (game_match_type(game_get_type(game),prefs_get_ladder_games()) && game_match_name(game_get_name(game),prefs_get_ladder_prefix())) return 1; return 0; } pvpgn-1.8.5/src/bnetd/handle_udp.c0000644000175000017500000001234111151345317015775 0ustar aaronaaron/* * Copyright (C) 1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "common/packet.h" #include "common/udp_protocol.h" #include "common/eventlog.h" #include "connection.h" #include "common/queue.h" #include "common/bn_type.h" #include "common/addr.h" #include "udptest_send.h" #include "handle_udp.h" #include "common/setup_after.h" extern int handle_udp_packet(int usock, unsigned int src_addr, unsigned short src_port, t_packet const * const packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",usock); return -1; } if (packet_get_class(packet)!=packet_class_udp) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",usock,(int)packet_get_class(packet)); return -1; } switch (packet_get_type(packet)) { case SERVER_UDPTEST: /* we might get these if a client is running on the same machine as us */ if (packet_get_size(packet)u.client_udpping.unknown1)); return 0; case CLIENT_SESSIONADDR1: if (packet_get_size(packet)u.client_sessionaddr1.sessionkey)))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] address not set (no connection with session key 0x%08x)",usock,bn_int_get(packet->u.client_sessionaddr1.sessionkey)); return -1; } if (conn_get_game_addr(c)!=src_addr || conn_get_game_port(c)!=src_port) eventlog(eventlog_level_info,__FUNCTION__,"[%d][%d] SESSIONADDR1 set new UDP address to %s",conn_get_socket(c),usock,addr_num_to_addr_str(src_addr,src_port)); conn_set_game_socket(c,usock); conn_set_game_addr(c,src_addr); conn_set_game_port(c,src_port); udptest_send(c); } return 0; case CLIENT_SESSIONADDR2: if (packet_get_size(packet)u.client_sessionaddr2.sessionnum)))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] address not set (no connection with session number %u)",usock,bn_int_get(packet->u.client_sessionaddr2.sessionnum)); return -1; } if (conn_get_sessionkey(c)!=bn_int_get(packet->u.client_sessionaddr2.sessionkey)) { eventlog(eventlog_level_error,__FUNCTION__,"[%d][%d] address not set (expected session key 0x%08x, got 0x%08x)",conn_get_socket(c),usock,conn_get_sessionkey(c),bn_int_get(packet->u.client_sessionaddr2.sessionkey)); return -1; } if (conn_get_game_addr(c)!=src_addr || conn_get_game_port(c)!=src_port) eventlog(eventlog_level_info,__FUNCTION__,"[%d][%d] SESSIONADDR2 set new UDP address to %s",conn_get_socket(c),usock,addr_num_to_addr_str(src_addr,src_port)); conn_set_game_socket(c,usock); conn_set_game_addr(c,src_addr); conn_set_game_port(c,src_port); udptest_send(c); } return 0; case CLIENT_SEARCH_LAN_GAMES: //added by Spider { eventlog(eventlog_level_debug,__FUNCTION__,"[%d] got SEARCH_LAN_GAMES packet from %s",usock,addr_num_to_addr_str(src_addr,src_port)); return 0; } default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] got unknown udp packet type 0x%04x, len %u from %s",usock,(unsigned int)packet_get_type(packet),packet_get_size(packet),addr_num_to_addr_str(src_addr,src_port)); } return 0; } pvpgn-1.8.5/src/bnetd/udptest_send.c0000644000175000017500000000744611151345317016405 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memset.h" #include #include "compat/strerror.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include /* FIXME: probably not needed... do some systems put types in here or something? */ #endif #include "compat/psock.h" #include "common/packet.h" #include "common/bn_type.h" #include "common/udp_protocol.h" #include "connection.h" #include "common/addr.h" #include "common/tag.h" #include "common/hexdump.h" #include "common/eventlog.h" #include "udptest_send.h" #include "common/setup_after.h" extern FILE * hexstrm; /* from main.c */ extern int udptest_send(t_connection const * c) { t_packet * upacket; struct sockaddr_in caddr; unsigned int tries,successes; memset(&caddr,0,sizeof(caddr)); caddr.sin_family = PSOCK_AF_INET; caddr.sin_port = htons(conn_get_game_port(c)); caddr.sin_addr.s_addr = htonl(conn_get_game_addr(c)); for (tries=successes=0; successes!=2 && tries<5; tries++) { if (!(upacket = packet_create(packet_class_udp))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not allocate memory for packet",conn_get_socket(c)); continue; } packet_set_size(upacket,sizeof(t_server_udptest)); packet_set_type(upacket,SERVER_UDPTEST); bn_int_tag_set(&upacket->u.server_udptest.bnettag,BNETTAG); if (hexstrm) { fprintf(hexstrm,"%d: send class=%s[0x%02x] type=%s[0x%04x] ", conn_get_game_socket(c), packet_get_class_str(upacket),(unsigned int)packet_get_class(upacket), packet_get_type_str(upacket,packet_dir_from_server),packet_get_type(upacket)); fprintf(hexstrm,"from=%s ", addr_num_to_addr_str(conn_get_game_addr(c),conn_get_game_port(c))); fprintf(hexstrm,"to=%s ", addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port))); fprintf(hexstrm,"length=%u\n", packet_get_size(upacket)); hexdump(hexstrm,packet_get_raw_data(upacket,0),packet_get_size(upacket)); } if (psock_sendto(conn_get_game_socket(c), packet_get_raw_data_const(upacket,0),packet_get_size(upacket), 0,(struct sockaddr *)&caddr,(psock_t_socklen)sizeof(caddr))!=(int)packet_get_size(upacket)) eventlog(eventlog_level_error,__FUNCTION__,"[%d] failed to send UDPTEST to %s (attempt %u) (psock_sendto: %s)",conn_get_socket(c),addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),conn_get_game_port(c)),tries+1,pstrerror(psock_errno())); else successes++; packet_del_ref(upacket); } if (successes!=2) return -1; return 0; } pvpgn-1.8.5/src/bnetd/character.c0000644000175000017500000004007511151345317015633 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define CHARACTER_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memcpy.h" #include "compat/strcasecmp.h" #include "compat/strdup.h" #include #include "compat/strerror.h" #include "common/eventlog.h" #include "common/list.h" #include "compat/uint.h" #include "common/bnet_protocol.h" #include "account.h" #include "account_wrap.h" #include "common/bn_type.h" #include "common/util.h" #include "common/xalloc.h" #include "character.h" #include "common/setup_after.h" static t_list * characterlist_head=NULL; static t_character_class bncharacter_class_to_character_class(t_uint8 class) { switch (class) { case D2CHAR_INFO_CLASS_AMAZON: return character_class_amazon; case D2CHAR_INFO_CLASS_SORCERESS: return character_class_sorceress; case D2CHAR_INFO_CLASS_NECROMANCER: return character_class_necromancer; case D2CHAR_INFO_CLASS_PALADIN: return character_class_paladin; case D2CHAR_INFO_CLASS_BARBARIAN: return character_class_barbarian; case D2CHAR_INFO_CLASS_DRUID: return character_class_druid; case D2CHAR_INFO_CLASS_ASSASSIN: return character_class_assassin; default: return character_class_none; } } /* Function unused static t_uint8 character_class_to_bncharacter_class(t_character_class class) { switch (class) { case character_class_amazon: return D2CHAR_INFO_CLASS_AMAZON; case character_class_sorceress: return D2CHAR_INFO_CLASS_SORCERESS; case character_class_necromancer: return D2CHAR_INFO_CLASS_NECROMANCER; case character_class_paladin: return D2CHAR_INFO_CLASS_PALADIN; case character_class_barbarian: return D2CHAR_INFO_CLASS_BARBARIAN; case character_class_druid: return D2CHAR_INFO_CLASS_DRUID; case character_class_assassin: return D2CHAR_INFO_CLASS_ASSASSIN; default: eventlog(eventlog_level_error,__FUNCTION__,"got unknown class %d",(int)class); case character_class_none: return D2CHAR_INFO_FILLER; } } */ static const char * character_class_to_classname (t_character_class class) { switch (class) { case character_class_amazon: return "Amazon"; case character_class_sorceress: return "Sorceress"; case character_class_necromancer: return "Necromancer"; case character_class_paladin: return "Paladin"; case character_class_barbarian: return "Barbarian"; case character_class_druid: return "Druid"; case character_class_assassin: return "Assassin"; default: return "Unknown"; } } static const char * character_expansion_to_expansionname (t_character_expansion expansion) { switch (expansion) { case character_expansion_classic: return "Classic"; case character_expansion_lod: return "LordOfDestruction"; default: return "Unknown"; } } static void decode_character_data(t_character * ch) { ch->unknownb1 = D2CHAR_INFO_UNKNOWNB1; ch->unknownb2 = D2CHAR_INFO_UNKNOWNB2; ch->helmgfx = D2CHAR_INFO_FILLER; ch->bodygfx = D2CHAR_INFO_FILLER; ch->leggfx = D2CHAR_INFO_FILLER; ch->lhandweapon = D2CHAR_INFO_FILLER; ch->lhandgfx = D2CHAR_INFO_FILLER; ch->rhandweapon = D2CHAR_INFO_FILLER; ch->rhandgfx = D2CHAR_INFO_FILLER; ch->unknownb3 = D2CHAR_INFO_FILLER; ch->unknownb4 = D2CHAR_INFO_FILLER; ch->unknownb5 = D2CHAR_INFO_FILLER; ch->unknownb6 = D2CHAR_INFO_FILLER; ch->unknownb7 = D2CHAR_INFO_FILLER; ch->unknownb8 = D2CHAR_INFO_FILLER; ch->unknownb9 = D2CHAR_INFO_FILLER; ch->unknownb10 = D2CHAR_INFO_FILLER; ch->unknownb11 = D2CHAR_INFO_FILLER; ch->unknown1 = 0xffffffff; ch->unknown2 = 0xffffffff; ch->unknown3 = 0xffffffff; ch->unknown4 = 0xffffffff; ch->level = 0x01; ch->status = 0x80; ch->title = 0x80; ch->unknownb13 = 0x80; ch->emblembgc = 0x80; ch->emblemfgc = 0xff; ch->emblemnum = 0xff; ch->unknownb14 = D2CHAR_INFO_FILLER; /* b1 b2 hg bg lg lw lg rw rg b3 b4 b5 b6 b7 b8 b9 bA bB cl u1 u1 u1 u1 u2 u2 u2 u2 u3 u3 u3 u3 u4 u4 u4 u4 lv st ti bC eb ef en bD \0 amazon_qwer.log: 83 80 ff ff ff ff ff 43 ff 1b ff ff ff ff ff ff ff ff 01 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 80 80 ff ff ff 00 sor_Bent.log: 83 80 ff ff ff ff ff 53 ff ff ff ff ff ff ff ff ff ff 02 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 80 80 ff ff ff 00 necro_Thorsen.log: 83 80 ff ff ff ff ff 2b ff ff ff ff ff ff ff ff ff ff 03 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 80 80 ff ff ff 00 pal_QlexTEST.log: 87 80 01 01 01 01 01 ff ff ff 01 01 ff ff ff ff ff ff 04 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 ff ff ff 80 80 00 barb_Qlex.log: 83 80 ff ff ff ff ff 2f ff 1b ff ff ff ff ff ff ff ff 05 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 80 80 ff ff ff 00 */ } static int load_initial_data (t_character * character, t_character_class class, t_character_expansion expansion) { char const * data_in_hex; eventlog(eventlog_level_debug,__FUNCTION__,"Initial Data for %s, %s %s", character->name, character_expansion_to_expansionname(expansion), character_class_to_classname(class)); /* Ideally, this would be loaded from bnetd_default_user, but I don't want to hack account.c just now */ /* The "default" character info if everything else messes up; */ data_in_hex = NULL; /* FIXME: what should we do if expansion or class isn't known... */ switch (expansion) { case character_expansion_classic: switch (class) { case character_class_amazon: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 01 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF"; break; case character_class_sorceress: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 02 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF"; break; case character_class_necromancer: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 03 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF"; break; case character_class_paladin: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 04 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF"; break; case character_class_barbarian: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 05 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF"; break; default: break; //should never reach that part ot the code... but to make compiler happy... } break; case character_expansion_lod: switch (class) { case character_class_amazon: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 01 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF"; break; case character_class_sorceress: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 02 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF"; break; case character_class_necromancer: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 03 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF"; break; case character_class_paladin: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 04 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF"; break; case character_class_barbarian: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 05 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF"; break; case character_class_druid: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 06 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF"; break; case character_class_assassin: data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 07 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF"; break; default: break; // again we will never get here... but how can compiler know that?!? } default: break; // well... like I said 2 times before.... } character->datalen = hex_to_str(data_in_hex, character->data, 33); decode_character_data(character); return 0; } extern int character_create(t_account * account, t_clienttag clienttag, char const * realmname, char const * name, t_character_class class, t_character_expansion expansion) { t_character * ch; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } if (!realmname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realmname"); return -1; } if (!name) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL name"); return -1; } ch = xmalloc(sizeof(t_character)); ch->name = xstrdup(name); ch->realmname = xstrdup(realmname); ch->guildname = xstrdup(""); /* FIXME: how does this work on Battle.net? */ if (account_check_closed_character(account, clienttag, realmname, name)) { eventlog(eventlog_level_error,__FUNCTION__,"a character with the name \"%s\" does already exist in realm \"%s\"",name,realmname); xfree((void *)ch->realmname); /* avoid warning */ xfree((void *)ch->name); /* avoid warning */ xfree(ch); return -1; } load_initial_data (ch, class, expansion); account_add_closed_character(account, clienttag, ch); return 0; } extern char const * character_get_name(t_character const * ch) { if (!ch) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character"); return NULL; } return ch->name; } extern char const * character_get_realmname(t_character const * ch) { if (!ch) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character"); return NULL; } return ch->realmname; } extern t_character_class character_get_class(t_character const * ch) { if (!ch) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character"); return character_class_none; } return bncharacter_class_to_character_class(ch->class); } extern char const * character_get_playerinfo(t_character const * ch) { t_d2char_info d2char_info; static char playerinfo[sizeof(t_d2char_info)+4]; if (!ch) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character"); return NULL; } /* ff 0f 68 00 ..h. 0x0040: 01 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................ 0x0050: d8 94 f6 08 b1 65 77 02 65 76 69 6c 67 72 75 73 .....ew.evilgrus 0x0060: 73 6c 65 72 00 56 44 32 44 42 65 74 61 57 65 73 sler.VD2DBetaWes 0x0070: 74 2c 74 61 72 61 6e 2c 83 80 ff ff ff ff ff 2f t,taran,......./ 0x0080: ff ff ff ff ff ff ff ff ff ff 03 ff ff ff ff ff ................ 0x0090: ff ff ff ff ff ff ff ff ff ff ff 07 80 80 80 80 ................ 0x00a0: ff ff ff 00 */ bn_byte_set(&d2char_info.unknownb1,ch->unknownb1); bn_byte_set(&d2char_info.unknownb2,ch->unknownb2); bn_byte_set(&d2char_info.helmgfx,ch->helmgfx); bn_byte_set(&d2char_info.bodygfx,ch->bodygfx); bn_byte_set(&d2char_info.leggfx,ch->leggfx); bn_byte_set(&d2char_info.lhandweapon,ch->lhandweapon); bn_byte_set(&d2char_info.lhandgfx,ch->lhandgfx); bn_byte_set(&d2char_info.rhandweapon,ch->rhandweapon); bn_byte_set(&d2char_info.rhandgfx,ch->rhandgfx); bn_byte_set(&d2char_info.unknownb3,ch->unknownb3); bn_byte_set(&d2char_info.unknownb4,ch->unknownb4); bn_byte_set(&d2char_info.unknownb5,ch->unknownb5); bn_byte_set(&d2char_info.unknownb6,ch->unknownb6); bn_byte_set(&d2char_info.unknownb7,ch->unknownb7); bn_byte_set(&d2char_info.unknownb8,ch->unknownb8); bn_byte_set(&d2char_info.unknownb9,ch->unknownb9); bn_byte_set(&d2char_info.unknownb10,ch->unknownb10); bn_byte_set(&d2char_info.unknownb11,ch->unknownb11); bn_byte_set(&d2char_info.class,ch->class); bn_int_set(&d2char_info.unknown1,ch->unknown1); bn_int_set(&d2char_info.unknown2,ch->unknown2); bn_int_set(&d2char_info.unknown3,ch->unknown3); bn_int_set(&d2char_info.unknown4,ch->unknown4); bn_byte_set(&d2char_info.level,ch->level); bn_byte_set(&d2char_info.status,ch->status); bn_byte_set(&d2char_info.title,ch->title); bn_byte_set(&d2char_info.unknownb13,ch->unknownb13); bn_byte_set(&d2char_info.emblembgc,ch->emblembgc); bn_byte_set(&d2char_info.emblemfgc,ch->emblemfgc); bn_byte_set(&d2char_info.emblemnum,ch->emblemnum); bn_byte_set(&d2char_info.unknownb14,ch->unknownb14); memcpy(playerinfo,&d2char_info,sizeof(d2char_info)); strcpy(&playerinfo[sizeof(d2char_info)],ch->guildname); return playerinfo; } extern char const * character_get_guildname(t_character const * ch) { if (!ch) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character"); return NULL; } return ch->guildname; } extern int character_verify_charlist(t_character const * ch, char const * charlist) { char * temp; char const * tok1; char const * tok2; if (!ch) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character"); return -1; } if (!charlist) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character"); return -1; } temp = xstrdup(charlist); tok1 = (char const *)strtok(temp,","); /* strtok modifies the string it is passed */ tok2 = strtok(NULL,","); while (tok1) { if (!tok2) { eventlog(eventlog_level_error,__FUNCTION__,"bad character list \"%s\"",temp); break; } if (strcasecmp(tok1,ch->realmname)==0 && strcasecmp(tok2,ch->name)==0) { xfree(temp); return 0; } tok1 = strtok(NULL,","); tok2 = strtok(NULL,","); } xfree(temp); return -1; } extern int characterlist_create(char const * dirname) { characterlist_head = list_create(); return 0; } extern int characterlist_destroy(void) { t_elem * curr; t_character * ch; if (characterlist_head) { LIST_TRAVERSE(characterlist_head,curr) { ch = elem_get_data(curr); if (!ch) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"characterlist contains NULL item"); continue; } if (list_remove_elem(characterlist_head,&curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); xfree(ch); } if (list_destroy(characterlist_head)<0) return -1; characterlist_head = NULL; } return 0; } extern t_character * characterlist_find_character(char const * realmname, char const * charname) { t_elem * curr; t_character * ch; if (!realmname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realmname"); return NULL; } if (!charname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL charname"); return NULL; } LIST_TRAVERSE(characterlist_head,curr) { ch = elem_get_data(curr); if (strcasecmp(ch->name,charname)==0 && strcasecmp(ch->realmname,realmname)==0) return ch; } return NULL; } pvpgn-1.8.5/src/bnetd/anongame_infos.c0000644000175000017500000020406511151345317016663 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define TIMER_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strrchr.h" #include #include "compat/strerror.h" #include "common/list.h" #include "common/eventlog.h" #include "common/util.h" #include "common/packet.h" #include "common/tag.h" #include "common/bn_type.h" #include "common/xalloc.h" #include "zlib/pvpgn_zlib.h" #include "tournament.h" #include "anongame_maplists.h" #include "anongame_infos.h" #include "common/setup_after.h" static FILE *fp = NULL; static t_anongame_infos *anongame_infos; static int zlib_compress(void const *src, int srclen, char **dest, int *destlen); static int anongame_infos_data_load(void); static int anongame_infos_URL_init(t_anongame_infos * anongame_infos) { char **anongame_infos_URL; int i; if (!(anongame_infos)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos"); return -1; } anongame_infos_URL = xmalloc(sizeof(char*)*anongame_infos_URL_count); for (i=0; ianongame_infos_URL = anongame_infos_URL; return 0; } static int anongame_infos_URL_destroy(char ** anongame_infos_URL) { int i; if (!(anongame_infos_URL)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos_URL"); return -1; } for (i=0; i langID = NULL; descs = xmalloc(sizeof(char *)*anongame_infos_DESC_count); for (i=0; idescs = descs; return anongame_infos_DESC; } static int anongame_infos_DESC_destroy(t_anongame_infos_DESC * anongame_infos_DESC) { int i; char ** descs; if (!(anongame_infos_DESC)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos_DESC"); return -1; } if (anongame_infos_DESC->langID) xfree((void *) anongame_infos_DESC->langID); if ((descs = anongame_infos_DESC->descs)) { for (i=0; ianongame_infos_THUMBSDOWN; for (i=0; ianongame_infos_ICON_REQ; anongame_infos_ICON_REQ[ICON_REQ_WAR3_Level1] = 25; anongame_infos_ICON_REQ[ICON_REQ_WAR3_Level2] = 250; anongame_infos_ICON_REQ[ICON_REQ_WAR3_Level3] = 500; anongame_infos_ICON_REQ[ICON_REQ_WAR3_Level4] = 1500; anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level1] = 25; anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level2] = 150; anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level3] = 350; anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level4] = 750; anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level5] = 1500; anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level1] = 10; anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level2] = 75; anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level3] = 150; anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level4] = 250; anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level5] = 500; return 0; } static t_anongame_infos_data_lang *anongame_infos_data_lang_init(char *langID) { t_anongame_infos_data_lang *anongame_infos_data_lang; anongame_infos_data_lang = xmalloc(sizeof(t_anongame_infos_data_lang)); anongame_infos_data_lang->langID = xstrdup(langID); anongame_infos_data_lang->desc_data = NULL; anongame_infos_data_lang->ladr_data = NULL; anongame_infos_data_lang->desc_comp_data = NULL; anongame_infos_data_lang->ladr_comp_data = NULL; anongame_infos_data_lang->desc_len = 0; anongame_infos_data_lang->ladr_len = 0; anongame_infos_data_lang->desc_comp_len = 0; anongame_infos_data_lang->ladr_comp_len = 0; return anongame_infos_data_lang; } static int anongame_infos_data_lang_destroy(t_anongame_infos_data_lang * anongame_infos_data_lang) { if (!(anongame_infos_data_lang)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos_data_lang"); return -1; } if (anongame_infos_data_lang->langID) xfree((void *) anongame_infos_data_lang->langID); if (anongame_infos_data_lang->desc_data) xfree((void *) anongame_infos_data_lang->desc_data); if (anongame_infos_data_lang->ladr_data) xfree((void *) anongame_infos_data_lang->ladr_data); if (anongame_infos_data_lang->desc_comp_data) xfree((void *) anongame_infos_data_lang->desc_comp_data); if (anongame_infos_data_lang->ladr_comp_data) xfree((void *) anongame_infos_data_lang->ladr_comp_data); xfree((void *) anongame_infos_data_lang); return 0; } static int anongame_infos_data_init(t_anongame_infos * anongame_infos) { t_anongame_infos_data *anongame_infos_data; t_list *anongame_infos_data_lang; if (!(anongame_infos)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos"); return -1; } anongame_infos_data = xmalloc(sizeof(t_anongame_infos_data)); anongame_infos_data_lang = list_create(); anongame_infos_data->url_comp_data = NULL; anongame_infos_data->url_comp_data_115 = NULL; anongame_infos_data->map_comp_data = NULL; anongame_infos_data->type_comp_data = NULL; anongame_infos_data->desc_comp_data = NULL; anongame_infos_data->ladr_comp_data = NULL; anongame_infos_data->url_comp_len = 0; anongame_infos_data->url_comp_len_115 = 0; anongame_infos_data->map_comp_len = 0; anongame_infos_data->type_comp_len = 0; anongame_infos_data->desc_comp_len = 0; anongame_infos_data->ladr_comp_len = 0; anongame_infos->anongame_infos_data_war3 = anongame_infos_data; anongame_infos->anongame_infos_data_lang_war3 = anongame_infos_data_lang; anongame_infos_data = xmalloc(sizeof(t_anongame_infos_data)); anongame_infos_data_lang = list_create(); anongame_infos_data->url_comp_data = NULL; anongame_infos_data->url_comp_data_115 = NULL; anongame_infos_data->map_comp_data = NULL; anongame_infos_data->type_comp_data = NULL; anongame_infos_data->desc_comp_data = NULL; anongame_infos_data->ladr_comp_data = NULL; anongame_infos_data->url_comp_len = 0; anongame_infos_data->url_comp_len_115 = 0; anongame_infos_data->map_comp_len = 0; anongame_infos_data->type_comp_len = 0; anongame_infos_data->desc_comp_len = 0; anongame_infos_data->ladr_comp_len = 0; anongame_infos->anongame_infos_data_w3xp = anongame_infos_data; anongame_infos->anongame_infos_data_lang_w3xp = anongame_infos_data_lang; return 0; } static int anongame_infos_data_destroy(t_anongame_infos_data * anongame_infos_data, t_list * anongame_infos_data_lang) { t_elem *curr; t_anongame_infos_data_lang *entry; if (anongame_infos_data->url_comp_data) xfree((void *) anongame_infos_data->url_comp_data); if (anongame_infos_data->url_comp_data_115) xfree((void *) anongame_infos_data->url_comp_data_115); if (anongame_infos_data->map_comp_data) xfree((void *) anongame_infos_data->map_comp_data); if (anongame_infos_data->type_comp_data) xfree((void *) anongame_infos_data->type_comp_data); if (anongame_infos_data->desc_comp_data) xfree((void *) anongame_infos_data->desc_comp_data); if (anongame_infos_data->ladr_comp_data) xfree((void *) anongame_infos_data->ladr_comp_data); xfree((void *) anongame_infos_data); if (anongame_infos_data_lang) { LIST_TRAVERSE(anongame_infos_data_lang, curr) { if (!(entry = elem_get_data(curr))) eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); else { anongame_infos_data_lang_destroy(entry); } list_remove_elem(anongame_infos_data_lang, &curr); } list_destroy(anongame_infos_data_lang); } return 0; } t_anongame_infos *anongame_infos_init(void) { t_anongame_infos *anongame_infos; anongame_infos = xmalloc(sizeof(t_anongame_infos)); if (anongame_infos_URL_init(anongame_infos) != 0) { xfree((void *) anongame_infos); return NULL; } if (anongame_infos_THUMBSDOWN_init(anongame_infos) != 0) { anongame_infos_URL_destroy(anongame_infos->anongame_infos_URL); xfree((void *) anongame_infos); return NULL; } if (anongame_infos_ICON_REQ_init(anongame_infos) != 0) { anongame_infos_URL_destroy(anongame_infos->anongame_infos_URL); xfree((void *) anongame_infos); return NULL; } if (anongame_infos_data_init(anongame_infos) != 0) { anongame_infos_URL_destroy(anongame_infos->anongame_infos_URL); xfree((void *) anongame_infos); return NULL; } anongame_infos->anongame_infos_DESC = NULL; anongame_infos->anongame_infos_DESC_list = list_create(); return anongame_infos; } static int anongame_infos_destroy(t_anongame_infos * anongame_infos) { t_elem *curr; t_anongame_infos_DESC *entry; if (!(anongame_infos)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos"); return -1; } if (anongame_infos->anongame_infos_DESC_list) { LIST_TRAVERSE(anongame_infos->anongame_infos_DESC_list, curr) { if (!(entry = elem_get_data(curr))) eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); else { anongame_infos_DESC_destroy(entry); } list_remove_elem(anongame_infos->anongame_infos_DESC_list, &curr); } list_destroy(anongame_infos->anongame_infos_DESC_list); anongame_infos->anongame_infos_DESC_list = NULL; } anongame_infos_DESC_destroy(anongame_infos->anongame_infos_DESC); anongame_infos_URL_destroy(anongame_infos->anongame_infos_URL); anongame_infos_data_destroy(anongame_infos->anongame_infos_data_war3, anongame_infos->anongame_infos_data_lang_war3); anongame_infos_data_destroy(anongame_infos->anongame_infos_data_w3xp, anongame_infos->anongame_infos_data_lang_w3xp); xfree((void *) anongame_infos); return 0; } static int anongame_infos_set_str(char **dst, char *src, char *errstr) { char *temp; if (!(src)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL %s", errstr); return -1; } temp = xstrdup(src); if (*dst) xfree((void *) *dst); *dst = temp; return 0; } static int anongame_infos_URL_set_URL(int member, char *URL) { char **anongame_infos_URLs; if (!(anongame_infos_URLs = anongame_infos->anongame_infos_URL)) { eventlog(eventlog_level_error, __FUNCTION__, "detected NULL anongame_infos_URL"); return -1; } return anongame_infos_set_str(&anongame_infos_URLs[member], URL, "URL"); } extern char *anongame_infos_URL_get_URL(int member) { char **anongame_infos_URLs; if (!(anongame_infos_URLs = anongame_infos->anongame_infos_URL)) return NULL; else return anongame_infos_URLs[member]; } static int anongame_infos_DESC_set_DESC(t_anongame_infos_DESC * anongame_infos_DESC, int member, char *DESC) { char ** descs; if (!(anongame_infos_DESC)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos_DESC"); return -1; } if (!(descs = anongame_infos_DESC->descs)) { eventlog(eventlog_level_error, __FUNCTION__, "anongame_infos_DESC had NULL descs"); return -1; } return anongame_infos_set_str(&descs[member], DESC, "DESC"); } static t_anongame_infos_DESC *anongame_infos_get_anongame_infos_DESC_by_langID(t_anongame_infos * anongame_infos, char *langID) { t_elem *curr; t_anongame_infos_DESC *entry; if (!(anongame_infos)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos"); return NULL; } if (!(langID)) return anongame_infos->anongame_infos_DESC; if (!(anongame_infos->anongame_infos_DESC_list)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos_DESC_list - default values"); return anongame_infos->anongame_infos_DESC; } LIST_TRAVERSE(anongame_infos->anongame_infos_DESC_list, curr) { if (!(entry = (t_anongame_infos_DESC *) elem_get_data(curr))) eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); else { if ((entry->langID) && (strcmp(entry->langID, langID) == 0)) return entry; } } return anongame_infos->anongame_infos_DESC; } extern char *anongame_infos_DESC_get_DESC(char *langID, int member) { char *result; t_anongame_infos_DESC * DESC; if ((DESC = anongame_infos_get_anongame_infos_DESC_by_langID(anongame_infos, langID))) if ((DESC->descs) && (result = DESC->descs[member])) return result; if ((DESC = anongame_infos->anongame_infos_DESC)) if ((DESC->descs) && (result = DESC->descs[member])) return result; return NULL; } /**********/ extern char *anongame_infos_get_short_desc(char *langID, int queue) { int member = 0; switch (queue) { case ANONGAME_TYPE_1V1: member = gametype_1v1_short; break; case ANONGAME_TYPE_2V2: member = gametype_2v2_short; break; case ANONGAME_TYPE_3V3: member = gametype_3v3_short; break; case ANONGAME_TYPE_4V4: member = gametype_4v4_short; break; case ANONGAME_TYPE_5V5: member = gametype_5v5_short; break; case ANONGAME_TYPE_6V6: member = gametype_6v6_short; break; case ANONGAME_TYPE_2V2V2: member = gametype_2v2v2_short; break; case ANONGAME_TYPE_3V3V3: member = gametype_3v3v3_short; break; case ANONGAME_TYPE_4V4V4: member = gametype_4v4v4_short; break; case ANONGAME_TYPE_2V2V2V2: member = gametype_2v2v2v2_short; break; case ANONGAME_TYPE_3V3V3V3: member = gametype_3v3v3v3_short; break; case ANONGAME_TYPE_SMALL_FFA: member = gametype_sffa_short; break; case ANONGAME_TYPE_TEAM_FFA: member = gametype_tffa_short; break; case ANONGAME_TYPE_AT_2V2: member = gametype_2v2_short; break; case ANONGAME_TYPE_AT_3V3: member = gametype_3v3_short; break; case ANONGAME_TYPE_AT_4V4: member = gametype_4v4_short; break; case ANONGAME_TYPE_AT_2V2V2: member = gametype_2v2v2_short; break; case ANONGAME_TYPE_TY: return tournament_get_format(); default: eventlog(eventlog_level_error, __FUNCTION__, "invalid queue (%d)", queue); return NULL; } return anongame_infos_DESC_get_DESC(langID,member); } extern char *anongame_infos_get_long_desc(char *langID, int queue) { int member = 0; switch (queue) { case ANONGAME_TYPE_1V1: member = gametype_1v1_long; break; case ANONGAME_TYPE_2V2: member = gametype_2v2_long; break; case ANONGAME_TYPE_3V3: member = gametype_3v3_long; break; case ANONGAME_TYPE_4V4: member = gametype_4v4_long; break; case ANONGAME_TYPE_5V5: member = gametype_5v5_long; break; case ANONGAME_TYPE_6V6: member = gametype_6v6_long; break; case ANONGAME_TYPE_2V2V2: member = gametype_2v2v2_long; break; case ANONGAME_TYPE_3V3V3: member = gametype_3v3v3_long; break; case ANONGAME_TYPE_4V4V4: member = gametype_4v4v4_long; break; case ANONGAME_TYPE_2V2V2V2: member = gametype_2v2v2v2_long; break; case ANONGAME_TYPE_3V3V3V3: member = gametype_3v3v3v3_long; break; case ANONGAME_TYPE_SMALL_FFA: member = gametype_sffa_long; break; case ANONGAME_TYPE_TEAM_FFA: member = gametype_tffa_long; break; case ANONGAME_TYPE_AT_2V2: member = gametype_2v2_long; break; case ANONGAME_TYPE_AT_3V3: member = gametype_3v3_long; break; case ANONGAME_TYPE_AT_4V4: member = gametype_4v4_long; break; case ANONGAME_TYPE_AT_2V2V2: member = gametype_2v2v2_long; break; case ANONGAME_TYPE_TY: return tournament_get_sponsor();; default: eventlog(eventlog_level_error, __FUNCTION__, "invalid queue (%d)", queue); return NULL; } return anongame_infos_DESC_get_DESC(langID,member); } /**********/ static int anongame_infos_THUMBSDOWN_set_THUMBSDOWN(char * anongame_infos_THUMBSDOWN, int member, char value) { if (!anongame_infos_THUMBSDOWN) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos_THUMBSDOWN"); return -1; } anongame_infos_THUMBSDOWN[member] = value; return 0; } /**********/ extern char anongame_infos_get_thumbsdown(int queue) { int member = 0; switch (queue) { case ANONGAME_TYPE_1V1: member = PG_1v1; break; case ANONGAME_TYPE_2V2: member = PG_2v2; break; case ANONGAME_TYPE_3V3: member = PG_3v3; break; case ANONGAME_TYPE_4V4: member = PG_4v4; break; case ANONGAME_TYPE_5V5: member = PG_5v5; break; case ANONGAME_TYPE_6V6: member = PG_6v6; break; case ANONGAME_TYPE_2V2V2: member = PG_2v2v2; break; case ANONGAME_TYPE_3V3V3: member = PG_3v3v3; break; case ANONGAME_TYPE_4V4V4: member = PG_4v4v4; break; case ANONGAME_TYPE_2V2V2V2: member = PG_2v2v2v2; break; case ANONGAME_TYPE_3V3V3V3: member = PG_3v3v3v3; break; case ANONGAME_TYPE_SMALL_FFA: member = PG_ffa; break; case ANONGAME_TYPE_TEAM_FFA: member = AT_ffa; break; case ANONGAME_TYPE_AT_2V2: member = AT_2v2; break; case ANONGAME_TYPE_AT_3V3: member = AT_3v3; break; case ANONGAME_TYPE_AT_4V4: member = AT_4v4; break; case ANONGAME_TYPE_AT_2V2V2: member = AT_2v2v2; break; case ANONGAME_TYPE_TY: return tournament_get_thumbs_down(); default: eventlog(eventlog_level_error, __FUNCTION__, "invalid queue (%d)", queue); return 1; } return anongame_infos->anongame_infos_THUMBSDOWN[member]; } /**********/ static int anongame_infos_ICON_REQ_set_REQ(t_anongame_infos * anongame_infos, int member, int value) { int * anongame_infos_ICON_REQ; if (!anongame_infos) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos"); return -1; } anongame_infos_ICON_REQ = anongame_infos->anongame_infos_ICON_REQ; anongame_infos_ICON_REQ[member] = value; return 0; } extern short anongame_infos_get_ICON_REQ(int Level, t_clienttag clienttag) { switch (clienttag) { case CLIENTTAG_WARCRAFT3_UINT: switch (Level) { case 0: return 0; case 1: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_WAR3_Level1]; case 2: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_WAR3_Level2]; case 3: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_WAR3_Level3]; case 4: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_WAR3_Level4]; default: return -1; } case CLIENTTAG_WAR3XP_UINT: switch (Level) { case 0: return 0; case 1: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level1]; case 2: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level2]; case 3: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level3]; case 4: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level4]; case 5: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_W3XP_Level5]; default: return -1; } default: eventlog(eventlog_level_error,__FUNCTION__,"invalid clienttag"); return -1; } } extern short anongame_infos_get_ICON_REQ_TOURNEY(int Level) { switch (Level) { case 0: return 0; case 1: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level1]; case 2: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level2]; case 3: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level3]; case 4: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level4]; case 5: return anongame_infos->anongame_infos_ICON_REQ[ICON_REQ_TRNY_Level5]; default: return -1; } } /**********/ extern char *anongame_infos_data_get_url(t_clienttag clienttag, int versionid, int *len) { if (clienttag==CLIENTTAG_WARCRAFT3_UINT) { if (versionid <= 0x0000000E) { (*len) = anongame_infos->anongame_infos_data_war3->url_comp_len; return anongame_infos->anongame_infos_data_war3->url_comp_data; } else { (*len) = anongame_infos->anongame_infos_data_war3->url_comp_len_115; return anongame_infos->anongame_infos_data_war3->url_comp_data_115; } } else { if (versionid <= 0x0000000E) { (*len) = anongame_infos->anongame_infos_data_w3xp->url_comp_len; return anongame_infos->anongame_infos_data_w3xp->url_comp_data; } else { (*len) = anongame_infos->anongame_infos_data_w3xp->url_comp_len_115; return anongame_infos->anongame_infos_data_w3xp->url_comp_data_115; } } } extern char *anongame_infos_data_get_map(t_clienttag clienttag, int versionid, int *len) { if (clienttag==CLIENTTAG_WARCRAFT3_UINT) { (*len) = anongame_infos->anongame_infos_data_war3->map_comp_len; return anongame_infos->anongame_infos_data_war3->map_comp_data; } else { (*len) = anongame_infos->anongame_infos_data_w3xp->map_comp_len; return anongame_infos->anongame_infos_data_w3xp->map_comp_data; } } extern char *anongame_infos_data_get_type(t_clienttag clienttag, int versionid, int *len) { if (clienttag==CLIENTTAG_WARCRAFT3_UINT) { (*len) = anongame_infos->anongame_infos_data_war3->type_comp_len; return anongame_infos->anongame_infos_data_war3->type_comp_data; } else { (*len) = anongame_infos->anongame_infos_data_w3xp->type_comp_len; return anongame_infos->anongame_infos_data_w3xp->type_comp_data; } } extern char *anongame_infos_data_get_desc(char const *langID, t_clienttag clienttag, int versionid, int *len) { t_elem *curr; t_anongame_infos_data_lang *entry; if (clienttag==CLIENTTAG_WARCRAFT3_UINT) { if (langID != NULL) { LIST_TRAVERSE(anongame_infos->anongame_infos_data_lang_war3, curr) { if ((entry = elem_get_data(curr)) && strcmp(entry->langID, langID) == 0) { (*len) = entry->desc_comp_len; return entry->desc_comp_data; } } } (*len) = anongame_infos->anongame_infos_data_war3->desc_comp_len; return anongame_infos->anongame_infos_data_war3->desc_comp_data; } else { if (langID != NULL) { LIST_TRAVERSE(anongame_infos->anongame_infos_data_lang_w3xp, curr) { if ((entry = elem_get_data(curr)) && strcmp(entry->langID, langID) == 0) { (*len) = entry->desc_comp_len; return entry->desc_comp_data; } } } (*len) = anongame_infos->anongame_infos_data_w3xp->desc_comp_len; return anongame_infos->anongame_infos_data_w3xp->desc_comp_data; } } extern char *anongame_infos_data_get_ladr(char const *langID, t_clienttag clienttag, int versionid, int *len) { t_elem *curr; t_anongame_infos_data_lang *entry; if (clienttag==CLIENTTAG_WARCRAFT3_UINT) { if (langID != NULL) { LIST_TRAVERSE(anongame_infos->anongame_infos_data_lang_war3, curr) { if ((entry = elem_get_data(curr)) && strcmp(entry->langID, langID) == 0) { (*len) = entry->ladr_comp_len; return entry->ladr_comp_data; } } } (*len) = anongame_infos->anongame_infos_data_war3->ladr_comp_len; return anongame_infos->anongame_infos_data_war3->ladr_comp_data; } else { if (langID != NULL) { LIST_TRAVERSE(anongame_infos->anongame_infos_data_lang_w3xp, curr) { if ((entry = elem_get_data(curr)) && strcmp(entry->langID, langID) == 0) { (*len) = entry->ladr_comp_len; return entry->ladr_comp_data; } } } (*len) = anongame_infos->anongame_infos_data_w3xp->ladr_comp_len; return anongame_infos->anongame_infos_data_w3xp->ladr_comp_data; } } /**********/ static void anongame_infos_set_defaults(t_anongame_infos * anongame_infos) { char ** anongame_infos_URL; t_anongame_infos_DESC *anongame_infos_DESC; char ** anongame_infos_DESCs; if (!(anongame_infos)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos"); return; } anongame_infos_URL = anongame_infos->anongame_infos_URL; anongame_infos_DESC = anongame_infos->anongame_infos_DESC; if (!(anongame_infos_URL)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos_URL, trying to init"); if (anongame_infos_URL_init(anongame_infos) != 0) { eventlog(eventlog_level_error, __FUNCTION__, "failed to init... PANIC!"); return; } } if (!(anongame_infos_DESC)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame_infos_DESC, trying to init"); if (!(anongame_infos_DESC = anongame_infos_DESC_init())) { eventlog(eventlog_level_error, __FUNCTION__, "failed to init... PANIC!"); return; } else anongame_infos->anongame_infos_DESC = anongame_infos_DESC; } // now set default values if (!(anongame_infos_URL[URL_server])) anongame_infos_URL_set_URL(URL_server, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_player])) anongame_infos_URL_set_URL(URL_player, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_tourney])) anongame_infos_URL_set_URL(URL_tourney, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_clan])) anongame_infos_URL_set_URL(URL_clan, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_PG_1v1])) anongame_infos_URL_set_URL(URL_ladder_PG_1v1, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_PG_ffa])) anongame_infos_URL_set_URL(URL_ladder_PG_ffa, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_PG_team])) anongame_infos_URL_set_URL(URL_ladder_PG_team, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_AT_2v2])) anongame_infos_URL_set_URL(URL_ladder_AT_2v2, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_AT_3v3])) anongame_infos_URL_set_URL(URL_ladder_AT_3v3, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_AT_4v4])) anongame_infos_URL_set_URL(URL_ladder_AT_4v4, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_clan_1v1])) anongame_infos_URL_set_URL(URL_ladder_clan_1v1, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_clan_2v2])) anongame_infos_URL_set_URL(URL_ladder_clan_2v2, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_clan_3v3])) anongame_infos_URL_set_URL(URL_ladder_clan_3v3, PVPGN_DEFAULT_URL); if (!(anongame_infos_URL[URL_ladder_clan_4v4])) anongame_infos_URL_set_URL(URL_ladder_clan_4v4, PVPGN_DEFAULT_URL); if (!(anongame_infos_DESCs = anongame_infos_DESC->descs)) return; if (!(anongame_infos_DESCs[ladder_PG_1v1_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_PG_1v1_desc, PVPGN_PG_1V1_DESC); if (!(anongame_infos_DESCs[ladder_PG_ffa_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_PG_ffa_desc, PVPGN_PG_FFA_DESC); if (!(anongame_infos_DESCs[ladder_PG_team_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_PG_team_desc, PVPGN_PG_TEAM_DESC); if (!(anongame_infos_DESCs[ladder_AT_2v2_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_AT_2v2_desc, PVPGN_AT_2V2_DESC); if (!(anongame_infos_DESCs[ladder_AT_3v3_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_AT_3v3_desc, PVPGN_AT_3V3_DESC); if (!(anongame_infos_DESCs[ladder_AT_4v4_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_AT_4v4_desc, PVPGN_AT_4V4_DESC); if (!(anongame_infos_DESCs[ladder_clan_1v1_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_clan_1v1_desc, PVPGN_CLAN_1V1_DESC); if (!(anongame_infos_DESCs[ladder_clan_2v2_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_clan_2v2_desc, PVPGN_CLAN_2V2_DESC); if (!(anongame_infos_DESCs[ladder_clan_3v3_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_clan_3v3_desc, PVPGN_CLAN_3V3_DESC); if (!(anongame_infos_DESCs[ladder_clan_4v4_desc])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, ladder_clan_4v4_desc, PVPGN_CLAN_4V4_DESC); if (!(anongame_infos_DESCs[gametype_1v1_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_1v1_short, PVPGN_1V1_GT_DESC); if (!(anongame_infos_DESCs[gametype_1v1_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_1v1_long, PVPGN_1V1_GT_LONG); if (!(anongame_infos_DESCs[gametype_2v2_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_2v2_short, PVPGN_2V2_GT_DESC); if (!(anongame_infos_DESCs[gametype_2v2_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_2v2_long, PVPGN_2V2_GT_LONG); if (!(anongame_infos_DESCs[gametype_3v3_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_3v3_short, PVPGN_3V3_GT_DESC); if (!(anongame_infos_DESCs[gametype_3v3_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_3v3_long, PVPGN_3V3_GT_LONG); if (!(anongame_infos_DESCs[gametype_4v4_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_4v4_short, PVPGN_4V4_GT_DESC); if (!(anongame_infos_DESCs[gametype_4v4_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_4v4_long, PVPGN_4V4_GT_LONG); if (!(anongame_infos_DESCs[gametype_sffa_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_sffa_short, PVPGN_SFFA_GT_DESC); if (!(anongame_infos_DESCs[gametype_sffa_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_sffa_long, PVPGN_SFFA_GT_LONG); if (!(anongame_infos_DESCs[gametype_tffa_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_tffa_short, PVPGN_TFFA_GT_DESC); if (!(anongame_infos_DESCs[gametype_tffa_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_tffa_long, PVPGN_TFFA_GT_LONG); if (!(anongame_infos_DESCs[gametype_2v2v2_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_2v2v2_short, PVPGN_2V2V2_GT_DESC); if (!(anongame_infos_DESCs[gametype_2v2v2_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_2v2v2_long, PVPGN_2V2V2_GT_LONG); if (!(anongame_infos_DESCs[gametype_3v3v3_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_3v3v3_short, PVPGN_3V3V3_GT_DESC); if (!(anongame_infos_DESCs[gametype_3v3v3_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_3v3v3_long, PVPGN_3V3V3_GT_LONG); if (!(anongame_infos_DESCs[gametype_4v4v4_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_4v4v4_short, PVPGN_4V4V4_GT_DESC); if (!(anongame_infos_DESCs[gametype_4v4v4_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_4v4v4_long, PVPGN_4V4V4_GT_LONG); if (!(anongame_infos_DESCs[gametype_2v2v2v2_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_2v2v2v2_short, PVPGN_2V2V2V2_GT_DESC); if (!(anongame_infos_DESCs[gametype_2v2v2v2_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_2v2v2v2_long, PVPGN_2V2V2V2_GT_LONG); if (!(anongame_infos_DESCs[gametype_3v3v3v3_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_3v3v3v3_short, PVPGN_3V3V3V3_GT_DESC); if (!(anongame_infos_DESCs[gametype_3v3v3v3_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_3v3v3v3_long, PVPGN_3V3V3V3_GT_LONG); if (!(anongame_infos_DESCs[gametype_5v5_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_5v5_short, PVPGN_5V5_GT_DESC); if (!(anongame_infos_DESCs[gametype_5v5_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_5v5_long, PVPGN_5V5_GT_LONG); if (!(anongame_infos_DESCs[gametype_6v6_short])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_6v6_short, PVPGN_6V6_GT_DESC); if (!(anongame_infos_DESCs[gametype_6v6_long])) anongame_infos_DESC_set_DESC(anongame_infos_DESC, gametype_6v6_long, PVPGN_6V6_GT_LONG); } typedef struct { const char *anongame_infos_URL_string; int member; } t_anongame_infos_URL_table_row; typedef struct { const char *anongame_infos_DESC_string; int member; } t_anongame_infos_DESC_table_row; typedef struct { const char *anongame_infos_THUMBSDOWN_string; int member; } t_anongame_infos_THUMBSDOWN_table_row; typedef struct { const char *anongame_infos_ICON_REQ_WAR3_string; int member; } t_anongame_infos_ICON_REQ_WAR3_table_row; typedef struct { const char *anongame_infos_ICON_REQ_W3XP_string; int member; } t_anongame_infos_ICON_REQ_W3XP_table_row; typedef struct { const char *anongame_infos_ICON_REQ_TOURNEY_string; int member; } t_anongame_infos_ICON_REQ_TOURNEY_table_row; static const t_anongame_infos_URL_table_row URL_handler_table[] = { {"server_URL", URL_server}, {"player_URL", URL_player}, {"tourney_URL", URL_tourney}, {"clan_URL", URL_clan}, {"ladder_PG_1v1_URL", URL_ladder_PG_1v1}, {"ladder_PG_ffa_URL", URL_ladder_PG_ffa}, {"ladder_PG_team_URL", URL_ladder_PG_team}, {"ladder_AT_2v2_URL", URL_ladder_AT_2v2}, {"ladder_AT_3v3_URL", URL_ladder_AT_3v3}, {"ladder_AT_4v4_URL", URL_ladder_AT_4v4}, {"ladder_clan_1v1_URL", URL_ladder_clan_1v1}, {"ladder_clan_2v2_URL", URL_ladder_clan_2v2}, {"ladder_clan_3v3_URL", URL_ladder_clan_3v3}, {"ladder_clan_4v4_URL", URL_ladder_clan_4v4}, {NULL, -1} }; static const t_anongame_infos_DESC_table_row DESC_handler_table[] = { {"ladder_PG_1v1_desc", ladder_PG_1v1_desc}, {"ladder_PG_ffa_desc", ladder_PG_ffa_desc}, {"ladder_PG_team_desc", ladder_PG_team_desc}, {"ladder_AT_2v2_desc", ladder_AT_2v2_desc}, {"ladder_AT_3v3_desc", ladder_AT_3v3_desc}, {"ladder_AT_4v4_desc", ladder_AT_4v4_desc}, {"ladder_clan_1v1_desc", ladder_clan_1v1_desc}, {"ladder_clan_2v2_desc", ladder_clan_2v2_desc}, {"ladder_clan_3v3_desc", ladder_clan_3v3_desc}, {"ladder_clan_4v4_desc", ladder_clan_4v4_desc}, {"gametype_1v1_short", gametype_1v1_short}, {"gametype_1v1_long", gametype_1v1_long}, {"gametype_2v2_short", gametype_2v2_short}, {"gametype_2v2_long", gametype_2v2_long}, {"gametype_3v3_short", gametype_3v3_short}, {"gametype_3v3_long", gametype_3v3_long}, {"gametype_4v4_short", gametype_4v4_short}, {"gametype_4v4_long", gametype_4v4_long}, {"gametype_sffa_short", gametype_sffa_short}, {"gametype_sffa_long", gametype_sffa_long}, {"gametype_tffa_short", gametype_tffa_short}, {"gametype_tffa_long", gametype_tffa_long}, {"gametype_2v2v2_short", gametype_2v2v2_short}, {"gametype_2v2v2_long", gametype_2v2v2_long}, {"gametype_3v3v3_short", gametype_3v3v3_short}, {"gametype_3v3v3_long", gametype_3v3v3_long}, {"gametype_4v4v4_short", gametype_4v4v4_short}, {"gametype_4v4v4_long", gametype_4v4v4_long}, {"gametype_2v2v2v2_short", gametype_2v2v2v2_short}, {"gametype_2v2v2v2_long", gametype_2v2v2v2_long}, {"gametype_3v3v3v3_short", gametype_3v3v3v3_short}, {"gametype_3v3v3v3_long", gametype_3v3v3v3_long}, {"gametype_5v5_short", gametype_5v5_short}, {"gametype_5v5_long", gametype_5v5_long}, {"gametype_6v6_short", gametype_6v6_short}, {"gametype_6v6_long", gametype_6v6_long}, {NULL, -1} }; static const t_anongame_infos_THUMBSDOWN_table_row THUMBSDOWN_handler_table[] = { {"PG_1v1", PG_1v1}, {"PG_2v2", PG_2v2}, {"PG_3v3", PG_3v3}, {"PG_4v4", PG_4v4}, {"PG_ffa", PG_ffa}, {"AT_2v2", AT_2v2}, {"AT_3v3", AT_3v3}, {"AT_4v4", AT_4v4}, {"AT_ffa", AT_ffa}, {"PG_5v5", PG_5v5}, {"PG_6v6", PG_6v6}, {"PG_2v2v2", PG_2v2v2}, {"PG_3v3v3", PG_3v3v3}, {"PG_4v4v4", PG_4v4v4}, {"PG_2v2v2v2", PG_2v2v2v2}, {"PG_3v3v3v3", PG_3v3v3v3}, {"AT_2v2v2", AT_2v2v2}, {NULL, -1} }; static const t_anongame_infos_ICON_REQ_WAR3_table_row ICON_REQ_WAR3_handler_table[] = { {"Level1", ICON_REQ_WAR3_Level1}, {"Level2", ICON_REQ_WAR3_Level2}, {"Level3", ICON_REQ_WAR3_Level3}, {"Level4", ICON_REQ_WAR3_Level4}, {NULL, -1} }; static const t_anongame_infos_ICON_REQ_W3XP_table_row ICON_REQ_W3XP_handler_table[] = { {"Level1", ICON_REQ_W3XP_Level1}, {"Level2", ICON_REQ_W3XP_Level2}, {"Level3", ICON_REQ_W3XP_Level3}, {"Level4", ICON_REQ_W3XP_Level4}, {"Level5", ICON_REQ_W3XP_Level5}, {NULL, -1} }; static const t_anongame_infos_ICON_REQ_TOURNEY_table_row ICON_REQ_TOURNEY_handler_table[] = { {"Level1", ICON_REQ_TRNY_Level1}, {"Level2", ICON_REQ_TRNY_Level2}, {"Level3", ICON_REQ_TRNY_Level3}, {"Level4", ICON_REQ_TRNY_Level4}, {"Level5", ICON_REQ_TRNY_Level5}, {NULL, -1} }; typedef enum { parse_UNKNOWN, parse_URL, parse_DESC, parse_THUMBSDOWN, parse_ICON_REQ_WAR3, parse_ICON_REQ_W3XP, parse_ICON_REQ_TOURNEY } t_parse_mode; typedef enum { changed, unchanged } t_parse_state; static t_parse_mode switch_parse_mode(char *text, char *langID) { if (!(text)) return parse_UNKNOWN; else if (strcmp(text, "[URL]") == 0) return parse_URL; else if (strcmp(text, "[THUMBS_DOWN_LIMIT]") == 0) return parse_THUMBSDOWN; else if (strcmp(text, "[ICON_REQUIRED_RACE_WINS_WAR3]") == 0) return parse_ICON_REQ_WAR3; else if (strcmp(text, "[ICON_REQUIRED_RACE_WINS_W3XP]") == 0) return parse_ICON_REQ_W3XP; else if (strcmp(text, "[ICON_REQUIRED_TOURNEY_WINS]") == 0) return parse_ICON_REQ_TOURNEY; else if (strcmp(text, "[DEFAULT_DESC]") == 0) { langID[0] = '\0'; return parse_DESC; } else if (strlen(text) == 6) { strncpy(langID, &(text[1]), 4); langID[4] = '\0'; return parse_DESC; } else eventlog(eventlog_level_error, __FUNCTION__, "got invalid section name: %s", text); return parse_UNKNOWN; } extern int anongame_infos_load(char const *filename) { unsigned int line; unsigned int pos; char *buff; char *temp; char langID[5]; t_parse_mode parse_mode = parse_UNKNOWN; t_parse_state parse_state = unchanged; t_anongame_infos_DESC *anongame_infos_DESC = NULL; char *pointer; char *variable; char *value = NULL; t_anongame_infos_DESC_table_row const *DESC_table_row; t_anongame_infos_URL_table_row const *URL_table_row; t_anongame_infos_THUMBSDOWN_table_row const *THUMBSDOWN_table_row; t_anongame_infos_ICON_REQ_WAR3_table_row const *ICON_REQ_WAR3_table_row; t_anongame_infos_ICON_REQ_W3XP_table_row const *ICON_REQ_W3XP_table_row; t_anongame_infos_ICON_REQ_TOURNEY_table_row const *ICON_REQ_TOURNEY_table_row; int int_value; char char_value; langID[0] = '\0'; if (!filename) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL filename"); return -1; } if (!(anongame_infos = anongame_infos_init())) { eventlog(eventlog_level_error, __FUNCTION__, "could not init anongame_infos"); return -1; } if (!(fp = fopen(filename, "r"))) { eventlog(eventlog_level_error, "anongameinfo_load", "could not open file \"%s\" for reading (fopen: %s), using default values", filename, pstrerror(errno)); goto anongame_infos_loading_failure; } for (line = 1; (buff = file_get_line(fp)); line++) { for (pos = 0; buff[pos] == '\t' || buff[pos] == ' '; pos++); if (buff[pos] == '\0' || buff[pos] == '#') { continue; } if ((temp = strrchr(buff, '#'))) { unsigned int len; unsigned int endpos; *temp = '\0'; len = strlen(buff) + 1; for (endpos = len - 1; buff[endpos] == '\t' || buff[endpos] == ' '; endpos--); buff[endpos + 1] = '\0'; } if ((buff[0] == '[') && (buff[strlen(buff) - 1] == ']')) { if ((parse_state == unchanged) && (anongame_infos_DESC != NULL)) { if (langID[0] != '\0') list_append_data(anongame_infos->anongame_infos_DESC_list, anongame_infos_DESC); else { if (anongame_infos->anongame_infos_DESC == NULL) anongame_infos->anongame_infos_DESC = anongame_infos_DESC; else { eventlog(eventlog_level_error, __FUNCTION__, "found another default_DESC block, deleting previous"); anongame_infos_DESC_destroy(anongame_infos->anongame_infos_DESC); anongame_infos->anongame_infos_DESC = anongame_infos_DESC; } } anongame_infos_DESC = NULL; } parse_mode = switch_parse_mode(buff, langID); parse_state = changed; } else if (buff[0] != '\0') switch (parse_mode) { case parse_UNKNOWN: { if ((buff[0] != '[') || (buff[strlen(buff) - 1] != ']')) { eventlog(eventlog_level_error, __FUNCTION__, "expected [] section start, but found %s on line %u", buff, line); } else { parse_mode = switch_parse_mode(buff, langID); parse_state = changed; } break; } case parse_URL: { parse_state = unchanged; variable = buff; pointer = strchr(variable, '='); for (pointer--; pointer[0] == ' '; pointer--); pointer[1] = '\0'; pointer++; pointer++; pointer = strchr(pointer, '\"'); pointer++; value = pointer; pointer = strchr(pointer, '\"'); pointer[0] = '\0'; for (URL_table_row = URL_handler_table; URL_table_row->anongame_infos_URL_string != NULL; URL_table_row++) if (strcmp(URL_table_row->anongame_infos_URL_string, variable) == 0) { if (URL_table_row->member != -1) anongame_infos_URL_set_URL(URL_table_row->member, value); } break; } case parse_DESC: { if (parse_state == changed) { anongame_infos_DESC = anongame_infos_DESC_init(); parse_state = unchanged; eventlog(eventlog_level_info, __FUNCTION__, "got langID: [%s]", langID); if (langID[0] != '\0') anongame_infos_DESC->langID = xstrdup(langID); } variable = buff; pointer = strchr(variable, '='); for (pointer--; pointer[0] == ' '; pointer--); pointer[1] = '\0'; pointer++; pointer++; pointer = strchr(pointer, '\"'); pointer++; value = pointer; pointer = strchr(pointer, '\"'); pointer[0] = '\0'; for (DESC_table_row = DESC_handler_table; DESC_table_row->anongame_infos_DESC_string != NULL; DESC_table_row++) if (strcmp(DESC_table_row->anongame_infos_DESC_string, variable) == 0) { if (DESC_table_row->member != -1) anongame_infos_DESC_set_DESC(anongame_infos_DESC, DESC_table_row->member, value); } break; } case parse_THUMBSDOWN: { parse_state = unchanged; variable = buff; pointer = strchr(variable, '='); for (pointer--; pointer[0] == ' '; pointer--); pointer[1] = '\0'; pointer++; pointer++; pointer = strchr(pointer, '='); pointer++; int_value = atoi(pointer); if (int_value < 0) int_value = 0; if (int_value > 127) int_value = 127; char_value = (char) int_value; for (THUMBSDOWN_table_row = THUMBSDOWN_handler_table; THUMBSDOWN_table_row->anongame_infos_THUMBSDOWN_string != NULL; THUMBSDOWN_table_row++) if (strcmp(THUMBSDOWN_table_row->anongame_infos_THUMBSDOWN_string, variable) == 0) { if (THUMBSDOWN_table_row->member != -1) anongame_infos_THUMBSDOWN_set_THUMBSDOWN(anongame_infos->anongame_infos_THUMBSDOWN, THUMBSDOWN_table_row->member,char_value); } break; } case parse_ICON_REQ_WAR3: { parse_state = unchanged; variable = buff; pointer = strchr(variable, '='); for (pointer--; pointer[0] == ' '; pointer--); pointer[1] = '\0'; pointer++; pointer++; pointer = strchr(pointer, '='); pointer++; int_value = atoi(pointer); if (int_value < 0) int_value = 0; for (ICON_REQ_WAR3_table_row = ICON_REQ_WAR3_handler_table; ICON_REQ_WAR3_table_row->anongame_infos_ICON_REQ_WAR3_string != NULL; ICON_REQ_WAR3_table_row++) if (strcmp(ICON_REQ_WAR3_table_row->anongame_infos_ICON_REQ_WAR3_string, variable) == 0) { if (ICON_REQ_WAR3_table_row->member != -1) anongame_infos_ICON_REQ_set_REQ(anongame_infos,ICON_REQ_WAR3_table_row->member,int_value); } break; } case parse_ICON_REQ_W3XP: { parse_state = unchanged; variable = buff; pointer = strchr(variable, '='); for (pointer--; pointer[0] == ' '; pointer--); pointer[1] = '\0'; pointer++; pointer++; pointer = strchr(pointer, '='); pointer++; int_value = atoi(pointer); if (int_value < 0) int_value = 0; for (ICON_REQ_W3XP_table_row = ICON_REQ_W3XP_handler_table; ICON_REQ_W3XP_table_row->anongame_infos_ICON_REQ_W3XP_string != NULL; ICON_REQ_W3XP_table_row++) if (strcmp(ICON_REQ_W3XP_table_row->anongame_infos_ICON_REQ_W3XP_string, variable) == 0) { if (ICON_REQ_W3XP_table_row->member != -1) anongame_infos_ICON_REQ_set_REQ(anongame_infos,ICON_REQ_W3XP_table_row->member,int_value); } break; } case parse_ICON_REQ_TOURNEY: { parse_state = unchanged; variable = buff; pointer = strchr(variable, '='); for (pointer--; pointer[0] == ' '; pointer--); pointer[1] = '\0'; pointer++; pointer++; pointer = strchr(pointer, '='); pointer++; int_value = atoi(pointer); if (int_value < 0) int_value = 0; for (ICON_REQ_TOURNEY_table_row = ICON_REQ_TOURNEY_handler_table; ICON_REQ_TOURNEY_table_row->anongame_infos_ICON_REQ_TOURNEY_string != NULL; ICON_REQ_TOURNEY_table_row++) if (strcmp(ICON_REQ_TOURNEY_table_row->anongame_infos_ICON_REQ_TOURNEY_string, variable) == 0) { if (ICON_REQ_TOURNEY_table_row->member != -1) anongame_infos_ICON_REQ_set_REQ(anongame_infos,ICON_REQ_TOURNEY_table_row->member,int_value); } break; } } } if (anongame_infos_DESC) { if (langID[0] != '\0') { list_append_data(anongame_infos->anongame_infos_DESC_list, anongame_infos_DESC); } else { if (anongame_infos->anongame_infos_DESC == NULL) anongame_infos->anongame_infos_DESC = anongame_infos_DESC; else { eventlog(eventlog_level_error, __FUNCTION__, "found another default_DESC block, deleting previous"); anongame_infos_DESC_destroy(anongame_infos->anongame_infos_DESC); anongame_infos->anongame_infos_DESC = anongame_infos_DESC; } } } file_get_line(NULL); // clear file_get_line buffer fclose(fp); anongame_infos_loading_failure: anongame_infos_set_defaults(anongame_infos); anongame_infos_data_load(); return 0; } static int anongame_infos_data_load(void) { t_elem *curr; t_packet *raw; int j, k, size; char ladr_count = 0; char desc_count; char mapscount_total; char value; char PG_gamestyles; char AT_gamestyles; char TY_gamestyles; char anongame_prefix[ANONGAME_TYPES][5] = { /* queue */ /* PG 1v1 */ {0x00, 0x00, 0x03, 0x3F, 0x00}, /* 0 */ /* PG 2v2 */ {0x01, 0x00, 0x02, 0x3F, 0x00}, /* 1 */ /* PG 3v3 */ {0x02, 0x00, 0x01, 0x3F, 0x00}, /* 2 */ /* PG 4v4 */ {0x03, 0x00, 0x01, 0x3F, 0x00}, /* 3 */ /* PG sffa */ {0x04, 0x00, 0x02, 0x3F, 0x00}, /* 4 */ /* AT 2v2 */ {0x00, 0x00, 0x02, 0x3F, 0x02}, /* 5 */ /* AT tffa */ {0x01, 0x00, 0x02, 0x3F, 0x02}, /* 6 */ /* AT 3v3 */ {0x02, 0x00, 0x02, 0x3F, 0x03}, /* 7 */ /* AT 4v4 */ {0x03, 0x00, 0x02, 0x3F, 0x04}, /* 8 */ /* TY */ {0x00, 0x01, 0x00, 0x3F, 0x00}, /* 9 */ /* PG 5v5 */ {0x05, 0x00, 0x01, 0x3F, 0x00}, /* 10 */ /* PG 6v6 */ {0x06, 0x00, 0x01, 0x3F, 0x00}, /* 11 */ /* PG 2v2v2 */ {0x07, 0x00, 0x01, 0x3F, 0x00}, /* 12 */ /* PG 3v3v3 */ {0x08, 0x00, 0x01, 0x3F, 0x00}, /* 13 */ /* PG 4v4v4 */ {0x09, 0x00, 0x01, 0x3F, 0x00}, /* 14 */ /* PG 2v2v2v2 */ {0x0A, 0x00, 0x01, 0x3F, 0x00}, /* 15 */ /* PG 3v3v3v3 */ {0x0B, 0x00, 0x01, 0x3F, 0x00}, /* 16 */ /* AT 2v2v2 */ {0x04, 0x00, 0x02, 0x3F, 0x02} /* 17 */ }; /* hack to give names for new gametypes untill there added to anongame_infos.c */ char *anongame_gametype_names[ANONGAME_TYPES] = { "One vs. One", "Two vs. Two", "Three vs. Three", "Four vs. Four", "Small Free for All", "Two vs. Two", "Team Free for All", "Three vs. Three", "Four vs. Four", "Tournament Game", "Five vs. Five", "Six Vs. Six", "Two vs. Two vs. Two", "3 vs. 3 vs. 3", "4 vs. 4 vs. 4", "2 vs. 2 vs. 2 vs. 2", "3 vs. 3 vs. 3 vs. 3", "Two vs. Two vs. Two" }; t_clienttag game_clienttag[2] = { CLIENTTAG_WARCRAFT3_UINT, CLIENTTAG_WAR3XP_UINT }; char anongame_PG_section = 0x00; char anongame_AT_section = 0x01; char anongame_TY_section = 0x02; /* set thumbsdown from the conf file */ for (j = 0; j < ANONGAME_TYPES; j++) anongame_prefix[j][2] = anongame_infos_get_thumbsdown(j); if ((raw = packet_create(packet_class_raw)) != NULL) { // assemble URL part with 3 URLs ( <1.15 ) packet_append_string(raw, anongame_infos_URL_get_URL(URL_server)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_player)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_tourney)); size = packet_get_size(raw); // create compressed data zlib_compress(packet_get_data_const(raw, 0, size), size, &anongame_infos->anongame_infos_data_war3->url_comp_data, &anongame_infos->anongame_infos_data_war3->url_comp_len); zlib_compress(packet_get_data_const(raw, 0, size), size, &anongame_infos->anongame_infos_data_w3xp->url_comp_data, &anongame_infos->anongame_infos_data_w3xp->url_comp_len); // append 4th URL for >= 1.15 clients packet_append_string(raw, anongame_infos_URL_get_URL(URL_clan)); size = packet_get_size(raw); zlib_compress(packet_get_data_const(raw, 0, size), size, &anongame_infos->anongame_infos_data_war3->url_comp_data_115, &anongame_infos->anongame_infos_data_war3->url_comp_len_115); zlib_compress(packet_get_data_const(raw, 0, size), size, &anongame_infos->anongame_infos_data_w3xp->url_comp_data_115, &anongame_infos->anongame_infos_data_w3xp->url_comp_len_115); for (k = 0; k < 2; k++) { packet_set_size(raw, 0); mapscount_total = maplists_get_totalmaps(game_clienttag[k]); packet_append_data(raw, &mapscount_total, 1); maplists_add_maps_to_packet(raw, game_clienttag[k]); size = packet_get_size(raw); if (k == 0) zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos->anongame_infos_data_war3->map_comp_data, &anongame_infos->anongame_infos_data_war3->map_comp_len); else zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos->anongame_infos_data_w3xp->map_comp_data, &anongame_infos->anongame_infos_data_w3xp->map_comp_len); } for (k = 0; k < 2; k++) { packet_set_size(raw, 0); value = 0; PG_gamestyles = 0; AT_gamestyles = 0; TY_gamestyles = 0; /* count of gametypes (PG, AT, TY) */ for (j = 0; j < ANONGAME_TYPES; j++) if (maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { if (!anongame_prefix[j][1] && !anongame_prefix[j][4]) PG_gamestyles++; if (!anongame_prefix[j][1] && anongame_prefix[j][4]) AT_gamestyles++; if (anongame_prefix[j][1]) TY_gamestyles++; } if (PG_gamestyles) value++; if (AT_gamestyles) value++; if (TY_gamestyles) value++; packet_append_data(raw, &value, 1); /* PG */ if (PG_gamestyles) { packet_append_data(raw, &anongame_PG_section, 1); packet_append_data(raw, &PG_gamestyles, 1); for (j = 0; j < ANONGAME_TYPES; j++) if (!anongame_prefix[j][1] && !anongame_prefix[j][4] && maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { packet_append_data(raw, &anongame_prefix[j], 5); maplists_add_map_info_to_packet(raw, game_clienttag[k], j); } } /* AT */ if (AT_gamestyles) { packet_append_data(raw, &anongame_AT_section, 1); packet_append_data(raw, &AT_gamestyles, 1); for (j = 0; j < ANONGAME_TYPES; j++) if (!anongame_prefix[j][1] && anongame_prefix[j][4] && maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { packet_append_data(raw, &anongame_prefix[j], 5); maplists_add_map_info_to_packet(raw, game_clienttag[k], j); } } /* TY */ if (TY_gamestyles) { packet_append_data(raw, &anongame_TY_section, 1); packet_append_data(raw, &TY_gamestyles, 1); for (j = 0; j < ANONGAME_TYPES; j++) if (anongame_prefix[j][1] && maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { /* set tournament races available */ anongame_prefix[j][3] = tournament_get_races(); /* set tournament type (PG or AT) * PG = 0 * AT = number players per team */ if (tournament_is_arranged()) anongame_prefix[j][4] = tournament_get_game_type(); else anongame_prefix[j][4] = 0; packet_append_data(raw, &anongame_prefix[j], 5); maplists_add_map_info_to_packet(raw, game_clienttag[k], j); } } size = packet_get_size(raw); if (k == 0) zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos->anongame_infos_data_war3->type_comp_data, &anongame_infos->anongame_infos_data_war3->type_comp_len); else zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos->anongame_infos_data_w3xp->type_comp_data, &anongame_infos->anongame_infos_data_w3xp->type_comp_len); } for (k = 0; k < 2; k++) { desc_count = 0; packet_set_size(raw, 0); for (j = 0; j < ANONGAME_TYPES; j++) if (maplists_get_totalmaps_by_queue(game_clienttag[k], j)) desc_count++; packet_append_data(raw, &desc_count, 1); /* PG description section */ for (j = 0; j < ANONGAME_TYPES; j++) if (!anongame_prefix[j][1] && !anongame_prefix[j][4] && maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { packet_append_data(raw, &anongame_PG_section, 1); packet_append_data(raw, &anongame_prefix[j][0], 1); if (anongame_infos_get_short_desc(NULL, j) == NULL) packet_append_string(raw, anongame_gametype_names[j]); else packet_append_string(raw, anongame_infos_get_short_desc(NULL, j)); if (anongame_infos_get_long_desc(NULL, j) == NULL) packet_append_string(raw, "No Descreption"); else packet_append_string(raw, anongame_infos_get_long_desc(NULL, j)); } /* AT description section */ for (j = 0; j < ANONGAME_TYPES; j++) if (!anongame_prefix[j][1] && anongame_prefix[j][4] && maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { packet_append_data(raw, &anongame_AT_section, 1); packet_append_data(raw, &anongame_prefix[j][0], 1); packet_append_string(raw, anongame_infos_get_short_desc(NULL, j)); packet_append_string(raw, anongame_infos_get_long_desc(NULL, j)); } /* TY description section */ for (j = 0; j < ANONGAME_TYPES; j++) if (anongame_prefix[j][1] && maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { packet_append_data(raw, &anongame_TY_section, 1); packet_append_data(raw, &anongame_prefix[j][0], 1); packet_append_string(raw, anongame_infos_get_short_desc(NULL, j)); packet_append_string(raw, anongame_infos_get_long_desc(NULL, j)); } size = packet_get_size(raw); if (k == 0) zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos->anongame_infos_data_war3->desc_comp_data, &anongame_infos->anongame_infos_data_war3->desc_comp_len); else zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos->anongame_infos_data_w3xp->desc_comp_data, &anongame_infos->anongame_infos_data_w3xp->desc_comp_len); } packet_set_size(raw, 0); /*FIXME: Still adding a static number (10) Also maybe need do do some checks to avoid prefs empty strings. */ ladr_count = 10; packet_append_data(raw, &ladr_count, 1); packet_append_data(raw, "OLOS", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_PG_1v1_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_PG_1v1)); packet_append_data(raw, "MAET", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_PG_team_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_PG_team)); packet_append_data(raw, " AFF", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_PG_ffa_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_PG_ffa)); packet_append_data(raw, "2SV2", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_AT_2v2_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_AT_2v2)); packet_append_data(raw, "3SV3", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_AT_3v3_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_AT_3v3)); packet_append_data(raw, "4SV4", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_AT_4v4_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_AT_4v4)); packet_append_data(raw, "SNLC", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_clan_1v1_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_clan_1v1)); packet_append_data(raw, "2NLC", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_clan_2v2_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_clan_2v2)); packet_append_data(raw, "3NLC", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_clan_3v3_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_clan_3v3)); packet_append_data(raw, "4NLC", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(NULL,ladder_clan_4v4_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_clan_4v4)); size = packet_get_size(raw); zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos->anongame_infos_data_war3->ladr_comp_data, &anongame_infos->anongame_infos_data_war3->ladr_comp_len); zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos->anongame_infos_data_w3xp->ladr_comp_data, &anongame_infos->anongame_infos_data_w3xp->ladr_comp_len); packet_destroy(raw); } if ((raw = packet_create(packet_class_raw)) != NULL) { t_anongame_infos_DESC *anongame_infos_DESC; t_anongame_infos_data_lang *anongame_infos_data_lang_war3; t_anongame_infos_data_lang *anongame_infos_data_lang_w3xp; char * langID; LIST_TRAVERSE(anongame_infos->anongame_infos_DESC_list, curr) { anongame_infos_DESC = elem_get_data(curr); langID = anongame_infos_DESC->langID; anongame_infos_data_lang_war3 = anongame_infos_data_lang_init(langID); anongame_infos_data_lang_w3xp = anongame_infos_data_lang_init(langID); for (k = 0; k < 2; k++) { desc_count = 0; packet_set_size(raw, 0); for (j = 0; j < ANONGAME_TYPES; j++) if (maplists_get_totalmaps_by_queue(game_clienttag[k], j)) desc_count++; packet_append_data(raw, &desc_count, 1); /* PG description section */ for (j = 0; j < ANONGAME_TYPES; j++) if (!anongame_prefix[j][1] && !anongame_prefix[j][4] && maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { packet_append_data(raw, &anongame_PG_section, 1); packet_append_data(raw, &anongame_prefix[j][0], 1); if (anongame_infos_get_short_desc(langID, j) == NULL) packet_append_string(raw, anongame_gametype_names[j]); else packet_append_string(raw, anongame_infos_get_short_desc(langID, j)); if (anongame_infos_get_long_desc(langID, j) == NULL) packet_append_string(raw, "No Descreption"); else packet_append_string(raw, anongame_infos_get_long_desc(langID, j)); } /* AT description section */ for (j = 0; j < ANONGAME_TYPES; j++) if (!anongame_prefix[j][1] && anongame_prefix[j][4] && maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { packet_append_data(raw, &anongame_AT_section, 1); packet_append_data(raw, &anongame_prefix[j][0], 1); packet_append_string(raw, anongame_infos_get_short_desc(langID, j)); packet_append_string(raw, anongame_infos_get_long_desc(langID, j)); } /* TY description section */ for (j = 0; j < ANONGAME_TYPES; j++) if (anongame_prefix[j][1] && maplists_get_totalmaps_by_queue(game_clienttag[k], j)) { packet_append_data(raw, &anongame_TY_section, 1); packet_append_data(raw, &anongame_prefix[j][0], 1); packet_append_string(raw, anongame_infos_get_short_desc(langID, j)); packet_append_string(raw, anongame_infos_get_long_desc(langID, j)); } size = packet_get_size(raw); if (k == 0) zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos_data_lang_war3->desc_comp_data, &anongame_infos_data_lang_war3->desc_comp_len); else zlib_compress(packet_get_data_const(raw,0,size), size, &anongame_infos_data_lang_w3xp->desc_comp_data, &anongame_infos_data_lang_w3xp->desc_comp_len); } packet_set_size(raw, 0); /*FIXME: Still adding a static number (10) Also maybe need do do some checks to avoid prefs empty strings. */ ladr_count = 10; packet_append_data(raw, &ladr_count, 1); packet_append_data(raw, "OLOS", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_PG_1v1_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_PG_1v1)); packet_append_data(raw, "MAET", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_PG_team_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_PG_team)); packet_append_data(raw, " AFF", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_PG_ffa_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_PG_ffa)); packet_append_data(raw, "2SV2", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_AT_2v2_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_AT_2v2)); packet_append_data(raw, "3SV3", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_AT_3v3_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_AT_3v3)); packet_append_data(raw, "4SV4", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_AT_4v4_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_AT_4v4)); packet_append_data(raw, "SNLC", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_clan_1v1_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_clan_1v1)); packet_append_data(raw, "2NLC", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_clan_2v2_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_clan_2v2)); packet_append_data(raw, "3NLC", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_clan_3v3_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_clan_3v3)); packet_append_data(raw, "4NLC", 4); packet_append_string(raw, anongame_infos_DESC_get_DESC(langID, ladder_clan_4v4_desc)); packet_append_string(raw, anongame_infos_URL_get_URL(URL_ladder_clan_4v4)); anongame_infos_data_lang_war3->ladr_len = packet_get_size(raw); anongame_infos_data_lang_war3->ladr_data = (char *) xmalloc(anongame_infos_data_lang_war3->ladr_len); memcpy(anongame_infos_data_lang_war3->ladr_data, packet_get_data_const(raw, 0, anongame_infos_data_lang_war3->ladr_len), anongame_infos_data_lang_war3->ladr_len); zlib_compress(anongame_infos_data_lang_war3->ladr_data, anongame_infos_data_lang_war3->ladr_len, &anongame_infos_data_lang_war3->ladr_comp_data, &anongame_infos_data_lang_war3->ladr_comp_len); list_append_data(anongame_infos->anongame_infos_data_lang_war3, anongame_infos_data_lang_war3); anongame_infos_data_lang_w3xp->ladr_len = packet_get_size(raw); anongame_infos_data_lang_w3xp->ladr_data = (char *) xmalloc(anongame_infos_data_lang_w3xp->ladr_len); memcpy(anongame_infos_data_lang_w3xp->ladr_data, packet_get_data_const(raw, 0, anongame_infos_data_lang_w3xp->ladr_len), anongame_infos_data_lang_w3xp->ladr_len); zlib_compress(anongame_infos_data_lang_w3xp->ladr_data, anongame_infos_data_lang_w3xp->ladr_len, &anongame_infos_data_lang_w3xp->ladr_comp_data, &anongame_infos_data_lang_w3xp->ladr_comp_len); list_append_data(anongame_infos->anongame_infos_data_lang_w3xp, anongame_infos_data_lang_w3xp); } packet_destroy(raw); } return 0; } extern int anongame_infos_unload(void) { return anongame_infos_destroy(anongame_infos); } static int zlib_compress(void const *src, int srclen, char **dest, int *destlen) { char *tmpdata; z_stream zcpr; int ret; int lorigtodo; int lorigdone; int all_read_before; ret = Z_OK; lorigtodo = srclen; lorigdone = 0; *dest = NULL; tmpdata = (unsigned char *) xmalloc(srclen + (srclen / 0x10) + 0x200 + 0x8000); memset(&zcpr, 0, sizeof(z_stream)); pvpgn_deflateInit(&zcpr, 9); zcpr.next_in = (void *) src; zcpr.next_out = tmpdata; do { all_read_before = zcpr.total_in; zcpr.avail_in = (lorigtodo < 0x8000) ? lorigtodo : 0x8000; zcpr.avail_out = 0x8000; ret = pvpgn_deflate(&zcpr, (zcpr.avail_in == lorigtodo) ? Z_FINISH : Z_SYNC_FLUSH); lorigdone += (zcpr.total_in - all_read_before); lorigtodo -= (zcpr.total_in - all_read_before); } while (ret == Z_OK); (*destlen) = zcpr.total_out; if ((*destlen) > 0) { (*dest) = xmalloc((*destlen) + 4); bn_short_set((bn_short *) (*dest), lorigdone); bn_short_set((bn_short *) (*dest + 2), *destlen); memcpy((*dest) + 4, tmpdata, (*destlen)); (*destlen) += 4; } pvpgn_deflateEnd(&zcpr); xfree((void *) tmpdata); return 0; } pvpgn-1.8.5/src/bnetd/runprog.h0000644000175000017500000000203111151345317015366 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_RUNPROG_PROTOS #define INCLUDED_RUNPROG_PROTOS #define JUST_NEED_TYPES #include #undef JUST_NEED_TYPES extern FILE * runprog_open(char const * command); extern int runprog_close(FILE * pp); #endif #endif pvpgn-1.8.5/src/bnetd/friends.h0000644000175000017500000000334011151345317015330 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_FRIENDS_H #define INCLUDED_FRIENDS_H typedef struct friend_struct { char mutual; /* -1 - unloaded(used to remove deleted elems when reload); 0 - not mutual ; 1 - is mutual */ t_account *friendacc; } t_friend; #ifndef JUST_NEED_TYPES extern t_account * friend_get_account(t_friend *); extern int friend_set_account(t_friend *, t_account * acc); extern char friend_get_mutual(t_friend *); extern int friend_set_mutual(t_friend *, char); extern int friendlist_unload(t_list *); extern int friendlist_close(t_list *); extern int friendlist_purge(t_list *); extern int friendlist_add_account(t_list *, t_account *, int); extern int friendlist_remove_friend(t_list * flist, t_friend *); extern int friendlist_remove_account(t_list *, t_account *); extern int friendlist_remove_username(t_list *, const char *); extern t_friend * friendlist_find_account(t_list *, t_account *); extern t_friend * friendlist_find_username(t_list *, const char *); extern t_friend * friendlist_find_uid(t_list *, int); #endif #endif pvpgn-1.8.5/src/bnetd/sql_pgsql.c0000644000175000017500000001715211151345317015704 0ustar aaronaaron/* * Copyright (C) 2002,2003 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef WITH_SQL_PGSQL #include "common/setup_before.h" #include #include #include "common/eventlog.h" #include "common/xalloc.h" #include "storage_sql.h" #include "sql_pgsql.h" #include "common/setup_after.h" static int sql_pgsql_init(const char *, const char *, const char *, const char *, const char *, const char *); static int sql_pgsql_close(void); static t_sql_res * sql_pgsql_query_res(const char *); static int sql_pgsql_query(const char *); static t_sql_row * sql_pgsql_fetch_row(t_sql_res *); static void sql_pgsql_free_result(t_sql_res *); static unsigned int sql_pgsql_num_rows(t_sql_res *); static unsigned int sql_pgsql_num_fields(t_sql_res *); static unsigned int sql_pgsql_affected_rows(void); static t_sql_field * sql_pgsql_fetch_fields(t_sql_res *); static int sql_pgsql_free_fields(t_sql_field *); static void sql_pgsql_escape_string(char *, const char *, int); t_sql_engine sql_pgsql = { '"', sql_pgsql_init, sql_pgsql_close, sql_pgsql_query_res, sql_pgsql_query, sql_pgsql_fetch_row, sql_pgsql_free_result, sql_pgsql_num_rows, sql_pgsql_num_fields, sql_pgsql_affected_rows, sql_pgsql_fetch_fields, sql_pgsql_free_fields, sql_pgsql_escape_string }; static PGconn *pgsql = NULL; static unsigned int lastarows = 0; typedef struct { int crow; char ** rowbuf; PGresult *pgres; } t_pgsql_res; static int sql_pgsql_init(const char *host, const char *port, const char *socket, const char *name, const char *user, const char *pass) { const char *tmphost; if (name == NULL || user == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL parameter"); return -1; } tmphost = host != NULL ? host : socket; if ((pgsql = PQsetdbLogin(host, port, NULL, NULL, name, user, pass)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "not enougn memory for new pgsql connection"); return -1; } if (PQstatus(pgsql) != CONNECTION_OK) { eventlog(eventlog_level_error, __FUNCTION__, "error connecting to database (db said: '%s')", PQerrorMessage(pgsql)); PQfinish(pgsql); pgsql = NULL; return -1; } return 0; } static int sql_pgsql_close(void) { if (pgsql) { PQfinish(pgsql); pgsql = NULL; } return 0; } static t_sql_res * sql_pgsql_query_res(const char * query) { t_pgsql_res *res; PGresult *pgres; if (pgsql == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "pgsql driver not initilized"); return NULL; } if (query == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL query"); return NULL; } if ((pgres = PQexec(pgsql, query)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "not enough memory for query (%s)", query); return NULL; } if (PQresultStatus(pgres) != PGRES_TUPLES_OK) { /* eventlog(eventlog_level_debug, __FUNCTION__, "got error from query (%s)", query); */ PQclear(pgres); return NULL; } res = (t_pgsql_res *)xmalloc(sizeof(t_pgsql_res)); res->rowbuf = xmalloc(sizeof(char *) * PQnfields(pgres)); res->pgres = pgres; res->crow = 0; /* eventlog(eventlog_level_debug, __FUNCTION__, "res: %p res->rowbuf: %p res->crow: %d res->pgres: %p", res, res->rowbuf, res->crow, res->pgres); */ return res; } static void _pgsql_update_arows (const char *str) { if (!str || str[0] == '\0') lastarows = 0; lastarows = (unsigned int)atoi(str); } static int sql_pgsql_query(const char * query) { PGresult *pgres; int res; if (pgsql == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "pgsql driver not initilized"); return -1; } if (query == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL query"); return -1; } if ((pgres = PQexec(pgsql, query)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "not enough memory for result"); return -1; } res = PQresultStatus(pgres) == PGRES_COMMAND_OK ? 0 : -1; /* Dizzy: HACK ALERT! cache affected rows here before destroying result */ if (!res) _pgsql_update_arows(PQcmdTuples(pgres)); PQclear(pgres); return res; } static t_sql_row * sql_pgsql_fetch_row(t_sql_res *result) { int nofields, i; t_pgsql_res *res = (t_pgsql_res *) result; if (res == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return NULL; } if (res->crow < 0) { eventlog(eventlog_level_error, __FUNCTION__, "got called without a proper res query"); return NULL; } if (res->crow >= PQntuples(res->pgres)) return NULL; /* end of result */ nofields = PQnfields(res->pgres); for(i = 0; i < nofields; i++) { res->rowbuf[i] = PQgetvalue(res->pgres, res->crow, i); /* the next line emulates the mysql way where NULL containing fields return NULL */ if (res->rowbuf[i] && res->rowbuf[i][0] == '\0') res->rowbuf[i] = NULL; } res->crow++; /* eventlog(eventlog_level_debug, __FUNCTION__, "res: %p res->rowbuf: %p res->crow: %d res->pgres: %p", res, res->rowbuf, res->crow, res->pgres); */ return res->rowbuf; } static void sql_pgsql_free_result(t_sql_res *result) { t_pgsql_res *res = (t_pgsql_res *) result; if (res == NULL) return; /* eventlog(eventlog_level_debug, __FUNCTION__, "res: %p res->rowbuf: %p res->crow: %d res->pgres: %p", res, res->rowbuf, res->crow, res->pgres); */ if (res->pgres) PQclear(res->pgres); if (res->rowbuf) xfree((void*)res->rowbuf); xfree((void*)res); } static unsigned int sql_pgsql_num_rows(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return 0; } return PQntuples(((t_pgsql_res *)result)->pgres); } static unsigned int sql_pgsql_num_fields(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return 0; } return PQnfields(((t_pgsql_res *)result)->pgres); } static unsigned int sql_pgsql_affected_rows(void) { return lastarows; } static t_sql_field * sql_pgsql_fetch_fields(t_sql_res *result) { t_pgsql_res *res = (t_pgsql_res *) result; unsigned fieldno, i; t_sql_field *rfields; if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return NULL; } fieldno = PQnfields(res->pgres); rfields = xmalloc(sizeof(t_sql_field) * (fieldno + 1)); for(i = 0; i < fieldno; i++) rfields[i] = PQfname(res->pgres, i); rfields[i] = NULL; return rfields; } static int sql_pgsql_free_fields(t_sql_field *fields) { if (fields == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL fields"); return -1; } xfree((void*)fields); return 0; /* PQclear() should free the rest properly */ } static void sql_pgsql_escape_string(char *escape, const char *from, int len) { PQescapeString(escape, from, len); } #endif /* WITH_SQL_PGSQL */ pvpgn-1.8.5/src/bnetd/command_groups.h0000644000175000017500000000236411151345317016720 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_COMMAND_GROUPS_TYPES #define INCLUDED_COMMAND_GROUPS_TYPES #ifdef COMMAND_GROUPS_INTERNAL_ACCESS typedef struct { char * command; unsigned int group; } t_command_groups; #endif #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_COMMAND_GROUPS_PROTOS #define INCLUDED_COMMAND_GROUPS_PROTOS extern int command_groups_load(char const * filename); extern int command_groups_unload(void); extern int command_groups_reload(char const * filename); extern unsigned int command_get_group(char const * command); #endif #endif pvpgn-1.8.5/src/bnetd/handle_bnet.h0000644000175000017500000000207211151345317016142 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_HANDLE_BNET_PROTOS #define INCLUDED_HANDLE_BNET_PROTOS #define JUST_NEED_TYPES #include "connection.h" #include "common/packet.h" #undef JUST_NEED_TYPES extern int handle_bnet_packet(t_connection * c, t_packet const * const packet); #endif #endif pvpgn-1.8.5/src/bnetd/handle_bnet.c0000644000175000017500000061726411151345317016154 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999,2000 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * Copyright (C) 2003 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define VERSIONCHECK_INTERNAL_ACCESS #include "common/setup_before.h" #include #include // amadeo #ifdef WIN32_GUI #include #endif // NonReal: #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS /* FIXME: remove ? */ # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef WIN32 #include "compat/socket.h" #endif #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include "compat/strchr.h" #include "compat/strdup.h" #include "common/packet.h" #include "common/bnet_protocol.h" #include "common/tag.h" #include "message.h" #include "common/eventlog.h" #include "command.h" #include "team.h" #include "account.h" #include "account_wrap.h" #include "realm.h" #include "connection.h" #include "channel.h" #include "game.h" #include "common/queue.h" #include "tick.h" #include "file.h" #include "prefs.h" #include "common/util.h" #include "common/bnethash.h" #include "common/bnethashconv.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "ladder.h" #include "adbanner.h" #include "common/list.h" #include "common/bnettime.h" #include "common/addr.h" #include "game_conv.h" #include "autoupdate.h" #include "character.h" #include "versioncheck.h" #include "anongame.h" #include "handle_anongame.h" #include "common/proginfo.h" #include "clan.h" #include "handle_bnet.h" #include "handlers.h" #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #include "watch.h" #include "anongame_infos.h" #include "news.h" //by Spider #include "friends.h" #include "server.h" #include "compat/uint.h" #include "common/trans.h" #include "common/xalloc.h" #include "common/lstr.h" #include "common/setup_after.h" extern int last_news; extern int first_news; /* handlers prototypes */ static int _client_unknown_1b(t_connection * c, t_packet const *const packet); static int _client_compinfo1(t_connection * c, t_packet const *const packet); static int _client_compinfo2(t_connection * c, t_packet const *const packet); static int _client_countryinfo1(t_connection * c, t_packet const *const packet); static int _client_countryinfo109(t_connection * c, t_packet const *const packet); static int _client_unknown2b(t_connection * c, t_packet const *const packet); static int _client_progident(t_connection * c, t_packet const *const packet); static int _client_createaccountw3(t_connection * c, t_packet const *const packet); static int _client_createacctreq1(t_connection * c, t_packet const *const packet); static int _client_createacctreq2(t_connection * c, t_packet const *const packet); static int _client_changepassreq(t_connection * c, t_packet const *const packet); static int _client_echoreply(t_connection * c, t_packet const *const packet); static int _client_authreq1(t_connection * c, t_packet const *const packet); static int _client_authreq109(t_connection * c, t_packet const *const packet); static int _client_regsnoopreply(t_connection * c, t_packet const *const packet); static int _client_iconreq(t_connection * c, t_packet const *const packet); static int _client_cdkey(t_connection * c, t_packet const *const packet); static int _client_cdkey2(t_connection * c, t_packet const *const packet); static int _client_cdkey3(t_connection * c, t_packet const *const packet); static int _client_udpok(t_connection * c, t_packet const *const packet); static int _client_fileinforeq(t_connection * c, t_packet const *const packet); static int _client_statsreq(t_connection * c, t_packet const *const packet); static int _client_loginreq1(t_connection * c, t_packet const *const packet); static int _client_loginreq2(t_connection * c, t_packet const *const packet); static int _client_loginreqw3(t_connection * c, t_packet const *const packet); static int _client_pingreq(t_connection * c, t_packet const *const packet); static int _client_logonproofreq(t_connection * c, t_packet const *const packet); static int _client_changegameport(t_connection * c, t_packet const *const packet); static int _client_friendslistreq(t_connection * c, t_packet const *const packet); static int _client_friendinforeq(t_connection * c, t_packet const *const packet); static int _client_atfriendscreen(t_connection * c, t_packet const *const packet); static int _client_atinvitefriend(t_connection * c, t_packet const *const packet); static int _client_atacceptinvite(t_connection * c, t_packet const *const packet); static int _client_atacceptdeclineinvite(t_connection * c, t_packet const *const packet); static int _client_motdw3(t_connection * c, t_packet const *const packet); static int _client_realmlistreq(t_connection * c, t_packet const *const packet); static int _client_realmlistreq110(t_connection * c, t_packet const *const packet); static int _client_profilereq(t_connection * c, t_packet const *const packet); static int _client_realmjoinreq109(t_connection * c, t_packet const *const packet); static int _client_unknown39(t_connection * c, t_packet const *const packet); static int _client_charlistreq(t_connection * c, t_packet const *const packet); static int _client_adreq(t_connection * c, t_packet const *const packet); static int _client_adack(t_connection * c, t_packet const *const packet); static int _client_adclick(t_connection * c, t_packet const *const packet); static int _client_adclick2(t_connection * c, t_packet const *const packet); static int _client_statsupdate(t_connection * c, t_packet const *const packet); static int _client_playerinforeq(t_connection * c, t_packet const *const packet); static int _client_progident2(t_connection * c, t_packet const *const packet); static int _client_joinchannel(t_connection * c, t_packet const *const packet); static int _client_message(t_connection * c, t_packet const *const packet); static int _client_gamelistreq(t_connection * c, t_packet const *const packet); static int _client_joingame(t_connection * c, t_packet const *const packet); static int _client_startgame1(t_connection * c, t_packet const *const packet); static int _client_startgame3(t_connection * c, t_packet const *const packet); static int _client_startgame4(t_connection * c, t_packet const *const packet); static int _client_closegame(t_connection * c, t_packet const *const packet); static int _client_gamereport(t_connection * c, t_packet const *const packet); static int _client_leavechannel(t_connection * c, t_packet const *const packet); static int _client_ladderreq(t_connection * c, t_packet const *const packet); static int _client_laddersearchreq(t_connection * c, t_packet const *const packet); static int _client_mapauthreq1(t_connection * c, t_packet const *const packet); static int _client_mapauthreq2(t_connection * c, t_packet const *const packet); static int _client_changeclient(t_connection * c, t_packet const *const packet); static int _client_w3xp_clanmemberlistreq(t_connection * c, t_packet const *const packet); static int _client_w3xp_clan_motdreq(t_connection * c, t_packet const *const packet); static int _client_w3xp_clan_motdchg(t_connection * c, t_packet const *const packet); static int _client_w3xp_clan_createreq(t_connection * c, t_packet const *const packet); static int _client_w3xp_clan_createinvitereq(t_connection * c, t_packet const *const packet); static int _client_w3xp_clan_createinvitereply(t_connection * c, t_packet const *const packet); static int _client_w3xp_clan_disbandreq(t_connection * c, t_packet const *const packet); static int _client_w3xp_clanmember_rankupdatereq(t_connection * c, t_packet const *const packet); static int _client_w3xp_clanmember_removereq(t_connection * c, t_packet const *const packet); static int _client_w3xp_clan_membernewchiefreq(t_connection * c, t_packet const *const packet); static int _client_w3xp_clan_invitereq(t_connection * c, t_packet const *const packet); static int _client_w3xp_clan_invitereply(t_connection * c, t_packet const *const packet); static int _client_crashdump(t_connection * c, t_packet const *const packet); static int _client_setemailreply(t_connection * c, t_packet const *const packet); static int _client_changeemailreq(t_connection * c, t_packet const *const packet); static int _client_getpasswordreq(t_connection * c, t_packet const *const packet); static int _client_claninforeq(t_connection * c, t_packet const *const packet); /* connection state connected handler table */ static const t_htable_row bnet_htable_con[] = { {CLIENT_UNKNOWN_1B, _client_unknown_1b}, {CLIENT_COMPINFO1, _client_compinfo1}, {CLIENT_COMPINFO2, _client_compinfo2}, {CLIENT_COUNTRYINFO1, _client_countryinfo1}, {CLIENT_COUNTRYINFO_109, _client_countryinfo109}, {CLIENT_UNKNOWN_2B, _client_unknown2b}, {CLIENT_PROGIDENT, _client_progident}, {CLIENT_CLOSEGAME, NULL}, {CLIENT_CREATEACCOUNT_W3, _client_createaccountw3}, {CLIENT_CREATEACCTREQ1, _client_createacctreq1}, {CLIENT_CREATEACCTREQ2, _client_createacctreq2}, {CLIENT_CHANGEPASSREQ, _client_changepassreq}, {CLIENT_ECHOREPLY, _client_echoreply}, {CLIENT_AUTHREQ1, _client_authreq1}, {CLIENT_AUTHREQ_109, _client_authreq109}, {CLIENT_REGSNOOPREPLY, _client_regsnoopreply}, {CLIENT_ICONREQ, _client_iconreq}, {CLIENT_CDKEY, _client_cdkey}, {CLIENT_CDKEY2, _client_cdkey2}, {CLIENT_CDKEY3, _client_cdkey3}, {CLIENT_UDPOK, _client_udpok}, {CLIENT_FILEINFOREQ, _client_fileinforeq}, {CLIENT_STATSREQ, _client_statsreq}, {CLIENT_PINGREQ, _client_pingreq}, {CLIENT_LOGINREQ1, _client_loginreq1}, {CLIENT_LOGINREQ2, _client_loginreq2}, {CLIENT_LOGINREQ_W3, _client_loginreqw3}, {CLIENT_LOGONPROOFREQ, _client_logonproofreq}, /* After this packet we know to translate the packets to the normal IDs */ {CLIENT_CHANGECLIENT, _client_changeclient}, {CLIENT_GETPASSWORDREQ, _client_getpasswordreq}, {CLIENT_CHANGEEMAILREQ, _client_changeemailreq}, {CLIENT_CRASHDUMP, _client_crashdump}, {-1, NULL} }; /* connection state loggedin handlers */ static const t_htable_row bnet_htable_log[] = { {CLIENT_CHANGEGAMEPORT, _client_changegameport}, {CLIENT_FRIENDSLISTREQ, _client_friendslistreq}, {CLIENT_FRIENDINFOREQ, _client_friendinforeq}, {CLIENT_ARRANGEDTEAM_FRIENDSCREEN, _client_atfriendscreen}, {CLIENT_ARRANGEDTEAM_INVITE_FRIEND, _client_atinvitefriend}, {CLIENT_ARRANGEDTEAM_ACCEPT_INVITE, _client_atacceptinvite}, {CLIENT_ARRANGEDTEAM_ACCEPT_DECLINE_INVITE, _client_atacceptdeclineinvite}, /* anongame packet (44ff) handled in handle_anongame.c */ {CLIENT_FINDANONGAME, handle_anongame_packet}, {CLIENT_FILEINFOREQ, _client_fileinforeq}, {CLIENT_MOTD_W3, _client_motdw3}, {CLIENT_REALMLISTREQ, _client_realmlistreq}, {CLIENT_REALMLISTREQ_110, _client_realmlistreq110}, {CLIENT_PROFILEREQ, _client_profilereq}, {CLIENT_REALMJOINREQ_109, _client_realmjoinreq109}, {CLIENT_UNKNOWN_37, _client_charlistreq}, {CLIENT_UNKNOWN_39, _client_unknown39}, {CLIENT_ECHOREPLY, _client_echoreply}, {CLIENT_PINGREQ, _client_pingreq}, {CLIENT_ADREQ, _client_adreq}, {CLIENT_ADACK, _client_adack}, {CLIENT_ADCLICK, _client_adclick}, {CLIENT_ADCLICK2, _client_adclick2}, {CLIENT_STATSREQ, _client_statsreq}, {CLIENT_STATSUPDATE, _client_statsupdate}, {CLIENT_PLAYERINFOREQ, _client_playerinforeq}, {CLIENT_PROGIDENT2, _client_progident2}, {CLIENT_JOINCHANNEL, _client_joinchannel}, {CLIENT_MESSAGE, _client_message}, {CLIENT_GAMELISTREQ, _client_gamelistreq}, {CLIENT_JOIN_GAME, _client_joingame}, {CLIENT_STARTGAME1, _client_startgame1}, {CLIENT_STARTGAME3, _client_startgame3}, {CLIENT_STARTGAME4, _client_startgame4}, {CLIENT_CLOSEGAME, _client_closegame}, {CLIENT_CLOSEGAME2, _client_closegame}, {CLIENT_GAME_REPORT, _client_gamereport}, {CLIENT_LEAVECHANNEL, _client_leavechannel}, {CLIENT_LADDERREQ, _client_ladderreq}, {CLIENT_LADDERSEARCHREQ, _client_laddersearchreq}, {CLIENT_MAPAUTHREQ1, _client_mapauthreq1}, {CLIENT_MAPAUTHREQ2, _client_mapauthreq2}, {CLIENT_W3XP_CLAN_DISBANDREQ, _client_w3xp_clan_disbandreq}, {CLIENT_W3XP_CLANMEMBERLIST_REQ, _client_w3xp_clanmemberlistreq}, {CLIENT_W3XP_CLAN_MOTDCHG, _client_w3xp_clan_motdchg}, {CLIENT_W3XP_CLAN_MOTDREQ, _client_w3xp_clan_motdreq}, {CLIENT_W3XP_CLAN_CREATEREQ, _client_w3xp_clan_createreq}, {CLIENT_W3XP_CLAN_CREATEINVITEREQ, _client_w3xp_clan_createinvitereq}, {CLIENT_W3XP_CLAN_CREATEINVITEREPLY, _client_w3xp_clan_createinvitereply}, {CLIENT_W3XP_CLANMEMBER_RANKUPDATE_REQ, _client_w3xp_clanmember_rankupdatereq}, {CLIENT_W3XP_CLANMEMBER_REMOVE_REQ, _client_w3xp_clanmember_removereq}, {CLIENT_W3XP_CLAN_MEMBERNEWCHIEFREQ, _client_w3xp_clan_membernewchiefreq}, {CLIENT_W3XP_CLAN_INVITEREQ, _client_w3xp_clan_invitereq}, {CLIENT_W3XP_CLAN_INVITEREPLY, _client_w3xp_clan_invitereply}, {CLIENT_CRASHDUMP, _client_crashdump}, {CLIENT_SETEMAILREPLY, _client_setemailreply}, {CLIENT_CLANINFOREQ, _client_claninforeq}, {CLIENT_NULL, NULL}, {-1, NULL} }; /* main handler function */ static int handle(const t_htable_row * htable, int type, t_connection * c, t_packet const *const packet); extern int handle_bnet_packet(t_connection * c, t_packet const *const packet) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL packet", conn_get_socket(c)); return -1; } if (packet_get_class(packet) != packet_class_bnet) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad packet (class %d)", conn_get_socket(c), (int) packet_get_class(packet)); return -1; } switch (conn_get_state(c)) { case conn_state_connected: switch (handle(bnet_htable_con, packet_get_type(packet), c, packet)) { case 1: eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown (unlogged in) bnet packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet)); break; case -1: eventlog(eventlog_level_error, __FUNCTION__, "[%d] (unlogged in) got error handling packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet)); break; }; break; case conn_state_loggedin: switch (handle(bnet_htable_log, packet_get_type(packet), c, packet)) { case 1: eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown (logged in) bnet packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet)); break; case -1: eventlog(eventlog_level_error, __FUNCTION__, "[%d] (logged in) got error handling packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet)); break; }; break; case conn_state_untrusted: eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown (untrusted) bnet packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet)); break; default: eventlog(eventlog_level_error, __FUNCTION__, "[%d] invalid login state %d", conn_get_socket(c), conn_get_state(c)); }; return 0; } static int handle(const t_htable_row * htable, int type, t_connection * c, t_packet const *const packet) { t_htable_row const *p; int res = 1; for (p = htable; p->type != -1; p++) if (p->type == type) { res = 0; if (p->handler != NULL) res = p->handler(c, packet); if (res != 2) break; /* return 2 means we want to continue parsing */ } return res; } /* checks if a clienttag is in the allowed_clients list * @ctag : clienttag integer to check * if it's allowed returns 0 * if it's not allowed returns -1 */ static int _check_allowed_client(t_clienttag ctag) { char *list, *p, *q; /* by default allow all */ if (!prefs_get_allowed_clients()) return 0; /* this shortcut check should make server as fast as before if * the configuration is left in default mode */ if (!strcasecmp(prefs_get_allowed_clients(), "all")) return 0; list = xstrdup(prefs_get_allowed_clients()); p = list; do { q = strchr(p, ','); if (q) *q = '\0'; if (!strcasecmp(p, "all")) goto ok; if (strlen(p) != 4) continue; if (ctag == tag_case_str_to_uint(p)) goto ok; /* client allowed */ if (q) p = q + 1; } while (q); xfree((void *) list); return -1; /* client NOT allowed */ ok: xfree((void *) list); return 0; } /* handlers for bnet packets */ static int _client_unknown_1b(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_unknown_1b)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UNKNOWN_1B packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_unknown_1b), packet_get_size(packet)); return -1; } { unsigned int newip; unsigned short newport; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] UNKNOWN_1B unknown1=0x%04hx", conn_get_socket(c), bn_short_get(packet->u.client_unknown_1b.unknown1)); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] UNKNOWN_1B unknown2=0x%08x", conn_get_socket(c), bn_int_get(packet->u.client_unknown_1b.unknown2)); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] UNKNOWN_1B unknown3=0x%08x", conn_get_socket(c), bn_int_get(packet->u.client_unknown_1b.unknown3)); newip = bn_int_nget(packet->u.client_unknown_1b.ip); newport = bn_short_nget(packet->u.client_unknown_1b.port); eventlog(eventlog_level_info, __FUNCTION__, "[%d] UNKNOWN_1B set new UDP address to %s", conn_get_socket(c), addr_num_to_addr_str(newip, newport)); conn_set_game_addr(c, newip); conn_set_game_port(c, newport); } return 0; } static int _client_compinfo1(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_compinfo1)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_compinfo1), packet_get_size(packet)); return -1; } { char const *host; char const *user; if (!(host = packet_get_str_const(packet, sizeof(t_client_compinfo1), MAX_WINHOST_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO1 packet (missing or too long host)", conn_get_socket(c)); return -1; } if (!(user = packet_get_str_const(packet, sizeof(t_client_compinfo1) + strlen(host) + 1, MAX_WINUSER_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO1 packet (missing or too long user)", conn_get_socket(c)); return -1; } conn_set_host(c, host); conn_set_user(c, user); } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_compreply)); packet_set_type(rpacket, SERVER_COMPREPLY); bn_int_set(&rpacket->u.server_compreply.reg_version, SERVER_COMPREPLY_REG_VERSION); bn_int_set(&rpacket->u.server_compreply.reg_auth, SERVER_COMPREPLY_REG_AUTH); bn_int_set(&rpacket->u.server_compreply.client_id, SERVER_COMPREPLY_CLIENT_ID); bn_int_set(&rpacket->u.server_compreply.client_token, SERVER_COMPREPLY_CLIENT_TOKEN); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_sessionkey1)); packet_set_type(rpacket, SERVER_SESSIONKEY1); bn_int_set(&rpacket->u.server_sessionkey1.sessionkey, conn_get_sessionkey(c)); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_compinfo2(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_compinfo2)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_compinfo2), packet_get_size(packet)); return -1; } { char const *host; char const *user; if (!(host = packet_get_str_const(packet, sizeof(t_client_compinfo2), MAX_WINHOST_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO2 packet (missing or too long host)", conn_get_socket(c)); return -1; } if (!(user = packet_get_str_const(packet, sizeof(t_client_compinfo2) + strlen(host) + 1, MAX_WINUSER_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO2 packet (missing or too long user)", conn_get_socket(c)); return -1; } conn_set_host(c, host); conn_set_user(c, user); } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_compreply)); packet_set_type(rpacket, SERVER_COMPREPLY); bn_int_set(&rpacket->u.server_compreply.reg_version, SERVER_COMPREPLY_REG_VERSION); bn_int_set(&rpacket->u.server_compreply.reg_auth, SERVER_COMPREPLY_REG_AUTH); bn_int_set(&rpacket->u.server_compreply.client_id, SERVER_COMPREPLY_CLIENT_ID); bn_int_set(&rpacket->u.server_compreply.client_token, SERVER_COMPREPLY_CLIENT_TOKEN); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_sessionkey2)); packet_set_type(rpacket, SERVER_SESSIONKEY2); bn_int_set(&rpacket->u.server_sessionkey2.sessionnum, conn_get_sessionnum(c)); bn_int_set(&rpacket->u.server_sessionkey2.sessionkey, conn_get_sessionkey(c)); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_countryinfo1(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_countryinfo1)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_countryinfo1), packet_get_size(packet)); return -1; } { char const *langstr; char const *countrycode; char const *country; unsigned int tzbias; if (!(langstr = packet_get_str_const(packet, sizeof(t_client_countryinfo1), MAX_LANG_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (missing or too long langstr)", conn_get_socket(c)); return -1; } if (!(countrycode = packet_get_str_const(packet, sizeof(t_client_countryinfo1) + strlen(langstr) + 1, MAX_COUNTRYCODE_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (missing or too long countrycode)", conn_get_socket(c)); return -1; } if (!(country = packet_get_str_const(packet, sizeof(t_client_countryinfo1) + strlen(langstr) + 1 + strlen(countrycode) + 1, MAX_COUNTRY_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (missing or too long country)", conn_get_socket(c)); return -1; } if (!(packet_get_str_const(packet, sizeof(t_client_countryinfo1) + strlen(langstr) + 1 + strlen(countrycode) + 1 + strlen(country) + 1, MAX_COUNTRYNAME_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (missing or too long countryname)", conn_get_socket(c)); return -1; } tzbias = bn_int_get(packet->u.client_countryinfo1.bias); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] COUNTRYINFO1 packet from tzbias=0x%04x(%+d) langstr=%s countrycode=%s country=%s", tzbias, uint32_to_int(tzbias), conn_get_socket(c), langstr, countrycode, country); conn_set_country(c, country); conn_set_tzbias(c, uint32_to_int(tzbias)); } return 0; } static int _client_countryinfo109(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_countryinfo_109)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO_109 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_countryinfo_109), packet_get_size(packet)); return -1; } { char const *langstr; char const *countryname; unsigned int tzbias; char archtag_str[5]; char clienttag_str[5]; char gamelang_str[5]; if (!(langstr = packet_get_str_const(packet, sizeof(t_client_countryinfo_109), MAX_LANG_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO_109 packet (missing or too long langstr)", conn_get_socket(c)); return -1; } if (!(countryname = packet_get_str_const(packet, sizeof(t_client_countryinfo_109) + strlen(langstr) + 1, MAX_COUNTRYNAME_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO_109 packet (missing or too long countryname)", conn_get_socket(c)); return -1; } /* check if it's an allowed client type */ if (_check_allowed_client(bn_int_get(packet->u.client_countryinfo_109.clienttag))) { conn_set_state(c, conn_state_destroy); return 0; } tzbias = bn_int_get(packet->u.client_countryinfo_109.bias); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] COUNTRYINFO_109 packet tzbias=0x%04x(%+d) lcid=%u langid=%u arch=\"%s\" client=\"%s\" versionid=0x%08x gamelang=\"%s\"", conn_get_socket(c), tzbias, uint32_to_int(tzbias), bn_int_get(packet->u.client_countryinfo_109.lcid), bn_int_get(packet->u.client_countryinfo_109.langid), tag_uint_to_str(archtag_str, bn_int_get(packet->u.client_countryinfo_109.archtag)), tag_uint_to_str(clienttag_str, bn_int_get(packet->u.client_countryinfo_109.clienttag)), bn_int_get(packet->u.client_countryinfo_109.versionid), tag_uint_to_str(gamelang_str, bn_int_get(packet->u.client_countryinfo_109.gamelang))); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] COUNTRYINFO_109 packet from \"%s\" \"%s\"", conn_get_socket(c), countryname, langstr); conn_set_country(c, langstr); /* FIXME: This isn't right. We want USA not ENU (English-US) */ conn_set_tzbias(c, uint32_to_int(tzbias)); conn_set_versionid(c, bn_int_get(packet->u.client_countryinfo_109.versionid)); conn_set_archtag(c, bn_int_get(packet->u.client_countryinfo_109.archtag)); conn_set_clienttag(c, bn_int_get(packet->u.client_countryinfo_109.clienttag)); conn_set_gamelang(c, bn_int_get(packet->u.client_countryinfo_109.gamelang)); /* First, send an ECHO_REQ */ if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_echoreq)); packet_set_type(rpacket, SERVER_ECHOREQ); bn_int_set(&rpacket->u.server_echoreq.ticks, get_ticks()); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } if ((rpacket = packet_create(packet_class_bnet))) { t_versioncheck *vc; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selecting version check", conn_get_socket(c)); vc = versioncheck_create(conn_get_archtag(c), conn_get_clienttag(c)); conn_set_versioncheck(c, vc); packet_set_size(rpacket, sizeof(t_server_authreq_109)); packet_set_type(rpacket, SERVER_AUTHREQ_109); if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT)) bn_int_set(&rpacket->u.server_authreq_109.logontype, SERVER_AUTHREQ_109_LOGONTYPE_W3); else if ((conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT)) bn_int_set(&rpacket->u.server_authreq_109.logontype, SERVER_AUTHREQ_109_LOGONTYPE_W3XP); else bn_int_set(&rpacket->u.server_authreq_109.logontype, SERVER_AUTHREQ_109_LOGONTYPE); bn_int_set(&rpacket->u.server_authreq_109.sessionkey, conn_get_sessionkey(c)); bn_int_set(&rpacket->u.server_authreq_109.sessionnum, conn_get_sessionnum(c)); file_to_mod_time(versioncheck_get_mpqfile(vc), &rpacket->u.server_authreq_109.timestamp); packet_append_string(rpacket, versioncheck_get_mpqfile(vc)); packet_append_string(rpacket, versioncheck_get_eqn(vc)); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selected \"%s\" \"%s\"", conn_get_socket(c), versioncheck_get_mpqfile(vc), versioncheck_get_eqn(vc)); if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT)) { char padding[128]; memset(padding, 0, 128); packet_append_data(rpacket, padding, 128); } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_unknown2b(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_unknown_2b)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UNKNOWN_2B packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_unknown_2b), packet_get_size(packet)); return -1; } return 0; } static int _client_progident(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_progident)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PROGIDENT packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_progident), packet_get_size(packet)); return -1; } if (_check_allowed_client(bn_int_get(packet->u.client_progident.clienttag))) { conn_set_state(c, conn_state_destroy); return 0; } eventlog(eventlog_level_debug, __FUNCTION__, "[%d] CLIENT_PROGIDENT archtag=0x%08x clienttag=0x%08x versionid=0x%08x unknown1=0x%08x", conn_get_socket(c), bn_int_get(packet->u.client_progident.archtag), bn_int_get(packet->u.client_progident.clienttag), bn_int_get(packet->u.client_progident.versionid), bn_int_get(packet->u.client_progident.unknown1)); conn_set_archtag(c, bn_int_get(packet->u.client_progident.archtag)); conn_set_clienttag(c, bn_int_get(packet->u.client_progident.clienttag)); if (prefs_get_skip_versioncheck()) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] attempting to skip version check by sending early authreply", conn_get_socket(c)); /* skip over SERVER_AUTHREQ1 and CLIENT_AUTHREQ1 */ if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_authreply1)); packet_set_type(rpacket, SERVER_AUTHREPLY1); bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_OK); packet_append_string(rpacket, ""); packet_append_string(rpacket, ""); /* FIXME: what's the second string for? */ conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } else { t_versioncheck *vc; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selecting version check", conn_get_socket(c)); vc = versioncheck_create(conn_get_archtag(c), conn_get_clienttag(c)); conn_set_versioncheck(c, vc); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_authreq1)); packet_set_type(rpacket, SERVER_AUTHREQ1); file_to_mod_time(versioncheck_get_mpqfile(vc), &rpacket->u.server_authreq1.timestamp); packet_append_string(rpacket, versioncheck_get_mpqfile(vc)); packet_append_string(rpacket, versioncheck_get_eqn(vc)); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selected \"%s\" \"%s\"", conn_get_socket(c), versioncheck_get_mpqfile(vc), versioncheck_get_eqn(vc)); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_createaccountw3(t_connection * c, t_packet const *const packet) { t_packet *rpacket; char const *username; char const *plainpass; char upass[20]; char lpass[20]; t_hash sc_hash; unsigned int i; if (packet_get_size(packet) < sizeof(t_client_createaccount_w3)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCOUNT_W3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_createaccount_w3), packet_get_size(packet)); return -1; } username = packet_get_str_const(packet, sizeof(t_client_createaccount_w3), UNCHECKED_NAME_STR); if (!username) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCOUNT_W3 (missing or too long username)", conn_get_socket(c)); return -1; } plainpass = packet_get_str_const(packet, 4 + 8 * 4, 16); if (!plainpass) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCOUNT_W3 (missing password)", conn_get_socket(c)); return -1; } rpacket = packet_create(packet_class_bnet); if (!rpacket) return -1; packet_set_size(rpacket, sizeof(t_server_createaccount_w3)); packet_set_type(rpacket, SERVER_CREATEACCOUNT_W3); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] new account requested for \"%s\"", conn_get_socket(c), username); if (prefs_get_allow_new_accounts() == 0) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (disabled)", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCOUNT_W3_RESULT_EXIST); goto out; } if (account_check_name(username) < 0) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (invalid symbols)", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCOUNT_W3_RESULT_INVALID); goto out; } /* convert plaintext password to uppercase */ strncpy(upass, plainpass, 16); upass[16] = 0; for (i = 0; i < strlen(upass); i++) if (isascii((int) upass[i]) && islower((int) upass[i])) upass[i] = toupper((int) upass[i]); /* convert plaintext password to lowercase for sc etc. */ strncpy(lpass, plainpass, 16); lpass[16] = 0; for (i = 0; i < strlen(lpass); i++) if (isascii((int) lpass[i]) && isupper((int) lpass[i])) lpass[i] = tolower((int) lpass[i]); //set password hash for sc etc. bnet_hash(&sc_hash, strlen(lpass), lpass); if (!accountlist_create_account(username, hash_get_str(sc_hash))) bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCOUNT_W3_RESULT_EXIST); else { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account created", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCOUNT_W3_RESULT_OK); } out: conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } static int _client_createacctreq1(t_connection * c, t_packet const *const packet) { t_packet *rpacket; char const *username; t_hash newpasshash1; if (packet_get_size(packet) < sizeof(t_client_createacctreq1)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCTREQ1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_createacctreq1), packet_get_size(packet)); return -1; } if (!(username = packet_get_str_const(packet, sizeof(t_client_createacctreq1), UNCHECKED_NAME_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCTREQ1 (missing or too long username)", conn_get_socket(c)); return -1; } eventlog(eventlog_level_debug, __FUNCTION__, "[%d] new account requested for \"%s\"", conn_get_socket(c), username); rpacket = packet_create(packet_class_bnet); if (!rpacket) return -1; packet_set_size(rpacket, sizeof(t_server_createacctreply1)); packet_set_type(rpacket, SERVER_CREATEACCTREPLY1); if (prefs_get_allow_new_accounts() == 0) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (disabled)", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createacctreply1.result, SERVER_CREATEACCTREPLY1_RESULT_NO); goto out; } bnhash_to_hash(packet->u.client_createacctreq1.password_hash1, &newpasshash1); if (!accountlist_create_account(username, hash_get_str(newpasshash1))) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (failed)", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createacctreply1.result, SERVER_CREATEACCTREPLY1_RESULT_NO); goto out; } eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account created", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createacctreply1.result, SERVER_CREATEACCTREPLY1_RESULT_OK); out: conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } static int _client_createacctreq2(t_connection * c, t_packet const *const packet) { t_packet *rpacket; char const *username; t_hash newpasshash1; if (packet_get_size(packet) < sizeof(t_client_createacctreq2)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_CREATEACCTREQ2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_createacctreq2), packet_get_size(packet)); return -1; } username = packet_get_str_const(packet, sizeof(t_client_createacctreq2), UNCHECKED_NAME_STR); if (!username) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCTREQ2 (missing or too long username)", conn_get_socket(c)); return -1; } eventlog(eventlog_level_debug, __FUNCTION__, "[%d] new account requested for \"%s\"", conn_get_socket(c), username); rpacket = packet_create(packet_class_bnet); if (!rpacket) return -1; packet_set_size(rpacket, sizeof(t_server_createacctreply2)); packet_set_type(rpacket, SERVER_CREATEACCTREPLY2); if (prefs_get_allow_new_accounts() == 0) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (disabled)", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createacctreply2.result, SERVER_CREATEACCTREPLY2_RESULT_EXIST); goto out; } if (account_check_name(username) < 0) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (invalid symbols)", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCTREPLY2_RESULT_INVALID); goto out; } bnhash_to_hash(packet->u.client_createacctreq2.password_hash1, &newpasshash1); if (!accountlist_create_account(username, hash_get_str(newpasshash1))) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (failed)", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createacctreply2.result, SERVER_CREATEACCTREPLY2_RESULT_EXIST); /* FIXME: return reason for failure */ goto out; } eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account created", conn_get_socket(c)); bn_int_set(&rpacket->u.server_createacctreply2.result, SERVER_CREATEACCTREPLY2_RESULT_OK); out: conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } static int _client_changepassreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_changepassreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CHANGEPASSREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_changepassreq), packet_get_size(packet)); return -1; } { char const *username; t_account *account; if (!(username = packet_get_str_const(packet, sizeof(t_client_changepassreq), UNCHECKED_NAME_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CHANGEPASSREQ (missing or too long username)", conn_get_socket(c)); return -1; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change requested for \"%s\"", conn_get_socket(c), username); if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_changepassack)); packet_set_type(rpacket, SERVER_CHANGEPASSACK); /* fail if logged in or no account */ if (connlist_find_connection_by_accountname(username) || !(account = accountlist_find_account(username))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" refused (no such account)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL); } else if (account_get_auth_changepass(account) == 0) { /* default to true */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" refused (no change access)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL); } else if (conn_get_sessionkey(c) != bn_int_get(packet->u.client_changepassreq.sessionkey)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] password change for \"%s\" refused (expected session key 0x%08x, got 0x%08x)", conn_get_socket(c), username, conn_get_sessionkey(c), bn_int_get(packet->u.client_changepassreq.sessionkey)); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL); } else { struct { bn_int ticks; bn_int sessionkey; bn_int passhash1[5]; } temp; char const *oldstrhash1; t_hash oldpasshash1; t_hash oldpasshash2; t_hash trypasshash2; t_hash newpasshash1; if ((oldstrhash1 = account_get_pass(account))) { bn_int_set(&temp.ticks, bn_int_get(packet->u.client_changepassreq.ticks)); bn_int_set(&temp.sessionkey, bn_int_get(packet->u.client_changepassreq.sessionkey)); if (hash_set_str(&oldpasshash1, oldstrhash1) < 0) { bnhash_to_hash(packet->u.client_changepassreq.newpassword_hash1, &newpasshash1); account_set_pass(account, hash_get_str(newpasshash1)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" successful (bad previous password)", conn_get_socket(c), account_get_name(account)); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_SUCCESS); } else { hash_to_bnhash((t_hash const *) &oldpasshash1, temp.passhash1); /* avoid warning */ bnet_hash(&oldpasshash2, sizeof(temp), &temp); /* do the double hash */ bnhash_to_hash(packet->u.client_changepassreq.oldpassword_hash2, &trypasshash2); if (hash_eq(trypasshash2, oldpasshash2) == 1) { bnhash_to_hash(packet->u.client_changepassreq.newpassword_hash1, &newpasshash1); account_set_pass(account, hash_get_str(newpasshash1)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" successful (previous password)", conn_get_socket(c), account_get_name(account)); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_SUCCESS); } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" refused (wrong password)", conn_get_socket(c), account_get_name(account)); conn_increment_passfail_count(c); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL); } } } else { bnhash_to_hash(packet->u.client_changepassreq.newpassword_hash1, &newpasshash1); account_set_pass(account, hash_get_str(newpasshash1)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" successful (no previous password)", conn_get_socket(c), account_get_name(account)); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_SUCCESS); } } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_echoreply(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_echoreply)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ECHOREPLY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_echoreply), packet_get_size(packet)); return -1; } { unsigned int now; unsigned int then; now = get_ticks(); then = bn_int_get(packet->u.client_echoreply.ticks); if (!now || !then || now < then) eventlog(eventlog_level_warn, __FUNCTION__, "[%d] bad timing in echo reply: now=%u then=%u", conn_get_socket(c), now, then); else conn_set_latency(c, now - then); } return 0; } static int _client_authreq1(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_authreq1)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_authreq1), packet_get_size(packet)); return -1; } { char verstr[16]; char const *exeinfo; char const *versiontag; int failed; failed = 0; if (bn_int_get(packet->u.client_authreq1.archtag) != conn_get_archtag(c)) failed = 1; if (bn_int_get(packet->u.client_authreq1.clienttag) != conn_get_clienttag(c)) failed = 1; if (!(exeinfo = packet_get_str_const(packet, sizeof(t_client_authreq1), MAX_EXEINFO_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ1 (missing or too long exeinfo)", conn_get_socket(c)); exeinfo = "badexe"; failed = 1; } conn_set_versionid(c, bn_int_get(packet->u.client_authreq1.versionid)); conn_set_checksum(c, bn_int_get(packet->u.client_authreq1.checksum)); conn_set_gameversion(c, bn_int_get(packet->u.client_authreq1.gameversion)); strcpy(verstr, vernum_to_verstr(bn_int_get(packet->u.client_authreq1.gameversion))); conn_set_clientver(c, verstr); conn_set_clientexe(c, exeinfo); eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_AUTHREQ1 archtag=0x%08x clienttag=0x%08x verstr=%s exeinfo=\"%s\" versionid=0x%08lx gameversion=0x%08lx checksum=0x%08lx", conn_get_socket(c), bn_int_get(packet->u.client_authreq1.archtag), bn_int_get(packet->u.client_authreq1.clienttag), verstr, exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c)); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_authreply1)); packet_set_type(rpacket, SERVER_AUTHREPLY1); if (!conn_get_versioncheck(c) && prefs_get_skip_versioncheck()) eventlog(eventlog_level_info, __FUNCTION__, "[%d] skip versioncheck enabled and client did not request validation", conn_get_socket(c)); else switch (versioncheck_validate(conn_get_versioncheck(c), conn_get_archtag(c), conn_get_clienttag(c), exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c))) { case -1: /* failed test... client has been modified */ if (!prefs_get_allow_bad_version()) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test (marking untrusted)", conn_get_socket(c)); failed = 1; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test, allowing anyway", conn_get_socket(c)); break; case 0: /* not listed in table... can't tell if client has been modified */ if (!prefs_get_allow_unknown_version()) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client (marking untrusted)", conn_get_socket(c)); failed = 1; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client, allowing anyway", conn_get_socket(c)); break; /* 1 == test passed... client seems to be ok */ } versiontag = versioncheck_get_versiontag(conn_get_versioncheck(c)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] client matches versiontag \"%s\"", conn_get_socket(c), versiontag); if (failed) { conn_set_state(c, conn_state_untrusted); bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_BADVERSION); packet_append_string(rpacket, ""); } else { char *mpqfilename; mpqfilename = autoupdate_check(conn_get_archtag(c), conn_get_clienttag(c), conn_get_gamelang(c), versiontag); /* Only handle updates when there is an update file available. */ if (mpqfilename != NULL) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] an upgrade for version %s is available \"%s\"", conn_get_socket(c), versioncheck_get_versiontag(conn_get_versioncheck(c)), mpqfilename); bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_UPDATE); packet_append_string(rpacket, mpqfilename); } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] no upgrade for %s is available", conn_get_socket(c), versioncheck_get_versiontag(conn_get_versioncheck(c))); bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_OK); packet_append_string(rpacket, ""); } if (mpqfilename) xfree((void *) mpqfilename); } packet_append_string(rpacket, ""); /* FIXME: what's the second string for? */ conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_authreq109(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_authreq_109)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ_109 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_authreq_109), packet_get_size(packet)); return 0; } { char verstr[16]; char const *exeinfo; char const *versiontag; int failed; char const *owner; unsigned int count; unsigned int pos; failed = 0; count = bn_int_get(packet->u.client_authreq_109.cdkey_number); pos = sizeof(t_client_authreq_109) + (count * sizeof(t_cdkey_info)); if (!(exeinfo = packet_get_str_const(packet, pos, MAX_EXEINFO_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ_109 (missing or too long exeinfo)", conn_get_socket(c)); exeinfo = "badexe"; failed = 1; } conn_set_clientexe(c, exeinfo); pos += strlen(exeinfo) + 1; if (!(owner = packet_get_str_const(packet, pos, MAX_OWNER_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ_109 (missing or too long owner)", conn_get_socket(c)); owner = ""; /* maybe owner was missing, use empty string */ } conn_set_owner(c, owner); conn_set_checksum(c, bn_int_get(packet->u.client_authreq_109.checksum)); conn_set_gameversion(c, bn_int_get(packet->u.client_authreq_109.gameversion)); strcpy(verstr, vernum_to_verstr(bn_int_get(packet->u.client_authreq_109.gameversion))); conn_set_clientver(c, verstr); conn_set_clientexe(c, exeinfo); eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_AUTHREQ_109 ticks=0x%08x, verstr=%s exeinfo=\"%s\" versionid=0x%08lx gameversion=0x%08lx checksum=0x%08lx", conn_get_socket(c), bn_int_get(packet->u.client_authreq_109.ticks), verstr, exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c)); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_authreply_109)); packet_set_type(rpacket, SERVER_AUTHREPLY_109); if (!conn_get_versioncheck(c) && prefs_get_skip_versioncheck()) eventlog(eventlog_level_info, __FUNCTION__, "[%d] skip versioncheck enabled and client did not request validation", conn_get_socket(c)); else switch (versioncheck_validate(conn_get_versioncheck(c), conn_get_archtag(c), conn_get_clienttag(c), exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c))) { case -1: /* failed test... client has been modified */ if (!prefs_get_allow_bad_version()) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test (closing connection)", conn_get_socket(c)); failed = 1; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test, allowing anyway", conn_get_socket(c)); break; case 0: /* not listed in table... can't tell if client has been modified */ if (!prefs_get_allow_unknown_version()) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client (closing connection)", conn_get_socket(c)); failed = 1; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client, allowing anyway", conn_get_socket(c)); break; /* 1 == test passed... client seems to be ok */ } versiontag = versioncheck_get_versiontag(conn_get_versioncheck(c)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] client matches versiontag \"%s\"", conn_get_socket(c), versiontag); if (failed) { conn_set_state(c, conn_state_untrusted); bn_int_set(&rpacket->u.server_authreply_109.message, SERVER_AUTHREPLY_109_MESSAGE_BADVERSION); packet_append_string(rpacket, ""); } else { char *mpqfilename; mpqfilename = autoupdate_check(conn_get_archtag(c), conn_get_clienttag(c), conn_get_gamelang(c), versiontag); /* Only handle updates when there is an update file available. */ if (mpqfilename != NULL) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] an upgrade for %s is available \"%s\"", conn_get_socket(c), versiontag, mpqfilename); bn_int_set(&rpacket->u.server_authreply_109.message, SERVER_AUTHREPLY_109_MESSAGE_UPDATE); packet_append_string(rpacket, mpqfilename); } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] no upgrade for %s is available", conn_get_socket(c), versiontag); bn_int_set(&rpacket->u.server_authreply_109.message, SERVER_AUTHREPLY_109_MESSAGE_OK); packet_append_string(rpacket, ""); } if (mpqfilename) xfree((void *) mpqfilename); } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_regsnoopreply(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_regsnoopreply)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REGSNOOPREPLY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_regsnoopreply), packet_get_size(packet)); return -1; } return 0; } static int _client_iconreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_iconreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ICONREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_iconreq), packet_get_size(packet)); return -1; } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_iconreply)); packet_set_type(rpacket, SERVER_ICONREPLY); file_to_mod_time(prefs_get_iconfile(), &rpacket->u.server_iconreply.timestamp); /* battle.net sends different file on iconreq for WAR3 and W3XP [Omega] */ if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT)) packet_append_string(rpacket, prefs_get_war3_iconfile()); /* battle.net still sends "icons.bni" to sc/bw clients * clients request icons_STAR.bni seperatly */ /* else if (strcmp(conn_get_clienttag(c),CLIENTTAG_STARCRAFT)==0) packet_append_string(rpacket,prefs_get_star_iconfile()); else if (strcmp(conn_get_clienttag(c),CLIENTTAG_BROODWARS)==0) packet_append_string(rpacket,prefs_get_star_iconfile()); */ else packet_append_string(rpacket, prefs_get_iconfile()); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_cdkey(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_cdkey)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_cdkey), packet_get_size(packet)); return -1; } { char const *cdkey; char const *owner; if (!(cdkey = packet_get_str_const(packet, sizeof(t_client_cdkey), MAX_CDKEY_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY packet (missing or too long cdkey)", conn_get_socket(c)); return -1; } if (!(owner = packet_get_str_const(packet, sizeof(t_client_cdkey) + strlen(cdkey) + 1, MAX_OWNER_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY packet (missing or too long owner)", conn_get_socket(c)); return -1; } conn_set_cdkey(c, cdkey); conn_set_owner(c, owner); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_cdkeyreply)); packet_set_type(rpacket, SERVER_CDKEYREPLY); bn_int_set(&rpacket->u.server_cdkeyreply.message, SERVER_CDKEYREPLY_MESSAGE_OK); packet_append_string(rpacket, owner); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } #if 0 /* Blizzard used this to track down pirates, should only be accepted by old clients */ if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_regsnoopreq)); packet_set_type(rpacket, SERVER_REGSNOOPREQ); bn_int_set(&rpacket->u.server_regsnoopreq.unknown1, SERVER_REGSNOOPREQ_UNKNOWN1); /* sequence num */ bn_int_set(&rpacket->u.server_regsnoopreq.hkey, SERVER_REGSNOOPREQ_HKEY_CURRENT_USER); packet_append_string(rpacket, SERVER_REGSNOOPREQ_REGKEY); packet_append_string(rpacket, SERVER_REGSNOOPREQ_REGVALNAME); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } #endif return 0; } static int _client_cdkey2(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_cdkey2)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_cdkey2), packet_get_size(packet)); return -1; } { char const *owner; if (!(owner = packet_get_str_const(packet, sizeof(t_client_cdkey2), MAX_OWNER_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY2 packet (missing or too long owner)", conn_get_socket(c)); return -1; } conn_set_owner(c, owner); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_cdkeyreply2)); packet_set_type(rpacket, SERVER_CDKEYREPLY2); bn_int_set(&rpacket->u.server_cdkeyreply2.message, SERVER_CDKEYREPLY2_MESSAGE_OK); packet_append_string(rpacket, owner); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_cdkey3(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_cdkey3)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_cdkey2), packet_get_size(packet)); return -1; } { char const *owner; if (!(owner = packet_get_str_const(packet, sizeof(t_client_cdkey3), MAX_OWNER_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY3 packet (missing or too long owner)", conn_get_socket(c)); return -1; } conn_set_owner(c, owner); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_cdkeyreply3)); packet_set_type(rpacket, SERVER_CDKEYREPLY3); bn_int_set(&rpacket->u.server_cdkeyreply3.message, SERVER_CDKEYREPLY3_MESSAGE_OK); packet_append_string(rpacket, ""); /* FIXME: owner, message, ??? */ conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_udpok(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_udpok)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UDPOK packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_udpok), packet_get_size(packet)); return -1; } /* we could check the contents but there really isn't any point */ conn_set_udpok(c); return 0; } static int _client_fileinforeq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_fileinforeq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad FILEINFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_fileinforeq), packet_get_size(packet)); return -1; } { char const *tosfile; if (!(tosfile = packet_get_str_const(packet, sizeof(t_client_fileinforeq), MAX_FILENAME_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad FILEINFOREQ packet (missing or too long tosfile)", conn_get_socket(c)); return -1; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] TOS requested: \"%s\" - type = 0x%02x", conn_get_socket(c), tosfile, bn_int_get(packet->u.client_fileinforeq.type)); /* TODO: if type is TOSFILE make bnetd to send default tosfile if selected is not found */ if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_fileinforeply)); packet_set_type(rpacket, SERVER_FILEINFOREPLY); bn_int_set(&rpacket->u.server_fileinforeply.type, bn_int_get(packet->u.client_fileinforeq.type)); bn_int_set(&rpacket->u.server_fileinforeply.unknown2, bn_int_get(packet->u.client_fileinforeq.unknown2)); /* Note from Sherpya: * timestamp -> 0x852b7d00 - 0x01c0e863 b.net send this (bn_int), * I suppose is not a long * if bnserver-D2DV is bad diablo 2 crashes * timestamp doesn't work correctly and starcraft * needs name in client locale or displays hostname */ file_to_mod_time(tosfile, &rpacket->u.server_fileinforeply.timestamp); packet_append_string(rpacket, tosfile); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static const char *_attribute_req(t_account * reqacc, t_account * myacc, const char *key) { const char *result = ""; const char *tval; if (!reqacc) goto out; if (reqacc != myacc && !strncasecmp(key, "BNET", 4)) goto out; tval = account_get_strattr(reqacc, key); if (tval) result = tval; out: return result; } static int _client_statsreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; char const *name; char const *key; unsigned int name_count; unsigned int key_count; unsigned int i, j; unsigned int name_off; unsigned int keys_off; unsigned int key_off; t_account *reqacc, *myacc; if (packet_get_size(packet) < sizeof(t_client_statsreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_statsreq), packet_get_size(packet)); return -1; } name_count = bn_int_get(packet->u.client_statsreq.name_count); key_count = bn_int_get(packet->u.client_statsreq.key_count); for (i = 0, name_off = sizeof(t_client_statsreq); i < name_count && (name = packet_get_str_const(packet, name_off, UNCHECKED_NAME_STR)); i++, name_off += strlen(name) + 1); if (i < name_count) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSREQ packet (only %u names of %u)", conn_get_socket(c), i, name_count); return -1; } keys_off = name_off; if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_statsreply)); packet_set_type(rpacket, SERVER_STATSREPLY); bn_int_set(&rpacket->u.server_statsreply.name_count, name_count); bn_int_set(&rpacket->u.server_statsreply.key_count, key_count); bn_int_set(&rpacket->u.server_statsreply.requestid, bn_int_get(packet->u.client_statsreq.requestid)); myacc = conn_get_account(c); for (i = 0, name_off = sizeof(t_client_statsreq); i < name_count && (name = packet_get_str_const(packet, name_off, UNCHECKED_NAME_STR)); i++, name_off += strlen(name) + 1) { reqacc = accountlist_find_account(name); if (!reqacc) reqacc = myacc; for (j = 0, key_off = keys_off; j < key_count && (key = packet_get_str_const(packet, key_off, MAX_ATTRKEY_STR)); j++, key_off += strlen(key) + 1) { if (*key == '\0') continue; packet_append_string(rpacket, _attribute_req(reqacc, myacc, key)); } } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } static int _client_loginreq1(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_loginreq1)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGINREQ1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_loginreq1), packet_get_size(packet)); return -1; } { char const *username; t_account *account; if (!(username = packet_get_str_const(packet, sizeof(t_client_loginreq1), USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGINREQ1 (missing or too long username)", conn_get_socket(c)); return -1; } if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_loginreply1)); packet_set_type(rpacket, SERVER_LOGINREPLY1); // too many logins? [added by NonReal] if (prefs_get_max_concurrent_logins() > 0) { if (prefs_get_max_concurrent_logins() <= connlist_login_get_length()) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] login denied, too many concurrent logins. max: %d. current: %d.", conn_get_socket(c), prefs_get_max_concurrent_logins(), connlist_login_get_length()); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL); return -1; } } /* fail if no account */ if (!(account = accountlist_find_account(username))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (no such account)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL); } else /* already logged in */ if (connlist_find_connection_by_account(account) && prefs_get_kick_old_login() == 0) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (already logged in)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL); } else if (account_get_auth_bnetlogin(account) == 0) { /* default to true */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (no bnet access)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL); } else if (account_get_auth_lock(account) == 1) { /* default to false */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (this account is locked)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL); } else if (conn_get_sessionkey(c) != bn_int_get(packet->u.client_loginreq1.sessionkey)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] login for \"%s\" refused (expected session key 0x%08x, got 0x%08x)", conn_get_socket(c), username, conn_get_sessionkey(c), bn_int_get(packet->u.client_loginreq1.sessionkey)); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL); } else { struct { bn_int ticks; bn_int sessionkey; bn_int passhash1[5]; } temp; char const *oldstrhash1; t_hash oldpasshash1; t_hash oldpasshash2; t_hash trypasshash2; if ((oldstrhash1 = account_get_pass(account))) { bn_int_set(&temp.ticks, bn_int_get(packet->u.client_loginreq1.ticks)); bn_int_set(&temp.sessionkey, bn_int_get(packet->u.client_loginreq1.sessionkey)); if (hash_set_str(&oldpasshash1, oldstrhash1) < 0) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (corrupted passhash1?)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL); } else { hash_to_bnhash((t_hash const *) &oldpasshash1, temp.passhash1); /* avoid warning */ bnet_hash(&oldpasshash2, sizeof(temp), &temp); /* do the double hash */ bnhash_to_hash(packet->u.client_loginreq1.password_hash2, &trypasshash2); if (hash_eq(trypasshash2, oldpasshash2) == 1) { conn_login(c, account, username); eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" logged in (correct password)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_SUCCESS); #ifdef WIN32_GUI guiOnUpdateUserList(); #endif } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (wrong password)", conn_get_socket(c), username); conn_increment_passfail_count(c); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL); } } } else { conn_login(c, account, username); eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" logged in (no password)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_SUCCESS); #ifdef WIN32_GUI guiOnUpdateUserList(); #endif } } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } void client_init_email(t_connection * c, t_account * account) { t_packet *packet; char const *email; if (!c || !account) return; if (!(email = account_get_email(account))) { if ((packet = packet_create(packet_class_bnet))) { packet_set_size(packet, sizeof(t_server_setemailreq)); packet_set_type(packet, SERVER_SETEMAILREQ); conn_push_outqueue(c, packet); packet_del_ref(packet); } } return; } static int _client_loginreq2(t_connection * c, t_packet const *const packet) { t_packet *rpacket; int success = 0; if (packet_get_size(packet) < sizeof(t_client_loginreq2)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGINREQ2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_loginreq2), packet_get_size(packet)); return -1; } { char const *username; t_account *account; if (!(username = packet_get_str_const(packet, sizeof(t_client_loginreq2), USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGINREQ2 (missing or too long username)", conn_get_socket(c)); return -1; } if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_loginreply2)); packet_set_type(rpacket, SERVER_LOGINREPLY2); // too many logins? [added by NonReal] if (prefs_get_max_concurrent_logins() > 0) { if (prefs_get_max_concurrent_logins() <= connlist_login_get_length()) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] login denied, too many concurrent logins. max: %d. current: %d.", conn_get_socket(c), prefs_get_max_concurrent_logins(), connlist_login_get_length()); bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS); return -1; } } /* fail if no account */ if (!(account = accountlist_find_account(username))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (no such account)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_NONEXIST); } /* already logged in */ else if (connlist_find_connection_by_account(account) && prefs_get_kick_old_login() == 0) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (already logged in)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS); } else if (account_get_auth_bnetlogin(account) == 0) { /* default to true */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (no bnet access)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS); } else if (account_get_auth_lock(account) == 1) { /* default to false */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (this account is locked)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS); } else if (conn_get_sessionkey(c) != bn_int_get(packet->u.client_loginreq2.sessionkey)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] login for \"%s\" refused (expected session key 0x%08x, got 0x%08x)", conn_get_socket(c), username, conn_get_sessionkey(c), bn_int_get(packet->u.client_loginreq2.sessionkey)); bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS); } else { struct { bn_int ticks; bn_int sessionkey; bn_int passhash1[5]; } temp; char const *oldstrhash1; t_hash oldpasshash1; t_hash oldpasshash2; t_hash trypasshash2; if ((oldstrhash1 = account_get_pass(account))) { bn_int_set(&temp.ticks, bn_int_get(packet->u.client_loginreq2.ticks)); bn_int_set(&temp.sessionkey, bn_int_get(packet->u.client_loginreq2.sessionkey)); if (hash_set_str(&oldpasshash1, oldstrhash1) < 0) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (corrupted passhash1?)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS); } else { hash_to_bnhash((t_hash const *) &oldpasshash1, temp.passhash1); /* avoid warning */ bnet_hash(&oldpasshash2, sizeof(temp), &temp); /* do the double hash */ bnhash_to_hash(packet->u.client_loginreq2.password_hash2, &trypasshash2); if (hash_eq(trypasshash2, oldpasshash2) == 1) { conn_login(c, account, username); eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" logged in (correct password)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_SUCCESS); success = 1; } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (wrong password)", conn_get_socket(c), username); conn_increment_passfail_count(c); bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS); } } } else { conn_login(c, account, username); eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" logged in (no password)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_SUCCESS); success = 1; } } if (success && account) { #ifdef WIN32_GUI guiOnUpdateUserList(); #endif client_init_email(c, account); } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_loginreqw3(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_loginreq_w3)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_LOGINREQ_W3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_loginreq_w3), packet_get_size(packet)); return -1; } { char const *username; t_account *account; int i; if (!(username = packet_get_str_const(packet, sizeof(t_client_loginreq_w3), USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_LOGINREQ_W3 (missing or too long username)", conn_get_socket(c)); return -1; } if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_loginreply_w3)); packet_set_type(rpacket, SERVER_LOGINREPLY_W3); for (i = 0; i < 16; i++) bn_int_set(&rpacket->u.server_loginreply_w3.unknown[i], 0); { /* too many logins? */ if (prefs_get_max_concurrent_logins() > 0 && prefs_get_max_concurrent_logins() <= connlist_login_get_length()) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] login denied, too many concurrent logins. max: %d. current: %d.", conn_get_socket(c), prefs_get_max_concurrent_logins(), connlist_login_get_length()); bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_BADACCT); } else /* fail if no account */ if (!(account = accountlist_find_account(username))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) login for \"%s\" refused (no such account)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_BADACCT); } else /* already logged in */ if (connlist_find_connection_by_account(account) && prefs_get_kick_old_login() == 0) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) login for \"%s\" refused (already logged in)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_ALREADY); } else if (account_get_auth_bnetlogin(account) == 0) { /* default to true */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) login for \"%s\" refused (no bnet access)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_BADACCT); } else if (account_get_auth_lock(account) == 1) { /* default to false */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (this account is locked)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY_W3_MESSAGE_BADACCT); } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) \"%s\" passed account check", conn_get_socket(c), username); conn_set_loggeduser(c, username); bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_SUCCESS); } } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_pingreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_pingreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PINGREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_pingreq), packet_get_size(packet)); return -1; } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_pingreply)); packet_set_type(rpacket, SERVER_PINGREPLY); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_logonproofreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_logonproofreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGONPROOFREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_logonproofreq), packet_get_size(packet)); return -1; } { char const *username; t_account *account; eventlog(eventlog_level_info, __FUNCTION__, "[%d] logon proof requested", conn_get_socket(c)); if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_logonproofreply)); packet_set_type(rpacket, SERVER_LOGONPROOFREPLY); bn_int_set(&rpacket->u.server_logonproofreply.response, SERVER_LOGONPROOFREPLY_RESPONSE_BADPASS); bn_int_set(&rpacket->u.server_logonproofreply.unknown1, SERVER_LOGONPROOFREPLY_UNKNOWN1); bn_short_set(&rpacket->u.server_logonproofreply.port0, (short) 0x0000); bn_int_set(&rpacket->u.server_logonproofreply.unknown2, SERVER_LOGONPROOFREPLY_UNKNOWN2); bn_short_set(&rpacket->u.server_logonproofreply.port1, (short) 0x0000); bn_int_set(&rpacket->u.server_logonproofreply.unknown3, SERVER_LOGONPROOFREPLY_UNKNOWN3); bn_int_set(&rpacket->u.server_logonproofreply.unknown4, SERVER_LOGONPROOFREPLY_UNKNOWN4); if (!(username = conn_get_loggeduser(c))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) got NULL username, 0x54ff before 0x53ff?", conn_get_socket(c)); } else if (!(account = accountlist_find_account(username))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) login in 0x54ff for \"%s\" refused (no such account)", conn_get_socket(c), username); } else { t_hash serverhash; t_hash clienthash; if (!packet_get_data_const(packet, 4, 20)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] (W3) got bad LOGONPROOFREQ packet (missing hash)", conn_get_socket(c)); return -1; } // endian fix clienthash[0] = bn_int_get(packet->u.client_logonproofreq.password_hash1[0]); clienthash[1] = bn_int_get(packet->u.client_logonproofreq.password_hash1[1]); clienthash[2] = bn_int_get(packet->u.client_logonproofreq.password_hash1[2]); clienthash[3] = bn_int_get(packet->u.client_logonproofreq.password_hash1[3]); clienthash[4] = bn_int_get(packet->u.client_logonproofreq.password_hash1[4]); hash_set_str(&serverhash, account_get_pass(account)); if (hash_eq(clienthash, serverhash)) { conn_login(c, account, username); eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) \"%s\" logged in (right password)", conn_get_socket(c), username); if ((conn_get_versionid(c) >= 0x0000000D) && (account_get_email(account) == NULL)) bn_int_set(&rpacket->u.server_logonproofreply.response, SERVER_LOGONPROOFREPLY_RESPONSE_EMAIL); else bn_int_set(&rpacket->u.server_logonproofreply.response, SERVER_LOGONPROOFREPLY_RESPONSE_OK); // by amadeo updates the userlist #ifdef WIN32_GUI guiOnUpdateUserList(); #endif } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) got wrong password for \"%s\"", conn_get_socket(c), username); conn_increment_passfail_count(c); } } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } clan_send_status_window(c); return 0; } static int _client_changegameport(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_changegameport)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad changegameport packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_changegameport), packet_get_size(packet)); return -1; } { unsigned short port = bn_short_get(packet->u.client_changegameport.port); if (port < 1024) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] invalid port in changegameport packet: %d", conn_get_socket(c), (int) port); return -1; } conn_set_game_port(c, port); } return 0; } static int _client_friendslistreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_friendslistreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad FRIENDSLISTREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_friendslistreq), packet_get_size(packet)); return -1; } { int friend; t_list *flist; t_friend *fr; t_account *account = conn_get_account(c); int i; int n = account_get_friendcount(account); int friendcount = 0; t_server_friendslistreply_status status; t_connection *dest_c; t_game *game; t_channel *channel; char stat; if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_friendslistreply)); packet_set_type(rpacket, SERVER_FRIENDSLISTREPLY); if ((flist = account_get_friends(account)) == NULL) return -1; for (i = 0; i < n; i++) { friend = account_get_friend(account, i); if ((fr = friendlist_find_uid(flist, friend)) == NULL) continue; packet_append_string(rpacket, account_get_name(friend_get_account(fr))); game = NULL; channel = NULL; if (!(dest_c = connlist_find_connection_by_uid(friend))) { bn_byte_set(&status.location, FRIENDSTATUS_OFFLINE); bn_byte_set(&status.status, 0); bn_int_set(&status.clienttag, 0); } else { bn_int_set(&status.clienttag, conn_get_clienttag(dest_c)); stat = 0; if ((friend_get_mutual(fr))) stat |= FRIEND_TYPE_MUTUAL; if ((conn_get_dndstr(dest_c))) stat |= FRIEND_TYPE_DND; if ((conn_get_awaystr(dest_c))) stat |= FRIEND_TYPE_AWAY; bn_byte_set(&status.status, stat); if ((game = conn_get_game(dest_c))) { if (game_get_flag(game) != game_flag_private) bn_byte_set(&status.location, FRIENDSTATUS_PUBLIC_GAME); else bn_byte_set(&status.location, FRIENDSTATUS_PRIVATE_GAME); } else if ((channel = conn_get_channel(dest_c))) { bn_byte_set(&status.location, FRIENDSTATUS_CHAT); } else { bn_byte_set(&status.location, FRIENDSTATUS_ONLINE); } } packet_append_data(rpacket, &status, sizeof(status)); if (game) packet_append_string(rpacket, game_get_name(game)); else if (channel) packet_append_string(rpacket, channel_get_name(channel)); else packet_append_string(rpacket, ""); friendcount++; } bn_byte_set(&rpacket->u.server_friendslistreply.friendcount, friendcount); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_friendinforeq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_friendinforeq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad FRIENDINFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_friendinforeq), packet_get_size(packet)); return -1; } { t_connection const *dest_c; t_game const *game; t_channel const *channel; t_account *account = conn_get_account(c); int friend; t_friend *fr; t_list *flist; int n = account_get_friendcount(account); char type; if (n == 0) return 0; if (bn_byte_get(packet->u.client_friendinforeq.friendnum) > n) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] bad friend number in FRIENDINFOREQ packet", conn_get_socket(c)); return -1; } if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_friendinforeply)); packet_set_type(rpacket, SERVER_FRIENDINFOREPLY); friend = account_get_friend(account, bn_byte_get(packet->u.client_friendinforeq.friendnum)); if (friend < 0) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] friend number %d not found", conn_get_socket(c), (int) bn_byte_get(packet->u.client_friendinforeq.friendnum)); return -1; } bn_byte_set(&rpacket->u.server_friendinforeply.friendnum, bn_byte_get(packet->u.client_friendinforeq.friendnum)); flist = account_get_friends(account); fr = friendlist_find_uid(flist, friend); if (fr == NULL || (dest_c = connlist_find_connection_by_account(friend_get_account(fr))) == NULL) { bn_byte_set(&rpacket->u.server_friendinforeply.type, FRIEND_TYPE_NON_MUTUAL); bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_OFFLINE); bn_int_set(&rpacket->u.server_friendinforeply.clienttag, 0); packet_append_string(rpacket, ""); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } type = FRIEND_TYPE_NON_MUTUAL; if (friend_get_mutual(fr)) type |= FRIEND_TYPE_MUTUAL; if ((conn_get_dndstr(dest_c))) type |= FRIEND_TYPE_DND; if ((conn_get_awaystr(dest_c))) type |= FRIEND_TYPE_AWAY; bn_byte_set(&rpacket->u.server_friendinforeply.type, type); if ((game = conn_get_game(dest_c))) { if (game_get_flag(game) != game_flag_private) bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_PUBLIC_GAME); else bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_PRIVATE_GAME); packet_append_string(rpacket, game_get_name(game)); } else if ((channel = conn_get_channel(dest_c))) { bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_CHAT); packet_append_string(rpacket, channel_get_name(channel)); } else { bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_ONLINE); packet_append_string(rpacket, ""); } bn_int_set(&rpacket->u.server_friendinforeply.clienttag, conn_get_clienttag(dest_c)); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_atfriendscreen(t_connection * c, t_packet const *const packet) { char const *myusername; char const *fname; t_connection *dest_c; unsigned char f_cnt = 0; t_account *account; t_packet *rpacket; char const *vt; char const *nvt; t_friend *fr; t_list *flist; t_elem *curr; t_channel *mychannel, *chan; int publicchan = 1; eventlog(eventlog_level_info, __FUNCTION__, "[%d] got CLIENT_ARRANGEDTEAM_FRIENDSCREEN packet", conn_get_socket(c)); myusername = conn_get_username(c); eventlog(eventlog_level_trace, "handle_bnet", "[%d] AT - Got Username %s", conn_get_socket(c), myusername); if (!(rpacket = packet_create(packet_class_bnet))) { eventlog(eventlog_level_error, "handle_bnet", "[%d] AT - can't create friendscreen server packet", conn_get_socket(c)); return -1; } packet_set_size(rpacket, sizeof(t_server_arrangedteam_friendscreen)); packet_set_type(rpacket, SERVER_ARRANGEDTEAM_FRIENDSCREEN); mychannel = conn_get_channel(c); if ((mychannel)) publicchan = channel_get_flags(mychannel) & channel_flags_public; vt = versioncheck_get_versiontag(conn_get_versioncheck(c)); flist = account_get_friends(conn_get_account(c)); LIST_TRAVERSE(flist, curr) { if (!(fr = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } account = friend_get_account(fr); if (!(dest_c = connlist_find_connection_by_account(account))) continue; // if user is offline, then continue to next friend nvt = versioncheck_get_versiontag(conn_get_versioncheck(dest_c)); if (vt && nvt && strcmp(vt, nvt)) continue; /* friend is using another game/version */ if (friend_get_mutual(fr)) { if (conn_get_dndstr(dest_c)) continue; // user is dnd if (conn_get_awaystr(dest_c)) continue; // user is away if (conn_get_game(dest_c)) continue; // user is some game if (!(chan = conn_get_channel(dest_c))) continue; if (!publicchan && (chan == mychannel)) continue; // don't list YET if in same private channel fname = account_get_name(account); eventlog(eventlog_level_trace, "handle_bnet", "AT - Friend: %s is available for a AT Game.", fname); f_cnt++; packet_append_string(rpacket, fname); } } if (!publicchan) { // now list matching users in same private chan for (dest_c = channel_get_first(mychannel); dest_c; dest_c = channel_get_next()) { if (dest_c == c) continue; // don'tlist yourself nvt = versioncheck_get_versiontag(conn_get_versioncheck(dest_c)); if (vt && nvt && strcmp(vt, nvt)) continue; /* user is using another game/version */ if (conn_get_dndstr(dest_c)) continue; // user is dnd if (conn_get_awaystr(dest_c)) continue; // user is away if (!(conn_get_account(dest_c))) continue; fname = account_get_name(conn_get_account(dest_c)); eventlog(eventlog_level_trace, "handle_bnet", "AT - user in private channel: %s is available for a AT Game.", fname); f_cnt++; packet_append_string(rpacket, fname); } } if (!f_cnt) eventlog(eventlog_level_info, "handle_bnet", "AT - no friends available for AT game."); bn_byte_set(&rpacket->u.server_arrangedteam_friendscreen.f_count, f_cnt); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } static int _client_atinvitefriend(t_connection * c, t_packet const *const packet) { t_packet *rpacket; t_clienttag ctag; if (packet_get_size(packet) < sizeof(t_client_arrangedteam_invite_friend)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ARRANGEDTEAM_INVITE_FRIEND packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_arrangedteam_invite_friend), packet_get_size(packet)); return -1; } ctag = conn_get_clienttag(c); { int count_to_invite, count, id; char const *invited_usernames[8]; t_account *members[MAX_TEAMSIZE]; int i, n, offset, teammemcount; t_connection *dest_c; t_team *team; unsigned int teamid; count_to_invite = bn_byte_get(packet->u.client_arrangedteam_invite_friend.numfriends); count = bn_int_get(packet->u.client_arrangedteam_invite_friend.count); id = bn_int_get(packet->u.client_arrangedteam_invite_friend.id); teammemcount = count_to_invite + 1; if ((count_to_invite < 1) || (count_to_invite > 3)) { eventlog(eventlog_level_error, __FUNCTION__, "got invalid number of users to invite to game"); return -1; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] got ARRANGEDTEAM INVITE packet for %d invitees", conn_get_socket(c), count_to_invite); offset = sizeof(t_client_arrangedteam_invite_friend); for (i = 0; i < count_to_invite; i++) { if (!(invited_usernames[i] = packet_get_str_const(packet, offset, USER_NAME_MAX))) { eventlog(eventlog_level_error, "handle_bnet", "Could not get username from invite packet"); return -1; } else { offset += strlen(invited_usernames[i]) + 1; eventlog(eventlog_level_debug, "handle_bnet", "Added user %s to invite array.", invited_usernames[i]); } } members[0] = conn_get_account(c); for (i = 1; i < MAX_TEAMSIZE; i++) { if ((i < teammemcount)) { if (!(members[i] = accountlist_find_account(invited_usernames[i - 1]))) { eventlog(eventlog_level_error, __FUNCTION__, "got invitation for non-existant user \"%s\"", invited_usernames[i - 1]); return -1; } } else members[i] = NULL; } if (!(team = account_find_team_by_accounts(members[0], members, ctag))) { team = create_team(members, ctag); //no need to free on return -1 because it's allready in teamlist eventlog(eventlog_level_trace, __FUNCTION__, "this team has never played before, creating new team"); } else { eventlog(eventlog_level_trace, __FUNCTION__, "this team has allready played before"); } teamid = team_get_teamid(team); account_set_currentatteam(conn_get_account(c), team_get_teamid(team)); //Create the packet to send to each of the users you wanted to invite conn_set_channel(c, NULL); for (i = 0; i < teammemcount; i++) { if (!(dest_c = account_get_conn(team_get_member(team, i)))) continue; if ((dest_c == c)) continue; if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_arrangedteam_send_invite)); packet_set_type(rpacket, SERVER_ARRANGEDTEAM_SEND_INVITE); bn_int_set(&rpacket->u.server_arrangedteam_send_invite.count, count); bn_int_set(&rpacket->u.server_arrangedteam_send_invite.id, id); { /* trans support */ unsigned short port = conn_get_game_port(c); unsigned int addr = conn_get_addr(c); trans_net(conn_get_addr(dest_c), &addr, &port); bn_int_nset(&rpacket->u.server_arrangedteam_send_invite.inviterip, addr); bn_short_set(&rpacket->u.server_arrangedteam_send_invite.port, port); } bn_byte_set(&rpacket->u.server_arrangedteam_send_invite.numfriends, count_to_invite); for (n = 0; n < teammemcount; n++) { if (n != i) packet_append_string(rpacket, account_get_name(team_get_member(team, n))); } //now send packet conn_push_outqueue(dest_c, rpacket); packet_del_ref(rpacket); account_set_currentatteam(conn_get_account(dest_c), teamid); } //now send a ACK to the inviter if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_arrangedteam_invite_friend_ack)); packet_set_type(rpacket, SERVER_ARRANGEDTEAM_INVITE_FRIEND_ACK); bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.count, count); bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.id, id); bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.timestamp, now); bn_byte_set(&rpacket->u.server_arrangedteam_invite_friend_ack.teamsize, count_to_invite + 1); /* * five int's to fill * fill with uid's of all teammembers, including the inviter * and the rest with FFFFFFFF * to be used when sever recieves anongame search * [Omega] */ for (i = 0; i < 5; i++) { if (i < teammemcount) { bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.info[i], team_get_memberuid(team, i)); } else { /* fill rest with FFFFFFFF */ bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.info[i], 0xFFFFFFFF); } } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_atacceptdeclineinvite(t_connection * c, t_packet const *const packet) { t_packet *rpacket; t_clienttag ctag; if (packet_get_size(packet) < sizeof(t_client_arrangedteam_accept_decline_invite)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ARRANGEDTEAM_ACCEPT_DECLINE_INVITE packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_arrangedteam_accept_decline_invite), packet_get_size(packet)); return -1; } ctag = conn_get_clienttag(c); { char const *inviter; t_connection *dest_c; //if user declined the invitation then if (bn_int_get(packet->u.client_arrangedteam_accept_decline_invite.option) == CLIENT_ARRANGEDTEAM_DECLINE) { inviter = packet_get_str_const(packet, sizeof(t_client_arrangedteam_accept_decline_invite), USER_NAME_MAX); dest_c = connlist_find_connection_by_accountname(inviter); eventlog(eventlog_level_info, "handle_bnet", "%s declined a arranged team game with %s", conn_get_username(c), inviter); if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_arrangedteam_member_decline)); packet_set_type(rpacket, SERVER_ARRANGEDTEAM_MEMBER_DECLINE); bn_int_set(&rpacket->u.server_arrangedteam_member_decline.count, bn_int_get(packet->u.client_arrangedteam_accept_decline_invite.count)); bn_int_set(&rpacket->u.server_arrangedteam_member_decline.action, SERVER_ARRANGEDTEAM_DECLINE); packet_append_string(rpacket, conn_get_username(c)); conn_push_outqueue(dest_c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_atacceptinvite(t_connection * c, t_packet const *const packet) { // t_packet * rpacket; if (packet_get_size(packet) < sizeof(t_client_arrangedteam_accept_invite)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ARRANGEDTEAM_ACCEPT_INVITE packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_arrangedteam_accept_invite), packet_get_size(packet)); return -1; } /* conn_set_channel(c, "Arranged Teams"); */ return 0; } typedef struct { t_connection *c; unsigned lnews; unsigned fnews; } t_motd_data; static int _news_cb(time_t date, t_lstr * lstr, void *data) { t_packet *rpacket; t_motd_data *motdd = (t_motd_data *) data; if (date < motdd->lnews) return -1; /* exit traversing */ rpacket = packet_create(packet_class_bnet); if (!rpacket) return -1; packet_set_size(rpacket, sizeof(t_server_motd_w3)); packet_set_type(rpacket, SERVER_MOTD_W3); bn_byte_set(&rpacket->u.server_motd_w3.msgtype, SERVER_MOTD_W3_MSGTYPE); bn_int_set(&rpacket->u.server_motd_w3.curr_time, now); bn_int_set(&rpacket->u.server_motd_w3.first_news_time, motdd->fnews); bn_int_set(&rpacket->u.server_motd_w3.timestamp, date); bn_int_set(&rpacket->u.server_motd_w3.timestamp2, date); /* Append news to packet, we used the already cached len in the lstr */ packet_append_lstr(rpacket, lstr); /* Send news packet */ conn_push_outqueue(motdd->c, rpacket); packet_del_ref(rpacket); return 0; } static int _client_motdw3(t_connection * c, t_packet const *const packet) { t_packet *rpacket; char serverinfo[512]; t_clienttag ctag; t_motd_data motdd; if (packet_get_size(packet) < sizeof(t_client_motd_w3)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_MOTD_W3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_motd_w3), packet_get_size(packet)); return -1; } ctag = conn_get_clienttag(c); /* if in a game, remove user from his game */ if (conn_get_game(c) != NULL) conn_set_game(c, NULL, NULL, NULL, game_type_none, 0); /* News */ motdd.lnews = bn_int_get(packet->u.client_motd_w3.last_news_time); motdd.fnews = news_get_firstnews(); motdd.c = c; eventlog(eventlog_level_trace, __FUNCTION__, "lastnews() %u news_time %u", news_get_lastnews(), motdd.lnews); news_traverse(_news_cb, &motdd); /* Welcome Message */ rpacket = packet_create(packet_class_bnet); if (!rpacket) return -1; packet_set_size(rpacket, sizeof(t_server_motd_w3)); packet_set_type(rpacket, SERVER_MOTD_W3); //bn_int_set(&rpacket->u.server_motd_w3.ticks,get_ticks()); bn_byte_set(&rpacket->u.server_motd_w3.msgtype, SERVER_MOTD_W3_MSGTYPE); bn_int_set(&rpacket->u.server_motd_w3.curr_time, now); bn_int_set(&rpacket->u.server_motd_w3.first_news_time, motdd.fnews); bn_int_set(&rpacket->u.server_motd_w3.timestamp, motdd.fnews + 1); bn_int_set(&rpacket->u.server_motd_w3.timestamp2, SERVER_MOTD_W3_WELCOME); sprintf(serverinfo, "Welcome to the " PVPGN_SOFTWARE " Version " PVPGN_VERSION "\r\n\r\nThere are currently %u user(s) in %u games of %s, and %u user(s) playing %u games and chatting in %u channels in %s.\r\n%s", conn_get_user_count_by_clienttag(conn_get_clienttag(c)), game_get_count_by_clienttag(ctag), clienttag_get_title(conn_get_clienttag(c)), connlist_login_get_length(), gamelist_get_length(), channellist_get_length(), prefs_get_servername(),prefs_get_server_info()); packet_append_string(rpacket, serverinfo); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } static int _client_realmlistreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_realmlistreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REALMLISTREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_realmlistreq), packet_get_size(packet)); return -1; } if ((rpacket = packet_create(packet_class_bnet))) { t_elem const *curr; t_realm const *realm; t_server_realmlistreply_data realmdata; unsigned int count; packet_set_size(rpacket, sizeof(t_server_realmlistreply)); packet_set_type(rpacket, SERVER_REALMLISTREPLY); bn_int_set(&rpacket->u.server_realmlistreply.unknown1, SERVER_REALMLISTREPLY_UNKNOWN1); count = 0; LIST_TRAVERSE_CONST(realmlist(), curr) { realm = elem_get_data(curr); if (!realm_get_active(realm)) continue; bn_int_set(&realmdata.unknown3, SERVER_REALMLISTREPLY_DATA_UNKNOWN3); bn_int_set(&realmdata.unknown4, SERVER_REALMLISTREPLY_DATA_UNKNOWN4); bn_int_set(&realmdata.unknown5, SERVER_REALMLISTREPLY_DATA_UNKNOWN5); bn_int_set(&realmdata.unknown6, SERVER_REALMLISTREPLY_DATA_UNKNOWN6); bn_int_set(&realmdata.unknown7, SERVER_REALMLISTREPLY_DATA_UNKNOWN7); bn_int_set(&realmdata.unknown8, SERVER_REALMLISTREPLY_DATA_UNKNOWN8); bn_int_set(&realmdata.unknown9, SERVER_REALMLISTREPLY_DATA_UNKNOWN9); packet_append_data(rpacket, &realmdata, sizeof(realmdata)); packet_append_string(rpacket, realm_get_name(realm)); packet_append_string(rpacket, realm_get_description(realm)); count++; } bn_int_set(&rpacket->u.server_realmlistreply.count, count); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_realmlistreq110(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_realmlistreq_110)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REALMLISTREQ_110 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_realmlistreq), packet_get_size(packet)); return -1; } if ((rpacket = packet_create(packet_class_bnet))) { t_elem const *curr; t_realm const *realm; t_server_realmlistreply_110_data realmdata; unsigned int count; packet_set_size(rpacket, sizeof(t_server_realmlistreply_110)); packet_set_type(rpacket, SERVER_REALMLISTREPLY_110); bn_int_set(&rpacket->u.server_realmlistreply_110.unknown1, SERVER_REALMLISTREPLY_110_UNKNOWN1); count = 0; LIST_TRAVERSE_CONST(realmlist(), curr) { realm = elem_get_data(curr); if (!realm_get_active(realm)) continue; bn_int_set(&realmdata.unknown1, SERVER_REALMLISTREPLY_110_DATA_UNKNOWN1); packet_append_data(rpacket, &realmdata, sizeof(realmdata)); packet_append_string(rpacket, realm_get_name(realm)); packet_append_string(rpacket, realm_get_description(realm)); count++; } bn_int_set(&rpacket->u.server_realmlistreply_110.count, count); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_claninforeq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; int count; char const *username; t_account *account; t_clanmember *clanmember; t_clan *clan; int clantag1; int clantag2; if (packet_get_size(packet) < sizeof(t_client_claninforeq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLANINFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_claninforeq), packet_get_size(packet)); return -1; } count = bn_int_get(packet->u.client_claninforeq.count); clantag1 = bn_int_get(packet->u.client_claninforeq.clantag); clan = NULL; if (!(username = packet_get_str_const(packet, sizeof(t_client_claninforeq), USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLANINFOREQ (missing or too long username)", conn_get_socket(c)); return -1; } if (!(account = accountlist_find_account(username))) { eventlog(eventlog_level_error, __FUNCTION__, "requested claninfo for non-existant account"); return -1; } if ((clanmember = account_get_clanmember(account)) && (clan = clanmember_get_clan(clanmember))) clantag2 = clan_get_clantag(clan); else clantag2 = 0; if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_claninforeply)); packet_set_type(rpacket, SERVER_CLANINFOREPLY); bn_int_set(&rpacket->u.server_profilereply.count, count); if (clantag1 == clantag2) { int temp; t_bnettime bn_time; bn_long ltime; bn_byte_set(&rpacket->u.server_claninforeply.fail, 0); packet_append_string(rpacket, clan_get_name(clan)); temp = clanmember_get_status(clanmember); packet_append_data(rpacket, &temp, 1); temp = clanmember_get_join_time(clanmember); bn_time = time_to_bnettime(temp, 0); bn_time = bnettime_add_tzbias(bn_time, -conn_get_tzbias(c)); bnettime_to_bn_long(bn_time, <ime); packet_append_data(rpacket, <ime, 8); } else bn_byte_set(&rpacket->u.server_claninforeply.fail, 1); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_profilereq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; int count; char const *username; t_account *account; t_clanmember *clanmember; t_clan *clan; bn_int clanTAG; if (packet_get_size(packet) < sizeof(t_client_profilereq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PROFILEREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_profilereq), packet_get_size(packet)); return -1; } count = bn_int_get(packet->u.client_profilereq.count); if (!(username = packet_get_str_const(packet, sizeof(t_client_profilereq), USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PROFILEREQ (missing or too long username)", conn_get_socket(c)); return -1; } if (!(account = accountlist_find_account(username))) { eventlog(eventlog_level_error, __FUNCTION__, "requested profile for non-existant account"); return -1; } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_profilereply)); packet_set_type(rpacket, SERVER_PROFILEREPLY); bn_int_set(&rpacket->u.server_profilereply.count, count); bn_byte_set(&rpacket->u.server_profilereply.fail, 0); packet_append_string(rpacket, account_get_desc(account)); packet_append_string(rpacket, account_get_loc(account)); if ((clanmember = account_get_clanmember(account)) && (clan = clanmember_get_clan(clanmember))) bn_int_set(&clanTAG, clan_get_clantag(clan)); else bn_int_set(&clanTAG, 0); packet_append_data(rpacket, clanTAG, 4); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_realmjoinreq109(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_realmjoinreq_109)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REALMJOINREQ_109 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_realmjoinreq_109), packet_get_size(packet)); return -1; } { char const *realmname; t_realm *realm; if (!(realmname = packet_get_str_const(packet, sizeof(t_client_realmjoinreq_109), REALM_NAME_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REALMJOINREQ_109 (missing or too long realmname)", conn_get_socket(c)); return -1; } if ((realm = realmlist_find_realm(realmname))) { unsigned int salt; struct { bn_int salt; bn_int sessionkey; bn_int sessionnum; bn_int secret; bn_int passhash[5]; } temp; char const *pass_str; t_hash secret_hash; t_hash passhash; t_realm *prev_realm; /* FIXME: should we only set this after they log in to the realm server? */ prev_realm = conn_get_realm(c); if (prev_realm) { if (prev_realm != realm) { realm_add_player_number(realm, 1); realm_add_player_number(prev_realm, -1); conn_set_realm(c, realm); } } else { realm_add_player_number(realm, 1); conn_set_realm(c, realm); } if ((pass_str = account_get_pass(conn_get_account(c)))) { if (hash_set_str(&passhash, pass_str) == 0) { hash_to_bnhash((t_hash const *) &passhash, temp.passhash); salt = bn_int_get(packet->u.client_realmjoinreq_109.seqno); bn_int_set(&temp.salt, salt); bn_int_set(&temp.sessionkey, conn_get_sessionkey(c)); bn_int_set(&temp.sessionnum, conn_get_sessionnum(c)); bn_int_set(&temp.secret, conn_get_secret(c)); bnet_hash(&secret_hash, sizeof(temp), &temp); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_realmjoinreply_109)); packet_set_type(rpacket, SERVER_REALMJOINREPLY_109); bn_int_set(&rpacket->u.server_realmjoinreply_109.seqno, salt); bn_int_set(&rpacket->u.server_realmjoinreply_109.u1, 0x0); bn_short_set(&rpacket->u.server_realmjoinreply_109.u3, 0x0); /* reg auth */ bn_int_set(&rpacket->u.server_realmjoinreply_109.bncs_addr1, 0x0); bn_int_set(&rpacket->u.server_realmjoinreply_109.sessionnum, conn_get_sessionnum(c)); { /* trans support */ unsigned int addr = realm_get_ip(realm); unsigned short port = realm_get_port(realm); trans_net(conn_get_addr(c), &addr, &port); bn_int_nset(&rpacket->u.server_realmjoinreply_109.addr, addr); bn_short_nset(&rpacket->u.server_realmjoinreply_109.port, port); } bn_int_set(&rpacket->u.server_realmjoinreply_109.sessionkey, conn_get_sessionkey(c)); bn_int_set(&rpacket->u.server_realmjoinreply_109.u5, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.u6, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.bncs_addr2, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.u7, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.versionid, conn_get_versionid(c)); bn_int_set(&rpacket->u.server_realmjoinreply_109.clienttag, conn_get_clienttag(c)); hash_to_bnhash((t_hash const *) &secret_hash, rpacket->u.server_realmjoinreply_109.secret_hash); /* avoid warning */ packet_append_string(rpacket, conn_get_username(c)); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] realm join for \"%s\" failed (unable to hash password)", conn_get_socket(c), conn_get_loggeduser(c)); } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] realm join for \"%s\" failed (no password)", conn_get_socket(c), conn_get_loggeduser(c)); } } else eventlog(eventlog_level_error, __FUNCTION__, "[%d] could not find active realm \"%s\"", conn_get_socket(c), realmname); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_realmjoinreply_109)); packet_set_type(rpacket, SERVER_REALMJOINREPLY_109); bn_int_set(&rpacket->u.server_realmjoinreply_109.seqno, bn_int_get(packet->u.client_realmjoinreq_109.seqno)); bn_int_set(&rpacket->u.server_realmjoinreply_109.u1, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.sessionnum, 0); bn_short_set(&rpacket->u.server_realmjoinreply_109.u3, 0); bn_int_nset(&rpacket->u.server_realmjoinreply_109.addr, 0); bn_short_nset(&rpacket->u.server_realmjoinreply_109.port, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.sessionkey, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.u5, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.u6, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.u7, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.bncs_addr1, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.bncs_addr2, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.versionid, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.clienttag, 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[0], 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[1], 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[2], 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[3], 0); bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[4], 0); packet_append_string(rpacket, ""); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_charlistreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_unknown_37)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UNKNOWN_37 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_unknown_37), packet_get_size(packet)); return -1; } /* 0x0070: 83 80 ff ff ff ff ff 2f t,taran,......./ 0x0080: ff ff ff ff ff ff ff ff ff ff 03 ff ff ff ff ff ................ 0x0090: ff ff ff ff ff ff ff ff ff ff ff 07 80 80 80 80 ................ 0x00a0: ff ff ff 00 */ if ((rpacket = packet_create(packet_class_bnet))) { char const *charlist; char *temp; packet_set_size(rpacket, sizeof(t_server_unknown_37)); packet_set_type(rpacket, SERVER_UNKNOWN_37); bn_int_set(&rpacket->u.server_unknown_37.unknown1, SERVER_UNKNOWN_37_UNKNOWN1); bn_int_set(&rpacket->u.server_unknown_37.unknown2, SERVER_UNKNOWN_37_UNKNOWN2); if (!(charlist = account_get_closed_characterlist(conn_get_account(c), conn_get_clienttag(c), realm_get_name(conn_get_realm(c))))) { bn_int_set(&rpacket->u.server_unknown_37.count, 0); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } temp = xstrdup(charlist); { char const *tok1; char const *tok2; t_character const *ch; unsigned int count; count = 0; tok1 = (char const *) strtok(temp, ","); /* strtok modifies the string it is passed */ tok2 = strtok(NULL, ","); while (tok1) { if (!tok2) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" has bad character list \"%s\"", conn_get_socket(c), conn_get_username(c), temp); break; } if ((ch = characterlist_find_character(tok1, tok2))) { packet_append_ntstring(rpacket, character_get_realmname(ch)); packet_append_ntstring(rpacket, ","); packet_append_string(rpacket, character_get_name(ch)); packet_append_string(rpacket, character_get_playerinfo(ch)); packet_append_string(rpacket, character_get_guildname(ch)); count++; } else eventlog(eventlog_level_error, __FUNCTION__, "[%d] character \"%s\" is missing", conn_get_socket(c), tok2); tok1 = strtok(NULL, ","); tok2 = strtok(NULL, ","); } xfree(temp); bn_int_set(&rpacket->u.server_unknown_37.count, count); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_unknown39(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_unknown_39)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UNKNOWN_39 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_unknown_39), packet_get_size(packet)); return -1; } return 0; } static int _client_adreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_adreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ADREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_adreq), packet_get_size(packet)); return -1; } { t_adbanner *ad; if (!(ad = adbanner_pick(c, bn_int_get(packet->u.client_adreq.prev_adid)))) return 0; /* eventlog(eventlog_level_debug,__FUNCTION__,"[%d] picking ad file=\"%s\" id=0x%06x tag=%u",conn_get_socket(c),adbanner_get_filename(ad),adbanner_get_id(ad),adbanner_get_extensiontag(ad)); */ if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_adreply)); packet_set_type(rpacket, SERVER_ADREPLY); bn_int_set(&rpacket->u.server_adreply.adid, adbanner_get_id(ad)); bn_int_set(&rpacket->u.server_adreply.extensiontag, adbanner_get_extensiontag(ad)); file_to_mod_time(adbanner_get_filename(ad), &rpacket->u.server_adreply.timestamp); packet_append_string(rpacket, adbanner_get_filename(ad)); packet_append_string(rpacket, adbanner_get_link(ad)); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_adack(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_adack)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ADACK packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_adack), packet_get_size(packet)); return -1; } /* { char const * tname; eventlog(eventlog_level_info,__FUNCTION__,"[%d] ad acknowledgement for adid 0x%04x from \"%s\"",conn_get_socket(c),bn_int_get(packet->u.client_adack.adid),(tname = conn_get_chatname(c))); conn_unget_chatname(c,tname); } */ return 0; } static int _client_adclick(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_adclick)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ADCLICK packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_adclick), packet_get_size(packet)); return -1; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] ad click for adid 0x%04x from \"%s\"", conn_get_socket(c), bn_int_get(packet->u.client_adclick.adid), conn_get_username(c)); return 0; } static int _client_adclick2(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_adclick2)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ADCLICK2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_adclick2), packet_get_size(packet)); return -1; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] ad click2 for adid 0x%04hx from \"%s\"", conn_get_socket(c), bn_int_get(packet->u.client_adclick2.adid), conn_get_username(c)); { t_adbanner *ad; if (!(ad = adbanner_get(c, bn_int_get(packet->u.client_adclick2.adid)))) return -1; if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_adclickreply2)); packet_set_type(rpacket, SERVER_ADCLICKREPLY2); bn_int_set(&rpacket->u.server_adclickreply2.adid, adbanner_get_id(ad)); packet_append_string(rpacket, adbanner_get_link(ad)); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_statsupdate(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_statsupdate)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSUPDATE packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_statsupdate), packet_get_size(packet)); return -1; } { char const *name; char const *key; char const *val; unsigned int name_count; unsigned int key_count; unsigned int i, j; unsigned int name_off; unsigned int keys_off; unsigned int key_off; unsigned int vals_off; unsigned int val_off; t_account *account; name_count = bn_int_get(packet->u.client_statsupdate.name_count); key_count = bn_int_get(packet->u.client_statsupdate.key_count); if (name_count != 1) eventlog(eventlog_level_warn, __FUNCTION__, "[%d] got suspicious STATSUPDATE packet (name_count=%u)", conn_get_socket(c), name_count); for (i = 0, name_off = sizeof(t_client_statsupdate); i < name_count && (name = packet_get_str_const(packet, name_off, UNCHECKED_NAME_STR)); i++, name_off += strlen(name) + 1); if (i < name_count) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSUPDATE packet (only %u names of %u)", conn_get_socket(c), i, name_count); return -1; } keys_off = name_off; for (i = 0, key_off = keys_off; i < key_count && (key = packet_get_str_const(packet, key_off, MAX_ATTRKEY_STR)); i++, key_off += strlen(key) + 1); if (i < key_count) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSUPDATE packet (only %u keys of %u)", conn_get_socket(c), i, key_count); return -1; } vals_off = key_off; if ((account = conn_get_account(c))) { if (account_get_auth_changeprofile(account) == 0) { /* default to true */ eventlog(eventlog_level_error, __FUNCTION__, "[%d] stats update for \"%s\" refused (no change profile access)", conn_get_socket(c), conn_get_username(c)); return -1; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] updating player profile for \"%s\"", conn_get_socket(c), conn_get_username(c)); for (i = 0, name_off = sizeof(t_client_statsupdate); i < name_count && (name = packet_get_str_const(packet, name_off, UNCHECKED_NAME_STR)); i++, name_off += strlen(name) + 1) for (j = 0, key_off = keys_off, val_off = vals_off; j < key_count && (key = packet_get_str_const(packet, key_off, MAX_ATTRKEY_STR)) && (val = packet_get_str_const(packet, val_off, MAX_ATTRVAL_STR)); j++, key_off += strlen(key) + 1, val_off += strlen(val) + 1) if (strlen(key) < 9 || strncasecmp(key, "profile\\", 8) != 0) eventlog(eventlog_level_error, __FUNCTION__, "[%d] got STATSUPDATE with suspicious key \"%s\" value \"%s\"", conn_get_socket(c), key, val); else account_set_strattr(account, key, val); } } return 0; } static int _client_playerinforeq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_playerinforeq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PLAYERINFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_playerinforeq), packet_get_size(packet)); return -1; } { char const *username; char const *info; t_account *account; if (!(username = packet_get_str_const(packet, sizeof(t_client_playerinforeq), USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PLAYERINFOREQ (missing or too long username)", conn_get_socket(c)); return -1; } if (!(info = packet_get_str_const(packet, sizeof(t_client_playerinforeq) + strlen(username) + 1, MAX_PLAYERINFO_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PLAYERINFOREQ (missing or too long info)", conn_get_socket(c)); return -1; } if (info[0] != '\0') conn_set_playerinfo(c, info); if (!username[0]) username = conn_get_loggeduser(c); account = conn_get_account(c); if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_playerinforeply)); packet_set_type(rpacket, SERVER_PLAYERINFOREPLY); if (account) { packet_append_string(rpacket, username); packet_append_string(rpacket, conn_get_playerinfo(c)); packet_append_string(rpacket, username); } else { packet_append_string(rpacket, ""); packet_append_string(rpacket, ""); packet_append_string(rpacket, ""); } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_progident2(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_progident2)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PROGIDENT2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_progident2), packet_get_size(packet)); return -1; } /* d2 uses this packet with clienttag = 0 to request the channel list */ if (bn_int_get(packet->u.client_progident2.clienttag)) { if (_check_allowed_client(bn_int_get(packet->u.client_progident2.clienttag))) { conn_set_state(c, conn_state_destroy); return 0; } eventlog(eventlog_level_debug, __FUNCTION__, "[%d] CLIENT_PROGIDENT2 clienttag=0x%08x", conn_get_socket(c), bn_int_get(packet->u.client_progident2.clienttag)); /* Hmm... no archtag. Hope we get it in CLIENT_AUTHREQ1 (but we won't if we use the shortcut) */ conn_set_clienttag(c, bn_int_get(packet->u.client_progident2.clienttag)); } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_channellist)); packet_set_type(rpacket, SERVER_CHANNELLIST); { t_channel *ch; t_elem const *curr; LIST_TRAVERSE_CONST(channellist(), curr) { ch = elem_get_data(curr); if ((!(channel_get_flags(ch) & channel_flags_clan)) && (!prefs_get_hide_temp_channels() || channel_get_permanent(ch)) && (!channel_get_clienttag(ch) || strcmp(channel_get_clienttag(ch), clienttag_uint_to_str(conn_get_clienttag(c))) == 0) && (!(channel_get_flags(ch) & channel_flags_thevoid)) && // don't display theVoid in channel list ((channel_get_max(ch) != 0) || ((channel_get_max(ch) == 0) && (account_is_operator_or_admin(conn_get_account(c), channel_get_name(ch)) == 1)))) // don't display restricted channel for no admins/ops packet_append_string(rpacket, channel_get_name(ch)); } } packet_append_string(rpacket, ""); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_joinchannel(t_connection * c, t_packet const *const packet) { t_account *account; char const *cname; int found = 1; t_clan *user_clan; int clantag; t_uint32 clienttag; t_channel *channel; if (packet_get_size(packet) < sizeof(t_client_joinchannel)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad JOINCHANNEL packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_joinchannel), packet_get_size(packet)); return -1; } account = conn_get_account(c); if (!(cname = packet_get_str_const(packet, sizeof(t_client_joinchannel), CHANNEL_NAME_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad JOINCHANNEL (missing or too long cname)", conn_get_socket(c)); return -1; } if ((channel = conn_get_channel(c)) && (strcasecmp(channel_get_name(channel), cname) == 0)) return 0; //we are allready in this channel clienttag = conn_get_clienttag(c); if ((clienttag == CLIENTTAG_WARCRAFT3_UINT) || (clienttag == CLIENTTAG_WAR3XP_UINT)) { conn_update_w3_playerinfo(c); switch (bn_int_get(packet->u.client_joinchannel.channelflag)) { case CLIENT_JOINCHANNEL_NORMAL: eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_JOINCHANNEL_NORMAL channel \"%s\"", conn_get_socket(c), cname); if (prefs_get_ask_new_channel() && (!(channellist_find_channel_by_name(cname, conn_get_country(c), realm_get_name(conn_get_realm(c)))))) { found = 0; eventlog(eventlog_level_info, __FUNCTION__, "[%d] didn't find channel \"%s\" to join", conn_get_socket(c), cname); message_send_text(c, message_type_channeldoesnotexist, c, cname); } break; case CLIENT_JOINCHANNEL_GENERIC: if ((user_clan = account_get_clan(account)) && (clantag = clan_get_clantag(user_clan))) sprintf((char *) cname, "Clan %c%c%c%c", (clantag >> 24), (clantag >> 16) & 0xff, (clantag >> 8) & 0xff, clantag & 0xff); eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_JOINCHANNEL_GENERIC channel \"%s\"", conn_get_socket(c), cname); /* don't have to do anything here */ break; case CLIENT_JOINCHANNEL_CREATE: eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_JOINCHANNEL_CREATE channel \"%s\"", conn_get_socket(c), cname); eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_JOINCHANNEL_CREATE channel \"%s\"", conn_get_socket(c), cname); /* don't have to do anything here */ break; } if (found && conn_set_channel(c, cname) < 0) conn_set_channel(c, CHANNEL_NAME_BANNED); /* should not fail */ } else { // not W3 if (conn_set_channel(c, cname) < 0) conn_set_channel(c, CHANNEL_NAME_BANNED); /* should not fail */ } // here we set channel flags on user channel_set_userflags(c); return 0; } static int _client_message(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_message)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MESSAGE packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_message), packet_get_size(packet)); return -1; } { char const *text; t_channel const *channel; if (!(text = packet_get_str_const(packet, sizeof(t_client_message), MAX_MESSAGE_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MESSAGE (missing or too long text)", conn_get_socket(c)); return -1; } conn_set_idletime(c); if ((channel = conn_get_channel(c))) channel_message_log(channel, c, 1, text); /* we don't log game commands currently */ if (text[0] == '/') handle_command(c, text); else if (channel && !conn_quota_exceeded(c, text)) channel_message_send(channel, message_type_talk, c, text); /* else discard */ } return 0; } struct glist_cbdata { unsigned tcount, counter; t_connection *c; t_game_type gtype; t_packet *rpacket; }; static int _glist_cb(t_game * game, void *data) { struct glist_cbdata *cbdata = (struct glist_cbdata*)data; char clienttag_str[5]; t_server_gamelistreply_game glgame; unsigned int addr; unsigned short port; bn_int game_spacer = { 1, 0, 0, 0 }; cbdata->tcount++; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] considering listing game=\"%s\", pass=\"%s\" clienttag=\"%s\" gtype=%d", conn_get_socket(cbdata->c), game_get_name(game), game_get_pass(game), tag_uint_to_str(clienttag_str, game_get_clienttag(game)), (int) game_get_type(game)); if (prefs_get_hide_pass_games() && game_get_flag(game) == game_flag_private) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is passworded or has private flag", conn_get_socket(cbdata->c)); return 0; } if (prefs_get_hide_started_games() && game_get_status(game) != game_status_open) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is not open", conn_get_socket(cbdata->c)); return 0; } if (game_get_clienttag(game) != conn_get_clienttag(cbdata->c)) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is for a different client", conn_get_socket(cbdata->c)); return 0; } if (cbdata->gtype != game_type_all && game_get_type(game) != cbdata->gtype) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is wrong type", conn_get_socket(cbdata->c)); return 0; } if (conn_get_versioncheck(cbdata->c) && conn_get_versioncheck(game_get_owner(game)) && versioncheck_get_versiontag(conn_get_versioncheck(cbdata->c)) && versioncheck_get_versiontag(conn_get_versioncheck(game_get_owner(game))) && strcmp(versioncheck_get_versiontag(conn_get_versioncheck(cbdata->c)), versioncheck_get_versiontag(conn_get_versioncheck(game_get_owner(game)))) != 0) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is wrong versiontag", conn_get_socket(cbdata->c)); return 0; } bn_short_set(&glgame.gametype, gtype_to_bngtype(game_get_type(game))); bn_short_set(&glgame.unknown1, SERVER_GAMELISTREPLY_GAME_UNKNOWN1); bn_short_set(&glgame.unknown3, SERVER_GAMELISTREPLY_GAME_UNKNOWN3); addr = game_get_addr(game); port = game_get_port(game); trans_net(conn_get_addr(cbdata->c), &addr, &port); bn_short_nset(&glgame.port, port); bn_int_nset(&glgame.game_ip, addr); bn_int_set(&glgame.unknown4, SERVER_GAMELISTREPLY_GAME_UNKNOWN4); bn_int_set(&glgame.unknown5, SERVER_GAMELISTREPLY_GAME_UNKNOWN5); switch (game_get_status(game)) { case game_status_started: bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_STARTED); break; case game_status_full: bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_FULL); break; case game_status_open: bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_OPEN); break; case game_status_done: bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_DONE); break; default: eventlog(eventlog_level_warn, __FUNCTION__, "[%d] game \"%s\" has bad status=%d", conn_get_socket(cbdata->c), game_get_name(game), (int) game_get_status(game)); bn_int_set(&glgame.status, 0); } bn_int_set(&glgame.unknown6, SERVER_GAMELISTREPLY_GAME_UNKNOWN6); if (packet_get_size(cbdata->rpacket) + sizeof(glgame) + strlen(game_get_name(game)) + 1 + strlen(game_get_pass(game)) + 1 + strlen(game_get_info(game)) + 1 > MAX_PACKET_SIZE) { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] out of room for games", conn_get_socket(cbdata->c)); return -1; /* no more room */ } if (cbdata->counter) { packet_append_data(cbdata->rpacket, &game_spacer, sizeof(game_spacer)); } packet_append_data(cbdata->rpacket, &glgame, sizeof(glgame)); packet_append_string(cbdata->rpacket, game_get_name(game)); packet_append_string(cbdata->rpacket, game_get_pass(game)); packet_append_string(cbdata->rpacket, game_get_info(game)); cbdata->counter++; return 0; } static int _client_gamelistreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; char const *gamename; char const *gamepass; unsigned short bngtype; t_game_type gtype; t_clienttag clienttag; t_game *game; t_server_gamelistreply_game glgame; unsigned int addr; unsigned short port; char clienttag_str[5]; if (packet_get_size(packet) < sizeof(t_client_gamelistreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad GAMELISTREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_gamelistreq), packet_get_size(packet)); return -1; } if (!(gamename = packet_get_str_const(packet, sizeof(t_client_gamelistreq), GAME_NAME_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad GAMELISTREQ (missing or too long gamename)", conn_get_socket(c)); return -1; } if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_gamelistreq) + strlen(gamename) + 1, GAME_PASS_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad GAMELISTREQ (missing or too long password)", conn_get_socket(c)); return -1; } bngtype = bn_short_get(packet->u.client_gamelistreq.gametype); clienttag = conn_get_clienttag(c); gtype = bngreqtype_to_gtype(clienttag, bngtype); if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_gamelistreply)); packet_set_type(rpacket, SERVER_GAMELISTREPLY); bn_int_set(&rpacket->u.server_gamelistreply.sstatus, 0); /* specific game requested? */ if (gamename[0] != '\0') { eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY looking for specific game tag=\"%s\" bngtype=0x%08x gtype=%d name=\"%s\" pass=\"%s\"", conn_get_socket(c), tag_uint_to_str(clienttag_str, clienttag), bngtype, (int) gtype, gamename, gamepass); if ((game = gamelist_find_game(gamename, clienttag, gtype))) { /* game found but first we need to make sure everything is OK */ bn_int_set(&rpacket->u.server_gamelistreply.gamecount, 0); switch (game_get_status(game)) { case game_status_started: bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_STARTED); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found but started", conn_get_socket(c)); break; case game_status_full: bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_FULL); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found but full", conn_get_socket(c)); break; case game_status_done: bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_NOTFOUND); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found but done", conn_get_socket(c)); break; case game_status_open: case game_status_loaded: if (strcmp(gamepass, game_get_pass(game))) { /* passworded game must match password in request */ bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_PASS); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found but is password protected and wrong password given", conn_get_socket(c)); break; } if (game_get_status(game) == game_status_loaded) { bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_LOADED); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found loaded game", conn_get_socket(c)); } /* everything seems fine, lets reply with the found game */ bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_OPEN); bn_short_set(&glgame.gametype, gtype_to_bngtype(game_get_type(game))); bn_short_set(&glgame.unknown1, SERVER_GAMELISTREPLY_GAME_UNKNOWN1); bn_short_set(&glgame.unknown3, SERVER_GAMELISTREPLY_GAME_UNKNOWN3); addr = game_get_addr(game); port = game_get_port(game); trans_net(conn_get_addr(c), &addr, &port); bn_short_nset(&glgame.port, port); bn_int_nset(&glgame.game_ip, addr); bn_int_set(&glgame.unknown4, SERVER_GAMELISTREPLY_GAME_UNKNOWN4); bn_int_set(&glgame.unknown5, SERVER_GAMELISTREPLY_GAME_UNKNOWN5); bn_int_set(&glgame.unknown6, SERVER_GAMELISTREPLY_GAME_UNKNOWN6); packet_append_data(rpacket, &glgame, sizeof(glgame)); packet_append_string(rpacket, game_get_name(game)); packet_append_string(rpacket, game_get_pass(game)); packet_append_string(rpacket, game_get_info(game)); bn_int_set(&rpacket->u.server_gamelistreply.gamecount, 1); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY specific game found", conn_get_socket(c)); break; default: eventlog(eventlog_level_warn, __FUNCTION__, "[%d] game \"%s\" has bad status %d", conn_get_socket(c), game_get_name(game), game_get_status(game)); } } else { bn_int_set(&rpacket->u.server_gamelistreply.gamecount, 0); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY specific game doesn't seem to exist", conn_get_socket(c)); } } else { /* list all public games of this type */ struct glist_cbdata cbdata; if (gtype == game_type_all) eventlog(eventlog_level_debug, __FUNCTION__, "GAMELISTREPLY looking for public games tag=\"%s\" bngtype=0x%08x gtype=all", tag_uint_to_str(clienttag_str, clienttag), bngtype); else eventlog(eventlog_level_debug, __FUNCTION__, "GAMELISTREPLY looking for public games tag=\"%s\" bngtype=0x%08x gtype=%d", tag_uint_to_str(clienttag_str, clienttag), bngtype, (int) gtype); cbdata.counter = 0; cbdata.tcount = 0; cbdata.c = c; cbdata.gtype = gtype; cbdata.rpacket = rpacket; gamelist_traverse(_glist_cb,&cbdata); bn_int_set(&rpacket->u.server_gamelistreply.gamecount, cbdata.counter); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY sent %u of %u games", conn_get_socket(c), cbdata.counter, cbdata.tcount); } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } static int _client_joingame(t_connection * c, t_packet const *const packet) { char const *gamename; char const *gamepass; t_game *game; t_game_type gtype; if (packet_get_size(packet) < sizeof(t_client_join_game)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad JOIN_GAME packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_join_game), packet_get_size(packet)); return -1; } if (!(gamename = packet_get_str_const(packet, sizeof(t_client_join_game), GAME_NAME_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_JOIN_GAME (missing or too long gamename)", conn_get_socket(c)); return -1; } if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_join_game) + strlen(gamename) + 1, GAME_PASS_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_JOIN_GAME packet (missing or too long gamepass)", conn_get_socket(c)); return -1; } eventlog(eventlog_level_debug, __FUNCTION__, "[%d] trying to join game \"%s\" pass=\"%s\"", conn_get_socket(c), gamename, gamepass); if (conn_get_joingamewhisper_ack(c) == 0) { watchlist_notify_event(conn_get_account(c), gamename, conn_get_clienttag(c), watch_event_joingame); conn_set_joingamewhisper_ack(c, 1); /* 1 = already whispered. We reset this each time user joins a channel */ clanmember_on_change_status_by_connection(c); } if (conn_get_channel(c)) conn_set_channel(c, NULL); if (!strcmp(gamename, "BNet") && !handle_anongame_join(c)) { gtype = game_type_anongame; gamename = NULL; return 0; /* tmp: do not record any anongames as yet */ } else { if (!(game = gamelist_find_game(gamename, conn_get_clienttag(c), game_type_all))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to find game \"%s\" for user to join", conn_get_socket(c), gamename); return 0; } gtype = game_get_type(game); gamename = game_get_name(game); if ((gtype == game_type_ladder && account_get_auth_joinladdergame(conn_get_account(c)) == 0) || /* default to true */ (gtype != game_type_ladder && account_get_auth_joinnormalgame(conn_get_account(c)) == 0)) { /* default to true */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] game join for \"%s\" to \"%s\" refused (no authority)", conn_get_socket(c), conn_get_username(c), gamename); /* If the user is not in a game, then map authorization will fail and keep them from playing. */ return 0; } } if (conn_set_game(c, gamename, gamepass, "", gtype, STARTVER_UNKNOWN) < 0) eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" joined game \"%s\", but could not be recorded on server", conn_get_socket(c), conn_get_username(c), gamename); else eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" joined game \"%s\"", conn_get_socket(c), conn_get_username(c), gamename); return 0; } static int _client_startgame1(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_startgame1)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_startgame1), packet_get_size(packet)); return -1; } { char const *gamename; char const *gamepass; char const *gameinfo; unsigned short bngtype; unsigned int status; t_game *currgame; if (!(gamename = packet_get_str_const(packet, sizeof(t_client_startgame1), GAME_NAME_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME1 packet (missing or too long gamename)", conn_get_socket(c)); return -1; } if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_startgame1) + strlen(gamename) + 1, GAME_PASS_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME1 packet (missing or too long gamepass)", conn_get_socket(c)); return -1; } if (!(gameinfo = packet_get_str_const(packet, sizeof(t_client_startgame1) + strlen(gamename) + 1 + strlen(gamepass) + 1, GAME_INFO_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME1 packet (missing or too long gameinfo)", conn_get_socket(c)); return -1; } if (conn_get_joingamewhisper_ack(c) == 0) { if (watchlist_notify_event(conn_get_account(c), gamename, conn_get_clienttag(c), watch_event_joingame) == 0) eventlog(eventlog_level_info, "handle_bnet", "Told Mutual Friends your in game %s", gamename); conn_set_joingamewhisper_ack(c, 1); //1 = already whispered. We reset this each time user joins a channel } bngtype = bn_short_get(packet->u.client_startgame1.gametype); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got startgame1 status for game \"%s\" is 0x%08x (gametype = 0x%04hx)", conn_get_socket(c), gamename, bn_int_get(packet->u.client_startgame1.status), bngtype); status = bn_int_get(packet->u.client_startgame1.status) & CLIENT_STARTGAME1_STATUSMASK; if ((currgame = conn_get_game(c))) { switch (status) { case CLIENT_STARTGAME1_STATUS_STARTED: game_set_status(currgame, game_status_started); break; case CLIENT_STARTGAME1_STATUS_FULL: game_set_status(currgame, game_status_full); break; case CLIENT_STARTGAME1_STATUS_OPEN: game_set_status(currgame, game_status_open); break; case CLIENT_STARTGAME1_STATUS_DONE: game_set_status(currgame, game_status_done); eventlog(eventlog_level_info, __FUNCTION__, "[%d] game \"%s\" is finished", conn_get_socket(c), gamename); break; } } else if (status != CLIENT_STARTGAME1_STATUS_DONE) { t_game_type gtype; gtype = bngtype_to_gtype(conn_get_clienttag(c), bngtype); if ((gtype == game_type_ladder && account_get_auth_createladdergame(conn_get_account(c)) == 0) || /* default to true */ (gtype != game_type_ladder && account_get_auth_createnormalgame(conn_get_account(c)) == 0)) /* default to true */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] game start for \"%s\" refused (no authority)", conn_get_socket(c), conn_get_username(c)); else conn_set_game(c, gamename, gamepass, gameinfo, gtype, STARTVER_GW1); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_startgame1_ack)); packet_set_type(rpacket, SERVER_STARTGAME1_ACK); if (conn_get_game(c)) bn_int_set(&rpacket->u.server_startgame1_ack.reply, SERVER_STARTGAME1_ACK_OK); else bn_int_set(&rpacket->u.server_startgame1_ack.reply, SERVER_STARTGAME1_ACK_NO); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] client tried to set game status DONE to destroyed game", conn_get_socket(c)); } return 0; } static int _client_startgame3(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_startgame3)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_startgame3), packet_get_size(packet)); return -1; } { char const *gamename; char const *gamepass; char const *gameinfo; unsigned short bngtype; unsigned int status; t_game *currgame; if (!(gamename = packet_get_str_const(packet, sizeof(t_client_startgame3), GAME_NAME_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME3 packet (missing or too long gamename)", conn_get_socket(c)); return -1; } if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_startgame3) + strlen(gamename) + 1, GAME_PASS_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME3 packet (missing or too long gamepass)", conn_get_socket(c)); return -1; } if (!(gameinfo = packet_get_str_const(packet, sizeof(t_client_startgame3) + strlen(gamename) + 1 + strlen(gamepass) + 1, GAME_INFO_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME3 packet (missing or too long gameinfo)", conn_get_socket(c)); return -1; } if (conn_get_joingamewhisper_ack(c) == 0) { if (watchlist_notify_event(conn_get_account(c), gamename, conn_get_clienttag(c), watch_event_joingame) == 0) eventlog(eventlog_level_info, "handle_bnet", "Told Mutual Friends your in game %s", gamename); conn_set_joingamewhisper_ack(c, 1); //1 = already whispered. We reset this each time user joins a channel } bngtype = bn_short_get(packet->u.client_startgame3.gametype); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got startgame3 status for game \"%s\" is 0x%08x (gametype = 0x%04hx)", conn_get_socket(c), gamename, bn_int_get(packet->u.client_startgame3.status), bngtype); status = bn_int_get(packet->u.client_startgame3.status) & CLIENT_STARTGAME3_STATUSMASK; if ((currgame = conn_get_game(c))) { switch (status) { case CLIENT_STARTGAME3_STATUS_STARTED: game_set_status(currgame, game_status_started); break; case CLIENT_STARTGAME3_STATUS_FULL: game_set_status(currgame, game_status_full); break; case CLIENT_STARTGAME3_STATUS_OPEN1: case CLIENT_STARTGAME3_STATUS_OPEN: game_set_status(currgame, game_status_open); break; case CLIENT_STARTGAME3_STATUS_DONE: game_set_status(currgame, game_status_done); eventlog(eventlog_level_info, __FUNCTION__, "[%d] game \"%s\" is finished", conn_get_socket(c), gamename); break; } } else if (status != CLIENT_STARTGAME3_STATUS_DONE) { t_game_type gtype; gtype = bngtype_to_gtype(conn_get_clienttag(c), bngtype); if ((gtype == game_type_ladder && account_get_auth_createladdergame(conn_get_account(c)) == 0) || (gtype != game_type_ladder && account_get_auth_createnormalgame(conn_get_account(c)) == 0)) eventlog(eventlog_level_info, __FUNCTION__, "[%d] game start for \"%s\" refused (no authority)", conn_get_socket(c), conn_get_username(c)); else conn_set_game(c, gamename, gamepass, gameinfo, gtype, STARTVER_GW3); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_startgame3_ack)); packet_set_type(rpacket, SERVER_STARTGAME3_ACK); if (conn_get_game(c)) bn_int_set(&rpacket->u.server_startgame3_ack.reply, SERVER_STARTGAME3_ACK_OK); else bn_int_set(&rpacket->u.server_startgame3_ack.reply, SERVER_STARTGAME3_ACK_NO); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] client tried to set game status DONE to destroyed game", conn_get_socket(c)); } return 0; } static int _client_startgame4(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_startgame4)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME4 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_startgame4), packet_get_size(packet)); return -1; } // Quick hack to make W3 part channels when creating a game if (conn_get_channel(c)) conn_set_channel(c, NULL); { char const *gamename; char const *gamepass; char const *gameinfo; unsigned short bngtype; unsigned int status; unsigned int flag; unsigned short option; t_game *currgame; if (!(gamename = packet_get_str_const(packet, sizeof(t_client_startgame4), GAME_NAME_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME4 packet (missing or too long gamename)", conn_get_socket(c)); return -1; } if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_startgame4) + strlen(gamename) + 1, GAME_PASS_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME4 packet (missing or too long gamepass)", conn_get_socket(c)); return -1; } if (!(gameinfo = packet_get_str_const(packet, sizeof(t_client_startgame4) + strlen(gamename) + 1 + strlen(gamepass) + 1, GAME_INFO_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME4 packet (missing or too long gameinfo)", conn_get_socket(c)); return -1; } if (conn_get_joingamewhisper_ack(c) == 0) { if (watchlist_notify_event(conn_get_account(c), gamename, conn_get_clienttag(c), watch_event_joingame) == 0) eventlog(eventlog_level_info, "handle_bnet", "Told Mutual Friends your in game %s", gamename); conn_set_joingamewhisper_ack(c, 1); //1 = already whispered. We reset this each time user joins a channel } bngtype = bn_short_get(packet->u.client_startgame4.gametype); option = bn_short_get(packet->u.client_startgame4.option); status = bn_int_get(packet->u.client_startgame4.status); flag = bn_short_get(packet->u.client_startgame4.flag); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got startgame4 status for game \"%s\" is 0x%08x (gametype=0x%04hx option=0x%04hx, flag=0x%04hx)", conn_get_socket(c), gamename, status, bngtype, option, flag); if ((currgame = conn_get_game(c))) { if ((status & CLIENT_STARTGAME4_STATUSMASK_OPEN_VALID) == status) { if (status & CLIENT_STARTGAME4_STATUS_START) game_set_status(currgame, game_status_started); else if (status & CLIENT_STARTGAME4_STATUS_FULL) game_set_status(currgame, game_status_full); else game_set_status(currgame, game_status_open); } else { eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown startgame4 status %d (clienttag: %s)", conn_get_socket(c), status, clienttag_uint_to_str(conn_get_clienttag(c))); } } else if ((status & CLIENT_STARTGAME4_STATUSMASK_INIT_VALID) == status) { /*valid creation status would be: 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x80, 0x81, 0x82, 0x83 */ t_game_type gtype; gtype = bngtype_to_gtype(conn_get_clienttag(c), bngtype); if ((gtype == game_type_ladder && account_get_auth_createladdergame(conn_get_account(c)) == 0) || (gtype != game_type_ladder && account_get_auth_createnormalgame(conn_get_account(c)) == 0)) eventlog(eventlog_level_info, __FUNCTION__, "[%d] game start for \"%s\" refused (no authority)", conn_get_socket(c), conn_get_username(c)); else if (conn_set_game(c, gamename, gamepass, gameinfo, gtype, STARTVER_GW4) == 0) { game_set_option(conn_get_game(c), bngoption_to_goption(conn_get_clienttag(c), gtype, option)); if (status & CLIENT_STARTGAME4_STATUS_PRIVATE) game_set_flag(conn_get_game(c), game_flag_private); if (status & CLIENT_STARTGAME4_STATUS_FULL) game_set_status(conn_get_game(c), game_status_full); if (bngtype == CLIENT_GAMELISTREQ_LOADED) /* PELISH: seems strange but it is really needed for loaded games */ game_set_status(conn_get_game(c), game_status_loaded); //FIXME: still need special handling for status disc-is-loss and replay } } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] client tried to set game status 0x%x to unexistent game (clienttag: %s)", conn_get_socket(c), status, clienttag_uint_to_str(conn_get_clienttag(c))); } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_startgame4_ack)); packet_set_type(rpacket, SERVER_STARTGAME4_ACK); if (conn_get_game(c)) bn_int_set(&rpacket->u.server_startgame4_ack.reply, SERVER_STARTGAME4_ACK_OK); else bn_int_set(&rpacket->u.server_startgame4_ack.reply, SERVER_STARTGAME4_ACK_NO); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } /* First, send an ECHO_REQ */ if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_echoreq)); packet_set_type(rpacket, SERVER_ECHOREQ); bn_int_set(&rpacket->u.server_echoreq.ticks, get_ticks()); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_closegame(t_connection * c, t_packet const *const packet) { t_game *game; eventlog(eventlog_level_info, __FUNCTION__, "[%d] client closing game", conn_get_socket(c)); if (packet_get_type(packet) == CLIENT_CLOSEGAME2 || ((conn_get_clienttag(c) != CLIENTTAG_WARCRAFT3_UINT) && (conn_get_clienttag(c) != CLIENTTAG_WAR3XP_UINT))) conn_set_game(c, NULL, NULL, NULL, game_type_none, 0); else if ((game = conn_get_game(c))) game_set_status(game, game_status_started); return 0; } static int _client_gamereport(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_game_report)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad GAME_REPORT packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_game_report), packet_get_size(packet)); return -1; } { t_account *my_account; t_account *other_account; t_game *game; unsigned int player_count; unsigned int i,s; t_client_game_report_result const *result_data; unsigned int result_off; t_game_result result; char const *player; unsigned int player_off; t_game_result *results; player_count = bn_int_get(packet->u.client_gamerep.count); if (!(game = conn_get_game(c))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got GAME_REPORT when not in a game for user \"%s\"", conn_get_socket(c), conn_get_username(c)); return -1; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_GAME_REPORT: %s (%u players)", conn_get_socket(c), conn_get_username(c), player_count); my_account = conn_get_account(c); results = xmalloc(sizeof(t_game_result) * game_get_count(game)); for (i = 0; i < game_get_count(game); i++) results[i] = game_result_none; for (i = 0, result_off = sizeof(t_client_game_report), player_off = sizeof(t_client_game_report) + player_count * sizeof(t_client_game_report_result); i < player_count; i++, result_off += sizeof(t_client_game_report_result), player_off += strlen(player) + 1) { if (!(result_data = packet_get_data_const(packet, result_off, sizeof(t_client_game_report_result)))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got corrupt GAME_REPORT packet (missing results %u-%u)", conn_get_socket(c), i + 1, player_count); break; } if (!(player = packet_get_str_const(packet, player_off, USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got corrupt GAME_REPORT packet (missing players %u-%u)", conn_get_socket(c), i + 1, player_count); break; } if (player[0] == '\0') /* empty slots have empty player name */ continue; if (i >= game_get_count(game)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got more results than the game had players - ignoring extra results", conn_get_socket(c)); break; } if (!(other_account = accountlist_find_account(player))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got GAME_REPORT with unknown player \"%s\"", conn_get_socket(c), player); break; } // as player position in game structure and in game report might differ, // search for right position for (s=0; sresult)); results[s] = result; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got player %d (\"%s\") result %s", conn_get_socket(c), i, player, game_result_get_str(result)); } else { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got GAME_REPORT for non-participating player \"%s\"",conn_get_socket(c),player); } } if (i == player_count) { /* if everything checked out... */ char const *head; char const *body; if (!(head = packet_get_str_const(packet, player_off, MAX_GAMEREP_HEAD_STR))) eventlog(eventlog_level_error, __FUNCTION__, "[%d] got GAME_REPORT with missing or too long report head", conn_get_socket(c)); else { player_off += strlen(head) + 1; if (!(body = packet_get_str_const(packet, player_off, MAX_GAMEREP_BODY_STR))) eventlog(eventlog_level_error, __FUNCTION__, "[%d] got GAME_REPORT with missing or too ling report body", conn_get_socket(c)); else game_set_report(game, my_account, head, body); } } if (game_set_reported_results(game, my_account, results) < 0) xfree((void *) results); eventlog(eventlog_level_debug, __FUNCTION__, "[%d] finished parsing result... now leaving game", conn_get_socket(c)); conn_set_game(c, NULL, NULL, NULL, game_type_none, 0); } return 0; } static int _client_leavechannel(t_connection * c, t_packet const *const packet) { /* If this user in a channel, notify everyone that the user has left */ if (conn_get_channel(c)) conn_set_channel(c, NULL); return 0; } static int _client_ladderreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_ladderreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LADDERREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_ladderreq), packet_get_size(packet)); return -1; } { t_ladder_entry entry; unsigned int i; unsigned int type; unsigned int start; unsigned int count; unsigned int idnum; t_account *account; t_clienttag clienttag; char const *timestr; t_bnettime bt; t_ladder_id id; clienttag = conn_get_clienttag(c); type = bn_int_get(packet->u.client_ladderreq.type); start = bn_int_get(packet->u.client_ladderreq.startplace); count = bn_int_get(packet->u.client_ladderreq.count); idnum = bn_int_get(packet->u.client_ladderreq.id); /* eventlog(eventlog_level_debug,__FUNCTION__,"got LADDERREQ type=%u start=%u count=%u id=%u",type,start,count,id); */ switch (idnum) { case CLIENT_LADDERREQ_ID_STANDARD: id = ladder_id_normal; break; case CLIENT_LADDERREQ_ID_IRONMAN: id = ladder_id_ironman; break; default: eventlog(eventlog_level_error, __FUNCTION__, "[%d] got unknown ladder ladderreq.id=0x%08x", conn_get_socket(c), idnum); id = ladder_id_normal; } if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_ladderreply)); packet_set_type(rpacket, SERVER_LADDERREPLY); bn_int_set(&rpacket->u.server_ladderreply.clienttag, clienttag); bn_int_set(&rpacket->u.server_ladderreply.id, idnum); bn_int_set(&rpacket->u.server_ladderreply.type, type); bn_int_set(&rpacket->u.server_ladderreply.startplace, start); bn_int_set(&rpacket->u.server_ladderreply.count, count); for (i = start; i < start + count; i++) { switch (type) { case CLIENT_LADDERREQ_TYPE_HIGHESTRATED: if (!(account = ladder_get_account_by_rank(i + 1, ladder_sort_highestrated, ladder_time_active, clienttag, id))) account = ladder_get_account_by_rank(i + 1, ladder_sort_highestrated, ladder_time_current, clienttag, id); break; case CLIENT_LADDERREQ_TYPE_MOSTWINS: if (!(account = ladder_get_account_by_rank(i + 1, ladder_sort_mostwins, ladder_time_active, clienttag, id))) account = ladder_get_account_by_rank(i + 1, ladder_sort_mostwins, ladder_time_current, clienttag, id); break; case CLIENT_LADDERREQ_TYPE_MOSTGAMES: if (!(account = ladder_get_account_by_rank(i + 1, ladder_sort_mostgames, ladder_time_active, clienttag, id))) account = ladder_get_account_by_rank(i + 1, ladder_sort_mostgames, ladder_time_current, clienttag, id); break; default: account = NULL; eventlog(eventlog_level_error, __FUNCTION__, "[%d] got unknown value for ladderreq.type=%u", conn_get_socket(c), type); } if (account) { bn_int_set(&entry.active.wins, account_get_ladder_active_wins(account, clienttag, id)); bn_int_set(&entry.active.loss, account_get_ladder_active_losses(account, clienttag, id)); bn_int_set(&entry.active.disconnect, account_get_ladder_active_disconnects(account, clienttag, id)); bn_int_set(&entry.active.rating, account_get_ladder_active_rating(account, clienttag, id)); bn_int_set(&entry.active.rank, account_get_ladder_active_rank(account,clienttag,id)-1); if (!(timestr = account_get_ladder_active_last_time(account, clienttag, id))) timestr = BNETD_LADDER_DEFAULT_TIME; bnettime_set_str(&bt, timestr); bnettime_to_bn_long(bt, &entry.lastgame_active); bn_int_set(&entry.current.wins, account_get_ladder_wins(account, clienttag, id)); bn_int_set(&entry.current.loss, account_get_ladder_losses(account, clienttag, id)); bn_int_set(&entry.current.disconnect, account_get_ladder_disconnects(account, clienttag, id)); bn_int_set(&entry.current.rating, account_get_ladder_rating(account, clienttag, id)); bn_int_set(&entry.current.rank, account_get_ladder_rank(account,clienttag,id)-1); if (!(timestr = account_get_ladder_last_time(account, clienttag, id))) timestr = BNETD_LADDER_DEFAULT_TIME; bnettime_set_str(&bt, timestr); bnettime_to_bn_long(bt, &entry.lastgame_current); } else { bn_int_set(&entry.active.wins, 0); bn_int_set(&entry.active.loss, 0); bn_int_set(&entry.active.disconnect, 0); bn_int_set(&entry.active.rating, 0); bn_int_set(&entry.active.rank, 0); bn_long_set_a_b(&entry.lastgame_active, 0, 0); bn_int_set(&entry.current.wins, 0); bn_int_set(&entry.current.loss, 0); bn_int_set(&entry.current.disconnect, 0); bn_int_set(&entry.current.rating, 0); bn_int_set(&entry.current.rank, 0); bn_long_set_a_b(&entry.lastgame_current, 0, 0); } bn_int_set(&entry.ttest[0], i); // rank bn_int_set(&entry.ttest[1], 0); // bn_int_set(&entry.ttest[2], 0); // if (account) bn_int_set(&entry.ttest[3], account_get_ladder_high_rating(account, clienttag, id)); else bn_int_set(&entry.ttest[3], 0); bn_int_set(&entry.ttest[4], 0); // bn_int_set(&entry.ttest[5], 0); // packet_append_data(rpacket, &entry, sizeof(entry)); if (account) packet_append_string(rpacket, account_get_name(account)); else packet_append_string(rpacket, " "); /* use a space so the client won't show the user's own account when double-clicked on */ } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_laddersearchreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_laddersearchreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LADDERSEARCHREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_laddersearchreq), packet_get_size(packet)); return -1; } { char const *playername; t_account *account; unsigned int idnum; unsigned int rank; /* starts at zero */ t_ladder_id id; t_clienttag ctag = conn_get_clienttag(c); idnum = bn_int_get(packet->u.client_laddersearchreq.id); switch (idnum) { case CLIENT_LADDERREQ_ID_STANDARD: id = ladder_id_normal; break; case CLIENT_LADDERREQ_ID_IRONMAN: id = ladder_id_ironman; break; default: eventlog(eventlog_level_error, __FUNCTION__, "[%d] got unknown ladder laddersearchreq.id=0x%08x", conn_get_socket(c), idnum); id = ladder_id_normal; } if (!(playername = packet_get_str_const(packet, sizeof(t_client_laddersearchreq), USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LADDERSEARCHREQ packet (missing or too long playername)", conn_get_socket(c)); return -1; } if (!(account = accountlist_find_account(playername))) rank = SERVER_LADDERSEARCHREPLY_RANK_NONE; else { switch (bn_int_get(packet->u.client_laddersearchreq.type)) { case CLIENT_LADDERSEARCHREQ_TYPE_HIGHESTRATED: if (!(rank=ladder_get_rank_by_account(account, ladder_sort_highestrated, ladder_time_active, ctag, id))) { if (!(rank = ladder_get_rank_by_account(account, ladder_sort_highestrated, ladder_time_current, ctag, id)) || (ladder_get_account_by_rank(rank, ladder_sort_highestrated, ladder_time_active, ctag, id))) rank = 0; } break; case CLIENT_LADDERSEARCHREQ_TYPE_MOSTWINS: if (!(rank=ladder_get_rank_by_account(account, ladder_sort_mostwins, ladder_time_active, ctag, id))) { if (!(rank = ladder_get_rank_by_account(account, ladder_sort_mostwins, ladder_time_current, ctag, id)) || (ladder_get_account_by_rank(rank, ladder_sort_mostwins, ladder_time_active, ctag, id))) rank = 0; } break; case CLIENT_LADDERSEARCHREQ_TYPE_MOSTGAMES: if (!(rank=ladder_get_rank_by_account(account, ladder_sort_mostgames, ladder_time_active, ctag, id))) { if (!(rank = ladder_get_rank_by_account(account, ladder_sort_mostgames, ladder_time_current, ctag, id)) || (ladder_get_account_by_rank(rank, ladder_sort_mostgames, ladder_time_active, ctag, id))) rank = 0; } break; default: rank = 0; eventlog(eventlog_level_error, __FUNCTION__, "[%d] got unknown ladder search type %u", conn_get_socket(c), bn_int_get(packet->u.client_laddersearchreq.type)); } if (rank == 0) rank = SERVER_LADDERSEARCHREPLY_RANK_NONE; else rank--; } if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_laddersearchreply)); packet_set_type(rpacket, SERVER_LADDERSEARCHREPLY); bn_int_set(&rpacket->u.server_laddersearchreply.rank, rank); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_mapauthreq1(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_mapauthreq1)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MAPAUTHREQ1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_mapauthreq1), packet_get_size(packet)); return -1; } { char const *mapname; t_game *game; if (!(mapname = packet_get_str_const(packet, sizeof(t_client_mapauthreq1), MAP_NAME_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MAPAUTHREQ1 packet (missing or too long mapname)", conn_get_socket(c)); return -1; } game = conn_get_game(c); if (game) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] map auth requested for map \"%s\" gametype \"%s\"", conn_get_socket(c), mapname, game_type_get_str(game_get_type(game))); game_set_mapname(game, mapname); } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] map auth requested when not in a game", conn_get_socket(c)); if ((rpacket = packet_create(packet_class_bnet))) { unsigned int val; if (!game) { val = SERVER_MAPAUTHREPLY1_NO; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] map authorization denied (not in a game)", conn_get_socket(c)); } else if (strcasecmp(game_get_mapname(game), mapname) != 0) { val = SERVER_MAPAUTHREPLY1_NO; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] map authorization denied (map name \"%s\" does not match game map name \"%s\")", conn_get_socket(c), mapname, game_get_mapname(game)); } else { game_set_status(game, game_status_started); if (game_get_type(game) == game_type_ladder) { val = SERVER_MAPAUTHREPLY1_LADDER_OK; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map ladder authorization (in a ladder game)", conn_get_socket(c)); } else if (ladder_check_map(game_get_mapname(game), game_get_maptype(game), conn_get_clienttag(c))) { val = SERVER_MAPAUTHREPLY1_LADDER_OK; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map ladder authorization (is a ladder map)", conn_get_socket(c)); } else { val = SERVER_MAPAUTHREPLY1_OK; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map normal authorization", conn_get_socket(c)); } } packet_set_size(rpacket, sizeof(t_server_mapauthreply1)); packet_set_type(rpacket, SERVER_MAPAUTHREPLY1); bn_int_set(&rpacket->u.server_mapauthreply1.response, val); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_mapauthreq2(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_mapauthreq2)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MAPAUTHREQ2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_mapauthreq2), packet_get_size(packet)); return -1; } { char const *mapname; t_game *game; if (!(mapname = packet_get_str_const(packet, sizeof(t_client_mapauthreq2), MAP_NAME_LEN))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MAPAUTHREQ2 packet (missing or too long mapname)", conn_get_socket(c)); return -1; } game = conn_get_game(c); if (game) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] map auth requested for map \"%s\" gametype \"%s\"", conn_get_socket(c), mapname, game_type_get_str(game_get_type(game))); game_set_mapname(game, mapname); } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] map auth requested when not in a game", conn_get_socket(c)); if ((rpacket = packet_create(packet_class_bnet))) { unsigned int val; if (!game) { val = SERVER_MAPAUTHREPLY2_NO; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] map authorization denied (not in a game)", conn_get_socket(c)); } else if (strcasecmp(game_get_mapname(game), mapname) != 0) { val = SERVER_MAPAUTHREPLY2_NO; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] map authorization denied (map name \"%s\" does not match game map name \"%s\")", conn_get_socket(c), mapname, game_get_mapname(game)); } else { game_set_status(game, game_status_started); if (game_get_type(game) == game_type_ladder) { val = SERVER_MAPAUTHREPLY2_LADDER_OK; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map ladder authorization (in a ladder game)", conn_get_socket(c)); } else if (ladder_check_map(game_get_mapname(game), game_get_maptype(game), conn_get_clienttag(c))) { val = SERVER_MAPAUTHREPLY2_LADDER_OK; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map ladder authorization (is a ladder map)", conn_get_socket(c)); } else { val = SERVER_MAPAUTHREPLY2_OK; eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map normal authorization", conn_get_socket(c)); } } packet_set_size(rpacket, sizeof(t_server_mapauthreply2)); packet_set_type(rpacket, SERVER_MAPAUTHREPLY2); bn_int_set(&rpacket->u.server_mapauthreply2.response, val); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_changeclient(t_connection * c, t_packet const *const packet) { t_versioncheck *vc; if (packet_get_size(packet) < sizeof(t_client_changeclient)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_CHANGECLIENT packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_changeclient), packet_get_size(packet)); return -1; } if (_check_allowed_client(bn_int_get(packet->u.client_changeclient.clienttag))) { conn_set_state(c, conn_state_destroy); return 0; } conn_set_clienttag(c, bn_int_get(packet->u.client_changeclient.clienttag)); vc = conn_get_versioncheck(c); versioncheck_set_versiontag(vc, clienttag_uint_to_str(conn_get_clienttag(c))); if (vc && versioncheck_get_versiontag(vc)) { switch (versioncheck_validate(vc, conn_get_archtag(c), conn_get_clienttag(c), conn_get_clientexe(c), conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c))) { case -1: /* failed test... client has been modified */ case 0: /* not listed in table... can't tell if client has been modified */ eventlog(eventlog_level_error, __FUNCTION__, "[%d] error revalidating, allowing anyway", conn_get_socket(c)); break; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] client versiontag set to \"%s\"", conn_get_socket(c), versioncheck_get_versiontag(vc)); } return 0; } static int _client_w3xp_clanmemberlistreq(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_w3xp_clanmemberlist_req)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLANMEMBERLIST_REQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clanmemberlist_req), packet_get_size(packet)); return -1; } clan_send_memberlist(c, packet); return 0; } static int _client_w3xp_clan_motdreq(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_motdreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_MOTDREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_motdreq), packet_get_size(packet)); return -1; } clan_send_motd_reply(c, packet); return 0; } static int _client_w3xp_clan_motdchg(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_motdreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_MOTDCHGREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_motdreq), packet_get_size(packet)); return -1; } clan_save_motd_chg(c, packet); return 0; } static int _client_w3xp_clan_disbandreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_disbandreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_DISBANDREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_disbandreq), packet_get_size(packet)); return -1; } if ((rpacket = packet_create(packet_class_bnet))) { t_clan *clan; t_clanmember *member; t_account *account; packet_set_size(rpacket, sizeof(t_server_w3xp_clan_disbandreply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_DISBANDREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_disbandreply.count, bn_int_get(packet->u.client_w3xp_clan_disbandreq.count)); if (!((account = conn_get_account(c)) && (clan = account_get_clan(account)) && (member = account_get_clanmember(account)) && (clanmember_get_status(member) >= CLAN_CHIEFTAIN))) { eventlog(eventlog_level_warn, __FUNCTION__, "[%d] got suspicious W3XP_CLAN_DISBANDREQ packet (request without required privileges)", conn_get_socket(c)); bn_byte_set(&rpacket->u.server_w3xp_clan_disbandreply.result, SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_NOT_AUTHORIZED); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } else if ((clanlist_remove_clan(clan) == 0) && (clan_remove(clan_get_clantag(clan)) == 0)) { bn_byte_set(&rpacket->u.server_w3xp_clan_disbandreply.result, SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_OK); clan_close_status_window_on_disband(clan); clan_send_packet_to_online_members(clan, rpacket); packet_del_ref(rpacket); clan_destroy(clan); } else { bn_byte_set(&rpacket->u.server_w3xp_clan_disbandreply.result, SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_EXCEPTION); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_w3xp_clan_createreq(t_connection * c, t_packet const *const packet) { if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_createreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createreq), packet_get_size(packet)); return -1; } clan_get_possible_member(c, packet); return 0; } static int _client_w3xp_clan_createinvitereq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; int size; const char *clanname; const char *username; int clantag; int offset; t_clan *clan; if ((size = packet_get_size(packet)) < sizeof(t_client_w3xp_clan_createinvitereq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createinvitereq), packet_get_size(packet)); return -1; } offset = sizeof(t_client_w3xp_clan_createinvitereq); if (!(clanname = packet_get_str_const(packet, offset, CLAN_NAME_MAX))) { eventlog(eventlog_level_error,__FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREQ packet (missing clanname)", conn_get_socket(c)); return -1; } offset += (strlen(clanname) + 1); if (packet_get_size(packet) < offset+4) { eventlog(eventlog_level_error,__FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREQ packet (missing clantag)", conn_get_socket(c)); return -1; } clantag = *((int *) packet_get_data_const(packet, offset, 4)); offset += 4; if ((rpacket = packet_create(packet_class_bnet))) { if ((clan = clan_create(conn_get_account(c), clantag, clanname, NULL)) && clanlist_add_clan(clan)) { char membercount; if (packet_get_size(packet) < offset+1) { eventlog(eventlog_level_error,__FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREQ packet (missing membercount)", conn_get_socket(c)); return -1; } membercount = *((char *) packet_get_data_const(packet, offset, 1)); clan_set_created(clan, -membercount); packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createinvitereq)); packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEINVITEREQ); bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereq.count, bn_int_get(packet->u.client_w3xp_clan_createinvitereq.count)); bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereq.clantag, clantag); packet_append_string(rpacket, clanname); packet_append_string(rpacket, conn_get_username(c)); packet_append_data(rpacket, packet_get_data_const(packet, offset, size - offset), size - offset); offset++; do { username = packet_get_str_const(packet, offset, USER_NAME_MAX); if (username) { t_connection *conn; offset += (strlen(username) + 1); if ((conn = connlist_find_connection_by_accountname(username)) != NULL) { if (prefs_get_clan_newer_time() > 0) clan_add_member(clan, conn_get_account(conn), CLAN_NEW); else clan_add_member(clan, conn_get_account(conn), CLAN_PEON); conn_push_outqueue(conn, rpacket); } } } while (username && (offset < size)); } else { packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createinvitereply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEINVITEREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereply.count, bn_int_get(packet->u.client_w3xp_clan_createinvitereply.count)); bn_byte_set(&rpacket->u.server_w3xp_clan_createinvitereply.status, 0); } packet_del_ref(rpacket); } return 0; } static int _client_w3xp_clan_createinvitereply(t_connection * c, t_packet const *const packet) { t_packet *rpacket; t_connection *conn; t_clan *clan; const char *username; int offset; char status; if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_createinvitereply)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREPLY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createinvitereq), packet_get_size(packet)); return -1; } offset = sizeof(t_client_w3xp_clan_createinvitereply); username = packet_get_str_const(packet, offset, USER_NAME_MAX); offset += (strlen(username) + 1); if (packet_get_size(packet) < offset+1) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREPLY packet (mising status)", conn_get_socket(c)); return -1; } status = *((char *) packet_get_data_const(packet, offset, 1)); if ((conn = connlist_find_connection_by_accountname(username)) == NULL) return -1; if ((clan = account_get_creating_clan(conn_get_account(conn))) == NULL) return -1; if ((status != W3XP_CLAN_INVITEREPLY_ACCEPT) && (rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createinvitereply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEINVITEREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereply.count, bn_int_get(packet->u.client_w3xp_clan_createinvitereply.count)); bn_byte_set(&rpacket->u.server_w3xp_clan_createinvitereply.status, status); packet_append_string(rpacket, conn_get_username(c)); conn_push_outqueue(conn, rpacket); packet_del_ref(rpacket); if (clan) { clanlist_remove_clan(clan); clan_destroy(clan); } } else { int created = clan_get_created(clan); if (created > 0) { eventlog(eventlog_level_error, __FUNCTION__, "clan %s has already been created", clan_get_name(clan)); return 0; } created++; if ((created >= 0) && (rpacket = packet_create(packet_class_bnet))) { clan_set_created(clan, 1); clan_set_creation_time(clan, time(NULL)); packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createinvitereply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEINVITEREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereply.count, bn_int_get(packet->u.client_w3xp_clan_createinvitereply.count)); bn_byte_set(&rpacket->u.server_w3xp_clan_createinvitereply.status, 0); packet_append_string(rpacket, ""); conn_push_outqueue(conn, rpacket); packet_del_ref(rpacket); clan_send_status_window_on_create(clan); clan_save(clan); } else clan_set_created(clan, created); } return 0; } static int _client_w3xp_clanmember_rankupdatereq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_w3xp_clanmember_rankupdate_req)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLANMEMBER_RANKUPDATE_REQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clanmember_rankupdate_req), packet_get_size(packet)); return -1; } if ((rpacket = packet_create(packet_class_bnet)) != NULL) { int offset = sizeof(t_client_w3xp_clanmember_rankupdate_req); const char *username; char status; t_clan *clan; t_clanmember *dest_member; t_clanmember *member; t_account *account; packet_set_size(rpacket, sizeof(t_server_w3xp_clanmember_rankupdate_reply)); packet_set_type(rpacket, SERVER_W3XP_CLANMEMBER_RANKUPDATE_REPLY); bn_int_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.count, bn_int_get(packet->u.client_w3xp_clanmember_rankupdate_req.count)); username = packet_get_str_const(packet, offset, USER_NAME_MAX); offset += (strlen(username) + 1); if (packet_get_size(packet) < offset+1) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLANMEMBER_RANKUPDATE_REQ packet (mising status)", conn_get_socket(c)); return -1; } status = *((char *) packet_get_data_const(packet, offset, 1)); account = (conn_get_account(c)); if ((clan = account_get_clan(account)) && (member = clan_find_member(clan,account)) && (dest_member = clan_find_member_by_name(clan, username)) && (member != dest_member)) { if ((status < CLAN_PEON) || (status > CLAN_SHAMAN)) { /* PELISH: CLAN_NEW can not be promoted to anything * and also noone can be promoted to CLAN_CHIEFTAIN */ DEBUG1("trying to change to bad status %u", status); bn_byte_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.result, SERVER_W3XP_CLANMEMBER_RANKUPDATE_FAILED); } else if ((((clanmember_get_status(member) == CLAN_SHAMAN) && (status < CLAN_SHAMAN) && (clanmember_get_status(dest_member) < CLAN_SHAMAN)) || (clanmember_get_status(member) == CLAN_CHIEFTAIN)) && (clanmember_set_status(dest_member, status) == 0)) { bn_byte_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.result, SERVER_W3XP_CLANMEMBER_RANKUPDATE_SUCCESS); clanmember_on_change_status(dest_member); } else { bn_byte_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.result, SERVER_W3XP_CLANMEMBER_RANKUPDATE_FAILED); } } else { bn_byte_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.result, SERVER_W3XP_CLANMEMBER_RANKUPDATE_FAILED); } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_w3xp_clanmember_removereq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_w3xp_clanmember_remove_req)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLANMEMBER_REMOVE_REQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clanmember_remove_req), packet_get_size(packet)); return -1; } if ((rpacket = packet_create(packet_class_bnet)) != NULL) { t_account *acc; t_clan *clan; const char *username; t_clanmember *member; t_connection *dest_conn; packet_set_size(rpacket, sizeof(t_server_w3xp_clanmember_remove_reply)); packet_set_type(rpacket, SERVER_W3XP_CLANMEMBER_REMOVE_REPLY); bn_int_set(&rpacket->u.server_w3xp_clanmember_remove_reply.count, bn_int_get(packet->u.client_w3xp_clanmember_remove_req.count)); username = packet_get_str_const(packet, sizeof(t_client_w3xp_clanmember_remove_req), USER_NAME_MAX); bn_byte_set(&rpacket->u.server_w3xp_clanmember_remove_reply.result, SERVER_W3XP_CLANMEMBER_REMOVE_FAILED); // initially presume it failed if ((acc = conn_get_account(c)) && (clan = account_get_clan(acc)) && (member = clan_find_member_by_name(clan, username))) { dest_conn = clanmember_get_conn(member); if (clan_remove_member(clan, member) == 0) { t_packet *rpacket2; if (dest_conn) { clan_close_status_window(dest_conn); conn_update_w3_playerinfo(dest_conn); channel_rejoin(dest_conn); } if ((rpacket2 = packet_create(packet_class_bnet)) != NULL) { packet_set_size(rpacket2, sizeof(t_server_w3xp_clanmember_removed_notify)); packet_set_type(rpacket2, SERVER_W3XP_CLANMEMBER_REMOVED_NOTIFY); packet_append_string(rpacket2, username); clan_send_packet_to_online_members(clan, rpacket2); packet_del_ref(rpacket2); } bn_byte_set(&rpacket->u.server_w3xp_clanmember_remove_reply.result, SERVER_W3XP_CLANMEMBER_REMOVE_SUCCESS); } } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } static int _client_w3xp_clan_membernewchiefreq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_membernewchiefreq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_MEMBERNEWCHIEFREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createreq), packet_get_size(packet)); return -1; } if ((rpacket = packet_create(packet_class_bnet)) != NULL) { t_account *acc; t_clan *clan; t_clanmember *oldmember; t_clanmember *newmember; const char *username; packet_set_size(rpacket, sizeof(t_server_w3xp_clan_membernewchiefreply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_MEMBERNEWCHIEFREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_membernewchiefreply.count, bn_int_get(packet->u.client_w3xp_clan_membernewchiefreq.count)); username = packet_get_str_const(packet, sizeof(t_client_w3xp_clan_membernewchiefreq), USER_NAME_MAX); if ((acc = conn_get_account(c)) && (oldmember = account_get_clanmember(acc)) && (clanmember_get_status(oldmember) == CLAN_CHIEFTAIN) && (clan = clanmember_get_clan(oldmember)) && (newmember = clan_find_member_by_name(clan, username)) && (clanmember_set_status(oldmember, CLAN_GRUNT) == 0) && (clanmember_set_status(newmember, CLAN_CHIEFTAIN) == 0)) { clanmember_on_change_status(oldmember); clanmember_on_change_status(newmember); bn_byte_set(&rpacket->u.server_w3xp_clan_membernewchiefreply.result, SERVER_W3XP_CLAN_MEMBERNEWCHIEFREPLY_SUCCESS); clan_send_packet_to_online_members(clan, rpacket); packet_del_ref(rpacket); } else { bn_byte_set(&rpacket->u.server_w3xp_clan_membernewchiefreply.result, SERVER_W3XP_CLAN_MEMBERNEWCHIEFREPLY_FAILED); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_w3xp_clan_invitereq(t_connection * c, t_packet const *const packet) { t_packet *rpacket; t_clan *clan; int clantag; const char *username; t_connection *conn; if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_invitereq)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INVITEREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createreq), packet_get_size(packet)); return -1; } if ((clan = account_get_clan(conn_get_account(c))) != NULL) { if (clan_get_member_count(clan) < prefs_get_clan_max_members()) { if ((clantag = clan_get_clantag(clan)) && (username = packet_get_str_const(packet, sizeof(t_client_w3xp_clan_invitereq), USER_NAME_MAX)) && (conn = connlist_find_connection_by_accountname(username)) && (rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereq)); packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREQ); bn_int_set(&rpacket->u.server_w3xp_clan_invitereq.count, bn_int_get(packet->u.client_w3xp_clan_invitereq.count)); bn_int_set(&rpacket->u.server_w3xp_clan_invitereq.clantag, clantag); packet_append_string(rpacket, clan_get_name(clan)); packet_append_string(rpacket, conn_get_username(c)); conn_push_outqueue(conn, rpacket); packet_del_ref(rpacket); } } else if ((rpacket = packet_create(packet_class_bnet)) != NULL) { packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_invitereply.count, bn_int_get(packet->u.client_w3xp_clan_invitereq.count)); bn_byte_set(&rpacket->u.server_w3xp_clan_invitereply.result, W3XP_CLAN_INVITEREPLY_CLANFULL); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_w3xp_clan_invitereply(t_connection * c, t_packet const *const packet) { t_packet *rpacket; t_clan *clan; const char *username; t_connection *conn; int offset; char status; if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_invitereply)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INVITEREPLY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createreq), packet_get_size(packet)); return -1; } offset = sizeof(t_client_w3xp_clan_invitereply); if (!(username = packet_get_str_const(packet, offset, USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INVITEREPLY packet (missing username)", conn_get_socket(c)); return -1; } offset += (strlen(username) + 1); if (packet_get_size(packet) < offset+1) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INVITEREPLY packet (mising status)", conn_get_socket(c)); return -1; } status = *((char *) packet_get_data_const(packet, offset, 1)); if ((conn = connlist_find_connection_by_accountname(username)) != NULL) { if ((status == W3XP_CLAN_INVITEREPLY_ACCEPT) && (clan = account_get_clan(conn_get_account(conn)))) { char channelname[10]; int clantag; if (clan_get_member_count(clan) < prefs_get_clan_max_members()) { t_clanmember *member = clan_add_member(clan, conn_get_account(c), 1); if ((member != NULL) && (clantag = clan_get_clantag(clan))) { sprintf(channelname, "Clan %c%c%c%c", (clantag >> 24), (clantag >> 16) & 0xff, (clantag >> 8) & 0xff, clantag & 0xff); if (conn_get_channel(c)) { conn_update_w3_playerinfo(c); channel_set_userflags(c); if (conn_set_channel(c, channelname) < 0) conn_set_channel(c, CHANNEL_NAME_BANNED); /* should not fail */ clanmember_set_online(c); } clan_send_status_window(c); } if ((rpacket = packet_create(packet_class_bnet)) != NULL) { packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_invitereply.count, bn_int_get(packet->u.client_w3xp_clan_invitereply.count)); bn_byte_set(&rpacket->u.server_w3xp_clan_invitereply.result, W3XP_CLAN_INVITEREPLY_SUCCESS); conn_push_outqueue(conn, rpacket); packet_del_ref(rpacket); } } else if ((rpacket = packet_create(packet_class_bnet)) != NULL) { packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_invitereply.count, bn_int_get(packet->u.client_w3xp_clan_invitereply.count)); bn_byte_set(&rpacket->u.server_w3xp_clan_invitereply.result, W3XP_CLAN_INVITEREPLY_CLANFULL); conn_push_outqueue(conn, rpacket); packet_del_ref(rpacket); } } else if ((rpacket = packet_create(packet_class_bnet)) != NULL) { packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_invitereply.count, bn_int_get(packet->u.client_w3xp_clan_invitereply.count)); bn_byte_set(&rpacket->u.server_w3xp_clan_invitereply.result, status); conn_push_outqueue(conn, rpacket); packet_del_ref(rpacket); } } return 0; } static int _client_crashdump(t_connection * c, t_packet const *const packet) { return 0; } static int _client_setemailreply(t_connection * c, t_packet const *const packet) { char const *email; t_account *account; if (!(email = packet_get_str_const(packet, sizeof(t_client_setemailreply), MAX_EMAIL_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad SETEMAILREPLY packet", conn_get_socket(c)); return -1; } if (!(account = conn_get_account(c))) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL account for connection in setemail request"); return -1; } if (account_get_email(account)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" already have email set, ignore set email", conn_get_socket(c), account_get_name(account)); return 0; } if (account_set_email(account, email) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] failed to init account \"%s\" email to \"%s\"", conn_get_socket(c), account_get_name(account), email); return 0; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] init account \"%s\" email to \"%s\"", conn_get_socket(c), account_get_name(account), email); return 0; } static int _client_changeemailreq(t_connection * c, t_packet const *const packet) { char const *old; char const *new; char const *username; char const *email; t_account *account; int pos; pos = sizeof(t_client_changeemailreq); if (!(username = packet_get_str_const(packet, pos, USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad username in CHANGEEMAILREQ packet", conn_get_socket(c)); return -1; } pos += (strlen(username) + 1); if (!(old = packet_get_str_const(packet, pos, MAX_EMAIL_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad old email in CHANGEEMAILREQ packet", conn_get_socket(c)); return -1; } pos += (strlen(old) + 1); if (!(new = packet_get_str_const(packet, pos, MAX_EMAIL_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad new email in CHANGEEMAILREQ packet", conn_get_socket(c)); return -1; } if (!(account = accountlist_find_account(username))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] change email for \"%s\" refused (no such account)", conn_get_socket(c), username); return 0; } if (!(email = account_get_email(account)) || !email[0]) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] account \"%s\" do not have email set, ignore changing", conn_get_socket(c), account_get_name(account)); return 0; } if (strcasecmp(email, old)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" email mismatch, ignore changing", conn_get_socket(c), account_get_name(account)); return 0; } if (account_set_email(account, new) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] failed to change account \"%s\" email to \"%s\"", conn_get_socket(c), account_get_name(account), new); return 0; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] change account \"%s\" email to \"%s\"", conn_get_socket(c), account_get_name(account), new); return 0; } static int _client_getpasswordreq(t_connection * c, t_packet const *const packet) { char const *username; char const *try_email; char const *email; t_account *account; int pos; pos = sizeof(t_client_getpasswordreq); if (!(username = packet_get_str_const(packet, pos, USER_NAME_MAX))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad username in GETPASSWORDREQ packet", conn_get_socket(c)); return -1; } pos += (strlen(username) + 1); if (!(try_email = packet_get_str_const(packet, pos, MAX_EMAIL_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad email in GETPASSWORDREQ packet", conn_get_socket(c)); return -1; } if (!(account = accountlist_find_account(username))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] get password for \"%s\" refused (no such account)", conn_get_socket(c), username); return 0; } if (!(email = account_get_email(account)) || !email[0]) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" do not have email set, ignore get password", conn_get_socket(c), account_get_name(account)); return 0; } if (strcasecmp(email, try_email)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" email mismatch, ignore get password", conn_get_socket(c), account_get_name(account)); return 0; } /* TODO: send mail to user with the real password or changed password!? * (as we cannot get the real password back, we should only change the password) --Soar */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] get password for account \"%s\" to email \"%s\"", conn_get_socket(c), account_get_name(account), email); return 0; } pvpgn-1.8.5/src/bnetd/tick.h0000644000175000017500000000163611151345317014636 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_TICK_PROTOS #define INCLUDED_TICK_PROTOS extern unsigned int get_ticks(void); #endif #endif pvpgn-1.8.5/src/bnetd/handle_bot.c0000644000175000017500000002551111151345317015774 0ustar aaronaaron/* * Copyright (C) 1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strdup.h" #include #include "common/packet.h" #include "common/bot_protocol.h" #include "common/tag.h" #include "message.h" #include "common/eventlog.h" #include "command.h" #include "account.h" #include "account_wrap.h" #include "connection.h" #include "channel.h" #include "common/queue.h" #include "common/bnethash.h" #include "common/bnethashconv.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/list.h" #include "common/xalloc.h" #include "handle_bot.h" #include "common/setup_after.h" extern int handle_bot_packet(t_connection * c, t_packet const * const packet) { t_packet * rpacket; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c)); return -1; } if (packet_get_class(packet)!=packet_class_raw) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet)); return -1; } { char const * const linestr=packet_get_str_const(packet,0,MAX_MESSAGE_LEN); if (packet_get_size(packet)<2) /* empty line */ return 0; if (!linestr) { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] line too long",conn_get_socket(c)); return 0; } switch (conn_get_state(c)) { case conn_state_connected: conn_add_flags(c,MF_PLUG); conn_set_clienttag(c,CLIENTTAG_BNCHATBOT_UINT); { char const * temp=linestr; if (temp[0]=='\004') /* FIXME: no echo, ignore for now (we always do no echo) */ temp = &temp[1]; if (temp[0]=='\0') /* empty line */ { conn_set_state(c,conn_state_bot_username); /* don't look for ^D or reset tag and flags */ break; } conn_set_state(c,conn_state_bot_password); if (conn_set_loggeduser(c,temp)<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),temp); { char const * const msg="\r\nPassword: "; if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } #if 1 /* don't echo */ packet_append_ntstring(rpacket,conn_get_loggeduser(c)); #endif packet_append_ntstring(rpacket,msg); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } break; case conn_state_bot_username: conn_set_state(c,conn_state_bot_password); if (conn_set_loggeduser(c,linestr)<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),linestr); { char const * const temp="\r\nPassword: "; if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } #if 1 /* don't echo */ packet_append_ntstring(rpacket,linestr); #endif packet_append_ntstring(rpacket,temp); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } break; case conn_state_bot_password: { char const * const tempa="\r\nLogin failed.\r\n\r\nUsername: "; char const * const tempb="\r\nAccount has no bot access.\r\n\r\nUsername: "; char const * loggeduser=conn_get_loggeduser(c); t_account * account; char const * oldstrhash1; t_hash trypasshash1; t_hash oldpasshash1; char * testpass; if (!loggeduser) /* error earlier in login */ { /* no log message... */ conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (connlist_find_connection_by_accountname(loggeduser)) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (already logged in)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (!(account = accountlist_find_account(loggeduser))) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (bad account)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if ((oldstrhash1 = account_get_pass(account))) { if (hash_set_str(&oldpasshash1,oldstrhash1)<0) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (corrupted passhash1?)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } testpass = xstrdup(linestr); { unsigned int i; for (i=0; i # endif # ifdef TIME_WITH_SYS_TIME # include # include # else # if HAVE_SYS_TIME_H # include # else # include # endif # endif # include "common/list.h" #else # define JUST_NEED_TYPES # ifdef HAVE_SYS_TYPES_H # include # endif # ifdef TIME_WITH_SYS_TIME # include # include # else # if HAVE_SYS_TIME_H # include # else # include # endif # endif # include "common/list.h" # undef JUST_NEED_TYPES #endif typedef struct { time_t inf; unsigned int count; } t_qline; typedef struct { unsigned int totcount; t_list * list; } t_quota; #endif pvpgn-1.8.5/src/bnetd/channel_conv.c0000644000175000017500000000264111151345317016331 0ustar aaronaaron/* * Copyright (C) 2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "common/bnet_protocol.h" #include "channel.h" #include "channel_conv.h" #include "common/setup_after.h" extern unsigned int cflags_to_bncflags(t_channel_flags flags) { unsigned int res; res = 0; if (flags&channel_flags_public) res |= CF_PUBLIC; if (flags&channel_flags_moderated) res |= CF_MODERATED; if (flags&channel_flags_restricted) res |= CF_RESTRICTED; if (flags&channel_flags_thevoid) res |= CF_THEVOID; if (flags&channel_flags_system) res |= CF_SYSTEM; if (flags&channel_flags_official) res |= CF_OFFICIAL; return res; } pvpgn-1.8.5/src/bnetd/channel.h0000644000175000017500000001503611151345317015313 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_CHANNEL_TYPES #define INCLUDED_CHANNEL_TYPES #ifdef JUST_NEED_TYPES # include "common/bn_type.h" #else # define JUST_NEED_TYPES # include "common/bn_type.h" # undef JUST_NEED_TYPES #endif # include "account.h" #ifdef CHANNEL_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include # include "connection.h" # include "common/list.h" #else # define JUST_NEED_TYPES # include # include "connection.h" # include "common/list.h" # undef JUST_NEED_TYPES #endif #endif #ifdef CHANNEL_INTERNAL_ACCESS typedef struct channelmember { /* standalone mode */ t_connection * connection; struct channelmember * next; } t_channelmember; #endif typedef enum { channel_flags_none=0x00, channel_flags_public=0x01, channel_flags_moderated=0x02, channel_flags_restricted=0x04, channel_flags_thevoid=0x08, channel_flags_system=0x10, channel_flags_official=0x20, channel_flags_permanent=0x40, channel_flags_allowbots=0x80, channel_flags_allowopers=0x100, channel_flags_clan=0x200, channel_flags_autoname=0x400 } t_channel_flags; typedef struct channel #ifdef CHANNEL_INTERNAL_ACCESS { char const * name; char const * shortname; /* short "alias" for permanent channels, NULL if none */ char const * country; char const * realmname; t_channel_flags flags; int maxmembers; int currmembers; char const * clienttag; unsigned int id; t_channelmember * memberlist; t_list * banlist; /* of char * */ char * logname; /* NULL if not logged */ FILE * log; /* NULL if not logging */ /** * Westwood Online Extensions */ char const * gameOwner; int gameOwnerIP; int gameType; int gameTournament; char const * gameOptions; } #endif t_channel; #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_CHANNEL_PROTOS #define INCLUDED_CHANNEL_PROTOS #define JUST_NEED_TYPES #include "connection.h" #include "message.h" #include "common/list.h" #undef JUST_NEED_TYPES #define CHANNEL_NAME_BANNED "THE VOID" #define CHANNEL_NAME_KICKED "THE VOID" #define CHANNEL_NAME_CHAT "Chat" extern int channel_set_userflags(t_connection * c); extern t_channel * channel_create(char const * fullname, char const * shortname, char const * clienttag, int permflag, int botflag, int operflag, int logflag, char const * country, char const * realmname, int maxmembers, int moderated, int clan,int autoname) ; extern int channel_destroy(t_channel * channel, t_elem ** elem); extern char const * channel_get_name(t_channel const * channel); extern char const * channel_get_shortname(t_channel const * channel); extern char const * channel_get_clienttag(t_channel const * channel); extern t_channel_flags channel_get_flags(t_channel const * channel); extern int channel_set_flags(t_channel * channel, t_channel_flags flags); extern int channel_get_permanent(t_channel const * channel); extern unsigned int channel_get_channelid(t_channel const * channel); extern int channel_set_channelid(t_channel * channel, unsigned int channelid); extern int channel_add_connection(t_channel * channel, t_connection * connection); extern int channel_del_connection(t_channel * channel, t_connection * connection); extern void channel_update_latency(t_connection * conn); extern void channel_update_userflags(t_connection * conn); extern void channel_message_log(t_channel const * channel, t_connection * me, int fromuser, char const * text); extern void channel_message_send(t_channel const * channel, t_message_type type, t_connection * conn, char const * text); extern int channel_ban_user(t_channel * channel, char const * user); extern int channel_unban_user(t_channel * channel, char const * user); extern int channel_check_banning(t_channel const * channel, t_connection const * user); extern int channel_rejoin(t_connection * conn); extern t_list * channel_get_banlist(t_channel const * channel); extern int channel_get_length(t_channel const * channel); extern int channel_get_max(t_channel const * channel); extern int channel_set_max(t_channel * channel, int maxmembers); extern int channel_get_curr(t_channel const * channel); extern int channel_conn_is_tmpOP(t_channel const * channel, t_connection * c); extern int channel_conn_has_tmpVOICE(t_channel const * channel, t_connection * c); extern t_connection * channel_get_first(t_channel const * channel); extern t_connection * channel_get_next(void); extern int channellist_create(void); extern int channellist_destroy(void); extern int channellist_reload(void); extern t_list * channellist(void); extern t_channel * channellist_find_channel_by_name(char const * name, char const * locale, char const * realmname); extern t_channel * channellist_find_channel_bychannelid(unsigned int channelid); extern int channellist_get_length(void); /** * Westwood Online Extensions */ extern char const * channel_wol_get_game_owner(t_channel const * channel); extern int channel_wol_set_game_owner(t_channel * channel, char const * gameOwner); extern int channel_wol_get_game_ownerip(t_channel const * channel); extern int channel_wol_set_game_ownerip(t_channel * channel, int gameOwnerIP); extern int channel_wol_get_game_type(t_channel const * channel); extern int channel_wol_set_game_type(t_channel * channel, int gameType); extern int channel_wol_get_game_tournament(t_channel const * channel); extern int channel_wol_set_game_tournament(t_channel * channel, int tournament); extern char const * channel_wol_get_game_options(t_channel const * channel); extern int channel_wol_set_game_options(t_channel * channel, char const * gameOptions); #endif #endif pvpgn-1.8.5/src/bnetd/message.h0000644000175000017500000000710111151345317015321 0ustar aaronaaron/* * Copyright (C) 1998,1999,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_MESSAGE_TYPES #define INCLUDED_MESSAGE_TYPES #ifdef MESSAGE_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include "common/packet.h" # include "connection.h" #else # define JUST_NEED_TYPES # include "common/packet.h" # include "connection.h" # undef JUST_NEED_TYPES #endif #endif typedef enum { message_type_adduser, message_type_join, message_type_part, message_type_whisper, message_type_talk, message_type_broadcast, message_type_channel, message_type_userflags, message_type_whisperack, message_type_friendwhisperack, message_type_channelfull, message_type_channeldoesnotexist, message_type_channelrestricted, message_type_info, message_type_error, message_type_emote, message_type_uniqueid, message_type_mode, /** * IRC specific messages */ message_type_notice, /** * Westwood Online Extensions */ message_wol_joingame, message_wol_gameopt_owner, message_wol_gameopt_join, message_wol_start_game, message_wol_page, message_type_null } t_message_type; typedef enum { message_class_normal, message_class_charjoin, /* use char*account (if account isnt d2 char is "") */ } t_message_class; typedef struct message #ifdef MESSAGE_INTERNAL_ACCESS { unsigned int num_cached; t_packet * * packets; /* cached messages */ t_conn_class * classes; /* classes of cached message connections */ unsigned int * dstflags; /* overlaid flags of cached messages */ t_message_class * mclasses; /* classes of cached messages */ /* ---- */ t_message_type type; /* format of message */ t_connection * src; /* originator message */ t_connection * dst; /* destination */ char const * text; /* text of message */ } #endif t_message; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_MESSAGE_PROTOS #define INCLUDED_MESSAGE_PROTOS #define JUST_NEED_TYPES #include #include "connection.h" #undef JUST_NEED_TYPES extern char * message_format_line(t_connection const * c, char const * in); extern t_message * message_create(t_message_type type, t_connection * src, t_connection * dst, char const * text); extern int message_destroy(t_message * message); extern int message_send(t_message * message, t_connection * dst); extern int message_send_all(t_message * message); extern int message_send_admins(t_connection * src, t_message_type type, char const * text); /* the following are "shortcuts" to avoid calling message_create(), message_send(), message_destroy() */ extern int message_send_text(t_connection * dst, t_message_type type, t_connection * src, char const * text); extern int message_send_formatted(t_connection * dst, char const * text); extern int message_send_file(t_connection * dst, FILE * fd); #endif #endif pvpgn-1.8.5/src/bnetd/support.h0000644000175000017500000000156711151345317015423 0ustar aaronaaron/* * Copyright (C) 2004 Lector * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SUPPORT_PROTOS #define INCLUDED_SUPPORT_PROTOS extern int support_check_files(char const * supportfile); #endif pvpgn-1.8.5/src/bnetd/connection.h0000644000175000017500000004526011151345317016044 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_CONNECTION_TYPES #define INCLUDED_CONNECTION_TYPES #ifdef CONNECTION_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # ifdef TIME_WITH_SYS_TIME # include # include # else # if HAVE_SYS_TIME_H # include # else # include # endif # endif # include "game.h" # include "common/queue.h" # include "channel.h" # include "account.h" # include "quota.h" # include "character.h" # include "versioncheck.h" # include "anongame.h" # include "realm.h" # include "common/tag.h" # include "common/elist.h" # include "common/packet.h" # include "common/rcm.h" #else # define JUST_NEED_TYPES # ifdef TIME_WITH_SYS_TIME # include # include # else # if HAVE_SYS_TIME_H # include # else # include # endif # endif # include "game.h" # include "common/queue.h" # include "channel.h" # include "account.h" # include "quota.h" # include "character.h" # include "versioncheck.h" # include "anongame.h" # include "realm.h" # include "common/tag.h" # include "common/elist.h" # include "common/packet.h" # include "common/rcm.h" # undef JUST_NEED_TYPES #endif #endif typedef enum { conn_class_init, conn_class_bnet, conn_class_file, conn_class_bot, conn_class_telnet, conn_class_irc, /* Internet Relay Chat */ conn_class_wol, /* Westwood Online */ conn_class_d2cs_bnetd, conn_class_w3route, conn_class_none } t_conn_class; typedef enum { conn_state_empty, conn_state_initial, conn_state_connected, conn_state_loggedin, conn_state_destroy, conn_state_bot_username, conn_state_bot_password, conn_state_untrusted, conn_state_pending_raw } t_conn_state; #ifdef CONNECTION_INTERNAL_ACCESS typedef enum { conn_flags_welcomed = 0x01, conn_flags_udpok = 0x02, conn_flags_joingamewhisper = 0x04, conn_flags_leavegamewhisper = 0x08, conn_flags_echoback = 0x10 } t_conn_flags; #endif typedef struct connection #ifdef CONNECTION_INTERNAL_ACCESS { struct { int tcp_sock; unsigned int tcp_addr; unsigned short tcp_port; int udp_sock; unsigned int udp_addr; unsigned short udp_port; unsigned int local_addr; unsigned short local_port; unsigned int real_local_addr; unsigned short real_local_port; int fdw_idx; } socket; /* IP and socket specific data */ struct { t_conn_class class; t_conn_state state; unsigned int sessionkey; unsigned int sessionnum; unsigned int secret; /* random number... never sent over net unencrypted */ unsigned int flags; unsigned int latency; t_account * account; struct { t_tag archtag; t_tag gamelang; t_clienttag clienttag; char const * clientver; unsigned long versionid; /* AKA bnversion */ unsigned long gameversion; unsigned long checksum; char const * country; int tzbias; char const * host; char const * user; char const * clientexe; char const * owner; char const * cdkey; t_versioncheck * versioncheck; /* equation and MPQ file used to validate game checksum */ } client; /* client program specific data */ struct { t_queue * outqueue; /* packets waiting to be sent */ unsigned int outsize; /* amount sent from the current output packet */ unsigned int outsizep; t_packet * inqueue; /* packet waiting to be processed */ unsigned int insize; /* amount received into the current input packet */ } queues; /* network queues and related data */ struct { t_channel * channel; char const * tmpOP_channel; char const * tmpVOICE_channel; char const * away; char const * dnd; t_account * * ignore_list; unsigned int ignore_count; t_quota quota; time_t last_message; char const * lastsender; /* last person to whisper to this connection */ struct { char const * ircline; /* line cache for IRC connections */ unsigned int ircping; /* value of last ping */ char const * ircpass; /* hashed password for PASS authentication */ } irc; /* irc chat specific data */ } chat; /* chat and messages specific data */ t_game * game; const char * loggeduser; /* username as logged in or given (not taken from account) */ struct connection * bound; /* matching Diablo II auth connection */ t_elist timers; /* cached list of timers for cleaning */ /* FIXME: this d2/w3 specific data could be unified into an union */ struct { t_realm * realm; t_rcm_regref realm_regref; t_character * character; char const * realminfo; char const * charname; } d2; struct { char const * w3_playerinfo; /* ADDED BY UNDYING SOULZZ 4/7/02 */ time_t anongame_search_starttime; /* [zap-zero] 20020527 - matching w3route connection for game connection / matching game connection for w3route connection */ /* FIXME: this "optimization" is so confusing leading to many possible bugs */ struct connection * routeconn; t_anongame * anongame; } w3; struct { int ingame; /* Are we in a game channel? */ int codepage; int locale; int gameType; char const * apgar; /* WOL User Password (encrypted) */ char const * gameOptions; /* Game Options */ } wol; int cr_time; /* Pass fail count for bruteforce protection */ unsigned int passfail_count; /* connection flag substituting some other values */ t_conn_flags cflags; } protocol; } #endif t_connection; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_CONNECTION_PROTOS #define INCLUDED_CONNECTION_PROTOS #define JUST_NEED_TYPES #include "common/packet.h" #include "common/queue.h" #include "channel.h" #include "game.h" #include "account.h" #include "common/list.h" #include "character.h" #include "versioncheck.h" #include "timer.h" #include "anongame.h" # include "realm.h" #include "message.h" #include "common/tag.h" #include "common/fdwatch.h" #undef JUST_NEED_TYPES #define DESTROY_FROM_CONNLIST 0 #define DESTROY_FROM_DEADLIST 1 extern t_anongame * conn_create_anongame(t_connection * c); extern void conn_destroy_anongame(t_connection * c); extern t_anongame * conn_get_anongame(t_connection *c); extern void conn_shutdown(t_connection * c, time_t now, t_timer_data foo); extern void conn_test_latency(t_connection * c, time_t now, t_timer_data delta); extern char const * conn_class_get_str(t_conn_class class) ; extern char const * conn_state_get_str(t_conn_state state) ; extern t_connection * conn_create(int tsock, int usock, unsigned int real_local_addr, unsigned short real_local_port, unsigned int local_addr, unsigned short local_port, unsigned int addr, unsigned short port) ; extern void conn_destroy(t_connection * c, t_elem ** elem, int conn_or_dead_list); extern int conn_match(t_connection const * c, char const * user); extern t_conn_class conn_get_class(t_connection const * c) ; extern void conn_set_class(t_connection * c, t_conn_class class); extern t_conn_state conn_get_state(t_connection const * c) ; extern void conn_set_state(t_connection * c, t_conn_state state); extern unsigned int conn_get_sessionkey(t_connection const * c) ; extern unsigned int conn_get_sessionnum(t_connection const * c) ; extern unsigned int conn_get_secret(t_connection const * c) ; extern unsigned int conn_get_addr(t_connection const * c) ; extern unsigned short conn_get_port(t_connection const * c) ; extern unsigned int conn_get_local_addr(t_connection const * c); extern unsigned short conn_get_local_port(t_connection const * c) ; extern unsigned int conn_get_real_local_addr(t_connection const * c) ; extern unsigned short conn_get_real_local_port(t_connection const * c) ; extern unsigned int conn_get_game_addr(t_connection const * c) ; extern int conn_set_game_addr(t_connection * c, unsigned int game_addr); extern unsigned short conn_get_game_port(t_connection const * c) ; extern int conn_set_game_port(t_connection * c, unsigned short game_port); extern void conn_set_host(t_connection * c, char const * host); extern void conn_set_user(t_connection * c, char const * user); extern const char * conn_get_user(t_connection const * c); extern void conn_set_owner(t_connection * c, char const * owner); extern const char * conn_get_owner(t_connection const * c); extern void conn_set_cdkey(t_connection * c, char const * cdkey); extern char const * conn_get_clientexe(t_connection const * c) ; extern void conn_set_clientexe(t_connection * c, char const * clientexe); extern t_tag conn_get_archtag(t_connection const * c) ; extern void conn_set_archtag(t_connection * c, t_tag archtag); extern t_tag conn_get_gamelang(t_connection const * c) ; extern void conn_set_gamelang(t_connection * c, t_tag gamelang); extern t_clienttag conn_get_clienttag(t_connection const * c) ; extern t_clienttag conn_get_fake_clienttag(t_connection const * c) ; extern void conn_set_clienttag(t_connection * c, t_clienttag clienttag); extern unsigned long conn_get_versionid(t_connection const * c) ; extern int conn_set_versionid(t_connection * c, unsigned long versionid); extern unsigned long conn_get_gameversion(t_connection const * c) ; extern int conn_set_gameversion(t_connection * c, unsigned long gameversion); extern unsigned long conn_get_checksum(t_connection const * c) ; extern int conn_set_checksum(t_connection * c, unsigned long checksum); extern char const * conn_get_clientver(t_connection const * c) ; extern void conn_set_clientver(t_connection * c, char const * clientver); extern int conn_get_tzbias(t_connection const * c) ; extern void conn_set_tzbias(t_connection * c, int tzbias); extern int conn_set_loggeduser(t_connection * c, char const * username); extern char const * conn_get_loggeduser(t_connection const * c); extern unsigned int conn_get_flags(t_connection const * c) ; extern int conn_set_flags(t_connection * c, unsigned int flags); extern void conn_add_flags(t_connection * c, unsigned int flags); extern void conn_del_flags(t_connection * c, unsigned int flags); extern unsigned int conn_get_latency(t_connection const * c) ; extern void conn_set_latency(t_connection * c, unsigned int ms); extern char const * conn_get_awaystr(t_connection const * c) ; extern int conn_set_awaystr(t_connection * c, char const * away); extern char const * conn_get_dndstr(t_connection const * c) ; extern int conn_set_dndstr(t_connection * c, char const * dnd); extern int conn_add_ignore(t_connection * c, t_account * account); extern int conn_del_ignore(t_connection * c, t_account const * account); extern int conn_add_watch(t_connection * c, t_account * account, t_clienttag clienttag); extern int conn_del_watch(t_connection * c, t_account * account, t_clienttag clienttag); extern t_channel * conn_get_channel(t_connection const * c) ; extern int conn_set_channel_var(t_connection * c, t_channel * channel); extern int conn_set_channel(t_connection * c, char const * channelname); extern t_game * conn_get_game(t_connection const * c) ; extern int conn_set_game(t_connection * c, char const * gamename, char const * gamepass, char const * gameinfo, t_game_type type, int version); extern unsigned int conn_get_tcpaddr(t_connection * c) ; extern t_packet * conn_get_in_queue(t_connection * c) ; extern void conn_put_in_queue(t_connection * c, t_packet *packet) ; extern unsigned int conn_get_in_size(t_connection const * c) ; extern void conn_set_in_size(t_connection * c, unsigned int size); extern unsigned int conn_get_out_size(t_connection const * c) ; extern void conn_set_out_size(t_connection * c, unsigned int size); extern int conn_push_outqueue(t_connection * c, t_packet * packet); extern t_packet * conn_peek_outqueue(t_connection * c); extern t_packet * conn_pull_outqueue(t_connection * c); extern int conn_check_ignoring(t_connection const * c, char const * me) ; extern t_account * conn_get_account(t_connection const * c) ; extern void conn_login(t_connection * c, t_account * account, const char *loggeduser); extern int conn_get_socket(t_connection const * c) ; extern int conn_get_game_socket(t_connection const * c) ; extern int conn_set_game_socket(t_connection * c, int usock); extern char const * conn_get_username_real(t_connection const * c, char const * fn, unsigned int ln); #define conn_get_username(C) conn_get_username_real(C,__FILE__,__LINE__) extern char const * conn_get_chatname(t_connection const * c); extern int conn_unget_chatname(t_connection const * c, char const * name); extern char const * conn_get_chatcharname(t_connection const * c, t_connection const * dst); extern int conn_unget_chatcharname(t_connection const * c, char const * name); extern t_message_class conn_get_message_class(t_connection const * c, t_connection const * dst); extern unsigned int conn_get_userid(t_connection const * c); extern char const * conn_get_playerinfo(t_connection const * c); extern int conn_set_playerinfo(t_connection const * c, char const * playerinfo); extern char const * conn_get_realminfo(t_connection const * c); extern int conn_set_realminfo(t_connection * c, char const * realminfo); extern char const * conn_get_charname(t_connection const * c); extern int conn_set_charname(t_connection * c, char const * charname); extern int conn_set_idletime(t_connection * c); extern unsigned int conn_get_idletime(t_connection const * c) ; extern t_realm * conn_get_realm(t_connection const * c); extern int conn_set_realm(t_connection * c, t_realm * realm); extern int conn_set_character(t_connection * c, t_character * ch); extern int conn_bind(t_connection * c1, t_connection * c2); extern void conn_set_country(t_connection * c, char const * country); extern char const * conn_get_country(t_connection const * c); extern int conn_quota_exceeded(t_connection * c, char const * message); extern int conn_set_lastsender(t_connection * c, char const * sender); extern char const * conn_get_lastsender(t_connection const * c); extern t_versioncheck * conn_get_versioncheck(t_connection * c) ; extern int conn_set_versioncheck(t_connection * c, t_versioncheck * versioncheck); extern int conn_get_echoback(t_connection * c) ; extern void conn_set_echoback(t_connection * c, int echoback); extern int conn_set_ircline(t_connection * c, char const * line); extern char const * conn_get_ircline(t_connection const * c); extern int conn_set_ircpass(t_connection * c, char const * pass); extern char const * conn_get_ircpass(t_connection const * c); extern int conn_set_ircping(t_connection * c, unsigned int ping); extern unsigned int conn_get_ircping(t_connection const * c); extern int conn_set_udpok(t_connection * c); extern int conn_get_welcomed(t_connection const * c) ; extern void conn_set_welcomed(t_connection * c, int welcomed); extern int conn_set_w3_playerinfo( t_connection * c, char const * w3_playerinfo ); extern const char * conn_get_w3_playerinfo( t_connection * c ); extern int conn_get_crtime(t_connection *c); extern int conn_set_w3_loginreq(t_connection * c, char const * loginreq); extern char const * conn_get_w3_loginreq(t_connection * c); extern int conn_set_routeconn(t_connection * c, t_connection * rc); extern t_connection * conn_get_routeconn(t_connection const * c); extern int connlist_create(void); extern void connlist_reap(void); extern int connlist_destroy(void); extern t_list * connlist(void) ; extern t_connection * connlist_find_connection_by_sessionkey(unsigned int sessionkey); extern t_connection * connlist_find_connection_by_socket(int socket); extern t_connection * connlist_find_connection_by_sessionnum(unsigned int sessionnum); extern t_connection * connlist_find_connection_by_name(char const * name, t_realm * realm); /* any chat name format */ extern t_connection * connlist_find_connection_by_accountname(char const * username); extern t_connection * connlist_find_connection_by_charname(char const * charname, char const * realmname); extern t_connection * connlist_find_connection_by_account(t_account * account); extern t_connection * connlist_find_connection_by_uid(unsigned int uid); extern int connlist_get_length(void) ; extern unsigned int connlist_login_get_length(void) ; extern int connlist_total_logins(void) ; extern int conn_set_joingamewhisper_ack(t_connection * c, unsigned int value); extern int conn_get_joingamewhisper_ack(t_connection * c); extern int conn_set_leavegamewhisper_ack(t_connection * c, unsigned int value); extern int conn_get_leavegamewhisper_ack(t_connection * c); extern int conn_set_anongame_search_starttime(t_connection * c, time_t t); extern time_t conn_get_anongame_search_starttime(t_connection * c); extern int conn_get_user_count_by_clienttag(t_clienttag ct); extern unsigned int connlist_count_connections(unsigned int addr); extern int conn_update_w3_playerinfo(t_connection * c); extern int conn_get_passfail_count(t_connection * c); extern int conn_set_passfail_count(t_connection * c, unsigned int failcount); extern int conn_increment_passfail_count (t_connection * c); extern int conn_set_tmpOP_channel(t_connection * c, char const * tmpOP_channel); extern char const * conn_get_tmpOP_channel(t_connection * c); extern int conn_set_tmpVOICE_channel(t_connection * c, char const * tmpVOICE_channel); extern char const * conn_get_tmpVOICE_channel(t_connection * c); extern t_elist *conn_get_timer(t_connection * c); extern int conn_add_fdwatch(t_connection *c, fdwatch_handler handle); /** * Westwood Online Extensions */ extern int conn_get_wol(t_connection * c); extern void conn_wol_set_ingame(t_connection * c, int wol_ingame); extern int conn_wol_get_ingame(t_connection * c); extern void conn_wol_set_apgar(t_connection * c, char const * apgar); extern char const * conn_wol_get_apgar(t_connection * c); extern void conn_wol_set_codepage(t_connection * c, int codepage); extern int conn_wol_get_codepage(t_connection * c); extern void conn_wol_set_locale(t_connection * c, int locale); extern int conn_wol_get_locale(t_connection * c); extern void conn_wol_set_game_type(t_connection * c, int gameType); extern int conn_wol_get_game_type(t_connection * c); extern void conn_wol_set_game_options(t_connection * c, char const * gameOptions); extern char const * conn_wol_get_game_options(t_connection * c); #endif #endif pvpgn-1.8.5/src/bnetd/channel.c0000644000175000017500000012664011151345317015312 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define CHANNEL_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strrchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include "connection.h" #include "common/eventlog.h" #include "common/list.h" #include "message.h" #include "account.h" #include "account_wrap.h" #include "common/util.h" #include "prefs.h" #include "common/token.h" #include "channel.h" #include "irc.h" #include "common/tag.h" #include "common/xalloc.h" #include "common/setup_after.h" static t_list * channellist_head=NULL; static t_channelmember * memberlist_curr=NULL; static int totalcount=0; static int channellist_load_permanent(char const * filename); static t_channel * channellist_find_channel_by_fullname(char const * name); static char * channel_format_name(char const * sname, char const * country, char const * realmname, unsigned int id); extern int channel_set_userflags(t_connection * c); extern t_channel * channel_create(char const * fullname, char const * shortname, char const * clienttag, int permflag, int botflag, int operflag, int logflag, char const * country, char const * realmname, int maxmembers, int moderated, int clanflag, int autoname) { t_channel * channel; if (!fullname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL fullname"); return NULL; } if (fullname[0]=='\0') { eventlog(eventlog_level_error,__FUNCTION__,"got empty fullname"); return NULL; } if (shortname && shortname[0]=='\0') { eventlog(eventlog_level_error,__FUNCTION__,"got empty shortname"); return NULL; } if (clienttag && strlen(clienttag)!=4) { eventlog(eventlog_level_error,__FUNCTION__,"client tag has bad length (%u chars)",strlen(clienttag)); return NULL; } /* non-permanent already checks for this in conn_set_channel */ if (permflag) { if ((channel = channellist_find_channel_by_fullname(fullname))) { if ((channel_get_clienttag(channel)) && (clienttag) && (strcmp(channel_get_clienttag(channel),clienttag)==0)) { eventlog(eventlog_level_error,__FUNCTION__,"could not create duplicate permanent channel (fullname \"%s\")",fullname); return NULL; } else if (((channel->flags & channel_flags_allowbots)!=(botflag?channel_flags_allowbots:0)) || ((channel->flags & channel_flags_allowopers)!=(operflag?channel_flags_allowopers:0)) || (channel->maxmembers!=maxmembers) || ((channel->flags & channel_flags_moderated)!=(moderated?channel_flags_moderated:0)) || (channel->logname && logflag==0) || (!(channel->logname) && logflag ==1)) { eventlog(eventlog_level_error,__FUNCTION__,"channel parameters do not match for \"%s\" and \"%s\"",fullname,channel->name); return NULL; } } } channel = xmalloc(sizeof(t_channel)); if (permflag) { channel->flags = channel_flags_public; if (clienttag && maxmembers!=-1) /* approximation.. we want things like "Starcraft USA-1" */ channel->flags |= channel_flags_system; } else channel->flags = channel_flags_none; if (moderated) channel->flags |= channel_flags_moderated; if(shortname && (!strcasecmp(shortname, CHANNEL_NAME_KICKED) || !strcasecmp(shortname, CHANNEL_NAME_BANNED))) channel->flags |= channel_flags_thevoid; eventlog(eventlog_level_debug,__FUNCTION__,"creating new channel \"%s\" shortname=%s%s%s clienttag=%s%s%s country=%s%s%s realm=%s%s%s",fullname, shortname?"\"":"(", /* all this is doing is printing the name in quotes else "none" in parens */ shortname?shortname:"none", shortname?"\"":")", clienttag?"\"":"(", clienttag?clienttag:"none", clienttag?"\"":")", country?"\"":"(", country?country:"none", country?"\"":")", realmname?"\"":"(", realmname?realmname:"none", realmname?"\"":")"); channel->name = xstrdup(fullname); if (!shortname) channel->shortname = NULL; else channel->shortname = xstrdup(shortname); if (clienttag) channel->clienttag = xstrdup(clienttag); else channel->clienttag = NULL; if (country) channel->country = xstrdup(country); else channel->country = NULL; if (realmname) channel->realmname = xstrdup(realmname); else channel->realmname=NULL; channel->banlist = list_create(); totalcount++; if (totalcount==0) /* if we wrap (yeah right), don't use id 0 */ totalcount = 1; channel->id = totalcount; channel->maxmembers = maxmembers; channel->currmembers = 0; channel->memberlist = NULL; if (permflag) channel->flags |= channel_flags_permanent; if (botflag) channel->flags |= channel_flags_allowbots; if (operflag) channel->flags |= channel_flags_allowopers; if (clanflag) channel->flags |= channel_flags_clan; if (autoname) channel->flags |= channel_flags_autoname; if (logflag) { time_t now; struct tm * tmnow; char dstr[64]; char timetemp[CHANLOG_TIME_MAXLEN]; now = time(NULL); if (!(tmnow = localtime(&now))) dstr[0] = '\0'; else sprintf(dstr,"%04d%02d%02d%02d%02d%02d", 1900+tmnow->tm_year, tmnow->tm_mon+1, tmnow->tm_mday, tmnow->tm_hour, tmnow->tm_min, tmnow->tm_sec); channel->logname = xmalloc(strlen(prefs_get_chanlogdir())+9+strlen(dstr)+1+6+1); /* dir + "/chanlog-" + dstr + "-" + id + NUL */ sprintf(channel->logname,"%s/chanlog-%s-%06u",prefs_get_chanlogdir(),dstr,channel->id); if (!(channel->log = fopen(channel->logname,"w"))) eventlog(eventlog_level_error,__FUNCTION__,"could not open channel log \"%s\" for writing (fopen: %s)",channel->logname,pstrerror(errno)); else { fprintf(channel->log,"name=\"%s\"\n",channel->name); if (channel->shortname) fprintf(channel->log,"shortname=\"%s\"\n",channel->shortname); else fprintf(channel->log,"shortname=none\n"); fprintf(channel->log,"permanent=\"%s\"\n",(channel->flags & channel_flags_permanent)?"true":"false"); fprintf(channel->log,"allowbotse=\"%s\"\n",(channel->flags & channel_flags_allowbots)?"true":"false"); fprintf(channel->log,"allowopers=\"%s\"\n",(channel->flags & channel_flags_allowopers)?"true":"false"); if (channel->clienttag) fprintf(channel->log,"clienttag=\"%s\"\n",channel->clienttag); else fprintf(channel->log,"clienttag=none\n"); if (tmnow) strftime(timetemp,sizeof(timetemp),CHANLOG_TIME_FORMAT,tmnow); else strcpy(timetemp,"?"); fprintf(channel->log,"created=\"%s\"\n\n",timetemp); fflush(channel->log); } } else { channel->logname = NULL; channel->log = NULL; } channel->gameOwner = NULL; channel->gameOwnerIP = 0; channel->gameType = 0; channel->gameTournament = 0; channel->gameOptions = NULL; list_append_data(channellist_head,channel); eventlog(eventlog_level_debug,__FUNCTION__,"channel created successfully"); return channel; } extern int channel_destroy(t_channel * channel, t_elem ** curr) { t_elem * ban; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } if (channel->memberlist) { eventlog(eventlog_level_debug,__FUNCTION__,"channel is not empty, deferring"); channel->flags &= ~channel_flags_permanent; /* make it go away when the last person leaves */ return -1; } if (list_remove_data(channellist_head,channel,curr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"destroying channel \"%s\"",channel->name); LIST_TRAVERSE(channel->banlist,ban) { char const * banned; if (!(banned = elem_get_data(ban))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL name in banlist"); else xfree((void *)banned); /* avoid warning */ if (list_remove_elem(channel->banlist,&ban)<0) eventlog(eventlog_level_error,__FUNCTION__,"unable to remove item from list"); } list_destroy(channel->banlist); if (channel->log) { time_t now; struct tm * tmnow; char timetemp[CHANLOG_TIME_MAXLEN]; now = time(NULL); if ((!(tmnow = localtime(&now)))) strcpy(timetemp,"?"); else strftime(timetemp,sizeof(timetemp),CHANLOG_TIME_FORMAT,tmnow); fprintf(channel->log,"\ndestroyed=\"%s\"\n",timetemp); if (fclose(channel->log)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close channel log \"%s\" after writing (fclose: %s)",channel->logname,pstrerror(errno)); } if (channel->logname) xfree((void *)channel->logname); /* avoid warning */ if (channel->country) xfree((void *)channel->country); /* avoid warning */ if (channel->realmname) xfree((void *)channel->realmname); /* avoid warning */ if (channel->clienttag) xfree((void *)channel->clienttag); /* avoid warning */ if (channel->shortname) xfree((void *)channel->shortname); /* avoid warning */ xfree((void *)channel->name); /* avoid warning */ xfree(channel); return 0; } extern char const * channel_get_name(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel"); return ""; } return channel->name; } extern char const * channel_get_clienttag(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return ""; } return channel->clienttag; } extern t_channel_flags channel_get_flags(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return channel_flags_none; } return channel->flags; } extern int channel_set_flags(t_channel * channel, t_channel_flags flags) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } channel->flags = flags; return 0; } extern int channel_get_permanent(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } return (channel->flags & channel_flags_permanent); } extern unsigned int channel_get_channelid(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } return channel->id; } extern int channel_set_channelid(t_channel * channel, unsigned int channelid) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } channel->id = channelid; return 0; } extern int channel_rejoin(t_connection * conn) { t_channel const * channel; char const * temp; char const * chname; if (!(channel = conn_get_channel(conn))) return -1; if (!(temp = channel_get_name(channel))) return -1; chname=xstrdup(temp); conn_set_channel(conn, NULL); if (conn_set_channel(conn,chname)<0) conn_set_channel(conn,CHANNEL_NAME_BANNED); xfree((void *)chname); return 0; } extern int channel_add_connection(t_channel * channel, t_connection * connection) { t_channelmember * member; t_connection * user; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } if (!connection) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (channel_check_banning(channel,connection)) { channel_message_log(channel,connection,0,"JOIN FAILED (banned)"); return -1; } member = xmalloc(sizeof(t_channelmember)); member->connection = connection; member->next = channel->memberlist; channel->memberlist = member; channel->currmembers++; channel_message_log(channel,connection,0,"JOINED"); message_send_text(connection,message_type_channel,connection,channel_get_name(channel)); if ((!(channel->flags & channel_flags_permanent)) && (!(channel->flags & channel_flags_thevoid)) && (!(channel->flags & channel_flags_clan)) && (channel->currmembers==1) && (account_is_operator_or_admin(conn_get_account(connection),channel_get_name(channel))==0)) { message_send_text(connection,message_type_info,connection,"you are now tempOP for this channel"); conn_set_tmpOP_channel(connection,(char *)channel_get_name(channel)); channel_update_userflags(connection); } if(!(channel_get_flags(channel) & channel_flags_thevoid)) for (user=channel_get_first(channel); user; user=channel_get_next()) { message_send_text(connection,message_type_adduser,user,NULL); if (user!=connection) message_send_text(user,message_type_join,connection,NULL); } /* please don't remove this notice */ if (channel->log) message_send_text(connection,message_type_info,connection,prefs_get_log_notice()); return 0; } extern int channel_del_connection(t_channel * channel, t_connection * connection) { t_channelmember * curr; t_channelmember * temp; t_elem * curr2; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } if (!connection) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } channel_message_log(channel,connection,0,"PARTED"); channel_message_send(channel,message_type_part,connection,NULL); curr = channel->memberlist; if (curr->connection==connection) { channel->memberlist = channel->memberlist->next; xfree(curr); } else { while (curr->next && curr->next->connection!=connection) curr = curr->next; if (curr->next) { temp = curr->next; curr->next = curr->next->next; xfree(temp); } else { eventlog(eventlog_level_error,__FUNCTION__,"[%d] connection not in channel member list",conn_get_socket(connection)); return -1; } } channel->currmembers--; if (conn_get_tmpOP_channel(connection) && strcmp(conn_get_tmpOP_channel(connection),channel_get_name(channel))==0) { conn_set_tmpOP_channel(connection,NULL); } if (!channel->memberlist && !(channel->flags & channel_flags_permanent)) /* if channel is empty, delete it unless it's a permanent channel */ { channel_destroy(channel,&curr2); } return 0; } extern void channel_update_latency(t_connection * me) { t_channel * channel; t_message * message; t_connection * c; if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!(channel = conn_get_channel(me))) { eventlog(eventlog_level_error,__FUNCTION__,"connection has no channel"); return; } if (!(message = message_create(message_type_userflags,me,NULL,NULL))) /* handles NULL text */ return; for (c=channel_get_first(channel); c; c=channel_get_next()) if (conn_get_class(c)==conn_class_bnet) message_send(message,c); message_destroy(message); } extern void channel_update_userflags(t_connection * me) { t_channel * channel; t_message * message; t_connection * c; if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!(channel = conn_get_channel(me))) { eventlog(eventlog_level_error,__FUNCTION__,"connection has no channel"); return; } if (!(message = message_create(message_type_userflags,me,NULL,NULL))) /* handles NULL text */ return; for (c=channel_get_first(channel); c; c=channel_get_next()) message_send(message,c); message_destroy(message); } extern void channel_message_log(t_channel const * channel, t_connection * me, int fromuser, char const * text) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return; } if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (channel->log) { time_t now; struct tm * tmnow; char timetemp[CHANLOG_TIME_MAXLEN]; now = time(NULL); if ((!(tmnow = localtime(&now)))) strcpy(timetemp,"?"); else strftime(timetemp,sizeof(timetemp),CHANLOGLINE_TIME_FORMAT,tmnow); if (fromuser) fprintf(channel->log,"%s: \"%s\" \"%s\"\n",timetemp,conn_get_username(me),text); else fprintf(channel->log,"%s: \"%s\" %s\n",timetemp,conn_get_username(me),text); fflush(channel->log); } } extern void channel_message_send(t_channel const * channel, t_message_type type, t_connection * me, char const * text) { t_connection * c; unsigned int heard; t_message * message; char const * tname; t_account * acc; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return; } if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } acc = conn_get_account(me); if(channel_get_flags(channel) & channel_flags_thevoid) // no talking in the void return; if(channel_get_flags(channel) & channel_flags_moderated) // moderated channel - only admins,OPs and voices may talk { if (type==message_type_talk || type==message_type_emote) { if (!((account_is_operator_or_admin(conn_get_account(me),channel_get_name(channel))) || (channel_conn_has_tmpVOICE(channel,me)) || (account_get_auth_voice(acc,channel_get_name(channel)) == 1))) { message_send_text(me,message_type_error,me,"This channel is moderated"); return; } } } if (!(message = message_create(type,me,NULL,text))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create message"); return; } heard = 0; tname = conn_get_chatname(me); for (c=channel_get_first(channel); c; c=channel_get_next()) { if (c==me && (type==message_type_talk || type==message_type_join || type==message_type_part || type==message_wol_gameopt_owner)) continue; /* ignore ourself */ if ((type==message_type_talk || type==message_type_whisper || type==message_type_emote || type==message_type_broadcast) && conn_check_ignoring(c,tname)==1) continue; /* ignore squelched players */ if (message_send(message,c)==0 && c!=me) heard = 1; } conn_unget_chatname(me,tname); message_destroy(message); if ((conn_get_wol(me) == 0)) { if (!heard && (type==message_type_talk || type==message_type_emote)) message_send_text(me,message_type_info,me,"No one hears you."); } } extern int channel_ban_user(t_channel * channel, char const * user) { t_elem const * curr; char * temp; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } if (!user) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL user"); return -1; } if (!channel->name) { eventlog(eventlog_level_error,__FUNCTION__,"got channel with NULL name"); return -1; } if (strcasecmp(channel->name,CHANNEL_NAME_BANNED)==0 || strcasecmp(channel->name,CHANNEL_NAME_KICKED)==0) return -1; LIST_TRAVERSE_CONST(channel->banlist,curr) if (strcasecmp(elem_get_data(curr),user)==0) return 0; temp = xstrdup(user); list_append_data(channel->banlist,temp); return 0; } extern int channel_unban_user(t_channel * channel, char const * user) { t_elem * curr; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } if (!user) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL user"); return -1; } LIST_TRAVERSE(channel->banlist,curr) { char const * banned; if (!(banned = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL name in banlist"); continue; } if (strcasecmp(banned,user)==0) { if (list_remove_elem(channel->banlist,&curr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"unable to remove item from list"); return -1; } xfree((void *)banned); /* avoid warning */ return 0; } } return -1; } extern int channel_check_banning(t_channel const * channel, t_connection const * user) { t_elem const * curr; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } if (!user) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL user"); return -1; } if (!(channel->flags & channel_flags_allowbots) && conn_get_class(user)==conn_class_bot) return 1; LIST_TRAVERSE_CONST(channel->banlist,curr) if (conn_match(user,elem_get_data(curr))==1) return 1; return 0; } extern int channel_get_length(t_channel const * channel) { t_channelmember const * curr; int count; for (curr=channel->memberlist,count=0; curr; curr=curr->next,count++); return count; } extern t_connection * channel_get_first(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return NULL; } memberlist_curr = channel->memberlist; return channel_get_next(); } extern t_connection * channel_get_next(void) { t_channelmember * member; if (memberlist_curr) { member = memberlist_curr; memberlist_curr = memberlist_curr->next; return member->connection; } return NULL; } extern t_list * channel_get_banlist(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel"); return NULL; } return channel->banlist; } extern char const * channel_get_shortname(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel"); return NULL; } return channel->shortname; } static int channellist_load_permanent(char const * filename) { FILE * fp; unsigned int line; unsigned int pos; int botflag; int operflag; int logflag; unsigned int modflag; char * buff; char * name; char * sname; char * tag; char * bot; char * oper; char * log; char * country; char * max; char * moderated; char * newname; char * realmname; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open channel file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return -1; } for (line=1; (buff = file_get_line(fp)); line++) { if (buff[0]=='#' || buff[0]=='\0') { continue; } pos = 0; if (!(name = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing name in line %u in file \"%s\"",line,filename); continue; } if (!(sname = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing sname in line %u in file \"%s\"",line,filename); continue; } if (!(tag = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing tag in line %u in file \"%s\"",line,filename); continue; } if (!(bot = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing bot in line %u in file \"%s\"",line,filename); continue; } if (!(oper = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing oper in line %u in file \"%s\"",line,filename); continue; } if (!(log = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing log in line %u in file \"%s\"",line,filename); continue; } if (!(country = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing country in line %u in file \"%s\"",line,filename); continue; } if (!(realmname = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing realmname in line %u in file \"%s\"",line,filename); continue; } if (!(max = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing max in line %u in file \"%s\"",line,filename); continue; } if (!(moderated = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing mod in line %u in file \"%s\"",line,filename); continue; } switch (str_get_bool(bot)) { case 1: botflag = 1; break; case 0: botflag = 0; break; default: eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 4 on line %u in file \"%s\"",bot,line,filename); continue; } switch (str_get_bool(oper)) { case 1: operflag = 1; break; case 0: operflag = 0; break; default: eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 5 on line %u in file \"%s\"",oper,line,filename); continue; } switch (str_get_bool(log)) { case 1: logflag = 1; break; case 0: logflag = 0; break; default: eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 5 on line %u in file \"%s\"",log,line,filename); continue; } switch (str_get_bool(moderated)) { case 1: modflag = 1; break; case 0: modflag = 0; break; default: eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 10 on line %u in file \"%s\"",moderated,line,filename); continue; } if (strcmp(sname,"NULL") == 0) sname = NULL; if (strcmp(tag,"NULL") == 0) tag = NULL; if (strcmp(name,"NONE") == 0) name = NULL; if (strcmp(country, "NULL") == 0) country = NULL; if (strcmp(realmname,"NULL") == 0) realmname = NULL; if (name) { channel_create(name,sname,tag,1,botflag,operflag,logflag,country,realmname,atoi(max),modflag,0,0); } else { newname = channel_format_name(sname,country,realmname,1); if (newname) { channel_create(newname,sname,tag,1,botflag,operflag,logflag,country,realmname,atoi(max),modflag,0,1); xfree(newname); } else { eventlog(eventlog_level_error,__FUNCTION__,"cannot format channel name"); } } /* FIXME: call channel_delete() on current perm channels and do a channellist_find_channel() and set the long name, perm flag, etc, otherwise call channel_create(). This will make HUPing the server handle re-reading this file correctly. */ } file_get_line(NULL); // clear file_get_line buffer if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close channel file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno)); return 0; } static char * channel_format_name(char const * sname, char const * country, char const * realmname, unsigned int id) { char * fullname; unsigned int len; if (!sname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL sname"); return NULL; } len = strlen(sname)+1; /* FIXME: check lengths and format */ if (country) len = len + strlen(country) + 1; if (realmname) len = len + strlen(realmname) + 1; len = len + 32 + 1; fullname=xmalloc(len); sprintf(fullname,"%s%s%s%s%s-%d", realmname?realmname:"", realmname?" ":"", sname, country?" ":"", country?country:"", id); return fullname; } extern int channellist_reload(void) { t_elem * curr; t_channel * channel, * old_channel; t_channelmember * memberlist, * member, * old_member; t_list * channellist_old; if (channellist_head) { channellist_old = list_create(); /* First pass - get members */ LIST_TRAVERSE(channellist_head,curr) { if (!(channel = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"channel list contains NULL item"); continue; } /* Trick to avoid automatic channel destruction */ channel->flags |= channel_flags_permanent; if (channel->memberlist) { /* we need only channel name and memberlist */ old_channel = (t_channel *) xmalloc(sizeof(t_channel)); old_channel->shortname = xstrdup(channel->shortname); old_channel->memberlist = NULL; member = channel->memberlist; /* First pass */ while (member) { old_member = xmalloc(sizeof(t_channelmember)); old_member->connection = member->connection; if (old_channel->memberlist) old_member->next = old_channel->memberlist; else old_member->next = NULL; old_channel->memberlist = old_member; member = member->next; } /* Second pass - remove connections from channel */ member = old_channel->memberlist; while (member) { channel_del_connection(channel,member->connection); conn_set_channel_var(member->connection,NULL); member = member->next; } list_prepend_data(channellist_old,old_channel); } /* Channel is empty - Destroying it */ channel->flags &= ~channel_flags_permanent; if (channel_destroy(channel,&curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not destroy channel"); } /* Cleanup and reload */ if (list_destroy(channellist_head)<0) return -1; channellist_head = NULL; channellist_create(); /* Now put all users on their previous channel */ LIST_TRAVERSE(channellist_old,curr) { if (!(channel = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"old channel list contains NULL item"); continue; } memberlist = channel->memberlist; while (memberlist) { member = memberlist; memberlist = memberlist->next; conn_set_channel(member->connection, channel->shortname); } } /* Ross don't blame me for this but this way the code is cleaner */ LIST_TRAVERSE(channellist_old,curr) { if (!(channel = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"old channel list contains NULL item"); continue; } memberlist = channel->memberlist; while (memberlist) { member = memberlist; memberlist = memberlist->next; xfree((void*)member); } if (channel->shortname) xfree((void*)channel->shortname); if (list_remove_data(channellist_old,channel,&curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); xfree((void*)channel); } if (list_destroy(channellist_old)<0) return -1; } return 0; } extern int channellist_create(void) { channellist_head = list_create(); return channellist_load_permanent(prefs_get_channelfile()); } extern int channellist_destroy(void) { t_channel * channel; t_elem * curr; if (channellist_head) { LIST_TRAVERSE(channellist_head,curr) { if (!(channel = elem_get_data(curr))) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"channel list contains NULL item"); continue; } channel_destroy(channel,&curr); } if (list_destroy(channellist_head)<0) return -1; channellist_head = NULL; } return 0; } extern t_list * channellist(void) { return channellist_head; } extern int channellist_get_length(void) { return list_get_length(channellist_head); } extern int channel_get_max(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } return channel->maxmembers; } extern int channel_set_max(t_channel * channel, int maxmembers) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } if (maxmembers) channel->maxmembers = maxmembers; return 1; } extern int channel_get_curr(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } return channel->currmembers; } extern int channel_conn_is_tmpOP(t_channel const * channel, t_connection * c) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return 0; } if (!conn_get_tmpOP_channel(c)) return 0; if (strcmp(conn_get_tmpOP_channel(c),channel_get_name(channel))==0) return 1; return 0; } extern int channel_conn_has_tmpVOICE(t_channel const * channel, t_connection * c) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return 0; } if (!conn_get_tmpVOICE_channel(c)) return 0; if (strcmp(conn_get_tmpVOICE_channel(c),channel_get_name(channel))==0) return 1; return 0; } static t_channel * channellist_find_channel_by_fullname(char const * name) { t_channel * channel; t_elem const * curr; if (channellist_head) { LIST_TRAVERSE(channellist_head,curr) { channel = elem_get_data(curr); if (!channel->name) { eventlog(eventlog_level_error,__FUNCTION__,"found channel with NULL name"); continue; } if (strcasecmp(channel->name,name)==0) return channel; } } return NULL; } /* Find a channel based on the name. * Create a new channel if it is a permanent-type channel and all others * are full. */ extern t_channel * channellist_find_channel_by_name(char const * name, char const * country, char const * realmname) { t_channel * channel; t_elem const * curr; int foundperm; int foundlang; int maxchannel; /* the number of "rollover" channels that exist */ char const * saveshortname; char const * savespecialname; char const * savetag; int savebotflag; int saveoperflag; int savelogflag; unsigned int savemoderated; char const * savecountry; char const * saverealmname; int savemaxmembers; t_channel * special_channel; // try to make gcc happy and initialize all variables saveshortname = savespecialname = savetag = savecountry = saverealmname = NULL; savebotflag = saveoperflag = savelogflag = savemaxmembers = savemoderated = 0; maxchannel = 0; foundperm = 0; foundlang = 0; if (channellist_head) { LIST_TRAVERSE(channellist_head,curr) { channel = elem_get_data(curr); if (!channel->name) { eventlog(eventlog_level_error,__FUNCTION__,"found channel with NULL name"); continue; } if (strcasecmp(channel->name,name)==0) { // eventlog(eventlog_level_debug,__FUNCTION__,"found exact match for \"%s\"",name); return channel; } if (channel->shortname && strcasecmp(channel->shortname,name)==0) { special_channel = channellist_find_channel_by_name(channel->name,country,realmname); if (special_channel) channel= special_channel; /* FIXME: what should we do if the client doesn't have a country? For now, just take the first * channel that would otherwise match. */ if ( ((!channel->country && !foundlang) || !country || (channel->country && country && (strcmp(channel->country, country)==0))) && (!channel->realmname || !realmname || !strcmp(channel->realmname, realmname)) ) { if (channel->maxmembers==-1 || channel->currmembersmaxmembers) { eventlog(eventlog_level_debug,__FUNCTION__,"found permanent channel \"%s\" for \"%s\"",channel->name,name); return channel; } if (!foundlang && (channel->country)) //remember we had found a language specific channel but it was full { foundlang = 1; if (!(channel->flags & channel_flags_autoname)) savespecialname = channel->name; maxchannel = 0; } maxchannel++; } // eventlog(eventlog_level_debug,__FUNCTION__,"countries didn't match"); foundperm = 1; /* save off some info in case we need to create a new copy */ saveshortname = channel->shortname; savetag = channel->clienttag; savebotflag = channel->flags & channel_flags_allowbots; saveoperflag = channel->flags & channel_flags_allowopers; if (channel->logname) savelogflag = 1; else savelogflag = 0; if (country) savecountry = country; else savecountry = channel->country; if (realmname) saverealmname = realmname; else saverealmname = channel->realmname; savemaxmembers = channel->maxmembers; savemoderated = channel->flags & channel_flags_moderated; } } } /* we've gone thru the whole list and either there was no match or the * channels are all full. */ if (foundperm) /* All the channels were full, create a new one */ { char * channelname; if (!foundlang || !savespecialname) { if (!(channelname=channel_format_name(saveshortname,savecountry,saverealmname,maxchannel+1))) return NULL; } else { if (!(channelname=channel_format_name(savespecialname,NULL,saverealmname,maxchannel+1))) return NULL; } channel = channel_create(channelname,saveshortname,savetag,1,savebotflag,saveoperflag,savelogflag,savecountry,saverealmname,savemaxmembers,savemoderated,0,1); xfree(channelname); eventlog(eventlog_level_debug,__FUNCTION__,"created copy \"%s\" of channel \"%s\"",(channel)?(channel->name):(""),name); return channel; } /* no match */ eventlog(eventlog_level_debug,__FUNCTION__,"could not find channel \"%s\"",name); return NULL; } extern t_channel * channellist_find_channel_bychannelid(unsigned int channelid) { t_channel * channel; t_elem const * curr; if (channellist_head) { LIST_TRAVERSE(channellist_head,curr) { channel = elem_get_data(curr); if (!channel->name) { eventlog(eventlog_level_error,__FUNCTION__,"found channel with NULL name"); continue; } if (channel->id==channelid) return channel; } } return NULL; } extern int channel_set_userflags(t_connection * c) { unsigned int newflags; char const * channel; t_account * acc; if (!c) return -1; // user not connected, no need to update his flags acc = conn_get_account(c); /* well... unfortunatly channel_get_name never returns NULL but "" instead so we first have to check if user is in a channel at all */ if ((!conn_get_channel(c)) || (!(channel = channel_get_name(conn_get_channel(c))))) return -1; if (account_get_auth_admin(acc,channel) == 1 || account_get_auth_admin(acc,NULL) == 1) newflags = MF_BLIZZARD; else if (account_get_auth_operator(acc,channel) == 1 || account_get_auth_operator(acc,NULL) == 1) newflags = MF_BNET; else if (channel_conn_is_tmpOP(conn_get_channel(c),c)) newflags = MF_GAVEL; else if ((account_get_auth_voice(acc,channel) == 1) || (channel_conn_has_tmpVOICE(conn_get_channel(c),c))) newflags = MF_VOICE; else if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT)) newflags = W3_ICON_SET; else newflags = 0; if (conn_get_flags(c) != newflags) { conn_set_flags(c, newflags); channel_update_userflags(c); } return 0; } /** * Westwood Online Extensions */ extern char const * channel_wol_get_game_owner(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return NULL; } return channel->gameOwner; } extern int channel_wol_set_game_owner(t_channel * channel, char const * gameOwner) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } if (channel->gameOwner) xfree((void *)channel->gameOwner); /* avoid warning */ channel->gameOwner = xstrdup(gameOwner); return 1; } extern int channel_wol_get_game_ownerip(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } return channel->gameOwnerIP; } extern int channel_wol_set_game_ownerip(t_channel * channel, int gameOwnerIP) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } if (gameOwnerIP) channel->gameOwnerIP = gameOwnerIP; return 1; } extern int channel_wol_get_game_type(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } return channel->gameType; } extern int channel_wol_set_game_type(t_channel * channel, int gameType) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } if (gameType) channel->gameType = gameType; return 1; } extern int channel_wol_get_game_tournament(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } return channel->gameTournament; } extern int channel_wol_set_game_tournament(t_channel * channel, int gameTournament) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } if (gameTournament) channel->gameTournament = gameTournament; return 1; } extern char const * channel_wol_get_game_options(t_channel const * channel) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return NULL; } return channel->gameOptions; } extern int channel_wol_set_game_options(t_channel * channel, char const * gameOptions) { if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } if (channel->gameOptions) xfree((void *)channel->gameOptions); /* avoid warning */ channel->gameOptions = xstrdup(gameOptions); return 1; } pvpgn-1.8.5/src/bnetd/handle_file.h0000644000175000017500000000207211151345317016131 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_HANDLE_FILE_PROTOS #define INCLUDED_HANDLE_FILE_PROTOS #define JUST_NEED_TYPES #include "connection.h" #include "common/packet.h" #undef JUST_NEED_TYPES extern int handle_file_packet(t_connection * c, t_packet const * const packet); #endif #endif pvpgn-1.8.5/src/bnetd/storage_file.h0000644000175000017500000000255511151345317016350 0ustar aaronaaron/* * Copyright (C) 2002,2003,2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INClUDED_STORAGE_FILE_TYPES #define INClUDED_STORAGE_FILE_TYPES #include "storage.h" typedef const char t_file_info; typedef struct { t_attr * (*read_attr)(const char *filename, const char *key); int (*read_attrs)(const char *filename, t_read_attr_func cb, void *data); int (*write_attrs)(const char *filename, const t_hlist *attributes); } t_file_engine; #endif /* INClUDED_STORAGE_FILE_TYPES */ #ifndef JUST_NEED_TYPES #ifndef INClUDED_STORAGE_FILE_PROTOS #define INClUDED_STORAGE_FILE_PROTOS extern t_storage storage_file; #endif /* INClUDED_STORAGE_FILE_PROTOS */ #endif /* JUST_NEED_TYPES */ pvpgn-1.8.5/src/bnetd/storage_sql.c0000644000175000017500000003625411151345317016226 0ustar aaronaaron/* * Copyright (C) 2002 TheUndying * Copyright (C) 2002 zap-zero * Copyright (C) 2002,2003 Dizzy * Copyright (C) 2002 Zzzoom * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef WITH_SQL #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include "compat/strtoul.h" #include "compat/snprintf.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "common/eventlog.h" #include "prefs.h" #include "common/util.h" #define CLAN_INTERNAL_ACCESS #define TEAM_INTERNAL_ACCESS #include "team.h" #include "account.h" #include "connection.h" #include "clan.h" #undef TEAM_INTERNAL_ACCESS #undef CLAN_INTERNAL_ACCESS #include "common/tag.h" #include "common/xalloc.h" #include "common/flags.h" #include "sql_dbcreator.h" #define SQL_INTERNAL # include "sql_common.h" #undef SQL_INTERNAL #include "storage_sql.h" #include "common/elist.h" #include "attr.h" #include "common/setup_after.h" static t_storage_info *sql_create_account(char const *); static int sql_read_attrs(t_storage_info *, t_read_attr_func, void *); static t_attr *sql_read_attr(t_storage_info *, const char *); static int sql_write_attrs(t_storage_info *, const t_hlist *); static t_storage_info * sql_read_account(const char *,unsigned); static const char *sql_escape_key(const char *); t_storage storage_sql = { sql_init, sql_close, sql_read_maxuserid, sql_create_account, sql_get_defacct, sql_free_info, sql_read_attrs, sql_write_attrs, sql_read_attr, sql_read_accounts, sql_read_account, sql_cmp_info, sql_escape_key, sql_load_clans, sql_write_clan, sql_remove_clan, sql_remove_clanmember, sql_load_teams, sql_write_team, sql_remove_team }; static char query[512]; #ifndef SQL_ON_DEMAND static const char *_db_add_tab(const char *tab, const char *key) { static char nkey[DB_MAX_ATTRKEY]; strncpy(nkey, tab, sizeof(nkey) - 1); nkey[strlen(nkey) + 1] = '\0'; nkey[strlen(nkey)] = '_'; strncpy(nkey + strlen(nkey), key, sizeof(nkey) - strlen(nkey)); return nkey; } #endif /* SQL_ON_DEMAND */ static int _db_get_tab(const char *key, char **ptab, char **pcol) { static char tab[DB_MAX_ATTRKEY]; static char col[DB_MAX_ATTRKEY]; strncpy(tab, key, DB_MAX_TAB - 1); tab[DB_MAX_TAB - 1] = 0; if (!strchr(tab, '_')) return -1; *(strchr(tab, '_')) = 0; strncpy(col, key + strlen(tab) + 1, DB_MAX_TAB - 1); col[DB_MAX_TAB - 1] = 0; /* return tab and col as 2 static buffers */ *ptab = tab; *pcol = col; return 0; } static t_storage_info *sql_create_account(char const *username) { t_sql_res *result = NULL; t_sql_row *row; int uid = maxuserid + 1; t_storage_info *info; char *user; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return NULL; } user = xstrdup(username); strlower(user); snprintf(query, sizeof(query), "SELECT count(*) FROM %sBNET WHERE username='%s'", tab_prefix, user); if ((result = sql->query_res(query)) != NULL) { int num; row = sql->fetch_row(result); if (row == NULL || row[0] == NULL) { sql->free_result(result); eventlog(eventlog_level_error, __FUNCTION__, "got NULL count"); goto err_dup; } num = atol(row[0]); sql->free_result(result); if (num > 0) { eventlog(eventlog_level_error, __FUNCTION__, "got existant username"); goto err_dup; } } else { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query); goto err_dup; } info = xmalloc(sizeof(t_sql_info)); *((unsigned int *) info) = uid; snprintf(query, sizeof(query), "DELETE FROM %sBNET WHERE "SQL_UID_FIELD" = '%u'", tab_prefix, uid); sql->query(query); snprintf(query, sizeof(query), "INSERT INTO %sBNET ("SQL_UID_FIELD",username) VALUES('%u','%s')", tab_prefix, uid, user); if (sql->query(query)) { eventlog(eventlog_level_error, __FUNCTION__, "user insert failed (query: '')", query); goto err_info; } snprintf(query, sizeof(query), "DELETE FROM %sprofile WHERE "SQL_UID_FIELD" = '%u'", tab_prefix, uid); sql->query(query); snprintf(query, sizeof(query), "INSERT INTO %sprofile ("SQL_UID_FIELD") VALUES('%u')", tab_prefix, uid); if (sql->query(query)) { eventlog(eventlog_level_error, __FUNCTION__, "user insert failed (query: '')", query); goto err_info; } snprintf(query, sizeof(query), "DELETE FROM %sRecord WHERE "SQL_UID_FIELD" = '%u'", tab_prefix, uid); sql->query(query); snprintf(query, sizeof(query), "INSERT INTO %sRecord ("SQL_UID_FIELD") VALUES('%u')", tab_prefix, uid); if (sql->query(query)) { eventlog(eventlog_level_error, __FUNCTION__, "user insert failed (query: '')", query); goto err_info; } snprintf(query, sizeof(query), "DELETE FROM %sfriend WHERE "SQL_UID_FIELD" = '%u'", tab_prefix, uid); sql->query(query); snprintf(query, sizeof(query), "INSERT INTO %sfriend ("SQL_UID_FIELD") VALUES('%u')", tab_prefix, uid); if (sql->query(query)) { eventlog(eventlog_level_error, __FUNCTION__, "user insert failed (query: '')", query); goto err_info; } xfree(user); return info; err_info: xfree((void *) info); err_dup: xfree(user); return NULL; } static int sql_read_attrs(t_storage_info * info, t_read_attr_func cb, void *data) { #ifndef SQL_ON_DEMAND t_sql_res *result = NULL; t_sql_row *row; char **tab; unsigned int uid; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } if (info == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL storage info"); return -1; } if (cb == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback"); return -1; } uid = *((unsigned int *) info); for (tab = sql_tables; *tab; tab++) { snprintf(query, sizeof(query), "SELECT * FROM %s%s WHERE "SQL_UID_FIELD"='%u'", tab_prefix, *tab, uid); // eventlog(eventlog_level_trace, __FUNCTION__, "query: \"%s\"",query); if ((result = sql->query_res(query)) != NULL && sql->num_rows(result) == 1 && sql->num_fields(result) > 1) { unsigned int i; t_sql_field *fields, *fentry; if ((fields = sql->fetch_fields(result)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not fetch the fields"); sql->free_result(result); return -1; } if (!(row = sql->fetch_row(result))) { eventlog(eventlog_level_error, __FUNCTION__, "could not fetch row"); sql->free_fields(fields); sql->free_result(result); return -1; } for (i = 0, fentry = fields; *fentry; fentry++, i++) { /* we have to skip "uid" */ char *output; /* we ignore the field used internally by sql */ if (strcmp(*fentry, SQL_UID_FIELD) == 0) continue; // eventlog(eventlog_level_trace, __FUNCTION__, "read key (step1): '%s' val: '%s'", _db_add_tab(*tab, *fentry), unescape_chars(row[i])); if (row[i] == NULL) continue; /* its an NULL value sql field */ // eventlog(eventlog_level_trace, __FUNCTION__, "read key (step2): '%s' val: '%s'", _db_add_tab(*tab, *fentry), unescape_chars(row[i])); if (cb(_db_add_tab(*tab, *fentry), (output = unescape_chars(row[i])), data)) eventlog(eventlog_level_error, __FUNCTION__, "got error from callback on UID: %u", uid); if (output) xfree((void *) output); // eventlog(eventlog_level_trace, __FUNCTION__, "read key (final): '%s' val: '%s'", _db_add_tab(*tab, *fentry), unescape_chars(row[i])); } sql->free_fields(fields); } if (result) sql->free_result(result); } #endif /* SQL_ON_DEMAND */ return 0; } static t_attr *sql_read_attr(t_storage_info * info, const char *key) { #ifdef SQL_ON_DEMAND t_sql_res *result = NULL; t_sql_row *row; char *tab, *col; unsigned int uid; t_attr *attr; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return NULL; } if (info == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL storage info"); return NULL; } if (key == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL key"); return NULL; } uid = *((unsigned int *) info); if (_db_get_tab(key, &tab, &col) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "error from _db_get_tab"); return NULL; } snprintf(query, sizeof(query), "SELECT %c%s%c FROM %s%s WHERE " SQL_UID_FIELD " = %u", sql->quote, col, sql->quote, tab_prefix, tab, uid); if ((result = sql->query_res(query)) == NULL) return NULL; if (sql->num_rows(result) != 1) { // eventlog(eventlog_level_debug, __FUNCTION__, "wrong numer of rows from query (%s)", query); sql->free_result(result); return NULL; } if (!(row = sql->fetch_row(result))) { eventlog(eventlog_level_error, __FUNCTION__, "could not fetch row"); sql->free_result(result); return NULL; } if (row[0] == NULL) { // eventlog(eventlog_level_debug, __FUNCTION__, "NULL value from query (%s)", query); sql->free_result(result); return NULL; } attr = attr_create(key, row[0]); sql->free_result(result); return (void *) attr; #else return NULL; #endif /* SQL_ON_DEMAND */ } /* write ONLY dirty attributes */ int sql_write_attrs(t_storage_info * info, const t_hlist *attrs) { char escape[DB_MAX_ATTRVAL * 2 + 1]; /* sql docs say the escape can take a maximum of double original size + 1 */ char safeval[DB_MAX_ATTRVAL]; char *p, *tab, *col; t_attr *attr; t_hlist *curr; unsigned int uid; char quote; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } if (info == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL sql info"); return -1; } if (attrs == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL attributes list"); return -1; } uid = *((unsigned int *) info); hlist_for_each(curr, (t_hlist*)attrs) { attr = hlist_entry(curr, t_attr, link); if (!attr_get_dirty(attr)) continue; /* save ONLY dirty attributes */ if (attr_get_key(attr) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL key in attributes list"); continue; } if (attr_get_val(attr) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL value in attributes list"); continue; } if (_db_get_tab(attr_get_key(attr), &tab, &col) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "error from _db_get_tab"); continue; } strncpy(safeval, attr_get_val(attr), DB_MAX_ATTRVAL - 1); safeval[DB_MAX_ATTRVAL - 1] = 0; for (p = safeval; *p; p++) if (*p == '\'') /* value shouldn't contain ' */ *p = '"'; sql->escape_string(escape, safeval, strlen(safeval)); quote = sql->quote; snprintf(query, sizeof(query), "UPDATE %s%s SET %c%s%c = '%s' WHERE "SQL_UID_FIELD" = '%u'", tab_prefix, tab, quote, col, quote, escape, uid); // eventlog(eventlog_level_trace, "db_set", "update query: %s", query); if (sql->query(query) || !sql->affected_rows()) { char query2[512]; // eventlog(eventlog_level_debug, __FUNCTION__, "trying to insert new column %s", col); snprintf(query2, sizeof(query2), "ALTER TABLE %s%s ADD COLUMN %c%s%c VARCHAR(128)", tab_prefix, tab, quote, col, quote); // eventlog(eventlog_level_trace, __FUNCTION__, "alter query: %s", query2); sql->query(query2); /* try query again */ // eventlog(eventlog_level_trace, "db_set", "retry insert query: %s", query); if (sql->query(query) || !sql->affected_rows()) { // Tried everything, now trying to insert that user to the table for the first time snprintf(query2, sizeof(query2), "INSERT INTO %s%s ("SQL_UID_FIELD",%c%s%c) VALUES ('%u','%s')", tab_prefix, tab, quote, col, quote, uid, escape); // eventlog(eventlog_level_error, __FUNCTION__, "update failed so tried INSERT for the last chance"); if (sql->query(query2)) { eventlog(eventlog_level_error, __FUNCTION__, "could not INSERT attribute '%s'->'%s'", attr_get_key(attr), attr_get_val(attr)); continue; } } } attr_clear_dirty(attr); } return 0; } static t_storage_info * sql_read_account(const char *name, unsigned uid) { t_sql_res *result = NULL; t_sql_row *row; t_storage_info *info; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return NULL; } /* SELECT uid from BNET WHERE uid=x sounds stupid, I agree but its a clean * way to check for account existence by an uid */ if (name) { char *user = xstrdup(name); strlower(user); snprintf(query, sizeof(query), "SELECT "SQL_UID_FIELD" FROM %sBNET WHERE username='%s'", tab_prefix, user); xfree(user); } else snprintf(query, sizeof(query), "SELECT "SQL_UID_FIELD" FROM %sBNET WHERE "SQL_UID_FIELD" = '%u'", tab_prefix, uid); result = sql->query_res(query); if (!result) { eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query); return NULL; } if (sql->num_rows(result) < 1) { sql->free_result(result); return NULL; /* empty user list */ } row = sql->fetch_row(result); if (!row) { /* could not fetch row, this should not happen */ sql->free_result(result); return NULL; } if (row[0] == NULL) /* empty UID field */ eventlog(eventlog_level_error, __FUNCTION__, "got NULL uid from db"); else if ((unsigned int) atoi(row[0]) == sql_defacct); /* skip default account */ else { info = xmalloc(sizeof(t_sql_info)); *((unsigned int *) info) = atoi(row[0]); sql->free_result(result); return info; } sql->free_result(result); return NULL; } static const char *sql_escape_key(const char *key) { const char *newkey = key; char *p; int idx; for(idx = 0, p = (char *)newkey; *p; p++, idx++) if ((*p < '0' || *p > '9') && (*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z')) { newkey = xstrdup(key); p = (char *)(newkey + idx); *(p++) = '_'; for(; *p; p++) if ((*p < '0' || *p > '9') && (*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z')) *p = '_'; break; } return newkey; } #endif /* WITH_SQL */ pvpgn-1.8.5/src/bnetd/timer.c0000644000175000017500000000640111151345317015012 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define TIMER_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "common/elist.h" #include "connection.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "timer.h" #include "common/setup_after.h" static t_elist timerlist_head; extern int timerlist_add_timer(t_connection * owner, time_t when, t_timer_cb cb, t_timer_data data) { t_timer * timer, *ctimer; t_elist * curr; if (!owner) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL owner"); return -1; } timer = xmalloc(sizeof(t_timer)); timer->owner = owner; timer->when = when; timer->cb = cb; timer->data = data; /* try to preserve a when based order */ elist_for_each(curr,&timerlist_head) { ctimer = elist_entry(curr,t_timer,timers); if (ctimer->when > when) break; } elist_add_tail(curr, &timer->timers); /* add it to the t_conn timers list */ elist_add_tail(conn_get_timer(owner), &timer->owners); return 0; } extern int timerlist_del_all_timers(t_connection * owner) { t_elist * curr, *save; t_timer * timer; if (!owner) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL owner"); return -1; } elist_for_each_safe(curr,conn_get_timer(owner),save) { timer = elist_entry(curr, t_timer, owners); if (timer->cb) timer->cb(timer->owner,(time_t)0,timer->data); elist_del(&timer->owners); elist_del(&timer->timers); xfree((void*)timer); } return 0; } extern int timerlist_check_timers(time_t when) { t_elist * curr, *save; t_timer * timer; elist_for_each_safe(curr,&timerlist_head,save) { timer = elist_entry(curr,t_timer,timers); if (timer->owner && timer->whencb) timer->cb(timer->owner,timer->when,timer->data); elist_del(&timer->owners); elist_del(&timer->timers); xfree((void*)timer); } else break; /* beeing sorted there is no need to go beyond this point */ } return 0; } extern int timerlist_create(void) { elist_init(&timerlist_head); return 0; } extern int timerlist_destroy(void) { t_elist * curr, *save; t_timer * timer; elist_for_each_safe(curr,&timerlist_head,save) { timer = elist_entry(curr,t_timer,timers); elist_del(&timer->owners); elist_del(&timer->timers); xfree((void*)timer); } elist_init(&timerlist_head); return 0; } pvpgn-1.8.5/src/bnetd/command.h0000644000175000017500000000201111151345317015306 0ustar aaronaaron/* * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_COMMAND_PROTOS #define INCLUDED_COMMAND_PROTOS #define JUST_NEED_TYPES #include "connection.h" #undef JUST_NEED_TYPES extern int handle_command(t_connection * c, char const * text); #endif #endif pvpgn-1.8.5/src/bnetd/tournament.h0000644000175000017500000000654711151345317016106 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_TOURNAMENT_TYPES #define INCLUDED_TOURNAMENT_TYPES typedef struct { unsigned int start_preliminary; unsigned int end_signup; unsigned int end_preliminary; unsigned int start_round_1; unsigned int start_round_2; unsigned int start_round_3; unsigned int start_round_4; unsigned int tournament_end; unsigned int game_selection; unsigned int game_type; unsigned int game_client; unsigned int races; char * format; char * sponsor; /* format: "ricon,sponsor" * ricon = W3+icon reversed , if 2 char icon is selected * or reversed icon if 4 char icon is selected * ie. "4R3W,The PvPGN Team" */ unsigned int thumbs_down; } t_tournament_info; typedef struct { char * name; unsigned int wins; unsigned int losses; unsigned int ties; int in_game; int in_finals; } t_tournament_user; #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_TOURNAMENT_PROTOS #define INCLUDED_TOURNAMENT_PROTOS #define JUST_NEED_TYPES #include "account.h" #undef JUST_NEED_TYPES extern int tournament_signup_user(t_account * account); extern int tournament_user_signed_up(t_account * account); extern int tournament_add_stat(t_account * account, int stat); extern int tournament_get_stat(t_account * account, int stat); extern int tournament_get_player_score(t_account * account); extern int tournament_set_in_game_status(t_account * account, int status); extern int tournament_get_in_finals_status(t_account * account); extern int tournament_get_game_in_progress(void); extern int tournament_check_client(t_clienttag clienttag); extern int tournament_get_totalplayers(void); extern int tournament_is_arranged(void); /*****/ extern int tournament_init(char const * filename); extern int tournament_destroy(void); extern int tournament_reload(char const * filename); /*****/ extern unsigned int tournament_get_start_preliminary(void); extern unsigned int tournament_get_end_signup(void); extern unsigned int tournament_get_end_preliminary(void); extern unsigned int tournament_get_start_round_1(void); extern unsigned int tournament_get_start_round_2(void); extern unsigned int tournament_get_start_round_3(void); extern unsigned int tournament_get_start_round_4(void); extern unsigned int tournament_get_tournament_end(void); extern unsigned int tournament_get_game_selection(void); extern unsigned int tournament_get_game_type(void); extern unsigned int tournament_get_races(void); extern char * tournament_get_format(void); extern char * tournament_get_sponsor(void); extern unsigned int tournament_get_thumbs_down(void); /*****/ #endif #endif pvpgn-1.8.5/src/bnetd/channel_conv.h0000644000175000017500000000212411151345317016332 0ustar aaronaaron/* * Copyright (C) 2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_CHANNEL_CONV_TYPES #define INCLUDED_CHANNEL_CONV_TYPES #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_CHANNEL_CONV_PROTOS #define INCLUDED_CHANNEL_CONV_PROTOS #define JUST_NEED_TYPES #include "channel.h" #undef JUST_NEED_TYPES extern unsigned int cflags_to_bncflags(t_channel_flags flags); #endif #endif pvpgn-1.8.5/src/bnetd/helpfile.c0000644000175000017500000001705611151345317015472 0ustar aaronaaron/* * Copyright (C) 2000 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strcasecmp.h" #include #include #include "compat/strerror.h" #include "message.h" #include "connection.h" #include "common/util.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "helpfile.h" #include "common/setup_after.h" #include "account_wrap.h" #include "command_groups.h" static FILE* hfd=NULL; /* helpfile descriptor */ static int list_commands(t_connection *); static int describe_command(t_connection *, char const *); extern int helpfile_init(char const *filename) { if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(hfd = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open help file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return -1; } return 0; } extern int helpfile_unload(void) { if (hfd!=NULL) { if (fclose(hfd)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close help file after reading (fclose: %s)",pstrerror(errno)); hfd = NULL; } return 0; } extern int handle_help_command(t_connection * c, char const * text) { unsigned int i,j; char comm[MAX_COMMAND_LEN]; if (hfd == NULL) { /* an error ocured opening readonly the help file, helpfile_unload was called, or helpfile_init hasn't been called */ message_send_text(c,message_type_error,c,"Oops ! There is a problem with the help file. Please contact the administrator of the server."); return 0; } rewind(hfd); for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='/') /* skip / in front of command (if present) */ i++; for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get comm */ if (j #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strcasecmp.h" #include "connection.h" #include "realm.h" #include "account.h" #include "account_wrap.h" #include "game.h" #include "d2cs/d2cs_bnetd_protocol.h" #include "common/bnethash.h" #include "common/bnethashconv.h" #include "common/eventlog.h" #include "common/queue.h" #include "common/packet.h" #include "common/addr.h" #include "common/bn_type.h" #include "prefs.h" #include "common/util.h" #include "common/field_sizes.h" #include "handle_d2cs.h" #include "common/tag.h" #include "common/xalloc.h" #include "common/setup_after.h" static int on_d2cs_accountloginreq(t_connection * c, t_packet const * packet); static int on_d2cs_charloginreq(t_connection * c, t_packet const * packet); static int on_d2cs_authreply(t_connection * c, t_packet const * packet); static int on_d2cs_gameinforeply(t_connection * c, t_packet const * packet); extern int handle_d2cs_packet(t_connection * c, t_packet const * packet) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (packet_get_class(packet)!=packet_class_d2cs_bnetd) { eventlog(eventlog_level_error,__FUNCTION__,"got bad packet class %d", packet_get_class(packet)); return -1; } switch (conn_get_state(c)) { case conn_state_connected: switch (packet_get_type(packet)) { case D2CS_BNETD_AUTHREPLY: on_d2cs_authreply(c,packet); break; default: eventlog(eventlog_level_error,__FUNCTION__, "got unknown packet type %d",packet_get_type(packet)); break; } break; case conn_state_loggedin: switch (packet_get_type(packet)) { case D2CS_BNETD_ACCOUNTLOGINREQ: on_d2cs_accountloginreq(c,packet); break; case D2CS_BNETD_CHARLOGINREQ: on_d2cs_charloginreq(c,packet); break; case D2CS_BNETD_GAMEINFOREPLY: on_d2cs_gameinforeply(c,packet); break; default: eventlog(eventlog_level_error,__FUNCTION__, "got unknown packet type %d",packet_get_type(packet)); break; } break; default: eventlog(eventlog_level_error,__FUNCTION__, "got unknown connection state %d",conn_get_state(c)); break; } return 0; } static int on_d2cs_authreply(t_connection * c, t_packet const * packet) { t_packet * rpacket; unsigned int version; unsigned int try_version; unsigned int reply; char const * realmname; t_realm * realm; if (packet_get_size(packet)u.d2cs_bnetd_authreply.version); if (version && version != try_version) { eventlog(eventlog_level_error,__FUNCTION__,"d2cs version mismatch 0x%X - 0x%X", try_version,version); reply=BNETD_D2CS_AUTHREPLY_BAD_VERSION; } else { reply=BNETD_D2CS_AUTHREPLY_SUCCEED; } if (reply==BNETD_D2CS_AUTHREPLY_SUCCEED) { eventlog(eventlog_level_info,__FUNCTION__,"d2cs %s authed", addr_num_to_ip_str(conn_get_addr(c))); conn_set_state(c,conn_state_loggedin); realm_active(realm,c); } else { eventlog(eventlog_level_error,__FUNCTION__,"failed to auth d2cs %s", addr_num_to_ip_str(conn_get_addr(c))); } if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket,sizeof(t_bnetd_d2cs_authreply)); packet_set_type(rpacket,BNETD_D2CS_AUTHREPLY); bn_int_set(&rpacket->u.bnetd_d2cs_authreply.h.seqno,1); bn_int_set(&rpacket->u.bnetd_d2cs_authreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } static int on_d2cs_accountloginreq(t_connection * c, t_packet const * packet) { unsigned int sessionkey; unsigned int sessionnum; unsigned int salt; char const * account; char const * tname; t_connection * client; int reply; t_packet * rpacket; struct { bn_int salt; bn_int sessionkey; bn_int sessionnum; bn_int secret; bn_int passhash[5]; } temp; t_hash secret_hash; char const * pass_str; t_hash passhash; t_hash try_hash; if (packet_get_size(packet)u.d2cs_bnetd_accountloginreq.sessionkey); sessionnum=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionnum); salt=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.seqno); if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) { eventlog(eventlog_level_error,__FUNCTION__,"sessionnum %d not found",sessionnum); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else if (sessionkey!=conn_get_sessionkey(client)) { eventlog(eventlog_level_error,__FUNCTION__,"sessionkey %d not match",sessionkey); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else if (!(tname=conn_get_username(client))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL username"); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else if (strcasecmp(account,tname)) { eventlog(eventlog_level_error,__FUNCTION__,"username %s not match",account); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else { bn_int_set(&temp.salt,salt); bn_int_set(&temp.sessionkey,sessionkey); bn_int_set(&temp.sessionnum,sessionnum); bn_int_set(&temp.secret,conn_get_secret(client)); pass_str=account_get_pass(conn_get_account(client)); if (hash_set_str(&passhash,pass_str)<0) { reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else { hash_to_bnhash((t_hash const *)&passhash,temp.passhash); bnet_hash(&secret_hash,sizeof(temp),&temp); bnhash_to_hash(packet->u.d2cs_bnetd_accountloginreq.secret_hash,&try_hash); if (hash_eq(try_hash,secret_hash)==1) { eventlog(eventlog_level_debug,__FUNCTION__,"user %s loggedin on d2cs", account); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_SUCCEED; } else { eventlog(eventlog_level_error,__FUNCTION__,"user %s hash not match", account); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } } } if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket,sizeof(t_bnetd_d2cs_accountloginreply)); packet_set_type(rpacket,BNETD_D2CS_ACCOUNTLOGINREPLY); bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.h.seqno, bn_int_get(packet->u.d2cs_bnetd_accountloginreq.h.seqno)); bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } #define CHAR_PORTRAIT_LEN 0x30 static int on_d2cs_charloginreq(t_connection * c, t_packet const * packet) { t_connection * client; char const * charname; char const * portrait; char const * clienttag; char * temp; unsigned int sessionnum; t_realm * realm; char const * realmname; unsigned int pos, reply; t_packet * rpacket; if (packet_get_size(packet)u.d2cs_bnetd_charloginreq.sessionnum); pos=sizeof(t_d2cs_bnetd_charloginreq); if (!(charname=packet_get_str_const(packet,pos,CHAR_NAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name"); return -1; } pos+=strlen(charname)+1; if (!(portrait=packet_get_str_const(packet,pos,CHAR_PORTRAIT_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character portrait"); return -1; } if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) { eventlog(eventlog_level_error,__FUNCTION__,"user %d not found",sessionnum); reply = BNETD_D2CS_CHARLOGINREPLY_FAILED; } else if (!(clienttag=clienttag_uint_to_str(conn_get_clienttag(client)))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag"); reply = BNETD_D2CS_CHARLOGINREPLY_FAILED; } else if (!(realm=conn_get_realm(client))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); reply = BNETD_D2CS_CHARLOGINREPLY_FAILED; } else { char revtag[8]; realmname = realm_get_name(realm); temp=xmalloc(strlen(clienttag)+strlen(realmname)+1+strlen(charname)+1+ strlen(portrait)+1); reply = BNETD_D2CS_CHARLOGINREPLY_SUCCEED; strcpy(revtag,clienttag); strreverse(revtag); sprintf(temp,"%4s%s,%s,%s",revtag,realmname,charname,portrait); conn_set_charname(client,charname); conn_set_realminfo(client,temp); xfree(temp); eventlog(eventlog_level_debug,__FUNCTION__, "loaded portrait for character %s",charname); } if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket,sizeof(t_bnetd_d2cs_charloginreply)); packet_set_type(rpacket,BNETD_D2CS_CHARLOGINREPLY); bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.h.seqno, bn_int_get(packet->u.d2cs_bnetd_charloginreq.h.seqno)); bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } extern int handle_d2cs_init(t_connection * c) { t_packet * packet; if ((packet=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(packet,sizeof(t_bnetd_d2cs_authreq)); packet_set_type(packet,BNETD_D2CS_AUTHREQ); bn_int_set(&packet->u.bnetd_d2cs_authreq.h.seqno,1); bn_int_set(&packet->u.bnetd_d2cs_authreq.sessionnum,conn_get_sessionnum(c)); conn_push_outqueue(c,packet); packet_del_ref(packet); } eventlog(eventlog_level_info,__FUNCTION__,"sent init packet to d2cs (sessionnum=%d)", conn_get_sessionnum(c)); return 0; } extern int send_d2cs_gameinforeq(t_connection * c) { t_packet * packet; t_game * game; t_realm * realm; if (!(c)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return -1; } if (!(game = conn_get_game(c))) { eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL game"); return -1; } if (!(realm = conn_get_realm(c))) { eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL realm"); return -1; } if ((packet=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(packet,sizeof(t_bnetd_d2cs_gameinforeq)); packet_set_type(packet,BNETD_D2CS_GAMEINFOREQ); bn_int_set(&packet->u.bnetd_d2cs_gameinforeq.h.seqno,0); packet_append_string(packet,game_get_name(game)); conn_push_outqueue(realm_get_conn(realm),packet); packet_del_ref(packet); } return 0; } static int on_d2cs_gameinforeply(t_connection * c, t_packet const * packet) { t_game * game; char const * gamename; unsigned int difficulty; t_game_difficulty diff; if (!(c)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!(gamename = packet_get_str_const(packet,sizeof(t_d2cs_bnetd_gameinforeply),GAME_NAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"missing or too long gamename"); return -1; } if (!(game = gamelist_find_game(gamename,CLIENTTAG_DIABLO2DV_UINT,game_type_diablo2closed)) && !(game = gamelist_find_game(gamename,CLIENTTAG_DIABLO2XP_UINT,game_type_diablo2closed))) { eventlog(eventlog_level_error,__FUNCTION__,"reply for unknown game \"%s\"",gamename); return -1; } difficulty = bn_byte_get(packet->u.d2cs_bnetd_gameinforeply.difficulty); switch (difficulty) { case 0: diff = game_difficulty_normal; break; case 1: diff = game_difficulty_nightmare; break; case 2: diff = game_difficulty_hell; break; default: diff = game_difficulty_none; } game_set_difficulty(game,diff); return 0; } pvpgn-1.8.5/src/bnetd/runprog.c0000644000175000017500000000722211151345317015370 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #endif #include #include "compat/strerror.h" #ifdef HAVE_UNISTD_H # include #endif #include "compat/stdfileno.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_WAIT_H # include #endif #include "common/eventlog.h" #include "runprog.h" #include "common/setup_after.h" #ifdef DO_SUBPROC static pid_t currpid=0; #endif extern FILE * runprog_open(char const * command) { #ifndef DO_SUBPROC return NULL; /* always fail */ #else int fds[2]; FILE * pp; if (!command) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command"); return NULL; } if (pipe(fds)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create pipe (pipe: %s)",pstrerror(errno)); return NULL; } switch ((currpid = fork())) { case 0: close(fds[0]); close(STDINFD); close(STDOUTFD); close(STDERRFD); /* FIXME: we should close all other fds to make sure the program doesn't use them. For now, leave it alone because we would either have to keep track of them all or do a for for (fd=0; fd #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "common/xalloc.h" #ifdef WIN32 # include "win32/service.h" #endif #ifdef WIN32_GUI # include "win32/winmain.h" # define printf gui_printf #endif #include "compat/strcasecmp.h" #include "common/eventlog.h" #include "common/conf.h" #include "common/setup_after.h" static struct { #ifdef DO_DAEMONIZE unsigned foreground; #endif const char *preffile; const char *hexfile; unsigned debug; } cmdline_config; static unsigned exitflag; static const char *progname; #ifdef DO_DAEMONIZE static int conf_set_foreground(const char *valstr); static int conf_setdef_foreground(void); #endif static int conf_set_preffile(const char *valstr); static int conf_setdef_preffile(void); static int conf_set_hexfile(const char *valstr); static int conf_setdef_hexfile(void); static int conf_set_debug(const char *valstr); static int conf_setdef_debug(void); static int conf_set_help(const char *valstr); static int conf_setdef_help(void); static int conf_set_version(const char *valstr); static int conf_setdef_version(void); #ifdef WIN32 static int conf_set_service(const char *valstr); static int conf_setdef_service(void); static int conf_set_servaction(const char *valstr); static int conf_setdef_servaction(void); #endif static t_conf_entry conftab[] = { { "c", conf_set_preffile, NULL, conf_setdef_preffile }, { "config", conf_set_preffile, NULL, conf_setdef_preffile }, { "d", conf_set_hexfile, NULL, conf_setdef_hexfile }, { "hexdump", conf_set_hexfile, NULL, conf_setdef_hexfile }, #ifdef DO_DAEMONIZE { "f", conf_set_foreground, NULL, conf_setdef_foreground }, { "foreground", conf_set_foreground, NULL, conf_setdef_foreground }, #endif { "D", conf_set_debug, NULL, conf_setdef_debug }, { "debug", conf_set_debug, NULL, conf_setdef_debug }, { "h", conf_set_help, NULL, conf_setdef_help }, { "help", conf_set_help, NULL, conf_setdef_help }, { "usage", conf_set_help, NULL, conf_setdef_help }, { "v", conf_set_version, NULL, conf_setdef_version }, { "version", conf_set_version, NULL, conf_setdef_version }, #ifdef WIN32 { "service", conf_set_service, NULL, conf_setdef_service }, { "s", conf_set_servaction, NULL, conf_setdef_servaction }, #endif { NULL, NULL, NULL, NULL } }; static void usage(void) { fprintf(stderr, "usage: %s []\n" " -c FILE, --config=FILE use FILE as configuration file (default is " BNETD_DEFAULT_CONF_FILE ")\n" " -d FILE, --hexdump=FILE do hex dump of packets into FILE\n" #ifdef DO_DAEMONIZE " -f, --foreground don't daemonize\n" #endif " -D, --debug run in debug mode (run in foreground and log to stdout)\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n" #ifdef WIN32 " Running as service functions:\n" " --service run as service\n" " -s install install service\n" " -s uninstall uninstall service\n" #endif ,progname); } extern int cmdline_load(int argc, char** argv) { int res; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return -1; } exitflag = 0; progname = argv[0]; res = conf_load_cmdline(argc, argv, conftab); if (res < 0) return -1; return exitflag ? 0 : 1; } extern void cmdline_unload(void) { conf_unload(conftab); } #ifdef DO_DAEMONIZE extern int cmdline_get_foreground(void) { return cmdline_config.foreground; } static int conf_set_foreground(const char *valstr) { return conf_set_bool(&cmdline_config.foreground, valstr, 0); } static int conf_setdef_foreground(void) { return conf_set_bool(&cmdline_config.foreground, NULL, 0); } #endif extern const char* cmdline_get_preffile(void) { return cmdline_config.preffile; } static int conf_set_preffile(const char *valstr) { return conf_set_str(&cmdline_config.preffile, valstr, NULL); } static int conf_setdef_preffile(void) { return conf_set_str(&cmdline_config.preffile, NULL, BNETD_DEFAULT_CONF_FILE); } extern const char* cmdline_get_hexfile(void) { return cmdline_config.hexfile; } static int conf_set_hexfile(const char *valstr) { return conf_set_str(&cmdline_config.hexfile, valstr, NULL); } static int conf_setdef_hexfile(void) { return conf_set_str(&cmdline_config.hexfile, NULL, NULL); } static int conf_set_debug(const char *valstr) { conf_set_bool(&cmdline_config.debug, valstr, 0); if (cmdline_config.debug) eventlog_set_debugmode(1); #ifdef DO_DAEMONIZE cmdline_config.foreground = 1; #endif return 0; } static int conf_setdef_debug(void) { return conf_set_bool(&cmdline_config.debug, NULL, 0); } static int conf_set_help(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { usage(); exitflag = 1; } return 0; } static int conf_setdef_help(void) { return 0; } static int conf_set_version(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { printf(PVPGN_SOFTWARE" version "PVPGN_VERSION"\n"); exitflag = 1; } return 0; } static int conf_setdef_version(void) { return 0; } #ifdef WIN32 static int conf_set_service(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { Win32_ServiceRun(); exitflag = 1; } return 0; } static int conf_setdef_service(void) { return 0; } static int conf_set_servaction(const char *valstr) { const char* tmp = NULL; conf_set_str(&tmp, valstr, NULL); if (tmp) { if (!strcasecmp(tmp, "install")) { fprintf(stderr, "Installing service"); Win32_ServiceInstall(); } else if (!strcasecmp(tmp, "uninstall")) { fprintf(stderr, "Uninstalling service"); Win32_ServiceUninstall(); } else { fprintf(stderr, "Unknown service action '%s'\n", tmp); } exitflag = 1; xfree((void *)tmp); } return 0; } static int conf_setdef_servaction(void) { return 0; } #endif pvpgn-1.8.5/src/bnetd/storage_file.c0000644000175000017500000005642011151345317016343 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * Copyright (C) 2002,2003,2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include #ifdef HAVE_LIMITS_H # include #endif #include "compat/char_bit.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include "compat/strerror.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #include "compat/access.h" #include "compat/rename.h" #include "compat/pdir.h" #include "common/eventlog.h" #include "prefs.h" #include "common/util.h" #include "common/field_sizes.h" #include "common/bnethash.h" #define CLAN_INTERNAL_ACCESS #define TEAM_INTERNAL_ACCESS #include "common/introtate.h" #include "team.h" #include "account.h" #include "common/hashtable.h" #include "storage.h" #include "storage_file.h" #include "file_plain.h" #include "file_cdb.h" #include "common/list.h" #include "connection.h" #include "watch.h" #include "clan.h" #undef ACCOUNT_INTERNAL_ACCESS #undef TEAM_INTERNAL_ACCESS #undef CLAN_INTERNAL_ACCESS #include "common/tag.h" #include "common/xalloc.h" #include "common/elist.h" #include "common/setup_after.h" /* file storage API functions */ static int file_init(const char *); static int file_close(void); static unsigned file_read_maxuserid(void); static t_storage_info *file_create_account(char const *); static t_storage_info *file_get_defacct(void); static int file_free_info(t_storage_info *); static int file_read_attrs(t_storage_info *, t_read_attr_func, void *); static t_attr *file_read_attr(t_storage_info *, const char *); static int file_write_attrs(t_storage_info *, const t_hlist *); static int file_read_accounts(int,t_read_accounts_func, void *); static t_storage_info *file_read_account(const char *, unsigned); static int file_cmp_info(t_storage_info *, t_storage_info *); static const char *file_escape_key(const char *); static int file_load_clans(t_load_clans_func); static int file_write_clan(void *); static int file_remove_clan(int); static int file_remove_clanmember(int); static int file_load_teams(t_load_teams_func); static int file_write_team(void *); static int file_remove_team(unsigned int); /* storage struct populated with the functions above */ t_storage storage_file = { file_init, file_close, file_read_maxuserid, file_create_account, file_get_defacct, file_free_info, file_read_attrs, file_write_attrs, file_read_attr, file_read_accounts, file_read_account, file_cmp_info, file_escape_key, file_load_clans, file_write_clan, file_remove_clan, file_remove_clanmember, file_load_teams, file_write_team, file_remove_team }; /* start of actual file storage code */ static const char *accountsdir = NULL; static const char *clansdir = NULL; static const char *teamsdir = NULL; static const char *defacct = NULL; static t_file_engine *file = NULL; static unsigned file_read_maxuserid(void) { return maxuserid; } static int file_init(const char *path) { char *tok, *copy, *tmp, *p; const char *dir = NULL; const char *clan = NULL; const char *team = NULL; const char *def = NULL; const char *driver = NULL; if (path == NULL || path[0] == '\0') { eventlog(eventlog_level_error, __FUNCTION__, "got NULL or empty path"); return -1; } copy = xstrdup(path); tmp = copy; while ((tok = strtok(tmp, ";")) != NULL) { tmp = NULL; if ((p = strchr(tok, '=')) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path, no '=' present in token"); xfree((void *) copy); return -1; } *p = '\0'; if (strcasecmp(tok, "dir") == 0) dir = p + 1; else if (strcasecmp(tok, "clan") == 0) clan = p + 1; else if (strcasecmp(tok, "team") == 0) team = p + 1; else if (strcasecmp(tok, "default") == 0) def = p + 1; else if (strcasecmp(tok, "mode") == 0) driver = p + 1; else eventlog(eventlog_level_warn, __FUNCTION__, "unknown token in storage_path : '%s'", tok); } if (def == NULL || clan == NULL || team == NULL || dir == NULL || driver == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path line for file module (doesnt have a 'dir', a 'clan', a 'team', a 'default' token and a 'mode' token)"); xfree((void *) copy); return -1; } if (!strcasecmp(driver, "plain")) file = &file_plain; else if (!strcasecmp(driver, "cdb")) file = &file_cdb; else { eventlog(eventlog_level_error, __FUNCTION__, "unknown mode '%s' must be either plain or cdb", driver); xfree((void *) copy); return -1; } if (accountsdir) file_close(); accountsdir = xstrdup(dir); clansdir = xstrdup(clan); teamsdir = xstrdup(team); defacct = xstrdup(def); xfree((void *) copy); return 0; } static int file_close(void) { if (accountsdir) xfree((void *) accountsdir); accountsdir = NULL; if (clansdir) xfree((void *) clansdir); clansdir = NULL; if (teamsdir) xfree((void *) teamsdir); teamsdir = NULL; if (defacct) xfree((void *) defacct); defacct = NULL; file = NULL; return 0; } static t_storage_info *file_create_account(const char *username) { char *temp; if (accountsdir == NULL || file == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized"); return NULL; } if (prefs_get_savebyname()) { char const *safename; if (!strcmp(username, defacct)) { eventlog(eventlog_level_error, __FUNCTION__, "username as defacct not allowed"); return NULL; } if (!(safename = escape_fs_chars(username, strlen(username)))) { eventlog(eventlog_level_error, __FUNCTION__, "could not escape username"); return NULL; } temp = xmalloc(strlen(accountsdir) + 1 + strlen(safename) + 1); /* dir + / + name + NUL */ sprintf(temp, "%s/%s", accountsdir, safename); xfree((void *) safename); /* avoid warning */ } else { temp = xmalloc(strlen(accountsdir) + 1 + 8 + 1); /* dir + / + uid + NUL */ sprintf(temp, "%s/%06u", accountsdir, maxuserid + 1); /* FIXME: hmm, maybe up the %06 to %08... */ } return temp; } static int file_write_attrs(t_storage_info * info, const t_hlist *attributes) { char *tempname; if (accountsdir == NULL || file == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized"); return -1; } if (info == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage"); return -1; } if (attributes == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL attributes"); return -1; } tempname = xmalloc(strlen(accountsdir) + 1 + strlen(BNETD_ACCOUNT_TMP) + 1); sprintf(tempname, "%s/%s", accountsdir, BNETD_ACCOUNT_TMP); if (file->write_attrs(tempname, attributes)) { /* no eventlog here, it should be reported from the file layer */ xfree(tempname); return -1; } if (p_rename(tempname, (const char *) info) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "could not rename account file to \"%s\" (rename: %s)", (char *) info, pstrerror(errno)); xfree(tempname); return -1; } xfree(tempname); return 0; } static int file_read_attrs(t_storage_info * info, t_read_attr_func cb, void *data) { if (accountsdir == NULL || file == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized"); return -1; } if (info == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage"); return -1; } if (cb == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback"); return -1; } eventlog(eventlog_level_debug, __FUNCTION__, "loading \"%s\"", (char *) info); if (file->read_attrs((const char *) info, cb, data)) { /* no eventlog, error reported earlier */ return -1; } return 0; } static t_attr *file_read_attr(t_storage_info * info, const char *key) { if (accountsdir == NULL || file == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized"); return NULL; } if (info == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage"); return NULL; } if (key == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL key"); return NULL; } return file->read_attr((const char *) info, key); } static int file_free_info(t_storage_info * info) { if (info) xfree((void *) info); return 0; } static t_storage_info *file_get_defacct(void) { t_storage_info *info; if (defacct == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized"); return NULL; } info = xstrdup(defacct); return info; } static int file_read_accounts(int flag,t_read_accounts_func cb, void *data) { char const *dentry; char *pathname; t_pdir *accountdir; if (accountsdir == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized"); return -1; } if (cb == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback"); return -1; } if (!(accountdir = p_opendir(accountsdir))) { eventlog(eventlog_level_error, __FUNCTION__, "unable to open user directory \"%s\" for reading (p_opendir: %s)", accountsdir, pstrerror(errno)); return -1; } while ((dentry = p_readdir(accountdir))) { if (dentry[0] == '.') continue; pathname = xmalloc(strlen(accountsdir) + 1 + strlen(dentry) + 1); /* dir + / + file + NUL */ sprintf(pathname, "%s/%s", accountsdir, dentry); cb(pathname, data); } if (p_closedir(accountdir) < 0) eventlog(eventlog_level_error, __FUNCTION__, "unable to close user directory \"%s\" (p_closedir: %s)", accountsdir, pstrerror(errno)); return 0; } static t_storage_info *file_read_account(const char *accname, unsigned uid) { char *pathname; if (accountsdir == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized"); return NULL; } /* ONLY if requesting for a username and if savebyname() is true * PS: yes its kind of a hack, we will make a proper index file */ if (accname && prefs_get_savebyname()) { pathname = xmalloc(strlen(accountsdir) + 1 + strlen(accname) + 1); /* dir + / + file + NUL */ sprintf(pathname, "%s/%s", accountsdir, accname); if (access(pathname, F_OK)) /* if it doesn't exist */ { xfree((void *) pathname); return NULL; } return pathname; } return NULL; } static int file_cmp_info(t_storage_info * info1, t_storage_info * info2) { return strcmp((const char *) info1, (const char *) info2); } static const char *file_escape_key(const char *key) { return key; } static int file_load_clans(t_load_clans_func cb) { char const *dentry; t_pdir *clandir; char *pathname; int clantag; t_clan *clan; FILE *fp; char *clanname, *motd, *p; char line[1024]; int cid, creation_time; int member_uid, member_join_time; char member_status; t_clanmember *member; if (cb == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback"); return -1; } if (!(clandir = p_opendir(clansdir))) { eventlog(eventlog_level_error, __FUNCTION__, "unable to open clan directory \"%s\" for reading (p_opendir: %s)", clansdir, pstrerror(errno)); return -1; } eventlog(eventlog_level_trace, __FUNCTION__, "start reading clans"); pathname = xmalloc(strlen(clansdir) + 1 + 4 + 1); while ((dentry = p_readdir(clandir)) != NULL) { if (dentry[0] == '.') continue; if (strlen(dentry) > 4) { eventlog(eventlog_level_error, __FUNCTION__, "found too long clan filename in clandir \"%s\"", dentry); continue; } sprintf(pathname, "%s/%s", clansdir, dentry); clantag = str_to_clantag(dentry); if ((fp = fopen(pathname, "r")) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "can't open clanfile \"%s\"", pathname); continue; } clan = xmalloc(sizeof(t_clan)); clan->clantag = clantag; if (!fgets(line, 1024, fp)) { eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: no first line"); xfree((void*)clan); continue; } clanname = line; if (*clanname != '"') { eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line"); xfree((void*)clan); continue; } clanname++; p = strchr(clanname, '"'); if (!p) { eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line"); xfree((void*)clan); continue; } *p = '\0'; if (strlen(clanname) >= CLAN_NAME_MAX) { eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line"); xfree((void*)clan); continue; } p++; if (*p != ',') { eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line"); xfree((void*)clan); continue; } p++; if (*p != '"') { eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line"); xfree((void*)clan); continue; } motd = p + 1; p = strchr(motd, '"'); if (!p) { eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line"); xfree((void*)clan); continue; } *p = '\0'; if (sscanf(p + 1, ",%d,%d\n", &cid, &creation_time) != 2) { eventlog(eventlog_level_error, __FUNCTION__, "invalid first line in clanfile"); xfree((void*)clan); continue; } clan->clanname = xstrdup(clanname); clan->clan_motd = xstrdup(motd); clan->clanid = cid; clan->creation_time = (time_t) creation_time; clan->created = 1; clan->modified = 0; clan->channel_type = prefs_get_clan_channel_default_private(); eventlog(eventlog_level_trace, __FUNCTION__, "name: %s motd: %s clanid: %i time: %i", clanname, motd, cid, creation_time); clan->members = list_create(); while (fscanf(fp, "%i,%c,%i\n", &member_uid, &member_status, &member_join_time) == 3) { member = xmalloc(sizeof(t_clanmember)); if (!(member->memberacc = accountlist_find_account_by_uid(member_uid))) { eventlog(eventlog_level_error, __FUNCTION__, "cannot find uid %u", member_uid); xfree((void *) member); continue; } member->status = member_status - '0'; member->join_time = member_join_time; member->clan = clan; if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600)) { member->status = CLAN_PEON; clan->modified = 1; } list_append_data(clan->members, member); account_set_clanmember(member->memberacc, member); eventlog(eventlog_level_trace, __FUNCTION__, "added member: uid: %i status: %c join_time: %i", member_uid, member_status + '0', member_join_time); } fclose(fp); cb(clan); } xfree((void *) pathname); if (p_closedir(clandir) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "unable to close clan directory \"%s\" (p_closedir: %s)", clansdir, pstrerror(errno)); } eventlog(eventlog_level_trace, __FUNCTION__, "finished reading clans"); return 0; } static int file_write_clan(void *data) { FILE *fp; t_elem *curr; t_clanmember *member; char *clanfile; t_clan *clan = (t_clan *) data; clanfile = xmalloc(strlen(clansdir) + 1 + 4 + 1); sprintf(clanfile, "%s/%c%c%c%c", clansdir, clan->clantag >> 24, (clan->clantag >> 16) & 0xff, (clan->clantag >> 8) & 0xff, clan->clantag & 0xff); if ((fp = fopen(clanfile, "w")) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "can't open clanfile \"%s\"", clanfile); xfree((void *) clanfile); return -1; } fprintf(fp, "\"%s\",\"%s\",%i,%i\n", clan->clanname, clan->clan_motd, clan->clanid, (int) clan->creation_time); LIST_TRAVERSE(clan->members, curr) { if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL elem in list"); continue; } if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600)) member->status = CLAN_PEON; fprintf(fp, "%i,%c,%u\n", account_get_uid(member->memberacc), member->status + '0', (unsigned) member->join_time); } fclose(fp); xfree((void *) clanfile); return 0; } static int file_remove_clan(int clantag) { char *tempname; tempname = xmalloc(strlen(clansdir) + 1 + 4 + 1); sprintf(tempname, "%s/%c%c%c%c", clansdir, clantag >> 24, (clantag >> 16) & 0xff, (clantag >> 8) & 0xff, clantag & 0xff); if (remove((const char *) tempname) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "could not delete clan file \"%s\" (remove: %s)", (char *) tempname, pstrerror(errno)); xfree(tempname); return -1; } xfree(tempname); return 0; } static int file_remove_clanmember(int uid) { return 0; } static int file_load_teams(t_load_teams_func cb) { char const *dentry; t_pdir *teamdir; char *pathname; unsigned int teamid; t_team *team; FILE *fp; char * line; unsigned int fteamid,lastgame; unsigned char size; char clienttag[5]; int i; if (cb == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback"); return -1; } if (!(teamdir = p_opendir(teamsdir))) { eventlog(eventlog_level_error, __FUNCTION__, "unable to open team directory \"%s\" for reading (p_opendir: %s)", teamsdir, pstrerror(errno)); return -1; } eventlog(eventlog_level_trace, __FUNCTION__, "start reading teams"); pathname = xmalloc(strlen(teamsdir) + 1 + 8 + 1); while ((dentry = p_readdir(teamdir)) != NULL) { if (dentry[0] == '.') continue; if (strlen(dentry) != 8) { eventlog(eventlog_level_error, __FUNCTION__, "found invalid team filename in teamdir \"%s\"", dentry); continue; } sprintf(pathname, "%s/%s", teamsdir, dentry); teamid = (unsigned int)strtoul(dentry,NULL,16); // we use hexadecimal teamid as filename if ((fp = fopen(pathname, "r")) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "can't open teamfile \"%s\"", pathname); continue; } team = xmalloc(sizeof(t_team)); team->teamid = teamid; if (!(line = file_get_line(fp))) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: file is empty"); goto load_team_failure; } if (sscanf(line,"%u,%c,%4s,%u",&fteamid,&size,clienttag,&lastgame)!=4) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid number of arguments on first line"); goto load_team_failure; } if (fteamid != teamid) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: filename and stored teamid don't match"); goto load_team_failure; } size -='0'; if ((size<2) || (size>4)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid team size"); goto load_team_failure; } team->size = size; if (!(tag_check_client(team->clienttag = tag_str_to_uint(clienttag)))) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid clienttag"); goto load_team_failure; } team->lastgame = (time_t)lastgame; if (!(line= file_get_line(fp))) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: missing 2nd line"); goto load_team_failure; } if (sscanf(line,"%u,%u,%u,%u",&team->teammembers[0],&team->teammembers[1],&team->teammembers[2],&team->teammembers[3])!=4) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid number of arguments on 2nd line"); goto load_team_failure; } for (i=0; iteammembers[i]==0)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: too few members"); goto load_team_failure; } } else { if ((team->teammembers[i]!=0)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: too many members"); goto load_team_failure; } } team->members[i] = NULL; } if (!(line= file_get_line(fp))) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: missing 3rd line"); goto load_team_failure; } if (sscanf(line,"%d,%d,%d,%d,%d",&team->wins,&team->losses,&team->xp,&team->level,&team->rank)!=5) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid number of arguments on 3rd line"); goto load_team_failure; } eventlog(eventlog_level_trace,__FUNCTION__,"succesfully loaded team %s",dentry); cb(team); goto load_team_success; load_team_failure: xfree((void*)team); eventlog(eventlog_level_error,__FUNCTION__,"error while reading file \"%s\"",dentry); load_team_success: file_get_line(NULL); // clear file_get_line buffer fclose(fp); } xfree((void *) pathname); if (p_closedir(teamdir) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "unable to close team directory \"%s\" (p_closedir: %s)", teamsdir, pstrerror(errno)); } eventlog(eventlog_level_trace, __FUNCTION__, "finished reading teams"); return 0; } static int file_write_team(void *data) { FILE *fp; char *teamfile; t_team *team = (t_team *) data; teamfile = xmalloc(strlen(teamsdir) + 1 + 8 + 1); sprintf(teamfile, "%s/%08x", teamsdir, team->teamid); if ((fp = fopen(teamfile, "w")) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "can't open teamfile \"%s\"", teamfile); xfree((void *) teamfile); return -1; } fprintf(fp,"%u,%c,%s,%u\n",team->teamid,team->size+'0',clienttag_uint_to_str(team->clienttag),(unsigned int)team->lastgame); fprintf(fp,"%u,%u,%u,%u\n",team->teammembers[0],team->teammembers[1],team->teammembers[2],team->teammembers[3]); fprintf(fp,"%d,%d,%d,%d,%d\n",team->wins,team->losses,team->xp,team->level,team->rank); fclose(fp); xfree((void *) teamfile); return 0; } static int file_remove_team(unsigned int teamid) { char *tempname; tempname = xmalloc(strlen(clansdir) + 1 + 8 + 1); sprintf(tempname, "%s/%08x", clansdir, teamid); if (remove((const char *) tempname) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "could not delete team file \"%s\" (remove: %s)", (char *) tempname, pstrerror(errno)); xfree(tempname); return -1; } xfree(tempname); return 0; } pvpgn-1.8.5/src/bnetd/handle_init.c0000644000175000017500000001052311151345317016150 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include "common/packet.h" #include "common/init_protocol.h" #include "common/eventlog.h" #include "common/queue.h" #include "common/bn_type.h" #include "connection.h" #include "realm.h" #include "prefs.h" #include "common/addr.h" #include "handle_init.h" #include "handle_d2cs.h" #include "common/setup_after.h" extern int handle_init_packet(t_connection * c, t_packet const * const packet) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c)); return -1; } if (packet_get_class(packet)!=packet_class_init) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet)); return -1; } switch (packet_get_type(packet)) { case CLIENT_INITCONN: switch (bn_byte_get(packet->u.client_initconn.class)) { case CLIENT_INITCONN_CLASS_BNET: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated bnet connection",conn_get_socket(c)); conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_bnet); break; case CLIENT_INITCONN_CLASS_FILE: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated file download connection",conn_get_socket(c)); conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_file); break; case CLIENT_INITCONN_CLASS_BOT: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated chat bot connection",conn_get_socket(c)); conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_bot); break; case CLIENT_INITCONN_CLASS_TELNET: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated telnet connection",conn_get_socket(c)); conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_telnet); break; case CLIENT_INITCONN_CLASS_D2CS_BNETD: { eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated d2cs_bnetd connection",conn_get_socket(c)); if (!(realmlist_find_realm_by_ip(conn_get_addr(c)))) { eventlog(eventlog_level_info,__FUNCTION__, "[%d] d2cs connection from unknown ip address %s",conn_get_socket(c),addr_num_to_addr_str(conn_get_addr(c),conn_get_port(c))); return -1; } conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_d2cs_bnetd); if (handle_d2cs_init(c)<0) { eventlog(eventlog_level_info,__FUNCTION__,"faild to init d2cs connection"); return -1; } } break; case CLIENT_INITCONN_CLASS_ENC: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated encrypted connection (not supported)",conn_get_socket(c)); return -1; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] client requested unknown class 0x%02x (length %d) (closing connection)",conn_get_socket(c),(unsigned int)bn_byte_get(packet->u.client_initconn.class),packet_get_size(packet)); return -1; } break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown init packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet)); return -1; } return 0; } pvpgn-1.8.5/src/bnetd/file_plain.c0000644000175000017500000001470111151345317015776 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * Copyright (C) 2002,2003,2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include #ifdef HAVE_LIMITS_H # include #endif #include "compat/char_bit.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include "compat/strerror.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_UNISTD_H # include #else # ifdef WIN32 # include # endif #endif #include "compat/pdir.h" #include "common/eventlog.h" #include "prefs.h" #include "common/util.h" #include "common/field_sizes.h" #include "common/bnethash.h" #define CLAN_INTERNAL_ACCESS #include "common/introtate.h" #include "account.h" #include "common/hashtable.h" #include "storage.h" #include "storage_file.h" #include "common/list.h" #include "common/xalloc.h" #include "connection.h" #include "watch.h" #include "clan.h" #undef CLAN_INTERNAL_ACCESS #include "common/elist.h" #include "attr.h" #include "common/tag.h" #include "common/setup_after.h" /* plain file storage API functions */ static t_attr * plain_read_attr(const char *filename, const char *key); static int plain_read_attrs(const char *filename, t_read_attr_func cb, void *data); static int plain_write_attrs(const char *filename, const t_hlist *attributes); /* file_engine struct populated with the functions above */ t_file_engine file_plain = { plain_read_attr, plain_read_attrs, plain_write_attrs }; static int plain_write_attrs(const char *filename, const t_hlist *attributes) { FILE * accountfile; t_hlist * curr; t_attr * attr; char const * key; char const * val; if (!(accountfile = fopen(filename,"w"))) { eventlog(eventlog_level_error, __FUNCTION__, "unable to open file \"%s\" for writing (fopen: %s)",filename,pstrerror(errno)); return -1; } hlist_for_each(curr, attributes) { attr = hlist_entry(curr, t_attr, link); if (attr_get_key(attr)) key = escape_chars(attr_get_key(attr),strlen(attr_get_key(attr))); else { eventlog(eventlog_level_error, __FUNCTION__, "attribute with NULL key in list"); key = NULL; } if (attr_get_val(attr)) val = escape_chars(attr_get_val(attr),strlen(attr_get_val(attr))); else { eventlog(eventlog_level_error, __FUNCTION__, "attribute with NULL val in list"); val = NULL; } if (key && val) { if (strncmp("BNET\\CharacterDefault\\", key, 20) == 0) { eventlog(eventlog_level_debug, __FUNCTION__, "skipping attribute key=\"%s\"",attr->key); } else { eventlog(eventlog_level_debug, __FUNCTION__, "saving attribute key=\"%s\" val=\"%s\"",attr->key,attr->val); fprintf(accountfile,"\"%s\"=\"%s\"\n",key,val); } } else eventlog(eventlog_level_error, __FUNCTION__,"could not save attribute key=\"%s\"",attr->key); if (key) xfree((void *)key); /* avoid warning */ if (val) xfree((void *)val); /* avoid warning */ attr_clear_dirty(attr); } if (fclose(accountfile)<0) { eventlog(eventlog_level_error, __FUNCTION__, "could not close account file \"%s\" after writing (fclose: %s)",filename,pstrerror(errno)); return -1; } return 0; } static int plain_read_attrs(const char *filename, t_read_attr_func cb, void *data) { FILE * accountfile; unsigned int line; char const * buff; unsigned int len; char * esckey; char * escval; char * key; char * val; if (!(accountfile = fopen(filename,"r"))) { eventlog(eventlog_level_error, __FUNCTION__,"could not open account file \"%s\" for reading (fopen: %s)", filename, pstrerror(errno)); return -1; } for (line=1; (buff=file_get_line(accountfile)); line++) { if (buff[0]=='#' || buff[0]=='\0') { continue; } if (strlen(buff)<6) /* "?"="" */ { eventlog(eventlog_level_error, __FUNCTION__, "malformed line %d of account file \"%s\"", line, filename); continue; } len = strlen(buff)-5+1; /* - ""="" + NUL */ esckey = xmalloc(len); escval = xmalloc(len); if (sscanf(buff,"\"%[^\"]\" = \"%[^\"]\"",esckey,escval)!=2) { if (sscanf(buff,"\"%[^\"]\" = \"\"",esckey)!=1) /* hack for an empty value field */ { eventlog(eventlog_level_error, __FUNCTION__,"malformed entry on line %d of account file \"%s\"", line, filename); xfree(escval); xfree(esckey); continue; } escval[0] = '\0'; } key = unescape_chars(esckey); val = unescape_chars(escval); /* eventlog(eventlog_level_debug,__FUNCTION__,"strlen(esckey)=%u (%c), len=%u",strlen(esckey),esckey[0],len);*/ xfree(esckey); xfree(escval); if (cb(key,val,data)) eventlog(eventlog_level_error, __FUNCTION__, "got error from callback (key: '%s' val:'%s')", key, val); if (key) xfree((void *)key); /* avoid warning */ if (val) xfree((void *)val); /* avoid warning */ } file_get_line(NULL); // clear file_get_line buffer if (fclose(accountfile)<0) eventlog(eventlog_level_error, __FUNCTION__, "could not close account file \"%s\" after reading (fclose: %s)", filename, pstrerror(errno)); return 0; } static t_attr * plain_read_attr(const char *filename, const char *key) { /* flat file storage doesnt know to read selective attributes */ return NULL; } pvpgn-1.8.5/src/bnetd/output.h0000644000175000017500000000156311151345317015243 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef NULL # define NULL ((void *)0) #endif extern void output_init(void); extern void output_dispose_filename(void); extern int output_write_to_file(void); pvpgn-1.8.5/src/bnetd/support.c0000644000175000017500000000501011151345317015401 0ustar aaronaaron/* * Copyright (C) 2004 Lector * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #ifdef HAVE_UNISTD_H #include #endif #include "compat/access.h" #include "compat/strerror.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "support.h" #include "prefs.h" #include "common/util.h" #include "common/setup_after.h" extern int support_check_files(char const * supportfile) { FILE *fp; char *buff; unsigned int line; int filedirlen; char * namebuff; if (!(supportfile)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL supportfile"); return -1; } if (!(fp = fopen(supportfile,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for reading (fopen: %s)",supportfile,pstrerror(errno)); eventlog(eventlog_level_error,__FUNCTION__,"can't guarantee that everything will run smooth"); return 0; } filedirlen = strlen(prefs_get_filedir()); for (line=1; (buff = file_get_line(fp)); line++) { if (buff[0]=='#' || buff[0]=='\0') { continue; } namebuff = xmalloc(filedirlen + 1 + strlen(buff) + 1); sprintf(namebuff,"%s/%s",prefs_get_filedir(),buff); if (access(namebuff, F_OK) < 0) { eventlog(eventlog_level_fatal,__FUNCTION__,"necessary file \"%s\" missing",namebuff); xfree((void *)namebuff); fclose(fp); return -1; } xfree((void *)namebuff); } file_get_line(NULL); // clear file_get_line buffer fclose(fp); return 0; } pvpgn-1.8.5/src/bnetd/sql_common.h0000644000175000017500000000572311151345317016054 0ustar aaronaaron/* * Copyright (C) 2002,2003,2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SQL_COMMON_TYPES #define INCLUDED_SQL_COMMON_TYPES typedef unsigned int t_sql_info; /* used as a pointer to it */ #define t_sql_res void typedef char * t_sql_row; typedef char * t_sql_field; typedef struct { char quote; /* quote character for column names, depending on backend */ int (*init)(const char *host, const char *port, const char *socket, const char *name, const char *user, const char *pass); int (*close)(void); t_sql_res * (*query_res)(const char *); int (*query)(const char *); t_sql_row * (*fetch_row)(t_sql_res *); void (*free_result)(t_sql_res *); unsigned int (*num_rows)(t_sql_res *); unsigned int (*num_fields)(t_sql_res *); unsigned int (*affected_rows)(void); t_sql_field * (*fetch_fields)(t_sql_res *); int (*free_fields)(t_sql_field *); void (*escape_string)(char *, const char *, int); } t_sql_engine; #endif /* INCLUDED_SQL_COMMON_TYPES */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_SQL_COMMON_PROTOS #define INCLUDED_SQL_COMMON_PROTOS #include "storage.h" extern t_storage storage_sql; #ifdef SQL_INTERNAL #define CURRENT_DB_VERSION 150 #define DB_MAX_ATTRKEY 128 #define DB_MAX_ATTRVAL 180 #define DB_MAX_TAB 64 #define SQL_UID_FIELD "uid" #define STORAGE_SQL_DEFAULT_UID 0 #define SQL_DEFAULT_PREFIX "" #define SQL_ON_DEMAND 1 extern t_sql_engine *sql; extern unsigned int sql_defacct; extern const char* tab_prefix; #ifndef SQL_ON_DEMAND extern char *sql_tables[]; #endif /* SQL_ON_DEMAND */ extern int sql_init(const char *); extern int sql_close(void); extern unsigned sql_read_maxuserid(void); extern int sql_read_accounts(int flag,t_read_accounts_func cb, void *data); extern int sql_cmp_info(t_storage_info * info1, t_storage_info * info2); extern int sql_free_info(t_storage_info * info); extern t_storage_info *sql_get_defacct(void); extern int sql_load_clans(t_load_clans_func cb); extern int sql_write_clan(void *data); extern int sql_remove_clan(int clantag); extern int sql_remove_clanmember(int uid); extern int sql_load_teams(t_load_teams_func cb); extern int sql_write_team(void *data); extern int sql_remove_team(unsigned int teamid); #endif /* SQL_INTERNAL */ #endif /* INCLUDED_SQL_COMMON_PROTOS */ #endif /* JUST_NEED_TYPES */ pvpgn-1.8.5/src/bnetd/prefs.c0000644000175000017500000027340611151345317015024 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 1999 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 2004,2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define PREFS_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include "compat/strcasecmp.h" #include #include "compat/strerror.h" #include #include "common/util.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/conf.h" #include "prefs.h" #include "common/setup_after.h" #define NONE 0 static struct { /* files and paths */ char const * filedir; char const * storage_path; char const * logfile; char const * loglevels; char const * motdfile; char const * newsfile; char const * channelfile; char const * pidfile; char const * adfile; char const * topicfile; char const * DBlayoutfile; unsigned int usersync; unsigned int userflush; unsigned int userstep; char const * servername; char const * hostname; unsigned int track; char const * location; char const * description; char const * url; char const * contact_name; char const * contact_email; unsigned int latency; unsigned int irc_latency; unsigned int shutdown_delay; unsigned int shutdown_decr; unsigned int new_accounts; unsigned int max_accounts; unsigned int kick_old_login; unsigned int ask_new_channel; unsigned int hide_pass_games; unsigned int hide_started_games; unsigned int hide_temp_channels; unsigned int hide_addr; unsigned int enable_conn_all; unsigned int extra_commands; char const * reportdir; unsigned int report_all_games; unsigned int report_diablo_games; char const * iconfile; char const * war3_iconfile; char const * star_iconfile; char const * tosfile; char const * mpqfile; char const * trackaddrs; char const * servaddrs; char const * w3routeaddr; char const * ircaddrs; unsigned int use_keepalive; unsigned int udptest_port; char const * ipbanfile; unsigned int disc_is_loss; char const * helpfile; char const * fortunecmd; char const * transfile; unsigned int chanlog; char const * chanlogdir; unsigned int quota; unsigned int quota_lines; unsigned int quota_time; unsigned int quota_wrapline; unsigned int quota_maxline; unsigned int ladder_init_rating; unsigned int quota_dobae; char const * realmfile; char const * issuefile; char const * effective_user; char const * effective_group; unsigned int nullmsg; unsigned int mail_support; unsigned int mail_quota; char const * maildir; char const * log_notice; unsigned int savebyname; unsigned int skip_versioncheck; unsigned int allow_bad_version; unsigned int allow_unknown_version; char const * versioncheck_file; unsigned int d2cs_version; unsigned int allow_d2cs_setname; unsigned int hashtable_size; char const * telnetaddrs; unsigned int ipban_check_int; char const * version_exeinfo_match; unsigned int version_exeinfo_maxdiff; unsigned int max_concurrent_logins; char const * server_info; char const * mapsfile; char const * xplevelfile; char const * xpcalcfile; unsigned int initkill_timer; unsigned int war3_ladder_update_secs; unsigned int output_update_secs; char const * ladderdir; char const * statusdir; unsigned int XML_output_ladder; unsigned int XML_status_output; char const * account_allowed_symbols; unsigned int account_force_username; char const * command_groups_file; char const * tournament_file; char const * aliasfile; char const * anongame_infos_file; unsigned int max_conns_per_IP; unsigned int max_friends; unsigned int clan_newer_time; unsigned int clan_max_members; unsigned int clan_channel_default_private; unsigned int passfail_count; unsigned int passfail_bantime; unsigned int maxusers_per_channel; char const * supportfile; char const * allowed_clients; char const * ladder_games; char const * ladder_prefix; unsigned int max_connections; unsigned int sync_on_logoff; char const * irc_network_name; char const * woladdrs; char const * woltimezone; char const * wollongitude; char const * wollatitude; } prefs_runtime_config; static int conf_set_filedir(const char *valstr); static const char *conf_get_filedir(void); static int conf_setdef_filedir(void); static int conf_set_storage_path(const char *valstr); static const char *conf_get_storage_path(void); static int conf_setdef_storage_path(void); static int conf_set_logfile(const char *valstr); static const char *conf_get_logfile(void); static int conf_setdef_logfile(void); static int conf_set_loglevels(const char *valstr); static const char *conf_get_loglevels(void); static int conf_setdef_loglevels(void); static int conf_set_motdfile(const char *valstr); static const char *conf_get_motdfile(void); static int conf_setdef_motdfile(void); static int conf_set_newsfile(const char *valstr); static const char *conf_get_newsfile(void); static int conf_setdef_newsfile(void); static int conf_set_channelfile(const char *valstr); static const char *conf_get_channelfile(void); static int conf_setdef_channelfile(void); static int conf_set_pidfile(const char *valstr); static const char *conf_get_pidfile(void); static int conf_setdef_pidfile(void); static int conf_set_adfile(const char *valstr); static const char *conf_get_adfile(void); static int conf_setdef_adfile(void); static int conf_set_topicfile(const char *valstr); static const char *conf_get_topicfile(void); static int conf_setdef_topicfile(void); static int conf_set_DBlayoutfile(const char *valstr); static const char *conf_get_DBlayoutfile(void); static int conf_setdef_DBlayoutfile(void); static int conf_set_supportfile(const char *valstr); static const char *conf_get_supportfile(void); static int conf_setdef_supportfile(void); static int conf_set_usersync(const char *valstr); static const char *conf_get_usersync(void); static int conf_setdef_usersync(void); static int conf_set_userflush(const char *valstr); static const char *conf_get_userflush(void); static int conf_setdef_userflush(void); static int conf_set_userstep(const char *valstr); static const char *conf_get_userstep(void); static int conf_setdef_userstep(void); static int conf_set_servername(const char *valstr); static const char *conf_get_servername(void); static int conf_setdef_servername(void); static int conf_set_hostname(const char *valstr); static const char *conf_get_hostname(void); static int conf_setdef_hostname(void); static int conf_set_track(const char *valstr); static const char *conf_get_track(void); static int conf_setdef_track(void); static int conf_set_location(const char *valstr); static const char *conf_get_location(void); static int conf_setdef_location(void); static int conf_set_description(const char *valstr); static const char *conf_get_description(void); static int conf_setdef_description(void); static int conf_set_url(const char *valstr); static const char *conf_get_url(void); static int conf_setdef_url(void); static int conf_set_contact_name(const char *valstr); static const char *conf_get_contact_name(void); static int conf_setdef_contact_name(void); static int conf_set_contact_email(const char *valstr); static const char *conf_get_contact_email(void); static int conf_setdef_contact_email(void); static int conf_set_latency(const char *valstr); static const char *conf_get_latency(void); static int conf_setdef_latency(void); static int conf_set_irc_latency(const char *valstr); static const char *conf_get_irc_latency(void); static int conf_setdef_irc_latency(void); static int conf_set_shutdown_delay(const char *valstr); static const char *conf_get_shutdown_delay(void); static int conf_setdef_shutdown_delay(void); static int conf_set_shutdown_decr(const char *valstr); static const char *conf_get_shutdown_decr(void); static int conf_setdef_shutdown_decr(void); static int conf_set_new_accounts(const char *valstr); static const char *conf_get_new_accounts(void); static int conf_setdef_new_accounts(void); static int conf_set_max_accounts(const char *valstr); static const char *conf_get_max_accounts(void); static int conf_setdef_max_accounts(void); static int conf_set_kick_old_login(const char *valstr); static const char *conf_get_kick_old_login(void); static int conf_setdef_kick_old_login(void); static int conf_set_ask_new_channel(const char *valstr); static const char *conf_get_ask_new_channel(void); static int conf_setdef_ask_new_channel(void); static int conf_set_hide_pass_games(const char *valstr); static const char *conf_get_hide_pass_games(void); static int conf_setdef_hide_pass_games(void); static int conf_set_hide_started_games(const char *valstr); static const char *conf_get_hide_started_games(void); static int conf_setdef_hide_started_games(void); static int conf_set_hide_temp_channels(const char *valstr); static const char *conf_get_hide_temp_channels(void); static int conf_setdef_hide_temp_channels(void); static int conf_set_hide_addr(const char *valstr); static const char *conf_get_hide_addr(void); static int conf_setdef_hide_addr(void); static int conf_set_enable_conn_all(const char *valstr); static const char *conf_get_enable_conn_all(void); static int conf_setdef_enable_conn_all(void); static int conf_set_extra_commands(const char *valstr); static const char *conf_get_extra_commands(void); static int conf_setdef_extra_commands(void); static int conf_set_reportdir(const char *valstr); static const char *conf_get_reportdir(void); static int conf_setdef_reportdir(void); static int conf_set_report_all_games(const char *valstr); static const char *conf_get_report_all_games(void); static int conf_setdef_report_all_games(void); static int conf_set_report_diablo_games(const char *valstr); static const char *conf_get_report_diablo_games(void); static int conf_setdef_report_diablo_games(void); static int conf_set_iconfile(const char *valstr); static const char *conf_get_iconfile(void); static int conf_setdef_iconfile(void); static int conf_set_war3_iconfile(const char *valstr); static const char *conf_get_war3_iconfile(void); static int conf_setdef_war3_iconfile(void); static int conf_set_star_iconfile(const char *valstr); static const char *conf_get_star_iconfile(void); static int conf_setdef_star_iconfile(void); static int conf_set_tosfile(const char *valstr); static const char *conf_get_tosfile(void); static int conf_setdef_tosfile(void); static int conf_set_mpqfile(const char *valstr); static const char *conf_get_mpqfile(void); static int conf_setdef_mpqfile(void); static int conf_set_trackaddrs(const char *valstr); static const char *conf_get_trackaddrs(void); static int conf_setdef_trackaddrs(void); static int conf_set_servaddrs(const char *valstr); static const char *conf_get_servaddrs(void); static int conf_setdef_servaddrs(void); static int conf_set_w3routeaddr(const char *valstr); static const char *conf_get_w3routeaddr(void); static int conf_setdef_w3routeaddr(void); static int conf_set_ircaddrs(const char *valstr); static const char *conf_get_ircaddrs(void); static int conf_setdef_ircaddrs(void); static int conf_set_use_keepalive(const char *valstr); static const char *conf_get_use_keepalive(void); static int conf_setdef_use_keepalive(void); static int conf_set_udptest_port(const char *valstr); static const char *conf_get_udptest_port(void); static int conf_setdef_udptest_port(void); static int conf_set_ipbanfile(const char *valstr); static const char *conf_get_ipbanfile(void); static int conf_setdef_ipbanfile(void); static int conf_set_disc_is_loss(const char *valstr); static const char *conf_get_disc_is_loss(void); static int conf_setdef_disc_is_loss(void); static int conf_set_helpfile(const char *valstr); static const char *conf_get_helpfile(void); static int conf_setdef_helpfile(void); static int conf_set_fortunecmd(const char *valstr); static const char *conf_get_fortunecmd(void); static int conf_setdef_fortunecmd(void); static int conf_set_transfile(const char *valstr); static const char *conf_get_transfile(void); static int conf_setdef_transfile(void); static int conf_set_chanlog(const char *valstr); static const char *conf_get_chanlog(void); static int conf_setdef_chanlog(void); static int conf_set_chanlogdir(const char *valstr); static const char *conf_get_chanlogdir(void); static int conf_setdef_chanlogdir(void); static int conf_set_quota(const char *valstr); static const char *conf_get_quota(void); static int conf_setdef_quota(void); static int conf_set_quota_lines(const char *valstr); static const char *conf_get_quota_lines(void); static int conf_setdef_quota_lines(void); static int conf_set_quota_time(const char *valstr); static const char *conf_get_quota_time(void); static int conf_setdef_quota_time(void); static int conf_set_quota_wrapline(const char *valstr); static const char *conf_get_quota_wrapline(void); static int conf_setdef_quota_wrapline(void); static int conf_set_quota_maxline(const char *valstr); static const char *conf_get_quota_maxline(void); static int conf_setdef_quota_maxline(void); static int conf_set_ladder_init_rating(const char *valstr); static const char *conf_get_ladder_init_rating(void); static int conf_setdef_ladder_init_rating(void); static int conf_set_quota_dobae(const char *valstr); static const char *conf_get_quota_dobae(void); static int conf_setdef_quota_dobae(void); static int conf_set_realmfile(const char *valstr); static const char *conf_get_realmfile(void); static int conf_setdef_realmfile(void); static int conf_set_issuefile(const char *valstr); static const char *conf_get_issuefile(void); static int conf_setdef_issuefile(void); static int conf_set_effective_user(const char *valstr); static const char *conf_get_effective_user(void); static int conf_setdef_effective_user(void); static int conf_set_effective_group(const char *valstr); static const char *conf_get_effective_group(void); static int conf_setdef_effective_group(void); static int conf_set_nullmsg(const char *valstr); static const char *conf_get_nullmsg(void); static int conf_setdef_nullmsg(void); static int conf_set_mail_support(const char *valstr); static const char *conf_get_mail_support(void); static int conf_setdef_mail_support(void); static int conf_set_mail_quota(const char *valstr); static const char *conf_get_mail_quota(void); static int conf_setdef_mail_quota(void); static int conf_set_maildir(const char *valstr); static const char *conf_get_maildir(void); static int conf_setdef_maildir(void); static int conf_set_log_notice(const char *valstr); static const char *conf_get_log_notice(void); static int conf_setdef_log_notice(void); static int conf_set_savebyname(const char *valstr); static const char *conf_get_savebyname(void); static int conf_setdef_savebyname(void); static int conf_set_skip_versioncheck(const char *valstr); static const char *conf_get_skip_versioncheck(void); static int conf_setdef_skip_versioncheck(void); static int conf_set_allow_bad_version(const char *valstr); static const char *conf_get_allow_bad_version(void); static int conf_setdef_allow_bad_version(void); static int conf_set_allow_unknown_version(const char *valstr); static const char *conf_get_allow_unknown_version(void); static int conf_setdef_allow_unknown_version(void); static int conf_set_versioncheck_file(const char *valstr); static const char *conf_get_versioncheck_file(void); static int conf_setdef_versioncheck_file(void); static int conf_set_d2cs_version(const char *valstr); static const char *conf_get_d2cs_version(void); static int conf_setdef_d2cs_version(void); static int conf_set_allow_d2cs_setname(const char *valstr); static const char *conf_get_allow_d2cs_setname(void); static int conf_setdef_allow_d2cs_setname(void); static int conf_set_hashtable_size(const char *valstr); static const char *conf_get_hashtable_size(void); static int conf_setdef_hashtable_size(void); static int conf_set_telnetaddrs(const char *valstr); static const char *conf_get_telnetaddrs(void); static int conf_setdef_telnetaddrs(void); static int conf_set_ipban_check_int(const char *valstr); static const char *conf_get_ipban_check_int(void); static int conf_setdef_ipban_check_int(void); static int conf_set_version_exeinfo_match(const char *valstr); static const char *conf_get_version_exeinfo_match(void); static int conf_setdef_version_exeinfo_match(void); static int conf_set_version_exeinfo_maxdiff(const char *valstr); static const char *conf_get_version_exeinfo_maxdiff(void); static int conf_setdef_version_exeinfo_maxdiff(void); static int conf_set_max_concurrent_logins(const char *valstr); static const char *conf_get_max_concurrent_logins(void); static int conf_setdef_max_concurrent_logins(void); static int conf_set_server_info(const char *valstr); static const char *conf_get_server_info(void); static int conf_setdef_server_info(void); static int conf_set_mapsfile(const char *valstr); static const char *conf_get_mapsfile(void); static int conf_setdef_mapsfile(void); static int conf_set_xplevelfile(const char *valstr); static const char *conf_get_xplevelfile(void); static int conf_setdef_xplevelfile(void); static int conf_set_xpcalcfile(const char *valstr); static const char *conf_get_xpcalcfile(void); static int conf_setdef_xpcalcfile(void); static int conf_set_initkill_timer(const char *valstr); static const char *conf_get_initkill_timer(void); static int conf_setdef_initkill_timer(void); static int conf_set_war3_ladder_update_secs(const char *valstr); static const char *conf_get_war3_ladder_update_secs(void); static int conf_setdef_war3_ladder_update_secs(void); static int conf_set_output_update_secs(const char *valstr); static const char *conf_get_output_update_secs(void); static int conf_setdef_output_update_secs(void); static int conf_set_ladderdir(const char *valstr); static const char *conf_get_ladderdir(void); static int conf_setdef_ladderdir(void); static int conf_set_statusdir(const char *valstr); static const char *conf_get_statusdir(void); static int conf_setdef_statusdir(void); static int conf_set_XML_output_ladder(const char *valstr); static const char *conf_get_XML_output_ladder(void); static int conf_setdef_XML_output_ladder(void); static int conf_set_XML_status_output(const char *valstr); static const char *conf_get_XML_status_output(void); static int conf_setdef_XML_status_output(void); static int conf_set_account_allowed_symbols(const char *valstr); static const char *conf_get_account_allowed_symbols(void); static int conf_setdef_account_allowed_symbols(void); static int conf_set_account_force_username(const char *valstr); static const char *conf_get_account_force_username(void); static int conf_setdef_account_force_username(void); static int conf_set_command_groups_file(const char *valstr); static const char *conf_get_command_groups_file(void); static int conf_setdef_command_groups_file(void); static int conf_set_tournament_file(const char *valstr); static const char *conf_get_tournament_file(void); static int conf_setdef_tournament_file(void); static int conf_set_aliasfile(const char *valstr); static const char *conf_get_aliasfile(void); static int conf_setdef_aliasfile(void); static int conf_set_anongame_infos_file(const char *valstr); static const char *conf_get_anongame_infos_file(void); static int conf_setdef_anongame_infos_file(void); static int conf_set_max_conns_per_IP(const char *valstr); static const char *conf_get_max_conns_per_IP(void); static int conf_setdef_max_conns_per_IP(void); static int conf_set_max_friends(const char *valstr); static const char *conf_get_max_friends(void); static int conf_setdef_max_friends(void); static int conf_set_clan_newer_time(const char *valstr); static const char *conf_get_clan_newer_time(void); static int conf_setdef_clan_newer_time(void); static int conf_set_clan_max_members(const char *valstr); static const char *conf_get_clan_max_members(void); static int conf_setdef_clan_max_members(void); static int conf_set_clan_channel_default_private(const char *valstr); static const char *conf_get_clan_channel_default_private(void); static int conf_setdef_clan_channel_default_private(void); static int conf_set_passfail_count(const char *valstr); static const char *conf_get_passfail_count(void); static int conf_setdef_passfail_count(void); static int conf_set_passfail_bantime(const char *valstr); static const char *conf_get_passfail_bantime(void); static int conf_setdef_passfail_bantime(void); static int conf_set_maxusers_per_channel(const char *valstr); static const char *conf_get_maxusers_per_channel(void); static int conf_setdef_maxusers_per_channel(void); static int conf_set_allowed_clients(const char *valstr); static const char *conf_get_allowed_clients(void); static int conf_setdef_allowed_clients(void); static int conf_set_ladder_games(const char *valstr); static const char *conf_get_ladder_games(void); static int conf_setdef_ladder_games(void); static int conf_set_max_connections(const char *valstr); static const char *conf_get_max_connections(void); static int conf_setdef_max_connections(void); static int conf_set_sync_on_logoff(const char *valstr); static const char *conf_get_sync_on_logoff(void); static int conf_setdef_sync_on_logoff(void); static int conf_set_ladder_prefix(const char *valstr); static const char *conf_get_ladder_prefix(void); static int conf_setdef_ladder_prefix(void); static int conf_setdef_irc_network_name(void); static int conf_set_irc_network_name(const char *valstr); static const char *conf_get_irc_network_name(void); static int conf_setdef_wol_addrs(void); static int conf_set_wol_addrs(const char *valstr); static const char *conf_get_wol_addrs(void); static int conf_set_wol_timezone(const char *valstr); static const char *conf_get_wol_timezone(void); static int conf_setdef_wol_timezone(void); static int conf_set_wol_longitude(const char *valstr); static const char *conf_get_wol_longitude(void); static int conf_setdef_wol_longitude(void); static int conf_set_wol_latitude(const char *valstr); static const char *conf_get_wol_latitude(void); static int conf_setdef_wol_latitude(void); /* directive set method get method */ static t_conf_entry conf_table[] = { { "filedir", conf_set_filedir, conf_get_filedir, conf_setdef_filedir}, { "storage_path", conf_set_storage_path, conf_get_storage_path, conf_setdef_storage_path}, { "logfile", conf_set_logfile, conf_get_logfile, conf_setdef_logfile}, { "loglevels", conf_set_loglevels, conf_get_loglevels, conf_setdef_loglevels}, { "motdfile", conf_set_motdfile, conf_get_motdfile, conf_setdef_motdfile}, { "newsfile", conf_set_newsfile, conf_get_newsfile, conf_setdef_newsfile}, { "channelfile", conf_set_channelfile, conf_get_channelfile, conf_setdef_channelfile}, { "pidfile", conf_set_pidfile, conf_get_pidfile, conf_setdef_pidfile}, { "adfile", conf_set_adfile, conf_get_adfile, conf_setdef_adfile}, { "topicfile", conf_set_topicfile, conf_get_topicfile, conf_setdef_topicfile}, { "DBlayoutfile", conf_set_DBlayoutfile, conf_get_DBlayoutfile, conf_setdef_DBlayoutfile}, { "supportfile", conf_set_supportfile, conf_get_supportfile, conf_setdef_supportfile}, { "usersync", conf_set_usersync, conf_get_usersync, conf_setdef_usersync}, { "userflush", conf_set_userflush, conf_get_userflush, conf_setdef_userflush}, { "userstep", conf_set_userstep, conf_get_userstep, conf_setdef_userstep}, { "servername", conf_set_servername, conf_get_servername, conf_setdef_servername}, { "hostname", conf_set_hostname, conf_get_hostname, conf_setdef_hostname}, { "track", conf_set_track, conf_get_track, conf_setdef_track}, { "location", conf_set_location, conf_get_location, conf_setdef_location}, { "description", conf_set_description, conf_get_description, conf_setdef_description}, { "url", conf_set_url, conf_get_url, conf_setdef_url}, { "contact_name", conf_set_contact_name, conf_get_contact_name, conf_setdef_contact_name}, { "contact_email", conf_set_contact_email, conf_get_contact_email,conf_setdef_contact_email}, { "latency", conf_set_latency, conf_get_latency, conf_setdef_latency}, { "irc_latency", conf_set_irc_latency, conf_get_irc_latency, conf_setdef_irc_latency}, { "shutdown_delay", conf_set_shutdown_delay, conf_get_shutdown_delay,conf_setdef_shutdown_delay}, { "shutdown_decr", conf_set_shutdown_decr, conf_get_shutdown_decr,conf_setdef_shutdown_decr}, { "new_accounts", conf_set_new_accounts, conf_get_new_accounts, conf_setdef_new_accounts}, { "max_accounts", conf_set_max_accounts, conf_get_max_accounts, conf_setdef_max_accounts}, { "kick_old_login", conf_set_kick_old_login, conf_get_kick_old_login,conf_setdef_kick_old_login}, { "ask_new_channel", conf_set_ask_new_channel, conf_get_ask_new_channel,conf_setdef_ask_new_channel}, { "hide_pass_games", conf_set_hide_pass_games, conf_get_hide_pass_games,conf_setdef_hide_pass_games}, { "hide_started_games", conf_set_hide_started_games, conf_get_hide_started_games,conf_setdef_hide_started_games}, { "hide_temp_channels", conf_set_hide_temp_channels, conf_get_hide_temp_channels,conf_setdef_hide_temp_channels}, { "hide_addr", conf_set_hide_addr, conf_get_hide_addr, conf_setdef_hide_addr}, { "enable_conn_all", conf_set_enable_conn_all, conf_get_enable_conn_all,conf_setdef_enable_conn_all}, { "extra_commands", conf_set_extra_commands, conf_get_extra_commands,conf_setdef_extra_commands}, { "reportdir", conf_set_reportdir, conf_get_reportdir, conf_setdef_reportdir}, { "report_all_games", conf_set_report_all_games, conf_get_report_all_games,conf_setdef_report_all_games}, { "report_diablo_games", conf_set_report_diablo_games, conf_get_report_diablo_games,conf_setdef_report_diablo_games}, { "iconfile", conf_set_iconfile, conf_get_iconfile, conf_setdef_iconfile}, { "war3_iconfile", conf_set_war3_iconfile, conf_get_war3_iconfile,conf_setdef_war3_iconfile}, { "star_iconfile", conf_set_star_iconfile, conf_get_star_iconfile,conf_setdef_star_iconfile}, { "tosfile", conf_set_tosfile, conf_get_tosfile, conf_setdef_tosfile}, { "mpqfile", conf_set_mpqfile, conf_get_mpqfile, conf_setdef_mpqfile}, { "trackaddrs", conf_set_trackaddrs, conf_get_trackaddrs, conf_setdef_trackaddrs}, { "servaddrs", conf_set_servaddrs, conf_get_servaddrs, conf_setdef_servaddrs}, { "w3routeaddr", conf_set_w3routeaddr, conf_get_w3routeaddr, conf_setdef_w3routeaddr}, { "ircaddrs", conf_set_ircaddrs, conf_get_ircaddrs, conf_setdef_ircaddrs}, { "use_keepalive", conf_set_use_keepalive, conf_get_use_keepalive,conf_setdef_use_keepalive}, { "udptest_port", conf_set_udptest_port, conf_get_udptest_port, conf_setdef_udptest_port}, { "ipbanfile", conf_set_ipbanfile, conf_get_ipbanfile, conf_setdef_ipbanfile}, { "disc_is_loss", conf_set_disc_is_loss, conf_get_disc_is_loss, conf_setdef_disc_is_loss}, { "helpfile", conf_set_helpfile, conf_get_helpfile, conf_setdef_helpfile}, { "fortunecmd", conf_set_fortunecmd, conf_get_fortunecmd, conf_setdef_fortunecmd}, { "transfile", conf_set_transfile, conf_get_transfile, conf_setdef_transfile}, { "chanlog", conf_set_chanlog, conf_get_chanlog, conf_setdef_chanlog}, { "chanlogdir", conf_set_chanlogdir, conf_get_chanlogdir, conf_setdef_chanlogdir}, { "quota", conf_set_quota, conf_get_quota, conf_setdef_quota}, { "quota_lines", conf_set_quota_lines, conf_get_quota_lines, conf_setdef_quota_lines}, { "quota_time", conf_set_quota_time, conf_get_quota_time, conf_setdef_quota_time}, { "quota_wrapline", conf_set_quota_wrapline, conf_get_quota_wrapline,conf_setdef_quota_wrapline}, { "quota_maxline", conf_set_quota_maxline, conf_get_quota_maxline,conf_setdef_quota_maxline}, { "ladder_init_rating", conf_set_ladder_init_rating, conf_get_ladder_init_rating,conf_setdef_ladder_init_rating}, { "quota_dobae", conf_set_quota_dobae, conf_get_quota_dobae, conf_setdef_quota_dobae}, { "realmfile", conf_set_realmfile, conf_get_realmfile, conf_setdef_realmfile}, { "issuefile", conf_set_issuefile, conf_get_issuefile, conf_setdef_issuefile}, { "effective_user", conf_set_effective_user, conf_get_effective_user,conf_setdef_effective_user}, { "effective_group", conf_set_effective_group, conf_get_effective_group,conf_setdef_effective_group}, { "nullmsg", conf_set_nullmsg, conf_get_nullmsg, conf_setdef_nullmsg}, { "mail_support", conf_set_mail_support, conf_get_mail_support, conf_setdef_mail_support}, { "mail_quota", conf_set_mail_quota, conf_get_mail_quota, conf_setdef_mail_quota}, { "maildir", conf_set_maildir, conf_get_maildir, conf_setdef_maildir}, { "log_notice", conf_set_log_notice, conf_get_log_notice, conf_setdef_log_notice}, { "savebyname", conf_set_savebyname, conf_get_savebyname, conf_setdef_savebyname}, { "skip_versioncheck", conf_set_skip_versioncheck, conf_get_skip_versioncheck,conf_setdef_skip_versioncheck}, { "allow_bad_version", conf_set_allow_bad_version, conf_get_allow_bad_version,conf_setdef_allow_bad_version}, { "allow_unknown_version", conf_set_allow_unknown_version,conf_get_allow_unknown_version,conf_setdef_allow_unknown_version}, { "versioncheck_file", conf_set_versioncheck_file, conf_get_versioncheck_file,conf_setdef_versioncheck_file}, { "d2cs_version", conf_set_d2cs_version, conf_get_d2cs_version, conf_setdef_d2cs_version}, { "allow_d2cs_setname", conf_set_allow_d2cs_setname, conf_get_allow_d2cs_setname,conf_setdef_allow_d2cs_setname}, { "hashtable_size", conf_set_hashtable_size, conf_get_hashtable_size,conf_setdef_hashtable_size}, { "telnetaddrs", conf_set_telnetaddrs, conf_get_telnetaddrs, conf_setdef_telnetaddrs}, { "ipban_check_int", conf_set_ipban_check_int, conf_get_ipban_check_int,conf_setdef_ipban_check_int}, { "version_exeinfo_match", conf_set_version_exeinfo_match,conf_get_version_exeinfo_match,conf_setdef_version_exeinfo_match}, { "version_exeinfo_maxdiff",conf_set_version_exeinfo_maxdiff,conf_get_version_exeinfo_maxdiff,conf_setdef_version_exeinfo_maxdiff}, { "max_concurrent_logins", conf_set_max_concurrent_logins,conf_get_max_concurrent_logins,conf_setdef_max_concurrent_logins}, { "server_info", conf_set_server_info, conf_get_server_info, conf_setdef_server_info}, { "mapsfile", conf_set_mapsfile, conf_get_mapsfile, conf_setdef_mapsfile}, { "xplevelfile", conf_set_xplevelfile, conf_get_xplevelfile, conf_setdef_xplevelfile}, { "xpcalcfile", conf_set_xpcalcfile, conf_get_xpcalcfile, conf_setdef_xpcalcfile}, { "initkill_timer", conf_set_initkill_timer, conf_get_initkill_timer,conf_setdef_initkill_timer}, { "war3_ladder_update_secs",conf_set_war3_ladder_update_secs,conf_get_war3_ladder_update_secs,conf_setdef_war3_ladder_update_secs}, { "output_update_secs", conf_set_output_update_secs, conf_get_output_update_secs,conf_setdef_output_update_secs}, { "ladderdir", conf_set_ladderdir, conf_get_ladderdir, conf_setdef_ladderdir}, { "statusdir", conf_set_statusdir, conf_get_statusdir, conf_setdef_statusdir}, { "XML_output_ladder", conf_set_XML_output_ladder, conf_get_XML_output_ladder,conf_setdef_XML_output_ladder}, { "XML_status_output", conf_set_XML_status_output, conf_get_XML_status_output,conf_setdef_XML_status_output}, { "account_allowed_symbols",conf_set_account_allowed_symbols,conf_get_account_allowed_symbols,conf_setdef_account_allowed_symbols}, { "account_force_username", conf_set_account_force_username,conf_get_account_force_username,conf_setdef_account_force_username}, { "command_groups_file", conf_set_command_groups_file, conf_get_command_groups_file,conf_setdef_command_groups_file}, { "tournament_file", conf_set_tournament_file, conf_get_tournament_file,conf_setdef_tournament_file}, { "aliasfile" , conf_set_aliasfile, conf_get_aliasfile, conf_setdef_aliasfile}, { "anongame_infos_file", conf_set_anongame_infos_file, conf_get_anongame_infos_file,conf_setdef_anongame_infos_file}, { "max_conns_per_IP", conf_set_max_conns_per_IP, conf_get_max_conns_per_IP,conf_setdef_max_conns_per_IP}, { "max_friends", conf_set_max_friends, conf_get_max_friends, conf_setdef_max_friends}, { "clan_newer_time", conf_set_clan_newer_time, conf_get_clan_newer_time,conf_setdef_clan_newer_time}, { "clan_max_members", conf_set_clan_max_members, conf_get_clan_max_members,conf_setdef_clan_max_members}, { "clan_channel_default_private",conf_set_clan_channel_default_private,conf_get_clan_channel_default_private,conf_setdef_clan_channel_default_private}, { "passfail_count", conf_set_passfail_count, conf_get_passfail_count,conf_setdef_passfail_count}, { "passfail_bantime", conf_set_passfail_bantime, conf_get_passfail_bantime,conf_setdef_passfail_bantime}, { "maxusers_per_channel", conf_set_maxusers_per_channel, conf_get_maxusers_per_channel,conf_setdef_maxusers_per_channel}, { "allowed_clients", conf_set_allowed_clients, conf_get_allowed_clients,conf_setdef_allowed_clients}, { "ladder_games", conf_set_ladder_games, conf_get_ladder_games, conf_setdef_ladder_games}, { "max_connections", conf_set_max_connections, conf_get_max_connections,conf_setdef_max_connections}, { "sync_on_logoff", conf_set_sync_on_logoff, conf_get_sync_on_logoff,conf_setdef_sync_on_logoff}, { "ladder_prefix", conf_set_ladder_prefix, conf_get_ladder_prefix,conf_setdef_ladder_prefix}, { "irc_network_name", conf_set_irc_network_name, conf_get_irc_network_name, conf_setdef_irc_network_name}, { "woladdrs", conf_set_wol_addrs, conf_get_wol_addrs, conf_setdef_wol_addrs}, { "woltimezone", conf_set_wol_timezone, conf_get_wol_timezone, conf_setdef_wol_timezone}, { "wollongitude", conf_set_wol_longitude, conf_get_wol_longitude, conf_setdef_wol_longitude}, { "wollatitude", conf_set_wol_latitude, conf_get_wol_latitude, conf_setdef_wol_latitude}, { NULL, NULL, NULL, NONE}, }; extern int prefs_load(char const * filename) { FILE *fd; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } fd = fopen(filename,"rt"); if (!fd) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file '%s'",filename); return -1; } if (conf_load_file(fd,conf_table)) { eventlog(eventlog_level_error,__FUNCTION__,"error loading config file '%s'",filename); fclose(fd); return -1; } fclose(fd); return 0; } extern void prefs_unload(void) { conf_unload(conf_table); } extern char const * prefs_get_storage_path(void) { return prefs_runtime_config.storage_path; } static int conf_set_storage_path(const char *valstr) { return conf_set_str(&prefs_runtime_config.storage_path,valstr,NULL); } static int conf_setdef_storage_path(void) { return conf_set_str(&prefs_runtime_config.storage_path,NULL,BNETD_STORAGE_PATH); } static const char* conf_get_storage_path(void) { return prefs_runtime_config.storage_path; } extern char const * prefs_get_filedir(void) { return prefs_runtime_config.filedir; } static int conf_set_filedir(const char *valstr) { return conf_set_str(&prefs_runtime_config.filedir,valstr,NULL); } static int conf_setdef_filedir(void) { return conf_set_str(&prefs_runtime_config.filedir,NULL,BNETD_FILE_DIR); } static const char* conf_get_filedir(void) { return prefs_runtime_config.filedir; } extern char const * prefs_get_logfile(void) { return prefs_runtime_config.logfile; } static int conf_set_logfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.logfile,valstr,NULL); } static int conf_setdef_logfile(void) { return conf_set_str(&prefs_runtime_config.logfile,NULL,BNETD_LOG_FILE); } static const char* conf_get_logfile(void) { return prefs_runtime_config.logfile; } extern char const * prefs_get_loglevels(void) { return prefs_runtime_config.loglevels; } static int conf_set_loglevels(const char *valstr) { return conf_set_str(&prefs_runtime_config.loglevels,valstr,NULL); } static int conf_setdef_loglevels(void) { return conf_set_str(&prefs_runtime_config.loglevels,NULL,BNETD_LOG_LEVELS); } static const char* conf_get_loglevels(void) { return prefs_runtime_config.loglevels; } extern char const * prefs_get_motdfile(void) { return prefs_runtime_config.motdfile; } static int conf_set_motdfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.motdfile,valstr,NULL); } static int conf_setdef_motdfile(void) { return conf_set_str(&prefs_runtime_config.motdfile,NULL,BNETD_MOTD_FILE); } static const char* conf_get_motdfile(void) { return prefs_runtime_config.motdfile; } extern char const * prefs_get_newsfile(void) { return prefs_runtime_config.newsfile; } static int conf_set_newsfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.newsfile,valstr,NULL); } static int conf_setdef_newsfile(void) { return conf_set_str(&prefs_runtime_config.newsfile,NULL,BNETD_NEWS_DIR); } static const char* conf_get_newsfile(void) { return prefs_runtime_config.newsfile; } extern char const * prefs_get_adfile(void) { return prefs_runtime_config.adfile; } static int conf_set_adfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.adfile,valstr,NULL); } static int conf_setdef_adfile(void) { return conf_set_str(&prefs_runtime_config.adfile,NULL,BNETD_AD_FILE); } static const char* conf_get_adfile(void) { return prefs_runtime_config.adfile; } extern char const * prefs_get_topicfile(void) { return prefs_runtime_config.topicfile; } static int conf_set_topicfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.topicfile,valstr,NULL); } static int conf_setdef_topicfile(void) { return conf_set_str(&prefs_runtime_config.topicfile,NULL,BNETD_TOPIC_FILE); } static const char* conf_get_topicfile(void) { return prefs_runtime_config.topicfile; } extern char const * prefs_get_DBlayoutfile(void) { return prefs_runtime_config.DBlayoutfile; } static int conf_set_DBlayoutfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.DBlayoutfile,valstr,NULL); } static int conf_setdef_DBlayoutfile(void) { return conf_set_str(&prefs_runtime_config.DBlayoutfile,NULL,BNETD_DBLAYOUT_FILE); } static const char* conf_get_DBlayoutfile(void) { return prefs_runtime_config.DBlayoutfile; } extern unsigned int prefs_get_user_sync_timer(void) { return prefs_runtime_config.usersync; } static int conf_set_usersync(const char *valstr) { return conf_set_int(&prefs_runtime_config.usersync,valstr,0); } static int conf_setdef_usersync(void) { return conf_set_int(&prefs_runtime_config.usersync,NULL,BNETD_USERSYNC); } static const char* conf_get_usersync(void) { return conf_get_int(prefs_runtime_config.usersync); } extern unsigned int prefs_get_user_flush_timer(void) { return prefs_runtime_config.userflush; } static int conf_set_userflush(const char *valstr) { return conf_set_int(&prefs_runtime_config.userflush,valstr,0); } static int conf_setdef_userflush(void) { return conf_set_int(&prefs_runtime_config.userflush,NULL,BNETD_USERFLUSH); } static const char* conf_get_userflush(void) { return conf_get_int(prefs_runtime_config.userflush); } extern unsigned int prefs_get_user_step(void) { return prefs_runtime_config.userstep; } static int conf_set_userstep(const char *valstr) { return conf_set_int(&prefs_runtime_config.userstep,valstr,0); } static int conf_setdef_userstep(void) { return conf_set_int(&prefs_runtime_config.userstep,NULL,BNETD_USERSTEP); } static const char* conf_get_userstep(void) { return conf_get_int(prefs_runtime_config.userstep); } extern char const * prefs_get_servername(void) { return prefs_runtime_config.servername; } static int conf_set_servername(const char *valstr) { return conf_set_str(&prefs_runtime_config.servername,valstr,NULL); } static int conf_setdef_servername(void) { return conf_set_str(&prefs_runtime_config.servername,NULL,BNETD_SERVERNAME); } static const char* conf_get_servername(void) { return prefs_runtime_config.servername; } extern char const * prefs_get_hostname(void) { return prefs_runtime_config.hostname; } static int conf_set_hostname(const char *valstr) { return conf_set_str(&prefs_runtime_config.hostname,valstr,NULL); } static int conf_setdef_hostname(void) { return conf_set_str(&prefs_runtime_config.hostname,NULL,""); } static const char* conf_get_hostname(void) { return prefs_runtime_config.hostname; } extern unsigned int prefs_get_track(void) { return prefs_runtime_config.track; } static int conf_set_track(const char *valstr) { unsigned int rez; conf_set_int(&prefs_runtime_config.track,valstr,0); rez = prefs_runtime_config.track; if (rez>0 && rez<60) rez = 60; return 0; } static int conf_setdef_track(void) { return conf_set_int(&prefs_runtime_config.track,NULL,BNETD_TRACK_TIME); } static const char* conf_get_track(void) { return conf_get_int(prefs_runtime_config.track); } extern char const * prefs_get_location(void) { return prefs_runtime_config.location; } static int conf_set_location(const char *valstr) { return conf_set_str(&prefs_runtime_config.location,valstr,NULL); } static int conf_setdef_location(void) { return conf_set_str(&prefs_runtime_config.location,NULL,""); } static const char* conf_get_location(void) { return prefs_runtime_config.location; } extern char const * prefs_get_description(void) { return prefs_runtime_config.description; } static int conf_set_description(const char *valstr) { return conf_set_str(&prefs_runtime_config.description,valstr,NULL); } static int conf_setdef_description(void) { return conf_set_str(&prefs_runtime_config.description,NULL,""); } static const char* conf_get_description(void) { return prefs_runtime_config.description; } extern char const * prefs_get_url(void) { return prefs_runtime_config.url; } static int conf_set_url(const char *valstr) { return conf_set_str(&prefs_runtime_config.url,valstr,NULL); } static int conf_setdef_url(void) { return conf_set_str(&prefs_runtime_config.url,NULL,""); } static const char* conf_get_url(void) { return prefs_runtime_config.url; } extern char const * prefs_get_contact_name(void) { return prefs_runtime_config.contact_name; } static int conf_set_contact_name(const char *valstr) { return conf_set_str(&prefs_runtime_config.contact_name,valstr,NULL); } static int conf_setdef_contact_name(void) { return conf_set_str(&prefs_runtime_config.contact_name,NULL,""); } static const char* conf_get_contact_name(void) { return prefs_runtime_config.contact_name; } extern char const * prefs_get_contact_email(void) { return prefs_runtime_config.contact_email; } static int conf_set_contact_email(const char *valstr) { return conf_set_str(&prefs_runtime_config.contact_email,valstr,NULL); } static int conf_setdef_contact_email(void) { return conf_set_str(&prefs_runtime_config.contact_email,NULL,""); } static const char* conf_get_contact_email(void) { return prefs_runtime_config.contact_email; } extern unsigned int prefs_get_latency(void) { return prefs_runtime_config.latency; } static int conf_set_latency(const char *valstr) { return conf_set_int(&prefs_runtime_config.latency,valstr,0); } static int conf_setdef_latency(void) { return conf_set_int(&prefs_runtime_config.latency,NULL,BNETD_LATENCY); } static const char* conf_get_latency(void) { return conf_get_int(prefs_runtime_config.latency); } extern unsigned int prefs_get_irc_latency(void) { return prefs_runtime_config.irc_latency; } static int conf_set_irc_latency(const char *valstr) { return conf_set_int(&prefs_runtime_config.irc_latency,valstr,0); } static int conf_setdef_irc_latency(void) { return conf_set_int(&prefs_runtime_config.irc_latency,NULL,BNETD_IRC_LATENCY); } static const char* conf_get_irc_latency(void) { return conf_get_int(prefs_runtime_config.irc_latency); } extern unsigned int prefs_get_shutdown_delay(void) { return prefs_runtime_config.shutdown_delay; } static int conf_set_shutdown_delay(const char *valstr) { return conf_set_int(&prefs_runtime_config.shutdown_delay,valstr,0); } static int conf_setdef_shutdown_delay(void) { return conf_set_int(&prefs_runtime_config.shutdown_delay,NULL,BNETD_SHUTDELAY); } static const char* conf_get_shutdown_delay(void) { return conf_get_int(prefs_runtime_config.shutdown_delay); } extern unsigned int prefs_get_shutdown_decr(void) { return prefs_runtime_config.shutdown_decr; } static int conf_set_shutdown_decr(const char *valstr) { return conf_set_int(&prefs_runtime_config.shutdown_decr,valstr,0); } static int conf_setdef_shutdown_decr(void) { return conf_set_int(&prefs_runtime_config.shutdown_decr,NULL,BNETD_SHUTDECR); } static const char* conf_get_shutdown_decr(void) { return conf_get_int(prefs_runtime_config.shutdown_decr); } extern unsigned int prefs_get_allow_new_accounts(void) { return prefs_runtime_config.new_accounts; } static int conf_set_new_accounts(const char *valstr) { return conf_set_bool(&prefs_runtime_config.new_accounts,valstr,0); } static int conf_setdef_new_accounts(void) { return conf_set_bool(&prefs_runtime_config.new_accounts,NULL,1); } static const char* conf_get_new_accounts(void) { return conf_get_bool(prefs_runtime_config.new_accounts); } extern unsigned int prefs_get_max_accounts(void) { return prefs_runtime_config.max_accounts; } static int conf_set_max_accounts(const char *valstr) { return conf_set_int(&prefs_runtime_config.max_accounts,valstr,0); } static int conf_setdef_max_accounts(void) { return conf_set_int(&prefs_runtime_config.max_accounts,NULL,0); } static const char* conf_get_max_accounts(void) { return conf_get_int(prefs_runtime_config.max_accounts); } extern unsigned int prefs_get_kick_old_login(void) { return prefs_runtime_config.kick_old_login; } static int conf_set_kick_old_login(const char *valstr) { return conf_set_bool(&prefs_runtime_config.kick_old_login,valstr,0); } static int conf_setdef_kick_old_login(void) { return conf_set_bool(&prefs_runtime_config.kick_old_login,NULL,1); } static const char* conf_get_kick_old_login(void) { return conf_get_bool(prefs_runtime_config.kick_old_login); } extern char const * prefs_get_channelfile(void) { return prefs_runtime_config.channelfile; } static int conf_set_channelfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.channelfile,valstr,NULL); } static int conf_setdef_channelfile(void) { return conf_set_str(&prefs_runtime_config.channelfile,NULL,BNETD_CHANNEL_FILE); } static const char* conf_get_channelfile(void) { return prefs_runtime_config.channelfile; } extern unsigned int prefs_get_ask_new_channel(void) { return prefs_runtime_config.ask_new_channel; } static int conf_set_ask_new_channel(const char *valstr) { return conf_set_bool(&prefs_runtime_config.ask_new_channel,valstr,0); } static int conf_setdef_ask_new_channel(void) { return conf_set_bool(&prefs_runtime_config.ask_new_channel,NULL,1); } static const char* conf_get_ask_new_channel(void) { return conf_get_bool(prefs_runtime_config.ask_new_channel); } extern unsigned int prefs_get_hide_pass_games(void) { return prefs_runtime_config.hide_pass_games; } static int conf_set_hide_pass_games(const char *valstr) { return conf_set_bool(&prefs_runtime_config.hide_pass_games,valstr,0); } static int conf_setdef_hide_pass_games(void) { return conf_set_bool(&prefs_runtime_config.hide_pass_games,NULL,1); } static const char* conf_get_hide_pass_games(void) { return conf_get_bool(prefs_runtime_config.hide_pass_games); } extern unsigned int prefs_get_hide_started_games(void) { return prefs_runtime_config.hide_started_games; } static int conf_set_hide_started_games(const char *valstr) { return conf_set_bool(&prefs_runtime_config.hide_started_games,valstr,0); } static int conf_setdef_hide_started_games(void) { return conf_set_bool(&prefs_runtime_config.hide_started_games,NULL,1); } static const char* conf_get_hide_started_games(void) { return conf_get_bool(prefs_runtime_config.hide_started_games); } extern unsigned int prefs_get_hide_temp_channels(void) { return prefs_runtime_config.hide_temp_channels; } static int conf_set_hide_temp_channels(const char *valstr) { return conf_set_bool(&prefs_runtime_config.hide_temp_channels,valstr,0); } static int conf_setdef_hide_temp_channels(void) { return conf_set_bool(&prefs_runtime_config.hide_temp_channels,NULL,1); } static const char* conf_get_hide_temp_channels(void) { return conf_get_bool(prefs_runtime_config.hide_temp_channels); } extern unsigned prefs_get_hide_addr(void) { return prefs_runtime_config.hide_addr; } static int conf_set_hide_addr(const char *valstr) { return conf_set_bool(&prefs_runtime_config.hide_addr,valstr,0); } static int conf_setdef_hide_addr(void) { return conf_set_bool(&prefs_runtime_config.hide_addr,NULL,1); } static const char* conf_get_hide_addr(void) { return conf_get_bool(prefs_runtime_config.hide_addr); } extern unsigned int prefs_get_enable_conn_all(void) { return prefs_runtime_config.enable_conn_all; } static int conf_set_enable_conn_all(const char *valstr) { return conf_set_bool(&prefs_runtime_config.enable_conn_all,valstr,0); } static int conf_setdef_enable_conn_all(void) { return conf_set_bool(&prefs_runtime_config.enable_conn_all,NULL,0); } static const char* conf_get_enable_conn_all(void) { return conf_get_bool(prefs_runtime_config.enable_conn_all); } extern unsigned int prefs_get_extra_commands(void) { return prefs_runtime_config.extra_commands; } static int conf_set_extra_commands(const char *valstr) { return conf_set_bool(&prefs_runtime_config.extra_commands,valstr,0); } static int conf_setdef_extra_commands(void) { return conf_set_bool(&prefs_runtime_config.extra_commands,NULL,0); } static const char* conf_get_extra_commands(void) { return conf_get_bool(prefs_runtime_config.extra_commands); } extern char const * prefs_get_reportdir(void) { return prefs_runtime_config.reportdir; } static int conf_set_reportdir(const char *valstr) { return conf_set_str(&prefs_runtime_config.reportdir,valstr,NULL); } static int conf_setdef_reportdir(void) { return conf_set_str(&prefs_runtime_config.reportdir,NULL,BNETD_REPORT_DIR); } static const char* conf_get_reportdir(void) { return prefs_runtime_config.reportdir; } extern unsigned int prefs_get_report_all_games(void) { return prefs_runtime_config.report_all_games; } static int conf_set_report_all_games(const char *valstr) { return conf_set_bool(&prefs_runtime_config.report_all_games,valstr,0); } static int conf_setdef_report_all_games(void) { return conf_set_bool(&prefs_runtime_config.report_all_games,NULL,0); } static const char* conf_get_report_all_games(void) { return conf_get_bool(prefs_runtime_config.report_all_games); } extern unsigned int prefs_get_report_diablo_games(void) { return prefs_runtime_config.report_diablo_games; } static int conf_set_report_diablo_games(const char *valstr) { return conf_set_bool(&prefs_runtime_config.report_diablo_games,valstr,0); } static int conf_setdef_report_diablo_games(void) { return conf_set_bool(&prefs_runtime_config.report_diablo_games,NULL,0); } static const char* conf_get_report_diablo_games(void) { return conf_get_bool(prefs_runtime_config.report_diablo_games); } extern char const * prefs_get_pidfile(void) { return prefs_runtime_config.pidfile; } static int conf_set_pidfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.pidfile,valstr,NULL); } static int conf_setdef_pidfile(void) { return conf_set_str(&prefs_runtime_config.pidfile,NULL,BNETD_PID_FILE); } static const char* conf_get_pidfile(void) { return prefs_runtime_config.pidfile; } extern char const * prefs_get_iconfile(void) { return prefs_runtime_config.iconfile; } static int conf_set_iconfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.iconfile,valstr,NULL); } static int conf_setdef_iconfile(void) { return conf_set_str(&prefs_runtime_config.iconfile,NULL,BNETD_ICON_FILE); } static const char* conf_get_iconfile(void) { return prefs_runtime_config.iconfile; } extern char const * prefs_get_war3_iconfile(void) { return prefs_runtime_config.war3_iconfile; } static int conf_set_war3_iconfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.war3_iconfile,valstr,NULL); } static int conf_setdef_war3_iconfile(void) { return conf_set_str(&prefs_runtime_config.war3_iconfile,NULL,BNETD_WAR3_ICON_FILE); } static const char* conf_get_war3_iconfile(void) { return prefs_runtime_config.war3_iconfile; } extern char const * prefs_get_star_iconfile(void) { return prefs_runtime_config.star_iconfile; } static int conf_set_star_iconfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.star_iconfile,valstr,NULL); } static int conf_setdef_star_iconfile(void) { return conf_set_str(&prefs_runtime_config.star_iconfile,NULL,BNETD_STAR_ICON_FILE); } static const char* conf_get_star_iconfile(void) { return prefs_runtime_config.star_iconfile; } extern char const * prefs_get_tosfile(void) { return prefs_runtime_config.tosfile; } static int conf_set_tosfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.tosfile,valstr,NULL); } static int conf_setdef_tosfile(void) { return conf_set_str(&prefs_runtime_config.tosfile,NULL,BNETD_TOS_FILE); } static const char* conf_get_tosfile(void) { return prefs_runtime_config.tosfile; } extern char const * prefs_get_mpqfile(void) { return prefs_runtime_config.mpqfile; } static int conf_set_mpqfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.mpqfile,valstr,NULL); } static int conf_setdef_mpqfile(void) { return conf_set_str(&prefs_runtime_config.mpqfile,NULL,BNETD_MPQ_FILE); } static const char* conf_get_mpqfile(void) { return prefs_runtime_config.mpqfile; } extern char const * prefs_get_trackserv_addrs(void) { return prefs_runtime_config.trackaddrs; } static int conf_set_trackaddrs(const char *valstr) { return conf_set_str(&prefs_runtime_config.trackaddrs,valstr,NULL); } static int conf_setdef_trackaddrs(void) { return conf_set_str(&prefs_runtime_config.trackaddrs,NULL,BNETD_TRACK_ADDRS); } static const char* conf_get_trackaddrs(void) { return prefs_runtime_config.trackaddrs; } extern char const * prefs_get_bnetdserv_addrs(void) { return prefs_runtime_config.servaddrs; } static int conf_set_servaddrs(const char *valstr) { return conf_set_str(&prefs_runtime_config.servaddrs,valstr,NULL); } static int conf_setdef_servaddrs(void) { return conf_set_str(&prefs_runtime_config.servaddrs,NULL,BNETD_SERV_ADDRS); } static const char* conf_get_servaddrs(void) { return prefs_runtime_config.servaddrs; } extern char const * prefs_get_w3route_addr(void) { return prefs_runtime_config.w3routeaddr; } static int conf_set_w3routeaddr(const char *valstr) { return conf_set_str(&prefs_runtime_config.w3routeaddr,valstr,NULL); } static int conf_setdef_w3routeaddr(void) { return conf_set_str(&prefs_runtime_config.w3routeaddr,NULL,BNETD_W3ROUTE_ADDR); } static const char* conf_get_w3routeaddr(void) { return prefs_runtime_config.w3routeaddr; } extern char const * prefs_get_irc_addrs(void) { return prefs_runtime_config.ircaddrs; } static int conf_set_ircaddrs(const char *valstr) { return conf_set_str(&prefs_runtime_config.ircaddrs,valstr,NULL); } static int conf_setdef_ircaddrs(void) { return conf_set_str(&prefs_runtime_config.ircaddrs,NULL,BNETD_IRC_ADDRS); } static const char* conf_get_ircaddrs(void) { return prefs_runtime_config.ircaddrs; } extern unsigned int prefs_get_use_keepalive(void) { return prefs_runtime_config.use_keepalive; } static int conf_set_use_keepalive(const char *valstr) { return conf_set_bool(&prefs_runtime_config.use_keepalive,valstr,0); } static int conf_setdef_use_keepalive(void) { return conf_set_bool(&prefs_runtime_config.use_keepalive,NULL,0); } static const char* conf_get_use_keepalive(void) { return conf_get_bool(prefs_runtime_config.use_keepalive); } extern unsigned int prefs_get_udptest_port(void) { return prefs_runtime_config.udptest_port; } static int conf_set_udptest_port(const char *valstr) { return conf_set_int(&prefs_runtime_config.udptest_port,valstr,0); } static int conf_setdef_udptest_port(void) { return conf_set_int(&prefs_runtime_config.udptest_port,NULL,BNETD_DEF_TEST_PORT); } static const char* conf_get_udptest_port(void) { return conf_get_int(prefs_runtime_config.udptest_port); } extern char const * prefs_get_ipbanfile(void) { return prefs_runtime_config.ipbanfile; } static int conf_set_ipbanfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.ipbanfile,valstr,NULL); } static int conf_setdef_ipbanfile(void) { return conf_set_str(&prefs_runtime_config.ipbanfile,NULL,BNETD_IPBAN_FILE); } static const char* conf_get_ipbanfile(void) { return prefs_runtime_config.ipbanfile; } extern unsigned int prefs_get_discisloss(void) { return prefs_runtime_config.disc_is_loss; } static int conf_set_disc_is_loss(const char *valstr) { return conf_set_bool(&prefs_runtime_config.disc_is_loss,valstr,0); } static int conf_setdef_disc_is_loss(void) { return conf_set_bool(&prefs_runtime_config.disc_is_loss,NULL,0); } static const char* conf_get_disc_is_loss(void) { return conf_get_bool(prefs_runtime_config.disc_is_loss); } extern char const * prefs_get_helpfile(void) { return prefs_runtime_config.helpfile; } static int conf_set_helpfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.helpfile,valstr,NULL); } static int conf_setdef_helpfile(void) { return conf_set_str(&prefs_runtime_config.helpfile,NULL,BNETD_HELP_FILE); } static const char* conf_get_helpfile(void) { return prefs_runtime_config.helpfile; } extern char const * prefs_get_fortunecmd(void) { return prefs_runtime_config.fortunecmd; } static int conf_set_fortunecmd(const char *valstr) { return conf_set_str(&prefs_runtime_config.fortunecmd,valstr,NULL); } static int conf_setdef_fortunecmd(void) { return conf_set_str(&prefs_runtime_config.fortunecmd,NULL,BNETD_FORTUNECMD); } static const char* conf_get_fortunecmd(void) { return prefs_runtime_config.fortunecmd; } extern char const * prefs_get_transfile(void) { return prefs_runtime_config.transfile; } static int conf_set_transfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.transfile,valstr,NULL); } static int conf_setdef_transfile(void) { return conf_set_str(&prefs_runtime_config.transfile,NULL,BNETD_TRANS_FILE); } static const char* conf_get_transfile(void) { return prefs_runtime_config.transfile; } extern unsigned int prefs_get_chanlog(void) { return prefs_runtime_config.chanlog; } static int conf_set_chanlog(const char *valstr) { return conf_set_bool(&prefs_runtime_config.chanlog,valstr,0); } static int conf_setdef_chanlog(void) { return conf_set_bool(&prefs_runtime_config.chanlog,NULL,BNETD_CHANLOG); } static const char* conf_get_chanlog(void) { return conf_get_bool(prefs_runtime_config.chanlog); } extern char const * prefs_get_chanlogdir(void) { return prefs_runtime_config.chanlogdir; } static int conf_set_chanlogdir(const char *valstr) { return conf_set_str(&prefs_runtime_config.chanlogdir,valstr,NULL); } static int conf_setdef_chanlogdir(void) { return conf_set_str(&prefs_runtime_config.chanlogdir,NULL,BNETD_CHANLOG_DIR); } static const char* conf_get_chanlogdir(void) { return prefs_runtime_config.chanlogdir; } extern unsigned int prefs_get_quota(void) { return prefs_runtime_config.quota; } static int conf_set_quota(const char *valstr) { return conf_set_bool(&prefs_runtime_config.quota,valstr,0); } static int conf_setdef_quota(void) { return conf_set_bool(&prefs_runtime_config.quota,NULL,0); } static const char* conf_get_quota(void) { return conf_get_bool(prefs_runtime_config.quota); } extern unsigned int prefs_get_quota_lines(void) { unsigned int rez; rez=prefs_runtime_config.quota_lines; if (rez<1) rez = 1; if (rez>100) rez = 100; return rez; } static int conf_set_quota_lines(const char *valstr) { return conf_set_int(&prefs_runtime_config.quota_lines,valstr,0); } static int conf_setdef_quota_lines(void) { return conf_set_int(&prefs_runtime_config.quota_lines,NULL,BNETD_QUOTA_LINES); } static const char* conf_get_quota_lines(void) { return conf_get_int(prefs_runtime_config.quota_lines); } extern unsigned int prefs_get_quota_time(void) { unsigned int rez; rez=prefs_runtime_config.quota_time; if (rez<1) rez = 1; if (rez>10) rez = 60; return rez; } static int conf_set_quota_time(const char *valstr) { return conf_set_int(&prefs_runtime_config.quota_time,valstr,0); } static int conf_setdef_quota_time(void) { return conf_set_int(&prefs_runtime_config.quota_time,NULL,BNETD_QUOTA_TIME); } static const char* conf_get_quota_time(void) { return conf_get_int(prefs_runtime_config.quota_time); } extern unsigned int prefs_get_quota_wrapline(void) { unsigned int rez; rez=prefs_runtime_config.quota_wrapline; if (rez<1) rez = 1; if (rez>256) rez = 256; return rez; } static int conf_set_quota_wrapline(const char *valstr) { return conf_set_int(&prefs_runtime_config.quota_wrapline,valstr,0); } static int conf_setdef_quota_wrapline(void) { return conf_set_int(&prefs_runtime_config.quota_wrapline,NULL,BNETD_QUOTA_WLINE); } static const char* conf_get_quota_wrapline(void) { return conf_get_int(prefs_runtime_config.quota_wrapline); } extern unsigned int prefs_get_quota_maxline(void) { unsigned int rez; rez=prefs_runtime_config.quota_maxline; if (rez<1) rez = 1; if (rez>256) rez = 256; return rez; } static int conf_set_quota_maxline(const char *valstr) { return conf_set_int(&prefs_runtime_config.quota_maxline,valstr,0); } static int conf_setdef_quota_maxline(void) { return conf_set_int(&prefs_runtime_config.quota_maxline,NULL,BNETD_QUOTA_MLINE); } static const char* conf_get_quota_maxline(void) { return conf_get_int(prefs_runtime_config.quota_maxline); } extern unsigned int prefs_get_ladder_init_rating(void) { return prefs_runtime_config.ladder_init_rating; } static int conf_set_ladder_init_rating(const char *valstr) { return conf_set_int(&prefs_runtime_config.ladder_init_rating,valstr,0); } static int conf_setdef_ladder_init_rating(void) { return conf_set_int(&prefs_runtime_config.ladder_init_rating,NULL,BNETD_LADDER_INIT_RAT); } static const char* conf_get_ladder_init_rating(void) { return conf_get_int(prefs_runtime_config.ladder_init_rating); } extern unsigned int prefs_get_quota_dobae(void) { unsigned int rez; rez=prefs_runtime_config.quota_dobae; if (rez<1) rez = 1; if (rez>100) rez = 100; return rez; } static int conf_set_quota_dobae(const char *valstr) { return conf_set_int(&prefs_runtime_config.quota_dobae,valstr,0); } static int conf_setdef_quota_dobae(void) { return conf_set_int(&prefs_runtime_config.quota_dobae,NULL,BNETD_QUOTA_DOBAE); } static const char* conf_get_quota_dobae(void) { return conf_get_int(prefs_runtime_config.quota_dobae); } extern char const * prefs_get_realmfile(void) { return prefs_runtime_config.realmfile; } static int conf_set_realmfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.realmfile,valstr,NULL); } static int conf_setdef_realmfile(void) { return conf_set_str(&prefs_runtime_config.realmfile,NULL,BNETD_REALM_FILE); } static const char* conf_get_realmfile(void) { return prefs_runtime_config.realmfile; } extern char const * prefs_get_issuefile(void) { return prefs_runtime_config.issuefile; } static int conf_set_issuefile(const char *valstr) { return conf_set_str(&prefs_runtime_config.issuefile,valstr,NULL); } static int conf_setdef_issuefile(void) { return conf_set_str(&prefs_runtime_config.issuefile,NULL,BNETD_ISSUE_FILE); } static const char* conf_get_issuefile(void) { return prefs_runtime_config.issuefile; } extern char const * prefs_get_effective_user(void) { return prefs_runtime_config.effective_user; } static int conf_set_effective_user(const char *valstr) { return conf_set_str(&prefs_runtime_config.effective_user,valstr,NULL); } static int conf_setdef_effective_user(void) { return conf_set_str(&prefs_runtime_config.effective_user,NULL,NULL); } static const char* conf_get_effective_user(void) { return prefs_runtime_config.effective_user; } extern char const * prefs_get_effective_group(void) { return prefs_runtime_config.effective_group; } static int conf_set_effective_group(const char *valstr) { return conf_set_str(&prefs_runtime_config.effective_group,valstr,NULL); } static int conf_setdef_effective_group(void) { return conf_set_str(&prefs_runtime_config.effective_group,NULL,NULL); } static const char* conf_get_effective_group(void) { return prefs_runtime_config.effective_group; } extern unsigned int prefs_get_nullmsg(void) { return prefs_runtime_config.nullmsg; } static int conf_set_nullmsg(const char *valstr) { return conf_set_int(&prefs_runtime_config.nullmsg,valstr,0); } static int conf_setdef_nullmsg(void) { return conf_set_int(&prefs_runtime_config.nullmsg,NULL,BNETD_DEF_NULLMSG); } static const char* conf_get_nullmsg(void) { return conf_get_int(prefs_runtime_config.nullmsg); } extern unsigned int prefs_get_mail_support(void) { return prefs_runtime_config.mail_support; } static int conf_set_mail_support(const char *valstr) { return conf_set_bool(&prefs_runtime_config.mail_support,valstr,0); } static int conf_setdef_mail_support(void) { return conf_set_bool(&prefs_runtime_config.mail_support,NULL,BNETD_MAIL_SUPPORT); } static const char* conf_get_mail_support(void) { return conf_get_bool(prefs_runtime_config.mail_support); } extern unsigned int prefs_get_mail_quota(void) { unsigned int rez; rez=prefs_runtime_config.mail_quota; if (rez<1) rez = 1; if (rez>30) rez = 30; return rez; } static int conf_set_mail_quota(const char *valstr) { return conf_set_int(&prefs_runtime_config.mail_quota,valstr,0); } static int conf_setdef_mail_quota(void) { return conf_set_int(&prefs_runtime_config.mail_quota,NULL,BNETD_MAIL_QUOTA); } static const char* conf_get_mail_quota(void) { return conf_get_int(prefs_runtime_config.mail_quota); } extern char const * prefs_get_maildir(void) { return prefs_runtime_config.maildir; } static int conf_set_maildir(const char *valstr) { return conf_set_str(&prefs_runtime_config.maildir,valstr,NULL); } static int conf_setdef_maildir(void) { return conf_set_str(&prefs_runtime_config.maildir,NULL,BNETD_MAIL_DIR); } static const char* conf_get_maildir(void) { return prefs_runtime_config.maildir; } extern char const * prefs_get_log_notice(void) { return prefs_runtime_config.log_notice; } static int conf_set_log_notice(const char *valstr) { return conf_set_str(&prefs_runtime_config.log_notice,valstr,NULL); } static int conf_setdef_log_notice(void) { return conf_set_str(&prefs_runtime_config.log_notice,NULL,BNETD_LOG_NOTICE); } static const char* conf_get_log_notice(void) { return prefs_runtime_config.log_notice; } extern unsigned int prefs_get_savebyname(void) { return prefs_runtime_config.savebyname; } static int conf_set_savebyname(const char *valstr) { return conf_set_bool(&prefs_runtime_config.savebyname,valstr,0); } static int conf_setdef_savebyname(void) { return conf_set_bool(&prefs_runtime_config.savebyname,NULL,1); } static const char* conf_get_savebyname(void) { return conf_get_bool(prefs_runtime_config.savebyname); } extern unsigned int prefs_get_skip_versioncheck(void) { return prefs_runtime_config.skip_versioncheck; } static int conf_set_skip_versioncheck(const char *valstr) { return conf_set_bool(&prefs_runtime_config.skip_versioncheck,valstr,0); } static int conf_setdef_skip_versioncheck(void) { return conf_set_bool(&prefs_runtime_config.skip_versioncheck,NULL,0); } static const char* conf_get_skip_versioncheck(void) { return conf_get_bool(prefs_runtime_config.skip_versioncheck); } extern unsigned int prefs_get_allow_bad_version(void) { return prefs_runtime_config.allow_bad_version; } static int conf_set_allow_bad_version(const char *valstr) { return conf_set_bool(&prefs_runtime_config.allow_bad_version,valstr,0); } static int conf_setdef_allow_bad_version(void) { return conf_set_bool(&prefs_runtime_config.allow_bad_version,NULL,0); } static const char* conf_get_allow_bad_version(void) { return conf_get_bool(prefs_runtime_config.allow_bad_version); } extern unsigned int prefs_get_allow_unknown_version(void) { return prefs_runtime_config.allow_unknown_version; } static int conf_set_allow_unknown_version(const char *valstr) { return conf_set_bool(&prefs_runtime_config.allow_unknown_version,valstr,0); } static int conf_setdef_allow_unknown_version(void) { return conf_set_bool(&prefs_runtime_config.allow_unknown_version,NULL,0); } static const char* conf_get_allow_unknown_version(void) { return conf_get_bool(prefs_runtime_config.allow_unknown_version); } extern char const * prefs_get_versioncheck_file(void) { return prefs_runtime_config.versioncheck_file; } static int conf_set_versioncheck_file(const char *valstr) { return conf_set_str(&prefs_runtime_config.versioncheck_file,valstr,NULL); } static int conf_setdef_versioncheck_file(void) { return conf_set_str(&prefs_runtime_config.versioncheck_file,NULL,PVPGN_VERSIONCHECK); } static const char* conf_get_versioncheck_file(void) { return prefs_runtime_config.versioncheck_file; } extern unsigned int prefs_allow_d2cs_setname(void) { return prefs_runtime_config.allow_d2cs_setname; } static int conf_set_allow_d2cs_setname(const char *valstr) { return conf_set_bool(&prefs_runtime_config.allow_d2cs_setname,valstr,0); } static int conf_setdef_allow_d2cs_setname(void) { return conf_set_bool(&prefs_runtime_config.allow_d2cs_setname,NULL,1); } static const char* conf_get_allow_d2cs_setname(void) { return conf_get_bool(prefs_runtime_config.allow_d2cs_setname); } extern unsigned int prefs_get_d2cs_version(void) { return prefs_runtime_config.d2cs_version; } static int conf_set_d2cs_version(const char *valstr) { return conf_set_int(&prefs_runtime_config.d2cs_version,valstr,0); } static int conf_setdef_d2cs_version(void) { return conf_set_int(&prefs_runtime_config.d2cs_version,NULL,0); } static const char* conf_get_d2cs_version(void) { return conf_get_int(prefs_runtime_config.d2cs_version); } extern unsigned int prefs_get_hashtable_size(void) { return prefs_runtime_config.hashtable_size; } static int conf_set_hashtable_size(const char *valstr) { return conf_set_int(&prefs_runtime_config.hashtable_size,valstr,0); } static int conf_setdef_hashtable_size(void) { return conf_set_int(&prefs_runtime_config.hashtable_size,NULL,BNETD_HASHTABLE_SIZE); } static const char* conf_get_hashtable_size(void) { return conf_get_int(prefs_runtime_config.hashtable_size); } extern char const * prefs_get_telnet_addrs(void) { return prefs_runtime_config.telnetaddrs; } static int conf_set_telnetaddrs(const char *valstr) { return conf_set_str(&prefs_runtime_config.telnetaddrs,valstr,NULL); } static int conf_setdef_telnetaddrs(void) { return conf_set_str(&prefs_runtime_config.telnetaddrs,NULL,BNETD_TELNET_ADDRS); } static const char* conf_get_telnetaddrs(void) { return prefs_runtime_config.telnetaddrs; } extern unsigned int prefs_get_ipban_check_int(void) { return prefs_runtime_config.ipban_check_int; } static int conf_set_ipban_check_int(const char *valstr) { return conf_set_int(&prefs_runtime_config.ipban_check_int,valstr,0); } static int conf_setdef_ipban_check_int(void) { return conf_set_int(&prefs_runtime_config.ipban_check_int,NULL,30); } static const char* conf_get_ipban_check_int(void) { return conf_get_int(prefs_runtime_config.ipban_check_int); } extern char const * prefs_get_version_exeinfo_match(void) { return prefs_runtime_config.version_exeinfo_match; } static int conf_set_version_exeinfo_match(const char *valstr) { return conf_set_str(&prefs_runtime_config.version_exeinfo_match,valstr,NULL); } static int conf_setdef_version_exeinfo_match(void) { return conf_set_str(&prefs_runtime_config.version_exeinfo_match,NULL,BNETD_EXEINFO_MATCH); } static const char* conf_get_version_exeinfo_match(void) { return prefs_runtime_config.version_exeinfo_match; } extern unsigned int prefs_get_version_exeinfo_maxdiff(void) { return prefs_runtime_config.version_exeinfo_maxdiff; } static int conf_set_version_exeinfo_maxdiff(const char *valstr) { return conf_set_int(&prefs_runtime_config.version_exeinfo_maxdiff,valstr,0); } static int conf_setdef_version_exeinfo_maxdiff(void) { return conf_set_int(&prefs_runtime_config.version_exeinfo_maxdiff,NULL,PVPGN_VERSION_TIMEDIV); } static const char* conf_get_version_exeinfo_maxdiff(void) { return conf_get_int(prefs_runtime_config.version_exeinfo_maxdiff); } extern unsigned int prefs_get_max_concurrent_logins(void) { return prefs_runtime_config.max_concurrent_logins; } static int conf_set_max_concurrent_logins(const char *valstr) { return conf_set_int(&prefs_runtime_config.max_concurrent_logins,valstr,0); } static int conf_setdef_max_concurrent_logins(void) { return conf_set_int(&prefs_runtime_config.max_concurrent_logins,NULL,0); } static const char* conf_get_max_concurrent_logins(void) { return conf_get_int(prefs_runtime_config.max_concurrent_logins); } extern char const * prefs_get_server_info( void ) { return prefs_runtime_config.server_info; } static int conf_set_server_info(const char *valstr) { return conf_set_str(&prefs_runtime_config.server_info,valstr,NULL); } static int conf_setdef_server_info(void) { return conf_set_str(&prefs_runtime_config.server_info,NULL,""); } static const char* conf_get_server_info(void) { return prefs_runtime_config.server_info; } extern char const * prefs_get_mapsfile(void) { return prefs_runtime_config.mapsfile; } static int conf_set_mapsfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.mapsfile,valstr,NULL); } static int conf_setdef_mapsfile(void) { return conf_set_str(&prefs_runtime_config.mapsfile,NULL,NULL); } static const char* conf_get_mapsfile(void) { return prefs_runtime_config.mapsfile; } extern char const * prefs_get_xplevel_file(void) { return prefs_runtime_config.xplevelfile; } static int conf_set_xplevelfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.xplevelfile,valstr,NULL); } static int conf_setdef_xplevelfile(void) { return conf_set_str(&prefs_runtime_config.xplevelfile,NULL,NULL); } static const char* conf_get_xplevelfile(void) { return prefs_runtime_config.xplevelfile; } extern char const * prefs_get_xpcalc_file(void) { return prefs_runtime_config.xpcalcfile; } static int conf_set_xpcalcfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.xpcalcfile,valstr,NULL); } static int conf_setdef_xpcalcfile(void) { return conf_set_str(&prefs_runtime_config.xpcalcfile,NULL,NULL); } static const char* conf_get_xpcalcfile(void) { return prefs_runtime_config.xpcalcfile; } extern int prefs_get_initkill_timer(void) { return prefs_runtime_config.initkill_timer; } static int conf_set_initkill_timer(const char *valstr) { return conf_set_int(&prefs_runtime_config.initkill_timer,valstr,0); } static int conf_setdef_initkill_timer(void) { return conf_set_int(&prefs_runtime_config.initkill_timer,NULL,0); } static const char* conf_get_initkill_timer(void) { return conf_get_int(prefs_runtime_config.initkill_timer); } extern int prefs_get_war3_ladder_update_secs(void) { return prefs_runtime_config.war3_ladder_update_secs; } static int conf_set_war3_ladder_update_secs(const char *valstr) { return conf_set_int(&prefs_runtime_config.war3_ladder_update_secs,valstr,0); } static int conf_setdef_war3_ladder_update_secs(void) { return conf_set_int(&prefs_runtime_config.war3_ladder_update_secs,NULL,0); } static const char* conf_get_war3_ladder_update_secs(void) { return conf_get_int(prefs_runtime_config.war3_ladder_update_secs); } extern int prefs_get_output_update_secs(void) { return prefs_runtime_config.output_update_secs; } static int conf_set_output_update_secs(const char *valstr) { return conf_set_int(&prefs_runtime_config.output_update_secs,valstr,0); } static int conf_setdef_output_update_secs(void) { return conf_set_int(&prefs_runtime_config.output_update_secs,NULL,0); } static const char* conf_get_output_update_secs(void) { return conf_get_int(prefs_runtime_config.output_update_secs); } extern char const * prefs_get_ladderdir(void) { return prefs_runtime_config.ladderdir; } static int conf_set_ladderdir(const char *valstr) { return conf_set_str(&prefs_runtime_config.ladderdir,valstr,NULL); } static int conf_setdef_ladderdir(void) { return conf_set_str(&prefs_runtime_config.ladderdir,NULL,BNETD_LADDER_DIR); } static const char* conf_get_ladderdir(void) { return prefs_runtime_config.ladderdir; } extern char const * prefs_get_outputdir(void) { return prefs_runtime_config.statusdir; } static int conf_set_statusdir(const char *valstr) { return conf_set_str(&prefs_runtime_config.statusdir,valstr,NULL); } static int conf_setdef_statusdir(void) { return conf_set_str(&prefs_runtime_config.statusdir,NULL,BNETD_STATUS_DIR); } static const char* conf_get_statusdir(void) { return prefs_runtime_config.statusdir; } extern int prefs_get_XML_output_ladder(void) { return prefs_runtime_config.XML_output_ladder; } static int conf_set_XML_output_ladder(const char *valstr) { return conf_set_bool(&prefs_runtime_config.XML_output_ladder,valstr,0); } static int conf_setdef_XML_output_ladder(void) { return conf_set_bool(&prefs_runtime_config.XML_output_ladder,NULL,0); } static const char* conf_get_XML_output_ladder(void) { return conf_get_bool(prefs_runtime_config.XML_output_ladder); } extern int prefs_get_XML_status_output(void) { return prefs_runtime_config.XML_status_output; } static int conf_set_XML_status_output(const char *valstr) { return conf_set_bool(&prefs_runtime_config.XML_status_output,valstr,0); } static int conf_setdef_XML_status_output(void) { return conf_set_bool(&prefs_runtime_config.XML_status_output,NULL,0); } static const char* conf_get_XML_status_output(void) { return conf_get_bool(prefs_runtime_config.XML_status_output); } extern char const * prefs_get_account_allowed_symbols(void) { return prefs_runtime_config.account_allowed_symbols; } static int conf_set_account_allowed_symbols(const char *valstr) { return conf_set_str(&prefs_runtime_config.account_allowed_symbols,valstr,NULL); } static int conf_setdef_account_allowed_symbols(void) { return conf_set_str(&prefs_runtime_config.account_allowed_symbols,NULL,PVPGN_DEFAULT_SYMB); } static const char* conf_get_account_allowed_symbols(void) { return prefs_runtime_config.account_allowed_symbols; } extern unsigned int prefs_get_account_force_username(void) { return prefs_runtime_config.account_force_username; } static int conf_set_account_force_username(const char *valstr) { return conf_set_bool(&prefs_runtime_config.account_force_username,valstr,0); } static int conf_setdef_account_force_username(void) { return conf_set_bool(&prefs_runtime_config.account_force_username,NULL,0); } static const char* conf_get_account_force_username(void) { return conf_get_bool(prefs_runtime_config.account_force_username); } extern char const * prefs_get_command_groups_file(void) { return prefs_runtime_config.command_groups_file; } static int conf_set_command_groups_file(const char *valstr) { return conf_set_str(&prefs_runtime_config.command_groups_file,valstr,NULL); } static int conf_setdef_command_groups_file(void) { return conf_set_str(&prefs_runtime_config.command_groups_file,NULL,BNETD_COMMAND_GROUPS_FILE); } static const char* conf_get_command_groups_file(void) { return prefs_runtime_config.command_groups_file; } extern char const * prefs_get_tournament_file(void) { return prefs_runtime_config.tournament_file; } static int conf_set_tournament_file(const char *valstr) { return conf_set_str(&prefs_runtime_config.tournament_file,valstr,NULL); } static int conf_setdef_tournament_file(void) { return conf_set_str(&prefs_runtime_config.tournament_file,NULL,BNETD_TOURNAMENT_FILE); } static const char* conf_get_tournament_file(void) { return prefs_runtime_config.tournament_file; } extern char const * prefs_get_aliasfile(void) { return prefs_runtime_config.aliasfile; } static int conf_set_aliasfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.aliasfile,valstr,NULL); } static int conf_setdef_aliasfile(void) { return conf_set_str(&prefs_runtime_config.aliasfile,NULL,BNETD_ALIASFILE); } static const char* conf_get_aliasfile(void) { return prefs_runtime_config.aliasfile; } extern char const * prefs_get_anongame_infos_file(void) { return prefs_runtime_config.anongame_infos_file; } static int conf_set_anongame_infos_file(const char *valstr) { return conf_set_str(&prefs_runtime_config.anongame_infos_file,valstr,NULL); } static int conf_setdef_anongame_infos_file(void) { return conf_set_str(&prefs_runtime_config.anongame_infos_file,NULL,PVPGN_AINFO_FILE); } static const char* conf_get_anongame_infos_file(void) { return prefs_runtime_config.anongame_infos_file; } extern unsigned int prefs_get_max_conns_per_IP(void) { return prefs_runtime_config.max_conns_per_IP; } static int conf_set_max_conns_per_IP(const char *valstr) { return conf_set_int(&prefs_runtime_config.max_conns_per_IP,valstr,0); } static int conf_setdef_max_conns_per_IP(void) { return conf_set_int(&prefs_runtime_config.max_conns_per_IP,NULL,0); } static const char* conf_get_max_conns_per_IP(void) { return conf_get_int(prefs_runtime_config.max_conns_per_IP); } extern int prefs_get_max_friends(void) { return prefs_runtime_config.max_friends; } static int conf_set_max_friends(const char *valstr) { return conf_set_int(&prefs_runtime_config.max_friends,valstr,0); } static int conf_setdef_max_friends(void) { return conf_set_int(&prefs_runtime_config.max_friends,NULL,MAX_FRIENDS); } static const char* conf_get_max_friends(void) { return conf_get_int(prefs_runtime_config.max_friends); } extern unsigned int prefs_get_clan_newer_time(void) { return prefs_runtime_config.clan_newer_time; } static int conf_set_clan_newer_time(const char *valstr) { return conf_set_int(&prefs_runtime_config.clan_newer_time,valstr,0); } static int conf_setdef_clan_newer_time(void) { return conf_set_int(&prefs_runtime_config.clan_newer_time,NULL,CLAN_NEWER_TIME); } static const char* conf_get_clan_newer_time(void) { return conf_get_int(prefs_runtime_config.clan_newer_time); } extern unsigned int prefs_get_clan_max_members(void) { return prefs_runtime_config.clan_max_members; } static int conf_set_clan_max_members(const char *valstr) { int rez = conf_set_int(&prefs_runtime_config.clan_max_members,valstr,0); if (!rez && valstr) { if (prefs_runtime_config.clan_max_members < CLAN_MIN_MEMBERS) { WARN1("Cannot set clan max members to %u lower than 10, setting to 10.", prefs_runtime_config.clan_max_members); prefs_runtime_config.clan_max_members = CLAN_MIN_MEMBERS; } else if (prefs_runtime_config.clan_max_members > CLAN_MAX_MEMBERS) { WARN1("Cannot set clan max members to %u higher than 100, setting to 100.", prefs_runtime_config.clan_max_members); prefs_runtime_config.clan_max_members = CLAN_MAX_MEMBERS; } } return rez; } static int conf_setdef_clan_max_members(void) { return conf_set_int(&prefs_runtime_config.clan_max_members,NULL,CLAN_DEFAULT_MAX_MEMBERS); } static const char* conf_get_clan_max_members(void) { return conf_get_int(prefs_runtime_config.clan_max_members); } extern unsigned int prefs_get_clan_channel_default_private(void) { return prefs_runtime_config.clan_channel_default_private; } static int conf_set_clan_channel_default_private(const char *valstr) { return conf_set_bool(&prefs_runtime_config.clan_channel_default_private,valstr,0); } static int conf_setdef_clan_channel_default_private(void) { return conf_set_bool(&prefs_runtime_config.clan_channel_default_private,NULL,0); } static const char* conf_get_clan_channel_default_private(void) { return conf_get_bool(prefs_runtime_config.clan_channel_default_private); } extern unsigned int prefs_get_passfail_count(void) { return prefs_runtime_config.passfail_count; } static int conf_set_passfail_count(const char *valstr) { return conf_set_int(&prefs_runtime_config.passfail_count,valstr,0); } static int conf_setdef_passfail_count(void) { return conf_set_int(&prefs_runtime_config.passfail_count,NULL,0); } static const char* conf_get_passfail_count(void) { return conf_get_int(prefs_runtime_config.passfail_count); } extern unsigned int prefs_get_passfail_bantime(void) { return prefs_runtime_config.passfail_bantime; } static int conf_set_passfail_bantime(const char *valstr) { return conf_set_int(&prefs_runtime_config.passfail_bantime,valstr,0); } static int conf_setdef_passfail_bantime(void) { return conf_set_int(&prefs_runtime_config.passfail_bantime,NULL,300); } static const char* conf_get_passfail_bantime(void) { return conf_get_int(prefs_runtime_config.passfail_bantime); } extern unsigned int prefs_get_maxusers_per_channel(void) { return prefs_runtime_config.maxusers_per_channel; } static int conf_set_maxusers_per_channel(const char *valstr) { return conf_set_int(&prefs_runtime_config.maxusers_per_channel,valstr,0); } static int conf_setdef_maxusers_per_channel(void) { return conf_set_int(&prefs_runtime_config.maxusers_per_channel,NULL,0); } static const char* conf_get_maxusers_per_channel(void) { return conf_get_int(prefs_runtime_config.maxusers_per_channel); } extern char const * prefs_get_supportfile(void) { return prefs_runtime_config.supportfile; } static int conf_set_supportfile(const char *valstr) { return conf_set_str(&prefs_runtime_config.supportfile,valstr,NULL); } static int conf_setdef_supportfile(void) { return conf_set_str(&prefs_runtime_config.supportfile,NULL,BNETD_SUPPORT_FILE); } static const char* conf_get_supportfile(void) { return prefs_runtime_config.supportfile; } extern char const * prefs_get_allowed_clients(void) { return prefs_runtime_config.allowed_clients; } static int conf_set_allowed_clients(const char *valstr) { return conf_set_str(&prefs_runtime_config.allowed_clients,valstr,NULL); } static int conf_setdef_allowed_clients(void) { return conf_set_str(&prefs_runtime_config.allowed_clients,NULL,NULL); } static const char* conf_get_allowed_clients(void) { return prefs_runtime_config.allowed_clients; } extern char const * prefs_get_ladder_games(void) { return prefs_runtime_config.ladder_games; } static int conf_set_ladder_games(const char *valstr) { return conf_set_str(&prefs_runtime_config.ladder_games,valstr,NULL); } static int conf_setdef_ladder_games(void) { return conf_set_str(&prefs_runtime_config.ladder_games,NULL,NULL); } static const char* conf_get_ladder_games(void) { return prefs_runtime_config.ladder_games; } extern char const * prefs_get_ladder_prefix(void) { return prefs_runtime_config.ladder_prefix; } static int conf_set_ladder_prefix(const char *valstr) { return conf_set_str(&prefs_runtime_config.ladder_prefix,valstr,NULL); } static int conf_setdef_ladder_prefix(void) { return conf_set_str(&prefs_runtime_config.ladder_prefix,NULL,NULL); } static const char* conf_get_ladder_prefix(void) { return prefs_runtime_config.ladder_prefix; } extern unsigned int prefs_get_max_connections(void) { return prefs_runtime_config.max_connections; } static int conf_set_max_connections(const char *valstr) { return conf_set_int(&prefs_runtime_config.max_connections,valstr,0); } static int conf_setdef_max_connections(void) { return conf_set_int(&prefs_runtime_config.max_connections,NULL,BNETD_MAX_SOCKETS); } static const char* conf_get_max_connections(void) { return conf_get_int(prefs_runtime_config.max_connections); } extern unsigned int prefs_get_sync_on_logoff(void) { return prefs_runtime_config.sync_on_logoff; } static int conf_set_sync_on_logoff(const char *valstr) { return conf_set_bool(&prefs_runtime_config.sync_on_logoff,valstr,0); } static int conf_setdef_sync_on_logoff(void) { return conf_set_bool(&prefs_runtime_config.sync_on_logoff,NULL,0); } static const char* conf_get_sync_on_logoff(void) { return conf_get_bool(prefs_runtime_config.sync_on_logoff); } extern char const * prefs_get_irc_network_name(void) { return prefs_runtime_config.irc_network_name; } static int conf_set_irc_network_name(const char *valstr) { return conf_set_str(&prefs_runtime_config.irc_network_name,valstr,NULL); } static int conf_setdef_irc_network_name(void) { return conf_set_str(&prefs_runtime_config.irc_network_name,NULL,BNETD_IRC_NETWORK_NAME); } static const char* conf_get_irc_network_name(void) { return prefs_runtime_config.irc_network_name; } /** * Westwood Online Extensions */ extern char const * prefs_get_wol_addrs(void) { return prefs_runtime_config.woladdrs; } static int conf_set_wol_addrs(const char *valstr) { return conf_set_str(&prefs_runtime_config.woladdrs,valstr,NULL); } static int conf_setdef_wol_addrs(void) { return conf_set_str(&prefs_runtime_config.woladdrs,NULL,BNETD_WOL_ADDRS); } static const char* conf_get_wol_addrs(void) { return prefs_runtime_config.woladdrs; } static int conf_set_wol_timezone(const char *valstr) { return conf_set_str(&prefs_runtime_config.woltimezone,valstr,NULL); } extern char const * prefs_get_wol_timezone(void) { return prefs_runtime_config.woltimezone; } static char const * conf_get_wol_timezone(void) { return prefs_runtime_config.woltimezone; } static int conf_setdef_wol_timezone(void) { return conf_set_str(&prefs_runtime_config.woltimezone,NULL,0); } static int conf_set_wol_longitude(const char *valstr) { return conf_set_str(&prefs_runtime_config.wollongitude,valstr,NULL); } extern char const * prefs_get_wol_longitude(void) { return prefs_runtime_config.wollongitude; } static char const * conf_get_wol_longitude(void) { return prefs_runtime_config.wollongitude; } static int conf_setdef_wol_longitude(void) { return conf_set_str(&prefs_runtime_config.wollongitude,NULL,0); } static int conf_set_wol_latitude(const char *valstr) { return conf_set_str(&prefs_runtime_config.wollatitude,valstr,NULL); } extern char const * prefs_get_wol_latitude(void) { return prefs_runtime_config.wollatitude; } static char const * conf_get_wol_latitude(void) { return prefs_runtime_config.wollatitude; } static int conf_setdef_wol_latitude(void) { return conf_set_str(&prefs_runtime_config.wollatitude,NULL,0); } pvpgn-1.8.5/src/bnetd/ladder_binary.h0000644000175000017500000000411311151345317016474 0ustar aaronaaron/* * Copyright (C) 2003 Aaron * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_BINARY_LADDER_TYPES #define INCLUDED_BINARY_LADDER_TYPES typedef enum { WAR3_SOLO, WAR3_TEAM, WAR3_FFA, WAR3_AT, W3XP_SOLO, W3XP_TEAM, W3XP_FFA, W3XP_AT, STAR_AR, STAR_AW, STAR_AG, /* AR = active-rating, AW = active-wins, AG = active-games */ STAR_CR, STAR_CW, STAR_CG, /* CR = current-rating, CW = current-wins, CG = current-games */ SEXP_AR, SEXP_AW, SEXP_AG, SEXP_CR, SEXP_CW, SEXP_CG, W2BN_AR, W2BN_AW, W2BN_AG, W2BN_CR, W2BN_CW, W2BN_CG, W2BN_ARI, W2BN_AWI, W2BN_AGI, /* I = Ironman */ W2BN_CRI, W2BN_CWI, W2BN_CGI } t_binary_ladder_types; typedef enum { load_success = 0, illegal_checksum, load_failed } t_binary_ladder_load_result; typedef int (* t_cb_get_from_ladder)(t_binary_ladder_types type, int rank, int *results); typedef int (* t_cb_add_to_ladder)(t_binary_ladder_types, int *values); #ifdef BINARY_LADDER_INTERNAL_ACCESS #define magick 0xdeadbeef #endif #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_BINARY_LADDER_PROTOS #define INCLUDED_BINARY_LADDER_PROTOS // some protos here extern int binary_ladder_save(t_binary_ladder_types type, unsigned int paracount, t_cb_get_from_ladder _cb_get_from_ladder); extern t_binary_ladder_load_result binary_ladder_load(t_binary_ladder_types type, unsigned int paracount, t_cb_add_to_ladder _cb_add_to_ladder); #endif #endif pvpgn-1.8.5/src/bnetd/character.h0000644000175000017500000000724111151345317015636 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_CHARACTER_TYPES #define INCLUDED_CHARACTER_TYPES #ifdef CHARACTER_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include "compat/uint.h" #else # define JUST_NEED_TYPES # include "compat/uint.h" # undef JUST_NEED_TYPES #endif #endif typedef enum { character_class_none, character_class_amazon, character_class_sorceress, character_class_necromancer, character_class_paladin, character_class_barbarian, character_class_druid, character_class_assassin } t_character_class; typedef enum { character_expansion_none, character_expansion_classic, character_expansion_lod } t_character_expansion; typedef struct character #ifdef CHARACTER_INTERNAL_ACCESS { char const * name; /* max 15 chars */ char const * realmname; char const * guildname; /* max 3 chars */ /* stored in Battle.net format for now */ t_uint8 helmgfx; t_uint8 bodygfx; t_uint8 leggfx; t_uint8 lhandweapon; t_uint8 lhandgfx; t_uint8 rhandweapon; t_uint8 rhandgfx; t_uint8 class; t_uint8 level; t_uint8 status; t_uint8 title; t_uint8 emblembgc; t_uint8 emblemfgc; t_uint8 emblemnum; /* not sure what these represent */ t_uint32 unknown1; t_uint32 unknown2; t_uint32 unknown3; t_uint32 unknown4; t_uint8 unknownb1; t_uint8 unknownb2; t_uint8 unknownb3; t_uint8 unknownb4; t_uint8 unknownb5; t_uint8 unknownb6; t_uint8 unknownb7; t_uint8 unknownb8; t_uint8 unknownb9; t_uint8 unknownb10; t_uint8 unknownb11; t_uint8 unknownb13; t_uint8 unknownb14; /* Keep some generic "data", basically the blob that is sent between client and server, in an array */ t_uint8 data[64]; t_uint8 datalen; } #endif t_character; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_CHARACTER_PROTOS #define INCLUDED_CHARACTER_PROTOS #define JUST_NEED_TYPES #include "compat/uint.h" #include "account.h" #undef JUST_NEED_TYPES extern int character_create(t_account * account, t_clienttag clienttag, char const * realmname, char const * name, t_character_class class, t_character_expansion expansion); extern char const * character_get_name(t_character const * ch); extern char const * character_get_realmname(t_character const * ch); extern char const * character_get_playerinfo(t_character const * ch); extern char const * character_get_guildname(t_character const * ch); extern t_character_class character_get_class(t_character const * ch); extern int character_verify_charlist(t_character const * ch, char const * charlist); extern int characterlist_create(char const * dirname); extern int characterlist_destroy(void); extern t_character * characterlist_find_character(char const * realmname, char const * charname); #endif #endif pvpgn-1.8.5/src/bnetd/storage_sql.h0000644000175000017500000000172411151345317016225 0ustar aaronaaron/* * Copyright (C) 2002,2003 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_STORAGE_SQL_PROTOS #define INCLUDED_STORAGE_SQL_PROTOS #include "storage.h" extern t_storage storage_sql; #endif /* INCLUDED_STORAGE_SQL_PROTOS */ #endif /* JUST_NEED_TYPES */ pvpgn-1.8.5/src/bnetd/tracker.c0000644000175000017500000001514711151345317015334 0ustar aaronaaron/* * Copyright (C) 1999 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define TRACKER_INTERNAL_ACCESS #define SERVER_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memset.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_UTSNAME_H # include #endif #include "compat/uname.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/send.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #include "compat/psock.h" #include "common/eventlog.h" #include "connection.h" #include "channel.h" #include "prefs.h" #include "game.h" #include "common/version.h" #include "server.h" #include "common/addr.h" #include "common/list.h" #include "common/tracker.h" #include "common/bn_type.h" #include "common/setup_after.h" static t_addrlist * track_servers=NULL; extern int tracker_set_servers(char const * servers) { t_addr const * addr; t_elem const * curr; char temp[32]; if (track_servers && addrlist_destroy(track_servers)<0) eventlog(eventlog_level_error,__FUNCTION__,"unable to destroy tracker list"); if (!servers) { track_servers = NULL; return 0; } if (!(track_servers = addrlist_create(servers,INADDR_LOOPBACK,BNETD_TRACK_PORT))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create tracking server list"); return -1; } LIST_TRAVERSE_CONST(track_servers,curr) { addr = elem_get_data(curr); if (!addr_get_addr_str(addr,temp,sizeof(temp))) strcpy(temp,"x.x.x.x:x"); eventlog(eventlog_level_info,__FUNCTION__,"tracking packets will be sent to %s",temp); } return 0; } extern int tracker_send_report(t_addrlist const * laddrs) { t_addr const * addrl; t_elem const * currl; t_addr const * addrt; t_elem const * currt; t_trackpacket packet; struct utsname utsbuf; struct sockaddr_in tempaddr; t_laddr_info * laddr_info; char tempa[64]; char tempb[64]; if (addrlist_get_length(track_servers)>0) { memset(&packet,0,sizeof(packet)); bn_short_nset(&packet.packet_version,(unsigned short)TRACK_VERSION); /* packet.port is set below */ bn_int_nset(&packet.flags, 0); strncpy((char *)packet.server_location, prefs_get_location(), sizeof(packet.server_location)); bn_byte_set(&packet.server_location[sizeof(packet.server_location)-1],'\0'); strncpy((char *)packet.software, PVPGN_SOFTWARE, sizeof(packet.software)); bn_byte_set(&packet.software[sizeof(packet.software)-1],'\0'); strncpy((char *)packet.version, PVPGN_VERSION, sizeof(packet.version)); bn_byte_set(&packet.version[sizeof(packet.version)-1],'\0'); strncpy((char *)packet.server_desc, prefs_get_description(), sizeof(packet.server_desc)); bn_byte_set(&packet.server_desc[sizeof(packet.server_desc)-1],'\0'); strncpy((char *)packet.server_url, prefs_get_url(), sizeof(packet.server_url)); bn_byte_set(&packet.server_url[sizeof(packet.server_url)-1],'\0'); strncpy((char *)packet.contact_name, prefs_get_contact_name(), sizeof(packet.contact_name)); bn_byte_set(&packet.contact_name[sizeof(packet.contact_name)-1],'\0'); strncpy((char *)packet.contact_email, prefs_get_contact_email(), sizeof(packet.contact_email)); bn_byte_set(&packet.contact_email[sizeof(packet.contact_email)-1],'\0'); bn_int_nset(&packet.users,connlist_login_get_length()); bn_int_nset(&packet.channels,channellist_get_length()); bn_int_nset(&packet.games,gamelist_get_length()); bn_int_nset(&packet.uptime,server_get_uptime()); bn_int_nset(&packet.total_logins,connlist_total_logins()); bn_int_nset(&packet.total_games,gamelist_total_games()); if (uname(&utsbuf)<0) { eventlog(eventlog_level_warn,__FUNCTION__,"could not get platform info (uname: %s)",pstrerror(errno)); strncpy((char *)packet.platform,"",sizeof(packet.platform)); } else { strncpy((char *)packet.platform, utsbuf.sysname, sizeof(packet.platform)); bn_byte_set(&packet.platform[sizeof(packet.platform)-1],'\0'); } LIST_TRAVERSE_CONST(laddrs,currl) { addrl = elem_get_data(currl); if (!(laddr_info = addr_get_data(addrl).p)) { eventlog(eventlog_level_error,__FUNCTION__,"address data is NULL"); continue; } if (laddr_info->type!=laddr_type_bnet) continue; /* don't report IRC, telnet, and other non-game ports */ bn_short_nset(&packet.port,addr_get_port(addrl)); LIST_TRAVERSE_CONST(track_servers,currt) { addrt = elem_get_data(currt); memset(&tempaddr,0,sizeof(tempaddr)); tempaddr.sin_family = PSOCK_AF_INET; tempaddr.sin_port = htons(addr_get_port(addrt)); tempaddr.sin_addr.s_addr = htonl(addr_get_ip(addrt)); if (!addr_get_addr_str(addrl,tempa,sizeof(tempa))) strcpy(tempa,"x.x.x.x:x"); if (!addr_get_addr_str(addrt,tempb,sizeof(tempb))) strcpy(tempa,"x.x.x.x:x"); /* eventlog(eventlog_level_debug,__FUNCTION__,"sending tracking info from %s to %s",tempa,tempb); */ if (psock_sendto(laddr_info->usocket,&packet,sizeof(packet),0,(struct sockaddr *)&tempaddr,(psock_t_socklen)sizeof(tempaddr))<0) eventlog(eventlog_level_warn,__FUNCTION__,"could not send tracking information from %s to %s (psock_sendto: %s)",tempa,tempb,pstrerror(errno)); } } } return 0; } pvpgn-1.8.5/src/bnetd/sql_common.c0000644000175000017500000005104711151345317016047 0ustar aaronaaron/* * Copyright (C) 2002 TheUndying * Copyright (C) 2002 zap-zero * Copyright (C) 2002,2003,2005 Dizzy * Copyright (C) 2002 Zzzoom * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef WITH_SQL #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include "compat/strtoul.h" #include "compat/snprintf.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "common/eventlog.h" #include "prefs.h" #include "common/util.h" #define CLAN_INTERNAL_ACCESS #define TEAM_INTERNAL_ACCESS #include "team.h" #include "account.h" #include "connection.h" #include "clan.h" #undef TEAM_INTERNAL_ACCESS #undef CLAN_INTERNAL_ACCESS #include "common/tag.h" #include "common/xalloc.h" #include "common/flags.h" #include "sql_dbcreator.h" #define SQL_INTERNAL # include "sql_common.h" #undef SQL_INTERNAL #ifdef WITH_SQL_MYSQL #include "sql_mysql.h" #endif #ifdef WITH_SQL_PGSQL #include "sql_pgsql.h" #endif #ifdef WITH_SQL_SQLITE3 #include "sql_sqlite3.h" #endif #ifdef WITH_SQL_ODBC #include "sql_odbc.h" #endif #include "common/elist.h" #include "common/setup_after.h" unsigned int sql_defacct; t_sql_engine *sql = NULL; #ifndef SQL_ON_DEMAND char *sql_tables[] = { "BNET", "Record", "profile", "friend", "Team", NULL }; #endif /* SQL_ON_DEMAND */ const char* tab_prefix = SQL_DEFAULT_PREFIX; static char query[1024]; extern int sql_init(const char *dbpath) { char *tok, *path, *tmp, *p; const char *dbhost = NULL; const char *dbname = NULL; const char *dbuser = NULL; const char *dbpass = NULL; const char *driver = NULL; const char *dbport = NULL; const char *dbsocket = NULL; const char *def = NULL; const char *pref = NULL; path = xstrdup(dbpath); tmp = path; while ((tok = strtok(tmp, ";")) != NULL) { tmp = NULL; if ((p = strchr(tok, '=')) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path, no '=' present in token"); xfree((void *) path); return -1; } *p = '\0'; if (strcasecmp(tok, "host") == 0) dbhost = p + 1; else if (strcasecmp(tok, "mode") == 0) driver = p + 1; else if (strcasecmp(tok, "name") == 0) dbname = p + 1; else if (strcasecmp(tok, "port") == 0) dbport = p + 1; else if (strcasecmp(tok, "socket") == 0) dbsocket = p + 1; else if (strcasecmp(tok, "user") == 0) dbuser = p + 1; else if (strcasecmp(tok, "pass") == 0) dbpass = p + 1; else if (strcasecmp(tok, "default") == 0) def = p + 1; else if (strcasecmp(tok, "prefix") == 0) pref = p + 1; else eventlog(eventlog_level_warn, __FUNCTION__, "unknown token in storage_path : '%s'", tok); } if (driver == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "no mode specified"); xfree((void *) path); return -1; } if (def == NULL) sql_defacct = STORAGE_SQL_DEFAULT_UID; else sql_defacct = atoi(def); if (pref == NULL) tab_prefix = SQL_DEFAULT_PREFIX; else tab_prefix = xstrdup(pref); do { #ifdef WITH_SQL_MYSQL if (strcasecmp(driver, "mysql") == 0) { sql = &sql_mysql; if (sql->init(dbhost, dbport, dbsocket, dbname, dbuser, dbpass)) { eventlog(eventlog_level_error, __FUNCTION__, "got error init db"); sql = NULL; xfree((void *) path); return -1; } break; } #endif /* WITH_SQL_MYSQL */ #ifdef WITH_SQL_PGSQL if (strcasecmp(driver, "pgsql") == 0) { sql = &sql_pgsql; if (sql->init(dbhost, dbport, dbsocket, dbname, dbuser, dbpass)) { eventlog(eventlog_level_error, __FUNCTION__, "got error init db"); sql = NULL; xfree((void *) path); return -1; } break; } #endif /* WITH_SQL_PGSQL */ #ifdef WITH_SQL_SQLITE3 if (strcasecmp(driver, "sqlite3") == 0) { sql = &sql_sqlite3; if (sql->init(NULL, 0, NULL, dbname, NULL, NULL)) { eventlog(eventlog_level_error, __FUNCTION__, "got error init db"); sql = NULL; xfree((void *) path); return -1; } break; } #endif /* WITH_SQL_SQLITE3 */ #ifdef WITH_SQL_ODBC if (strcasecmp(driver, "odbc") == 0) { sql = &sql_odbc; if (sql->init(dbhost, dbport, dbsocket, dbname, dbuser, dbpass)) { eventlog(eventlog_level_error, __FUNCTION__, "got error init db"); sql = NULL; free((void *) path); return -1; } break; } #endif /* WITH_SQL_ODBC */ eventlog(eventlog_level_error, __FUNCTION__, "no driver found for '%s'", driver); xfree((void *) path); return -1; } while (0); xfree((void *) path); sql_dbcreator(sql); return 0; } extern int sql_close(void) { if (sql == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "sql not initilized"); return -1; } sql->close(); sql = NULL; if (tab_prefix != SQL_DEFAULT_PREFIX) { xfree((void*)tab_prefix); tab_prefix = NULL; } return 0; } extern unsigned sql_read_maxuserid(void) { t_sql_res *result; t_sql_row *row; long maxuid; if (sql == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "sql not initilized"); return 0; } snprintf(query, sizeof(query), "SELECT max("SQL_UID_FIELD") FROM %sBNET", tab_prefix); if ((result = sql->query_res(query)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"SELECT max("SQL_UID_FIELD") FROM %sBNET\"", tab_prefix); return 0; } row = sql->fetch_row(result); if (row == NULL || row[0] == NULL) { sql->free_result(result); eventlog(eventlog_level_error, __FUNCTION__, "got NULL max"); return 0; } maxuid = atol(row[0]); sql->free_result(result); if (maxuid < 0) { eventlog(eventlog_level_error, __FUNCTION__, "got invalid maxuserid"); return 0; } return maxuid; } extern int sql_read_accounts(int flag,t_read_accounts_func cb, void *data) { t_sql_res *result = NULL; t_sql_row *row; t_storage_info *info; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } if (cb == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback"); return -1; } /* don't actually load anything here if ST_FORCE is not set as SQL is indexed */ if (!FLAG_ISSET(flag,ST_FORCE)) return 1; snprintf(query, sizeof(query), "SELECT DISTINCT("SQL_UID_FIELD") FROM %sBNET", tab_prefix); if ((result = sql->query_res(query)) != NULL) { if (sql->num_rows(result) <= 1) { sql->free_result(result); return 0; /* empty user list */ } while ((row = sql->fetch_row(result)) != NULL) { if (row[0] == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL uid from db"); continue; } if ((unsigned int) atoi(row[0]) == sql_defacct) continue; /* skip default account */ info = xmalloc(sizeof(t_sql_info)); *((unsigned int *) info) = atoi(row[0]); cb(info, data); } sql->free_result(result); } else { eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query); return -1; } return 0; } extern int sql_cmp_info(t_storage_info * info1, t_storage_info * info2) { return *((unsigned int *) info1) != *((unsigned int *) info2); } extern int sql_free_info(t_storage_info * info) { if (info) xfree((void *) info); return 0; } extern t_storage_info *sql_get_defacct(void) { t_storage_info *info; info = xmalloc(sizeof(t_sql_info)); *((unsigned int *) info) = sql_defacct; return info; } extern int sql_load_clans(t_load_clans_func cb) { t_sql_res *result; t_sql_res *result2; t_sql_row *row; t_sql_row *row2; t_clan *clan; int member_uid; t_clanmember *member; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } if (cb == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback"); return -1; } snprintf(query, sizeof(query), "SELECT cid, short, name, motd, creation_time FROM %sclan WHERE cid > 0", tab_prefix); if ((result = sql->query_res(query)) != NULL) { if (sql->num_rows(result) < 1) { sql->free_result(result); return 0; /* empty clan list */ } while ((row = sql->fetch_row(result)) != NULL) { if (row[0] == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL cid from db"); continue; } clan = xmalloc(sizeof(t_clan)); if (!(clan->clanid = atoi(row[0]))) { eventlog(eventlog_level_error, __FUNCTION__, "got bad cid"); sql->free_result(result); return -1; } clan->clantag = atoi(row[1]); clan->clanname = xstrdup(row[2]); clan->clan_motd = xstrdup(row[3]); clan->creation_time = atoi(row[4]); clan->created = 1; clan->modified = 0; clan->channel_type = prefs_get_clan_channel_default_private(); clan->members = list_create(); snprintf(query, sizeof(query), "SELECT "SQL_UID_FIELD", status, join_time FROM %sclanmember WHERE cid='%u'", tab_prefix, clan->clanid); if ((result2 = sql->query_res(query)) != NULL) { if (sql->num_rows(result2) >= 1) while ((row2 = sql->fetch_row(result2)) != NULL) { member = xmalloc(sizeof(t_clanmember)); if (row2[0] == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL uid from db"); continue; } if (!(member_uid = atoi(row2[0]))) continue; if (!(member->memberacc = accountlist_find_account_by_uid(member_uid))) { eventlog(eventlog_level_error, __FUNCTION__, "cannot find uid %u", member_uid); xfree((void *) member); continue; } member->status = atoi(row2[1]); member->join_time = atoi(row2[2]); member->clan = clan; if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600)) { member->status = CLAN_PEON; clan->modified = 1; member->modified = 1; } list_append_data(clan->members, member); account_set_clanmember(member->memberacc, member); eventlog(eventlog_level_trace, __FUNCTION__, "added member: uid: %i status: %c join_time: %u", member_uid, member->status + '0', (unsigned) member->join_time); } sql->free_result(result2); cb(clan); } else eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query); } sql->free_result(result); } else { eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query); return -1; } return 0; } extern int sql_write_clan(void *data) { char esc_motd[CLAN_MOTD_MAX * 2 + 1]; t_sql_res *result; t_sql_row *row; t_elem *curr; t_clanmember *member; t_clan *clan = (t_clan *) data; int num; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } snprintf(query, sizeof(query), "SELECT count(*) FROM %sclan WHERE cid='%u'", tab_prefix, clan->clanid); if ((result = sql->query_res(query)) != NULL) { row = sql->fetch_row(result); if (row == NULL || row[0] == NULL) { sql->free_result(result); eventlog(eventlog_level_error, __FUNCTION__, "got NULL count"); return -1; } num = atol(row[0]); sql->free_result(result); sql->escape_string(esc_motd, clan->clan_motd, strlen(clan->clan_motd)); if (num < 1) snprintf(query, sizeof(query), "INSERT INTO %sclan (cid, short, name, motd, creation_time) VALUES('%u', '%d', '%s', '%s', '%u')", tab_prefix, clan->clanid, clan->clantag, clan->clanname, esc_motd, (unsigned) clan->creation_time); else snprintf(query, sizeof(query), "UPDATE %sclan SET short='%d', name='%s', motd='%s', creation_time='%u' WHERE cid='%u'", tab_prefix, clan->clantag, clan->clanname, esc_motd, (unsigned) clan->creation_time, clan->clanid); if (sql->query(query) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query); return -1; } LIST_TRAVERSE(clan->members, curr) { unsigned int uid; if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL elem in list"); continue; } if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600)) { member->status = CLAN_PEON; member->modified = 1; } if (member->modified) { uid = account_get_uid(member->memberacc); snprintf(query, sizeof(query), "SELECT count(*) FROM %sclanmember WHERE "SQL_UID_FIELD"='%u'", tab_prefix, uid); if ((result = sql->query_res(query)) != NULL) { row = sql->fetch_row(result); if (row == NULL || row[0] == NULL) { sql->free_result(result); eventlog(eventlog_level_error, __FUNCTION__, "got NULL count"); return -1; } num = atol(row[0]); sql->free_result(result); if (num < 1) snprintf(query, sizeof(query), "INSERT INTO %sclanmember (cid, "SQL_UID_FIELD", status, join_time) VALUES('%u', '%u', '%d', '%u')", tab_prefix, clan->clanid, uid, member->status, (unsigned) member->join_time); else snprintf(query, sizeof(query), "UPDATE %sclanmember SET cid='%u', status='%d', join_time='%u' WHERE "SQL_UID_FIELD"='%u'", tab_prefix, clan->clanid, member->status, (unsigned) member->join_time, uid); if (sql->query(query) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query); return -1; } } else { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query); return -1; } member->modified = 0; } } } else { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query); return -1; } return 0; } extern int sql_remove_clan(int clantag) { t_sql_res *result; t_sql_row *row; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } snprintf(query, sizeof(query), "SELECT cid FROM %sclan WHERE short = '%d'", tab_prefix, clantag); if (!(result = sql->query_res(query))) { eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query); return -1; } if (sql->num_rows(result) != 1) { sql->free_result(result); return -1; /*clan not found or found more than 1 */ } if ((row = sql->fetch_row(result))) { unsigned int cid = atoi(row[0]); snprintf(query, sizeof(query), "DELETE FROM %sclanmember WHERE cid='%u'", tab_prefix, cid); if (sql->query(query) != 0) return -1; snprintf(query, sizeof(query), "DELETE FROM %sclan WHERE cid='%u'", tab_prefix, cid); if (sql->query(query) != 0) return -1; } sql->free_result(result); return 0; } extern int sql_remove_clanmember(int uid) { if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } snprintf(query, sizeof(query), "DELETE FROM %sclanmember WHERE "SQL_UID_FIELD"='%u'", tab_prefix, uid); if (sql->query(query) != 0) { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query); return -1; } return 0; } extern int sql_load_teams(t_load_teams_func cb) { t_sql_res *result; t_sql_row *row; t_team *team; int i; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } if (cb == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback"); return -1; } snprintf(query, sizeof(query), "SELECT teamid, size, clienttag, lastgame, member1, member2, member3, member4, wins,losses, xp, level, rank FROM %sarrangedteam WHERE teamid > 0", tab_prefix); if ((result = sql->query_res(query)) != NULL) { if (sql->num_rows(result) < 1) { sql->free_result(result); return 0; /* empty team list */ } while ((row = sql->fetch_row(result)) != NULL) { if (row[0] == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL teamid from db"); continue; } team = xmalloc(sizeof(t_team)); if (!(team->teamid = atoi(row[0]))) { eventlog(eventlog_level_error, __FUNCTION__, "got bad teamid"); sql->free_result(result); return -1; } team->size = atoi(row[1]); team->clienttag=tag_str_to_uint(row[2]); team->lastgame = strtoul(row[3],NULL,10); team->teammembers[0] = strtoul(row[4],NULL,10); team->teammembers[1] = strtoul(row[5],NULL,10); team->teammembers[2] = strtoul(row[6],NULL,10); team->teammembers[3] = strtoul(row[7],NULL,10); for (i=0; isize) { if ((team->teammembers[i]==0)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team data: too few members"); free((void *)team); goto load_team_failure; } } else { if ((team->teammembers[i]!=0)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid team data: too many members"); free((void *)team); goto load_team_failure; } } team->members[i] = NULL; } team->wins = atoi(row[8]); team->losses = atoi(row[9]); team->xp = atoi(row[10]); team->level = atoi(row[11]); team->rank = atoi(row[12]); eventlog(eventlog_level_trace,__FUNCTION__,"succesfully loaded team %u",team->teamid); cb(team); load_team_failure: ; } sql->free_result(result); } else { eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query); return -1; } return 0; } extern int sql_write_team(void *data) { t_sql_res *result; t_sql_row *row; t_team *team = (t_team *) data; int num; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } snprintf(query, sizeof(query), "SELECT count(*) FROM %sarrangedteam WHERE teamid='%u'", tab_prefix, team->teamid); if ((result = sql->query_res(query)) != NULL) { row = sql->fetch_row(result); if (row == NULL || row[0] == NULL) { sql->free_result(result); eventlog(eventlog_level_error, __FUNCTION__, "got NULL count"); return -1; } num = atol(row[0]); sql->free_result(result); if (num < 1) snprintf(query, sizeof(query), "INSERT INTO %sarrangedteam (teamid, size, clienttag, lastgame, member1, member2, member3, member4, wins,losses, xp, level, rank) VALUES('%u', '%c', '%s', '%u', '%u', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d')", tab_prefix, team->teamid, team->size + '0', clienttag_uint_to_str(team->clienttag),(unsigned int)team->lastgame, team->teammembers[0], team->teammembers[1], team->teammembers[2], team->teammembers[3], team->wins, team->losses, team->xp, team->level, team->rank); else snprintf(query, sizeof(query), "UPDATE %sarrangedteam SET size='%c', clienttag='%s', lastgame='%u', member1='%u', member2='%u', member3='%u', member4='%u', wins='%d', losses='%d', xp='%d', level='%d', rank='%d' WHERE teamid='%u'", tab_prefix, team->size + '0', clienttag_uint_to_str(team->clienttag),(unsigned int)team->lastgame, team->teammembers[0], team->teammembers[1], team->teammembers[2], team->teammembers[3], team->wins, team->losses, team->xp, team->level, team->rank, team->teamid); if (sql->query(query) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query); return -1; } } else { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query); return -1; } return 0; } extern int sql_remove_team(unsigned int teamid) { if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } snprintf(query, sizeof(query), "DELETE FROM %sarrangedteam WHERE teamid='%u'", tab_prefix, teamid); if (sql->query(query) != 0) return -1; return 0; } #endif /* WITH_SQL */ pvpgn-1.8.5/src/bnetd/ipban.c0000644000175000017500000006724611151345317015001 0ustar aaronaaron/* * Copyright (C) 2000 Gediminas (gugini@fortas.ktu.lt) * Copyright (C) 2002 Bart³omiej Butyn (bartek@milc.com.pl) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define IPBAN_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "compat/strchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strsep.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "common/eventlog.h" #include "common/util.h" #include "connection.h" #include "message.h" #include "prefs.h" #include "common/list.h" #include "common/xalloc.h" #include "server.h" #include "ipban.h" #include "common/setup_after.h" static int identify_ipban_function(const char * funcstr); static int ipban_func_del(t_connection * c, char const * cp); static int ipban_func_list(t_connection * c); static int ipban_func_check(t_connection * c, char const * cp); static int ipban_unload_entry(t_ipban_entry * e); static int ipban_identical_entry(t_ipban_entry * e1, t_ipban_entry * e2); static t_ipban_entry * ipban_str_to_ipban_entry(char const * cp); static char * ipban_entry_to_str(t_ipban_entry const * entry); static unsigned long ipban_str_to_ulong(char const * ipaddr); static int ipban_could_be_exact_ip_str(char const * str); static int ipban_could_be_ip_str(char const * ipstr); static void ipban_usage(t_connection * c); static t_list * ipbanlist_head = NULL; static time_t lastchecktime = 0; extern int ipbanlist_create(void) { ipbanlist_head = list_create(); return 0; } extern int ipbanlist_destroy(void) { t_elem * curr; t_ipban_entry * entry; if (ipbanlist_head) { LIST_TRAVERSE(ipbanlist_head,curr) { entry = elem_get_data(curr); if (!entry) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"ipbanlist contains NULL item"); continue; } if (list_remove_elem(ipbanlist_head,&curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); ipban_unload_entry(entry); } if (list_destroy(ipbanlist_head)<0) return -1; ipbanlist_head = NULL; } return 0; } extern int ipbanlist_load(char const * filename) { FILE * fp; char * buff; char * ip; char * timestr; unsigned int currline; unsigned int endtime; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open banlist file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return -1; } for (currline=1; (buff = file_get_line(fp)); currline++) { ip = buff; /* eat whitespace in front */ while (*ip=='\t' || *ip==' ') ip++; if (*ip=='\0' || *ip=='#') { continue; } /* eat whitespace in back */ while (ip[strlen(ip)-1]==' ' || ip[strlen(ip)-1]=='\t') ip[strlen(ip)-1] = '\0'; if (strchr(ip,' ') || strchr(ip,'\t')) { timestr = ip; while (*timestr!=' ' && *timestr!='\t') timestr++; *timestr = '\0'; timestr++; while (*timestr==' ' || *timestr=='\t') timestr++; } else timestr = NULL; if (!timestr) endtime = 0; else if (clockstr_to_seconds(timestr,&endtime)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not convert to seconds. Banning pernamently."); endtime = 0; } if (ipbanlist_add(NULL,ip,endtime)!=0) { eventlog(eventlog_level_warn,__FUNCTION__,"error in %.64s at line %u",filename,currline); continue; } } file_get_line(NULL); // clear file_get_line buffer if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close banlist file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno)); return 0; } extern int ipbanlist_save(char const * filename) { t_elem const * curr; t_ipban_entry * entry; FILE * fp; char * ipstr; char line[1024]; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(fp = fopen(filename,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open banlist file \"%s\" for writing (fopen: %s)",filename,pstrerror(errno)); return -1; } /* if (ftruncate(fp,0)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not truncate banlist file \"%s\" (ftruncate: %s)",filename,pstrerror(errno)); return -1; }*/ LIST_TRAVERSE_CONST(ipbanlist_head,curr) { entry = elem_get_data(curr); if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"ipbanlist contains NULL element"); continue; } if (!(ipstr = ipban_entry_to_str(entry))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ipstr"); continue; } if (entry->endtime == 0) sprintf(line,"%s\n",ipstr); else sprintf(line,"%s %ld\n",ipstr,entry->endtime); if (!(fwrite(line,strlen(line),1,fp))) eventlog(eventlog_level_error,__FUNCTION__,"could not write to banlist file (write: %s)",pstrerror(errno)); xfree(ipstr); } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close banlist file \"%s\" after writing (fclose: %s)",filename,pstrerror(errno)); return -1; } return 0; } extern int ipbanlist_check(char const * ipaddr) { t_elem const * curr; t_ipban_entry * entry; char * whole; char const * ip1; char const * ip2; char const * ip3; char const * ip4; int counter; if (!ipaddr) { eventlog(eventlog_level_warn,__FUNCTION__,"got NULL ipaddr"); return -1; } whole = xstrdup(ipaddr); eventlog(eventlog_level_debug,__FUNCTION__,"lastcheck: %u, now: %u, now-lc: %u.",(unsigned)lastchecktime,(unsigned)now,(unsigned)(now-lastchecktime)); if (now - lastchecktime >= (signed)prefs_get_ipban_check_int()) /* unsigned; no need to check prefs < 0 */ { ipbanlist_unload_expired(); lastchecktime = now; } ip1 = strtok(whole,"."); ip2 = strtok(NULL,"."); ip3 = strtok(NULL,"."); ip4 = strtok(NULL,"."); if (!ip1 || !ip2 || !ip3 || !ip4) { eventlog(eventlog_level_warn,__FUNCTION__,"got bad IP address \"%s\"",ipaddr); xfree(whole); return -1; } eventlog(eventlog_level_debug,__FUNCTION__,"checking %s.%s.%s.%s",ip1,ip2,ip3,ip4); counter = 0; LIST_TRAVERSE_CONST(ipbanlist_head,curr) { entry = elem_get_data(curr); if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"ipbanlist contains NULL item"); return -1; } counter++; switch (entry->type) { case ipban_type_exact: if (strcmp(entry->info1,ipaddr)==0) { eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched exact %s",ipaddr,entry->info1); xfree(whole); return counter; } eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match exact %s",ipaddr,entry->info1); continue; case ipban_type_wildcard: if (strcmp(entry->info1,"*")!=0 && strcmp(ip1,entry->info1)!=0) { eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match part 1 of wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4); continue; } if (strcmp(entry->info2,"*")!=0 && strcmp(ip2,entry->info2)!=0) { eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match part 2 of wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4); continue; } if (strcmp(entry->info3,"*")!=0 && strcmp(ip3,entry->info3)!=0) { eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match part 3 of wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4); continue; } if (strcmp(entry->info4,"*")!=0 && strcmp(ip4,entry->info4)!=0) { eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match part 4 of wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4); continue; } eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4); xfree(whole); return counter; case ipban_type_range: if ((ipban_str_to_ulong(ipaddr) >= ipban_str_to_ulong(entry->info1)) && (ipban_str_to_ulong(ipaddr) <= ipban_str_to_ulong(entry->info2))) { eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched range %s-%s",ipaddr,entry->info1,entry->info2); xfree(whole); return counter; } eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match range %s-%s",ipaddr,entry->info1,entry->info2); continue; case ipban_type_netmask: { unsigned long lip1; unsigned long lip2; unsigned long netmask; if (!(lip1 = ipban_str_to_ulong(ipaddr))) return -1; if (!(lip2 = ipban_str_to_ulong(entry->info1))) return -1; if (!(netmask = ipban_str_to_ulong(entry->info2))) return -1; lip1 = lip1 & netmask; lip2 = lip2 & netmask; if (lip1 == lip2) { eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched netmask %s/%s",ipaddr,entry->info1,entry->info2); xfree(whole); return counter; } eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match netmask %s/%s",ipaddr,entry->info1,entry->info2); continue; } case ipban_type_prefix: { unsigned long lip1; unsigned long lip2; int prefix; if (!(lip1 = ipban_str_to_ulong(ipaddr))) return -1; if (!(lip2 = ipban_str_to_ulong(entry->info1))) return -1; prefix = atoi(entry->info2); lip1 = lip1 >> (32 - prefix); lip2 = lip2 >> (32 - prefix); if (lip1 == lip2) { eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched prefix %s/%s",ipaddr,entry->info1,entry->info2); xfree(whole); return counter; } eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match prefix %s/%s",ipaddr,entry->info1,entry->info2); continue; } default: /* unknown type */ eventlog(eventlog_level_warn,__FUNCTION__,"found bad ban type %d",(int)entry->type); } } xfree(whole); return 0; } extern int ipbanlist_add(t_connection * c, char const * cp, time_t endtime) { t_ipban_entry * entry; char tstr[MAX_MESSAGE_LEN]; if (!(entry = ipban_str_to_ipban_entry(cp))) { if (c) message_send_text(c,message_type_error,c,"Bad IP."); eventlog(eventlog_level_error,__FUNCTION__,"could not convert to t_ipban_entry: \"%s\"",cp); return -1; } entry->endtime = endtime; list_append_data(ipbanlist_head,entry); if (c) { if (endtime == 0) { sprintf(tstr,"%s banned permamently by %s.",cp,conn_get_username(c)); eventlog(eventlog_level_info,__FUNCTION__,tstr); message_send_admins(c,message_type_info,tstr); sprintf(tstr,"%s banned permamently.",cp); message_send_text(c,message_type_info,c,tstr); } else { sprintf(tstr,"%s banned for %.48s by %s.",cp,seconds_to_timestr(entry->endtime - now),conn_get_username(c)); eventlog(eventlog_level_info,__FUNCTION__,tstr); message_send_admins(c,message_type_info,tstr); sprintf(tstr,"%s banned for %.48s.",cp,seconds_to_timestr(entry->endtime - now)); message_send_text(c,message_type_info,c,tstr); } } return 0; } extern int ipbanlist_unload_expired(void) { t_elem * curr; t_ipban_entry * entry; char removed; removed = 0; LIST_TRAVERSE(ipbanlist_head,curr) { entry = elem_get_data(curr); if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"ipbanlist_contains NULL element"); return -1; } if ((entry->endtime - now <= 0) && (entry->endtime != 0)) { eventlog(eventlog_level_debug,__FUNCTION__,"removing item: %s",entry->info1); removed = 1; if (list_remove_elem(ipbanlist_head,&curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove item"); else ipban_unload_entry(entry); } } if (removed==1) ipbanlist_save(prefs_get_ipbanfile()); return 0; } extern time_t ipbanlist_str_to_time_t(t_connection * c, char const * timestr) { unsigned int bmin; char minstr[MAX_TIME_STR]; unsigned int i; char tstr[MAX_MESSAGE_LEN]; for (i=0; isdigit((int)timestr[i]) && i counter) { sprintf(tstr,"There are only %u entries.",counter); message_send_text(c,message_type_error,c,tstr); return -1; } return 0; } static int ipban_func_list(t_connection * c) { t_elem const * curr; t_ipban_entry * entry; char tstr[MAX_MESSAGE_LEN]; unsigned int counter; char timestr[50]; char * ipstr; counter = 0; message_send_text(c,message_type_info,c,"Banned IPs:"); LIST_TRAVERSE_CONST(ipbanlist_head,curr) { entry = elem_get_data(curr); if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"ipbanlist contains NULL item"); return -1; } counter++; if (entry->endtime == 0) sprintf(timestr,"(perm)"); else sprintf(timestr,"(%.48s)",seconds_to_timestr(entry->endtime - now)); if (!(ipstr = ipban_entry_to_str(entry))) { eventlog(eventlog_level_error,__FUNCTION__,"could not convert entry to string"); continue; } sprintf(tstr,"%u: %s %s",counter,ipstr,timestr); message_send_text(c,message_type_info,c,tstr); xfree(ipstr); } if (counter == 0) message_send_text(c,message_type_info,c,"none"); return 0; } static int ipban_func_check(t_connection * c, char const * cp) { int res; char entry[MAX_MESSAGE_LEN]; res = ipbanlist_check(cp); switch (res) { case 0: message_send_text(c,message_type_info,c,"IP not banned."); break; case -1: message_send_text(c,message_type_error,c,"Error occured."); break; default: sprintf(entry,"IP banned by rule #%i.",res); message_send_text(c,message_type_info,c,entry); } return 0; } static int ipban_identical_entry(t_ipban_entry * e1, t_ipban_entry * e2) { if (e1->type != e2->type) return 0; switch (e2->type) { case ipban_type_exact: if (strcmp(e1->info1,e2->info1)==0) return 1; break; case ipban_type_range: if (strcmp(e1->info1,e2->info1)==0 && strcmp(e1->info2,e2->info2)==0) return 1; break; case ipban_type_wildcard: if (strcmp(e1->info1,e2->info1)==0 && strcmp(e1->info2,e2->info2)==0 && strcmp(e1->info3,e2->info3)==0 && strcmp(e1->info4,e2->info4)==0) return 1; break; case ipban_type_netmask: if (strcmp(e1->info1,e2->info1)==0 && strcmp(e1->info2,e2->info2)==0) return 1; break; case ipban_type_prefix: if (strcmp(e1->info1,e2->info1)==0 && strcmp(e1->info2,e2->info2)==0) return 1; break; default: /* unknown type */ eventlog(eventlog_level_warn,__FUNCTION__,"found bad ban type %d",(int)e2->type); } return 0; } static int ipban_unload_entry(t_ipban_entry * e) { switch (e->type) { case ipban_type_exact: case ipban_type_wildcard: if (e->info1) xfree(e->info1); break; case ipban_type_range: case ipban_type_netmask: case ipban_type_prefix: if (e->info1) xfree(e->info1); if (e->info2) xfree(e->info2); break; default: /* unknown type */ eventlog(eventlog_level_warn,__FUNCTION__,"found bad ban type %d",(int)e->type); return -1; } xfree(e); return 0; } static t_ipban_entry * ipban_str_to_ipban_entry(char const * ipstr) { char * matched; char * whole; char * cp; t_ipban_entry * entry; entry = xmalloc(sizeof(t_ipban_entry)); if (!ipstr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL IP"); xfree(entry); return NULL; } if (ipstr[0] == '\0') { eventlog(eventlog_level_warn,__FUNCTION__,"got empty IP string"); xfree(entry); return NULL; } cp = xstrdup(ipstr); if (ipban_could_be_ip_str(cp)==0) { eventlog(eventlog_level_debug,__FUNCTION__,"string: \"%.32s\" can not be valid IP",cp); xfree(entry); return NULL; } if ((matched = strchr(cp,'-'))) /* range */ { entry->type = ipban_type_range; eventlog(eventlog_level_debug,__FUNCTION__,"entry: %s matched as ipban_type_range",cp); matched[0] = '\0'; entry->info1 = xstrdup(cp); /* start of range */ entry->info2 = xstrdup(&matched[1]); /* end of range */ entry->info3 = NULL; /* clear unused elements so debugging is nicer */ entry->info4 = NULL; } else if (strchr(cp,'*')) /* wildcard */ { entry->type = ipban_type_wildcard; eventlog(eventlog_level_debug,__FUNCTION__,"entry: %s matched as ipban_type_wildcard",cp); /* only xfree() info1! */ whole = xstrdup(cp); entry->info1 = strtok(whole,"."); entry->info2 = strtok(NULL,"."); entry->info3 = strtok(NULL,"."); entry->info4 = strtok(NULL,"."); if (!entry->info4) /* not enough dots */ { eventlog(eventlog_level_error,__FUNCTION__,"wildcard entry \"%s\" does not contain all four octets",cp); xfree(entry->info1); xfree(entry); xfree(cp); return NULL; } } else if ((matched = strchr(cp,'/'))) /* netmask or prefix */ { if (strchr(&matched[1],'.')) { entry->type = ipban_type_netmask; eventlog(eventlog_level_debug,__FUNCTION__,"entry: %s matched as ipban_type_netmask",cp); } else { entry->type = ipban_type_prefix; eventlog(eventlog_level_debug,__FUNCTION__,"entry: %s matched as ipban_type_prefix",cp); } matched[0] = '\0'; entry->info1 = xstrdup(cp); entry->info2 = xstrdup(&matched[1]); entry->info3 = NULL; /* clear unused elements so debugging is nicer */ entry->info4 = NULL; } else /* exact */ { entry->type = ipban_type_exact; eventlog(eventlog_level_debug,__FUNCTION__,"entry: %s matched as ipban_type_exact",cp); entry->info1 = xstrdup(cp); entry->info2 = NULL; /* clear unused elements so debugging is nicer */ entry->info3 = NULL; entry->info4 = NULL; } xfree(cp); return entry; } static char * ipban_entry_to_str(t_ipban_entry const * entry) { char tstr[MAX_MESSAGE_LEN]; char * str; switch (entry->type) { case ipban_type_exact: sprintf(tstr,"%s",entry->info1); break; case ipban_type_wildcard: sprintf(tstr,"%s.%s.%s.%s",entry->info1,entry->info2,entry->info3,entry->info4); break; case ipban_type_range: sprintf(tstr,"%s-%s",entry->info1,entry->info2); break; case ipban_type_netmask: case ipban_type_prefix: sprintf(tstr,"%s/%s",entry->info1,entry->info2); break; default: /* unknown type */ eventlog(eventlog_level_warn,__FUNCTION__,"found bad ban type %d",(int)entry->type); return NULL; } str = xstrdup(tstr); return str; } static unsigned long ipban_str_to_ulong(char const * ipaddr) { unsigned long lip; char * ip1; char * ip2; char * ip3; char * ip4; char * tipaddr; tipaddr = xstrdup(ipaddr); ip1 = strtok(tipaddr,"."); ip2 = strtok(NULL,"."); ip3 = strtok(NULL,"."); ip4 = strtok(NULL,"."); lip = (atoi(ip1) << 24) + (atoi(ip2) << 16) + (atoi(ip3) << 8) + (atoi(ip4)); xfree(tipaddr); return lip; } static int ipban_could_be_exact_ip_str(char const * str) { char * ipstr; char * s; char * ttok; int i; ipstr = xstrdup(str); s = ipstr; for (i=0; i<4; i++) { ttok = (char *)strsep(&ipstr, "."); if (!ttok || strlen(ttok)<1 || strlen(ttok)>3) { xfree(s); return 0; } } xfree(s); return 1; } static int ipban_could_be_ip_str(char const * str) { char * matched; char * ipstr; unsigned int i; if (strlen(str)<7) { eventlog(eventlog_level_error,__FUNCTION__,"string too short"); return 0; } for (i=0; i32) /* can not be less than 0 because IP/-24 is matched as range */ { xfree(ipstr); return 0; } } } else { if (ipban_could_be_exact_ip_str(ipstr)==0) { xfree(ipstr); return 0; } } xfree(ipstr); return 1; } static void ipban_usage(t_connection * c) { message_send_text(c,message_type_info,c,"to print this information:"); message_send_text(c,message_type_info,c," /ipban h[elp]"); message_send_text(c,message_type_info,c,"to print all baned IPs"); message_send_text(c,message_type_info,c," /ipban [l[ist]]"); message_send_text(c,message_type_info,c,"to erase ban:"); message_send_text(c,message_type_info,c," /ipban d[el] "); message_send_text(c,message_type_info,c," (IP have to be entry accepted in bnban)"); message_send_text(c,message_type_info,c,"to add ban:"); message_send_text(c,message_type_info,c," /ipban a[dd] IP"); message_send_text(c,message_type_info,c," (IP have to be entry accepted in bnban)"); message_send_text(c,message_type_info,c,"to check is specified IP banned:"); message_send_text(c,message_type_info,c," /ipban c[heck] IP"); } pvpgn-1.8.5/src/bnetd/file_plain.h0000644000175000017500000000034111151345317015776 0ustar aaronaaron#ifndef JUST_NEED_TYPES #ifndef INClUDED_FILE_PLAIN_PROTOS #define INClUDED_FILE_PLAIN_PROTOS #include "storage_file.h" extern t_file_engine file_plain; #endif /* INClUDED_FILE_PLAIN_PROTOS */ #endif /* JUST_NEED_TYPES */ pvpgn-1.8.5/src/bnetd/sql_mysql.c0000644000175000017500000001624711151345317015727 0ustar aaronaaron/* * Copyright (C) 2002,2003 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef WITH_SQL_MYSQL #include "common/setup_before.h" #ifdef WIN32 #include #include #else #include #endif #include #include "common/eventlog.h" #include "common/xalloc.h" #include "storage_sql.h" #include "sql_mysql.h" #include "common/setup_after.h" static int sql_mysql_init(const char *, const char *, const char *, const char *, const char *, const char *); static int sql_mysql_close(void); static t_sql_res * sql_mysql_query_res(const char *); static int sql_mysql_query(const char *); static t_sql_row * sql_mysql_fetch_row(t_sql_res *); static void sql_mysql_free_result(t_sql_res *); static unsigned int sql_mysql_num_rows(t_sql_res *); static unsigned int sql_mysql_num_fields(t_sql_res *); static unsigned int sql_mysql_affected_rows(void); static t_sql_field * sql_mysql_fetch_fields(t_sql_res *); static int sql_mysql_free_fields(t_sql_field *); static void sql_mysql_escape_string(char *, const char *, int); t_sql_engine sql_mysql = { '`', sql_mysql_init, sql_mysql_close, sql_mysql_query_res, sql_mysql_query, sql_mysql_fetch_row, sql_mysql_free_result, sql_mysql_num_rows, sql_mysql_num_fields, sql_mysql_affected_rows, sql_mysql_fetch_fields, sql_mysql_free_fields, sql_mysql_escape_string }; static MYSQL *mysql = NULL; static int sql_mysql_init(const char *host, const char *port, const char *socket, const char *name, const char *user, const char *pass) { if (name == NULL || user == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL parameter"); return -1; } if ((mysql = mysql_init(NULL)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got error from mysql_init"); return -1; } #if MYSQL_VERSION_ID >= 50003 #if MYSQL_VERSION_ID < 50013 eventlog(eventlog_level_warn,__FUNCTION__,"Your mySQL client lib version does not support reconnecting after a timeout."); eventlog(eventlog_level_warn,__FUNCTION__,"If this causes you any trouble you are advices to upgrade"); eventlog(eventlog_level_warn,__FUNCTION__,"your mySQL client libs to at least mySQL 5.0.13 to resolve this problem."); // we might try a dirty hack like the following, but I'm not sure if it will work // mysql->reconnect = 1; #endif #if MYSQL_VERSION_ID >= 50019 my_bool my_true = (my_bool)1; if (mysql_options(mysql, MYSQL_OPT_RECONNECT, &my_true)){ eventlog(eventlog_level_warn,__FUNCTION__,"Failed to turn on MYSQL_OPT_RECONNECT."); }else{ eventlog(eventlog_level_info,__FUNCTION__,"Successfully turned on MYSQL_OPT_RECONNECT."); } #endif #endif if (mysql_real_connect(mysql, host, user, pass, name, port ? atoi(port) : 0, socket, CLIENT_FOUND_ROWS) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "error connecting to database (db said: '%s')", mysql_error(mysql)); mysql_close(mysql); return -1; } #if MYSQL_VERSION_ID >= 50013 #if MYSQL_VERSION_ID < 50019 my_bool my_true = (my_bool)1; if (mysql_options(mysql, MYSQL_OPT_RECONNECT, &my_true)){ eventlog(eventlog_level_warn,__FUNCTION__,"Failed to turn on MYSQL_OPT_RECONNECT."); }else{ eventlog(eventlog_level_info,__FUNCTION__,"Successfully turned on MYSQL_OPT_RECONNECT."); } #endif #endif return 0; } static int sql_mysql_close(void) { if (mysql) { mysql_close(mysql); mysql = NULL; } return 0; } static t_sql_res * sql_mysql_query_res(const char * query) { t_sql_res *res; if (mysql == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "mysql driver not initilized"); return NULL; } if (query == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL query"); return NULL; } if (mysql_query(mysql, query)) { // eventlog(eventlog_level_debug, __FUNCTION__, "got error from query (%s)", query); return NULL; } res = mysql_store_result(mysql); if (res == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got error from store result"); return NULL; } return res; } static int sql_mysql_query(const char * query) { if (mysql == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "mysql driver not initilized"); return -1; } if (query == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL query"); return -1; } return mysql_query(mysql, query) == 0 ? 0 : -1; } static t_sql_row * sql_mysql_fetch_row(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return NULL; } return mysql_fetch_row((MYSQL_RES *)result); } static void sql_mysql_free_result(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return; } mysql_free_result((MYSQL_RES *)result); } static unsigned int sql_mysql_num_rows(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return 0; } return mysql_num_rows((MYSQL_RES *)result); } static unsigned int sql_mysql_num_fields(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return 0; } return mysql_num_fields((MYSQL_RES *)result); } static unsigned int sql_mysql_affected_rows(void) { return mysql_affected_rows(mysql); } static t_sql_field * sql_mysql_fetch_fields(t_sql_res *result) { MYSQL_FIELD *fields; unsigned fieldno, i; t_sql_field *rfields; if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return NULL; } fieldno = mysql_num_fields((MYSQL_RES *)result); fields = mysql_fetch_fields((MYSQL_RES *)result); rfields = xmalloc(sizeof(t_sql_field) * (fieldno + 1)); for(i = 0; i < fieldno; i++) rfields[i] = fields[i].name; rfields[i] = NULL; return rfields; } static int sql_mysql_free_fields(t_sql_field *fields) { if (fields == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL fields"); return -1; } xfree((void*)fields); return 0; /* mysql_free_result() should free the rest properly */ } static void sql_mysql_escape_string(char *escape, const char *from, int len) { if (mysql == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "mysql driver not initilized"); return; } mysql_real_escape_string(mysql, escape, from, len); } #endif /* WITH_SQL_MYSQL */ pvpgn-1.8.5/src/bnetd/main.c0000644000175000017500000004004011151345317014613 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include #include "compat/strerror.h" #ifdef HAVE_UNISTD_H # include #endif #include "compat/stdfileno.h" #include "compat/psock.h" #include "common/hexdump.h" #include "channel.h" #include "game.h" #include "server.h" #include "common/eventlog.h" #include "account.h" #include "connection.h" #include "game.h" #include "common/version.h" #include "prefs.h" #include "ladder.h" #include "adbanner.h" #include "ipban.h" #include "autoupdate.h" #include "helpfile.h" #include "timer.h" #include "watch.h" #include "common/tracker.h" #include "realm.h" #include "character.h" #include "common/give_up_root_privileges.h" #include "versioncheck.h" #include "storage.h" #include "anongame.h" #include "command_groups.h" #include "output.h" #include "alias_command.h" #include "anongame_infos.h" #include "anongame_maplists.h" #include "tournament.h" #include "news.h" #include "clan.h" #include "team.h" #include "topic.h" #include "support.h" #include "common/trans.h" #include "common/xalloc.h" #include "common/fdwatch.h" #include "attrlayer.h" #ifdef WIN32 # include "win32/service.h" #endif #ifdef WIN32_GUI # include "win32/winmain.h" # define printf gui_printf #endif #include "cmdline.h" #include "common/setup_after.h" /* out of memory safety */ #define OOM_SAFE_MEM 1000000 /* 1 Mbyte of safety memory */ void *oom_buffer = NULL; static int bnetd_oom_handler(void) { /* no safety buffer, sorry :( */ if (!oom_buffer) return 0; /* free the safety buffer hoping next allocs will succeed */ free(oom_buffer); oom_buffer = NULL; eventlog(eventlog_level_fatal,__FUNCTION__,"out of memory, forcing immediate shutdown"); /* shutdown immediatly */ server_quit_delay(-1); return 1; /* ask xalloc codes to retry the allocation request */ } static int oom_setup(void) { /* use calloc so it initilizez the memory so it will make some lazy * allocators really alocate it (ex. the linux kernel) */ oom_buffer = calloc(1, OOM_SAFE_MEM); if (!oom_buffer) return -1; xalloc_setcb(bnetd_oom_handler); return 0; } static void oom_free(void) { if (oom_buffer) free(oom_buffer); oom_buffer = NULL; } FILE *hexstrm = NULL; char serviceLongName[] = "PvPGN service"; char serviceName[] = "pvpgn"; char serviceDescription[] = "Player vs. Player Gaming Network - Server"; /* * by quetzal. indicates service status * -1 - not in service mode * 0 - stopped * 1 - running * 2 - paused */ int g_ServiceStatus = -1; /* added some more exit status --> put in "compat/exitstatus.h" ??? */ #define STATUS_OOM_FAILURE 20 #define STATUS_STORAGE_FAILURE 30 #define STATUS_PSOCK_FAILURE 35 #define STATUS_MAPLISTS_FAILURE 40 #define STATUS_MATCHLISTS_FAILURE 50 #define STATUS_LADDERLIST_FAILURE 60 #define STATUS_WAR3XPTABLES_FAILURE 70 #define STATUS_SUPPORT_FAILURE 80 #define STATUS_FDWATCH_FAILURE 90 int pre_server_startup(void); void post_server_shutdown(int status); int eventlog_startup(void); int fork_bnetd(int foreground); char * write_to_pidfile(void); void pvpgn_greeting(void); int eventlog_startup(void) { char const * levels; char * temp; char const * tok; eventlog_clear_level(); if ((levels = prefs_get_loglevels())) { temp = xstrdup(levels); tok = strtok(temp,","); /* strtok modifies the string it is passed */ while (tok) { if (eventlog_add_level(tok)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add log level \"%s\"",tok); tok = strtok(NULL,","); } xfree(temp); } if (eventlog_open(prefs_get_logfile())<0) { if (prefs_get_logfile()) { eventlog(eventlog_level_fatal,__FUNCTION__,"could not use file \"%s\" for the eventlog (exiting)",prefs_get_logfile()); } else { eventlog(eventlog_level_fatal,__FUNCTION__,"no logfile specified in configuration file \"%s\" (exiting)",cmdline_get_preffile()); } return -1; } eventlog(eventlog_level_info,__FUNCTION__,"logging event levels: %s",prefs_get_loglevels()); return 0; } int fork_bnetd(int foreground) { int pid; #ifdef DO_DAEMONIZE if (!foreground) { if (chdir("/")<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not change working directory to / (chdir: %s)",pstrerror(errno)); return -1; } switch ((pid = fork())) { case -1: eventlog(eventlog_level_error,__FUNCTION__,"could not fork (fork: %s)",pstrerror(errno)); return -1; case 0: /* child */ break; default: /* parent */ return pid; } #ifndef WITH_D2 close(STDINFD); close(STDOUTFD); close(STDERRFD); #endif # ifdef HAVE_SETPGID if (setpgid(0,0)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgid: %s)",pstrerror(errno)); return -1; } # else # ifdef HAVE_SETPGRP # ifdef SETPGRP_VOID if (setpgrp()<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)",pstrerror(errno)); return -1; } # else if (setpgrp(0,0)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)",pstrerror(errno)); return -1; } # endif # else # ifdef HAVE_SETSID if (setsid()<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setsid: %s)",pstrerror(errno)); return -1; } # else # error "One of setpgid(), setpgrp(), or setsid() is required" # endif # endif # endif } return 0; #endif return 0; } char * write_to_pidfile(void) { char *pidfile = xstrdup(prefs_get_pidfile()); if (pidfile[0]=='\0') { xfree((void *)pidfile); /* avoid warning */ return NULL; } if (pidfile) { #ifdef HAVE_GETPID FILE * fp; if (!(fp = fopen(pidfile,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to open pid file \"%s\" for writing (fopen: %s)",pidfile,pstrerror(errno)); xfree((void *)pidfile); /* avoid warning */ return NULL; } else { fprintf(fp,"%u",(unsigned int)getpid()); if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close pid file \"%s\" after writing (fclose: %s)",pidfile,pstrerror(errno)); } #else eventlog(eventlog_level_warn,__FUNCTION__,"no getpid() system call, disable pid file in bnetd.conf"); xfree((void *)pidfile); /* avoid warning */ return NULL; #endif } return pidfile; } int pre_server_startup(void) { pvpgn_greeting(); if (oom_setup() < 0) { eventlog(eventlog_level_error, __FUNCTION__, "OOM init failed"); return STATUS_OOM_FAILURE; } if (storage_init(prefs_get_storage_path()) < 0) { eventlog(eventlog_level_error, "pre_server_startup", "storage init failed"); return STATUS_STORAGE_FAILURE; } if (psock_init() < 0) { eventlog(eventlog_level_error, __FUNCTION__, "could not initialize socket functions"); return STATUS_PSOCK_FAILURE; } if (support_check_files(prefs_get_supportfile()) < 0) { eventlog(eventlog_level_error, "pre_server_startup","some needed files are missing"); eventlog(eventlog_level_error, "pre_server_startup","please make sure you installed the supportfiles in %s",prefs_get_filedir()); return STATUS_SUPPORT_FAILURE; } if (anongame_maplists_create() < 0) { eventlog(eventlog_level_error, "pre_server_startup", "could not load maps"); return STATUS_MAPLISTS_FAILURE; } if (anongame_matchlists_create() < 0) { eventlog(eventlog_level_error, "pre_server_startup", "could not create matchlists"); return STATUS_MATCHLISTS_FAILURE; } if (fdwatch_init(prefs_get_max_connections())) { eventlog(eventlog_level_error, __FUNCTION__, "error initilizing fdwatch"); return STATUS_FDWATCH_FAILURE; } connlist_create(); gamelist_create(); timerlist_create(); server_set_hostname(); channellist_create(); if (helpfile_init(prefs_get_helpfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load helpfile"); ipbanlist_create(); if (ipbanlist_load(prefs_get_ipbanfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load IP ban list"); if (adbannerlist_create(prefs_get_adfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load adbanner list"); if (autoupdate_load(prefs_get_mpqfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load autoupdate list"); if (versioncheck_load(prefs_get_versioncheck_file())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load versioncheck list"); if (news_load(prefs_get_newsfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load news list"); watchlist_create(); output_init(); attrlayer_init(); accountlist_create(); if (ladder_createxptable(prefs_get_xplevel_file(),prefs_get_xpcalc_file())<0) { eventlog(eventlog_level_error, "pre_server_startup", "could not load WAR3 xp calc tables"); return STATUS_WAR3XPTABLES_FAILURE; } ladders_init(); ladders_load_accounts_to_ladderlists(); ladder_update_all_accounts(); if (characterlist_create("")<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load character list"); if (prefs_get_track()) /* setup the tracking mechanism */ tracker_set_servers(prefs_get_trackserv_addrs()); if (command_groups_load(prefs_get_command_groups_file())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load command_groups list"); aliasfile_load(prefs_get_aliasfile()); if (trans_load(prefs_get_transfile(),TRANS_BNETD)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load trans list"); tournament_init(prefs_get_tournament_file()); anongame_infos_load(prefs_get_anongame_infos_file()); clanlist_load(); teamlist_load(); if (realmlist_create(prefs_get_realmfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load realm list"); topiclist_load(prefs_get_topicfile()); return 0; } void post_server_shutdown(int status) { switch (status) { case 0: topiclist_unload(); realmlist_destroy(); teamlist_unload(); clanlist_unload(); tournament_destroy(); anongame_infos_unload(); trans_unload(); aliasfile_unload(); command_groups_unload(); tracker_set_servers(NULL); characterlist_destroy(); ladder_destroyxptable(); case STATUS_WAR3XPTABLES_FAILURE: case STATUS_LADDERLIST_FAILURE: ladder_update_all_accounts(); ladders_destroy(); output_dispose_filename(); accountlist_destroy(); attrlayer_cleanup(); watchlist_destroy(); news_unload(); versioncheck_unload(); autoupdate_unload(); adbannerlist_destroy(); ipbanlist_save(prefs_get_ipbanfile()); ipbanlist_destroy(); helpfile_unload(); channellist_destroy(); server_clear_hostname(); timerlist_destroy(); gamelist_destroy(); connlist_destroy(); fdwatch_close(); case STATUS_FDWATCH_FAILURE: anongame_matchlists_destroy(); case STATUS_MATCHLISTS_FAILURE: anongame_maplists_destroy(); case STATUS_MAPLISTS_FAILURE: case STATUS_SUPPORT_FAILURE: if (psock_deinit()) eventlog(eventlog_level_error, __FUNCTION__, "got error from psock_deinit()"); case STATUS_PSOCK_FAILURE: storage_close(); case STATUS_STORAGE_FAILURE: oom_free(); case STATUS_OOM_FAILURE: case -1: break; default: eventlog(eventlog_level_error,__FUNCTION__,"got bad status \"%d\" during shutdown",status); } return; } void pvpgn_greeting(void) { #ifdef HAVE_GETPID eventlog(eventlog_level_info,__FUNCTION__,PVPGN_SOFTWARE" version "PVPGN_VERSION" process %u",(unsigned int)getpid()); #else eventlog(eventlog_level_info,__FUNCTION__,PVPGN_SOFTWARE" version "PVPGN_VERSION); #endif printf("You are currently Running "PVPGN_SOFTWARE" "PVPGN_VERSION"\n"); printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"); printf("If you need support:\n"); printf(" * READ the documentation at http://pvpgndocs.berlios.de/\n"); printf(" * you can subscribe to the pvpgn-users mailing list at \n"); printf(" https://lists.berlios.de/mailman/listinfo/pvpgn-users\n"); printf(" * you can try our wiki page at http://wiki.pvpgn.org \n"); printf(" * check out the forums at https://forums.pvpgn.org\n"); printf(" * visit us on IRC on irc.pvpgn.org channel #pvpgn\n"); printf("\nServer is now running.\n"); printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"); return; } #ifdef WIN32_GUI extern int server_main(int argc, char * * argv) #else extern int main(int argc, char * * argv) #endif { int a; char *pidfile; if ((a = cmdline_load(argc, argv)) != 1) return a; #ifdef DO_DAEMONIZE if ((a = fork_bnetd(cmdline_get_foreground())) != 0) return a < 0 ? a : 0; /* dont return code != 0 when things are OK! */ #endif eventlog_set(stderr); /* errors to eventlog from here on... */ if (prefs_load(cmdline_get_preffile())<0) { eventlog(eventlog_level_fatal,__FUNCTION__,"could not parse configuration file (exiting)"); return -1; } /* Start logging to log file */ if (eventlog_startup() == -1) return -1; /* eventlog goes to log file from here on... */ /* Give up root privileges */ /* Hakan: That's way too late to give up root privileges... Have to look for a better place */ if (give_up_root_privileges(prefs_get_effective_user(),prefs_get_effective_group())<0) { eventlog(eventlog_level_fatal,__FUNCTION__,"could not give up privileges (exiting)"); return -1; } /* Write the pidfile */ pidfile = write_to_pidfile(); if (cmdline_get_hexfile()) { if (!(hexstrm = fopen(cmdline_get_hexfile(),"w"))) eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for writing the hexdump (fopen: %s)",cmdline_get_hexfile(),pstrerror(errno)); else fprintf(hexstrm,"# dump generated by "PVPGN_SOFTWARE" version "PVPGN_VERSION"\n"); } /* Run the pre server stuff */ a = pre_server_startup(); /* now process connections and network traffic */ if (a == 0) { if (server_process() < 0) eventlog(eventlog_level_fatal,__FUNCTION__,"failed to initialize network (exiting)"); } // run post server stuff and exit post_server_shutdown(a); // Close hexfile if (hexstrm) { fprintf(hexstrm,"# end of dump\n"); if (fclose(hexstrm)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close hexdump file \"%s\" after writing (fclose: %s)",cmdline_get_hexfile(),pstrerror(errno)); } // Delete pidfile if (pidfile) { if (remove(pidfile)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove pid file \"%s\" (remove: %s)",pidfile,pstrerror(errno)); xfree((void *)pidfile); /* avoid warning */ } if (a == 0) eventlog(eventlog_level_info,__FUNCTION__,"server has shut down"); prefs_unload(); eventlog_close(); cmdline_unload(); if (a == 0) return 0; return -1; } pvpgn-1.8.5/src/bnetd/adbanner.c0000644000175000017500000003601411151345317015447 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define ADBANNER_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_ASSERT_H # include #endif #include "compat/strrchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include #include "compat/strerror.h" #include "common/tag.h" #include "common/bn_type.h" #include "common/eventlog.h" #include "common/list.h" #include "common/util.h" #include "common/xalloc.h" #include "connection.h" #include "adbanner.h" #include "common/setup_after.h" static t_list * adbannerlist_init_head=NULL; static t_list * adbannerlist_start_head=NULL; static t_list * adbannerlist_norm_head=NULL; static unsigned int adbannerlist_init_count=0; static unsigned int adbannerlist_start_count=0; static unsigned int adbannerlist_norm_count=0; static t_adbanner * adbanner_create(unsigned int id, unsigned int next_id, unsigned int delay, bn_int tag, char const * filename, char const * link, char const * client); static int adbanner_destroy(t_adbanner const * ad); static int adbannerlist_insert(t_list * head, unsigned int * count, char const * filename, unsigned int delay, char const * link, unsigned int next_id, char const * client); static t_adbanner * adbannerlist_find_adbanner_by_id(t_list const * head, unsigned int id, t_clienttag clienttag); static t_adbanner * adbannerlist_get_random(t_list const * head, t_clienttag client); static t_adbanner * adbanner_create(unsigned int id, unsigned int next_id, unsigned int delay, bn_int tag, char const * filename, char const * link, char const * client) { t_adbanner * ad; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return NULL; } if (!link) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL link"); return NULL; } if (!client) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL client"); return NULL; } ad = xmalloc(sizeof(t_adbanner)); ad->id = id; ad->extensiontag = bn_int_get(tag); ad->delay = delay; ad->next = next_id; ad->filename = xstrdup(filename); ad->link = xstrdup(link); if (strcasecmp(client,"NULL")==0) ad->client = 0; else ad->client = clienttag_str_to_uint(client); /* I'm aware that this statement looks stupid */ if (ad->client && (!tag_check_client(ad->client))) { eventlog(eventlog_level_error,__FUNCTION__,"banner with invalid clienttag \"%s\"encountered",client); xfree((void *)ad->link); xfree((void *)ad->filename); /* avoid warning */ xfree(ad); return NULL; } eventlog(eventlog_level_debug,__FUNCTION__,"created ad id=0x%08x filename=\"%s\" extensiontag=0x%04x delay=%u link=\"%s\" next_id=0x%08x client=\"%s\"",ad->id,ad->filename,ad->extensiontag,ad->delay,ad->link,ad->next,ad->client?client:""); return ad; } static int adbanner_destroy(t_adbanner const * ad) { if (!ad) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ad"); return -1; } xfree((void *)ad->filename); /* avoid warning */ xfree((void *)ad->link); /* avoid warning */ xfree((void *)ad); /* avoid warning */ return 0; } extern t_adbanner * adbanner_get(t_connection const * c, unsigned int id) { t_adbanner * banner; t_clienttag ctag = conn_get_clienttag(c); banner = adbannerlist_find_adbanner_by_id(adbannerlist_init_head,id,ctag); if (!banner) banner = adbannerlist_find_adbanner_by_id(adbannerlist_start_head,id,ctag); if (!banner) banner = adbannerlist_find_adbanner_by_id(adbannerlist_norm_head,id,ctag); return banner; } extern t_adbanner * adbanner_pick(t_connection const * c, unsigned int prev_id) { t_adbanner const * prev; unsigned int next_id; t_clienttag ctag; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } ctag = conn_get_clienttag(c); /* eventlog(eventlog_level_debug,__FUNCTION__,"prev_id=%u init_count=%u start_count=%u norm_count=%u",prev_id,adbannerlist_init_count,adbannerlist_start_count,adbannerlist_norm_count); */ /* if this is the first ad, randomly choose an init sequence (if there is one) */ if (prev_id==0 && adbannerlist_init_count>0) return adbannerlist_get_random(adbannerlist_init_head,ctag); // return list_get_data_by_pos(adbannerlist_init_head,((unsigned int)rand())%adbannerlist_init_count); /* eventlog(eventlog_level_debug,__FUNCTION__,"not sending init banner"); */ /* find the previous adbanner */ if ((prev = adbannerlist_find_adbanner_by_id(adbannerlist_init_head,prev_id,ctag))) next_id = prev->next; else if ((prev = adbannerlist_find_adbanner_by_id(adbannerlist_start_head,prev_id,ctag))) next_id = prev->next; else if ((prev = adbannerlist_find_adbanner_by_id(adbannerlist_norm_head,prev_id,ctag))) next_id = prev->next; else next_id = 0; /* return its next ad if there is one */ if (next_id) { t_adbanner * curr; if ((curr = adbannerlist_find_adbanner_by_id(adbannerlist_init_head,next_id,ctag))) return curr; if ((curr = adbannerlist_find_adbanner_by_id(adbannerlist_start_head,next_id,ctag))) return curr; if ((curr = adbannerlist_find_adbanner_by_id(adbannerlist_norm_head,next_id,ctag))) return curr; eventlog(eventlog_level_error,__FUNCTION__,"could not locate next requested ad with id 0x%06x",next_id); } /* eventlog(eventlog_level_debug,__FUNCTION__,"not sending next banner"); */ /* otherwise choose another starting point randomly */ if (adbannerlist_start_count>0) return adbannerlist_get_random(adbannerlist_start_head,ctag); /* eventlog(eventlog_level_debug,__FUNCTION__,"not sending start banner... nothing to return"); */ return NULL; /* nothing else to return */ } extern unsigned int adbanner_get_id(t_adbanner const * ad) { if (!ad) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ad"); return 0; } return ad->id; } extern unsigned int adbanner_get_extensiontag(t_adbanner const * ad) { if (!ad) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ad"); return 0; } return ad->extensiontag; } extern char const * adbanner_get_filename(t_adbanner const * ad) { if (!ad) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ad"); return NULL; } return ad->filename; } extern char const * adbanner_get_link(t_adbanner const * ad) { if (!ad) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ad"); return NULL; } return ad->link; } extern t_clienttag adbanner_get_client(t_adbanner const * ad) { if (!ad) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ad"); return CLIENTTAG_UNKNOWN_UINT; } return ad->client; } static t_adbanner * adbannerlist_find_adbanner_by_id(t_list const * head, unsigned int id, t_clienttag clienttag) { t_elem const * curr; t_adbanner * temp; if (!head) return NULL; LIST_TRAVERSE_CONST(head,curr) { if (!(temp = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL adbanner in list"); continue; } if (temp->id==id && (temp->client == 0 || temp->client == clienttag)) return temp; } return NULL; } /* * Dizzy: maybe we should use a temporary list, right now we parse the list for * 2 times. It should not matter for servers without more than 20 ads :) */ static t_adbanner * adbannerlist_get_random(t_list const * head, t_clienttag client) { t_elem const * curr; t_adbanner * temp; unsigned int ccount, ocount, pos; if (!head) return NULL; ocount = 0; ccount = 0; LIST_TRAVERSE_CONST(head,curr) { if (!(temp = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL adbanner in list"); continue; } if ((adbanner_get_client(temp) == client)) ccount++; else if ((adbanner_get_client(temp) == 0)) ocount++; } if (ccount) { pos = ((unsigned int)rand())%ccount; ccount = 0; LIST_TRAVERSE_CONST(head,curr) { if (!(temp = elem_get_data(curr))) continue; if ((adbanner_get_client(temp) == client)) if (ccount++ == pos) return temp; } eventlog(eventlog_level_error,__FUNCTION__,"found client ads but couldnt locate random chosed!"); } else if (ocount) { pos = ((unsigned int)rand())%ocount; ocount = 0; LIST_TRAVERSE_CONST(head,curr) { if (!(temp = elem_get_data(curr))) continue; if ((adbanner_get_client(temp) == 0)) if (ocount++ == pos) return temp; } eventlog(eventlog_level_error,__FUNCTION__,"couldnt locate random chosed!"); } return NULL; } static int adbannerlist_insert(t_list * head, unsigned int * count, char const * filename, unsigned int delay, char const * link, unsigned int next_id, char const * client) { t_adbanner * ad; unsigned int id; char * ext; bn_int bntag; assert(head != NULL); assert(count != NULL); assert(filename != NULL); assert(link != NULL); if (strlen(filename)<7) { eventlog(eventlog_level_error,__FUNCTION__,"got bad ad filename \"%s\"",filename); return -1; } ext = xmalloc(strlen(filename)); if (sscanf(filename,"%*c%*c%x.%s",&id,ext)!=2) { eventlog(eventlog_level_error,__FUNCTION__,"got bad ad filename \"%s\"",filename); xfree(ext); return -1; } if (strcasecmp(ext,"pcx")==0) bn_int_tag_set(&bntag,EXTENSIONTAG_PCX); else if (strcasecmp(ext,"mng")==0) bn_int_tag_set(&bntag,EXTENSIONTAG_MNG); else if (strcasecmp(ext,"smk")==0) bn_int_tag_set(&bntag,EXTENSIONTAG_SMK); else { eventlog(eventlog_level_error,__FUNCTION__,"unknown extension on filename \"%s\"",filename); xfree(ext); return -1; } xfree(ext); if (!(ad = adbanner_create(id,next_id,delay,bntag,filename,link,client))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create ad"); return -1; } list_prepend_data(head,ad); (*count)++; return 0; } extern int adbannerlist_create(char const * filename) { FILE * fp; unsigned int line; unsigned int pos; unsigned int len; char * buff; char * name; char * when; char * link; char * client; char * temp; unsigned int delay; unsigned int next_id; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } adbannerlist_init_head = list_create(); adbannerlist_start_head = list_create(); adbannerlist_norm_head = list_create(); if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open adbanner file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); list_destroy(adbannerlist_norm_head); list_destroy(adbannerlist_start_head); list_destroy(adbannerlist_init_head); adbannerlist_init_head=adbannerlist_start_head=adbannerlist_norm_head = NULL; return -1; } for (line=1; (buff = file_get_line(fp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if ((temp = strrchr(buff,'#'))) { unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } len = strlen(buff)+1; name = xmalloc(len); when = xmalloc(len); link = xmalloc(len); client = xmalloc(len); if (sscanf(buff," \"%[^\"]\" %[a-z] %u \"%[^\"]\" %x \"%[^\"]\"",name,when,&delay,link,&next_id,client)!=6) { eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\"",line,filename); xfree(client); xfree(link); xfree(name); xfree(when); continue; } if (strcmp(when,"init")==0) adbannerlist_insert(adbannerlist_init_head,&adbannerlist_init_count,name,delay,link,next_id,client); else if (strcmp(when,"start")==0) adbannerlist_insert(adbannerlist_start_head,&adbannerlist_start_count,name,delay,link,next_id,client); else if (strcmp(when,"norm")==0) adbannerlist_insert(adbannerlist_norm_head,&adbannerlist_norm_count,name,delay,link,next_id,client); else eventlog(eventlog_level_error,__FUNCTION__,"when field has unknown value on line %u in file \"%s\"",line,filename); xfree(client); xfree(link); xfree(name); xfree(when); } file_get_line(NULL); // clear file_get_line buffer if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close adbanner file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno)); return 0; } extern int adbannerlist_destroy(void) { t_elem * curr; t_adbanner * ad; if (adbannerlist_init_head) { LIST_TRAVERSE(adbannerlist_init_head,curr) { if (!(ad = elem_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL adbanner in init list"); else adbanner_destroy(ad); list_remove_elem(adbannerlist_init_head,&curr); } list_destroy(adbannerlist_init_head); adbannerlist_init_head = NULL; adbannerlist_init_count = 0; } if (adbannerlist_start_head) { LIST_TRAVERSE(adbannerlist_start_head,curr) { if (!(ad = elem_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL adbanner in start list"); else adbanner_destroy(ad); list_remove_elem(adbannerlist_start_head,&curr); } list_destroy(adbannerlist_start_head); adbannerlist_start_head = NULL; adbannerlist_start_count = 0; } if (adbannerlist_norm_head) { LIST_TRAVERSE(adbannerlist_norm_head,curr) { if (!(ad = elem_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL adbanner in norm list"); else adbanner_destroy(ad); list_remove_elem(adbannerlist_norm_head,&curr); } list_destroy(adbannerlist_norm_head); adbannerlist_norm_head = NULL; adbannerlist_norm_count = 0; } return 0; } pvpgn-1.8.5/src/bnetd/handle_irc.h0000644000175000017500000000171711151345317015774 0ustar aaronaaron/* * Copyright (C) 2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_HANDLE_IRC_PROTOS #define INCLUDED_HANDLE_IRC_PROTOS extern int handle_irc_packet(t_connection * conn,t_packet const * const packet); #endif #endif pvpgn-1.8.5/src/bnetd/connection.c0000644000175000017500000031006011151345317016030 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define CONNECTION_INTERNAL_ACCESS #include "common/setup_before.h" #include // amadeo #ifdef WIN32_GUI #include #endif #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/strtoul.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_ASSERT_H # include #endif #include "compat/strchr.h" #include "compat/strrchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include #include "compat/strerror.h" #ifdef HAVE_UNISTD_H # include #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/difftime.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/psock.h" #include "common/eventlog.h" #include "common/addr.h" #include "account.h" #include "account_wrap.h" #include "realm.h" #include "channel.h" #include "game.h" #include "common/queue.h" #include "tick.h" #include "common/packet.h" #include "common/tag.h" #include "common/bn_type.h" #include "message.h" #include "common/version.h" #include "prefs.h" #include "common/util.h" #include "common/list.h" #include "watch.h" #include "timer.h" #include "irc.h" #include "ipban.h" #include "game_conv.h" #include "udptest_send.h" #include "character.h" #include "versioncheck.h" #include "common/bnet_protocol.h" #include "common/field_sizes.h" #include "anongame.h" #include "clan.h" #include "connection.h" #include "topic.h" #include "server.h" #include "handle_d2cs.h" #include "command_groups.h" #include "attrlayer.h" #include "common/rcm.h" #include "common/fdwatch.h" #include "common/elist.h" #include "common/xalloc.h" #include "common/setup_after.h" /* types and data structures used for the connlist array */ typedef struct { t_connection *c; t_elist freelist; } t_conn_entry; t_conn_entry *connarray = NULL; t_elist arrayflist; static int totalcount=0; static t_list * conn_head=NULL; static t_list * conn_dead=NULL; static void conn_send_welcome(t_connection * c); static void conn_send_issue(t_connection * c); static int connarray_create(void); static void connarray_destroy(void); static t_connection *connarray_get_conn(unsigned index); static unsigned connarray_add_conn(t_connection *c); static void connarray_del_conn(unsigned index); static void conn_send_welcome(t_connection * c) { char const * filename; FILE * fp; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (c->protocol.cflags & conn_flags_welcomed) return; if ((conn_get_class(c)==conn_class_irc)|| (conn_get_class(c)==conn_class_wol)) { c->protocol.cflags|= conn_flags_welcomed; return; } if ((filename = prefs_get_motdfile())) { if ((fp = fopen(filename,"r"))) { message_send_file(c,fp); if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close MOTD file \"%s\" after reading (fopen: %s)",filename,pstrerror(errno)); } } else { eventlog(eventlog_level_error,__FUNCTION__,"could not open MOTD file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); } } c->protocol.cflags|= conn_flags_welcomed; } static void conn_send_issue(t_connection * c) { char const * filename; FILE * fp; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if ((filename = prefs_get_issuefile())) if ((fp = fopen(filename,"r"))) { message_send_file(c,fp); if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close issue file \"%s\" after reading (fopen: %s)",filename,pstrerror(errno)); } else eventlog(eventlog_level_error,__FUNCTION__,"could not open issue file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); else eventlog(eventlog_level_debug,__FUNCTION__,"no issue file"); } // [zap-zero] 20020629 extern void conn_shutdown(t_connection * c, time_t now, t_timer_data foo) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (now==(time_t)0) /* zero means user logged out before expiration */ { eventlog(eventlog_level_trace,__FUNCTION__,"[%d] connection allready closed",conn_get_socket(c)); return; } eventlog(eventlog_level_trace,__FUNCTION__,"[%d] closing connection",conn_get_socket(c)); conn_set_state(c, conn_state_destroy); } extern void conn_test_latency(t_connection * c, time_t now, t_timer_data delta) { t_packet * packet; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (now==(time_t)0) /* zero means user logged out before expiration */ return; if (conn_get_state(c)==conn_state_destroy) // [zap-zero] 20020910 return; // state_destroy: do nothing if ((conn_get_class(c)==conn_class_irc)|| (conn_get_class(c)==conn_class_wol)) { /* We should start pinging the client after we received the first line ... */ /* NOTE: RFC2812 only suggests that PINGs are being sent * if no other activity is detected. However it explecitly * allows PINGs to be sent if there is activity on this * connection. In other words we just don't care :) */ if (conn_get_ircping(c)!=0) { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] ping timeout (closing connection)",conn_get_socket(c)); conn_set_latency(c,0); conn_set_state(c,conn_state_destroy); } irc_send_ping(c); } else if(conn_get_class(c)==conn_class_w3route) { if(!(packet = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] packet_create failed",conn_get_socket(c)); } else { packet_set_size(packet,sizeof(t_server_w3route_echoreq)); packet_set_type(packet,SERVER_W3ROUTE_ECHOREQ); bn_int_set(&packet->u.server_w3route_echoreq.ticks,get_ticks()); conn_push_outqueue(c, packet); packet_del_ref(packet); } } else { /* FIXME: I think real Battle.net sends these even before login */ if (!conn_get_game(c)) { if ((packet = packet_create(packet_class_bnet))) { packet_set_size(packet,sizeof(t_server_echoreq)); packet_set_type(packet,SERVER_ECHOREQ); bn_int_set(&packet->u.server_echoreq.ticks,get_ticks()); conn_push_outqueue(c,packet); packet_del_ref(packet); } else { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); } } } if (timerlist_add_timer(c,now+(time_t)delta.n,conn_test_latency,delta)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add timer"); } static void conn_send_nullmsg(t_connection * c, time_t now, t_timer_data delta) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (now==(time_t)0) /* zero means user logged out before expiration */ return; message_send_text(c,message_type_null,c,NULL); if (timerlist_add_timer(c,now+(time_t)delta.n,conn_send_nullmsg,delta)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add timer"); } extern char const * conn_class_get_str(t_conn_class class) { switch (class) { case conn_class_init: return "init"; case conn_class_bnet: return "bnet"; case conn_class_file: return "file"; case conn_class_bot: return "bot"; case conn_class_d2cs_bnetd: return "d2cs_bnetd"; case conn_class_telnet: return "telnet"; case conn_class_irc: return "irc"; case conn_class_wol: return "wol"; case conn_class_none: return "none"; case conn_class_w3route: return "w3route"; default: return "UNKNOWN"; } } extern char const * conn_state_get_str(t_conn_state state) { switch (state) { case conn_state_empty: return "empty"; case conn_state_initial: return "initial"; case conn_state_connected: return "connected"; case conn_state_bot_username: return "bot_username"; case conn_state_bot_password: return "bot_password"; case conn_state_loggedin: return "loggedin"; case conn_state_destroy: return "destroy"; case conn_state_untrusted: return "untrusted"; case conn_state_pending_raw: return "pending_raw"; default: return "UNKNOWN"; } } extern int conn_set_realm_cb(void *data, void *newref); extern t_connection * conn_create(int tsock, int usock, unsigned int real_local_addr, unsigned short real_local_port, unsigned int local_addr, unsigned short local_port, unsigned int addr, unsigned short port) { t_connection * temp; if (tsock<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad TCP socket %d",tsock); return NULL; } if (usock<-1) /* -1 is allowed for some connection classes like bot, irc, and telnet */ { eventlog(eventlog_level_error,__FUNCTION__,"got bad UDP socket %d",usock); return NULL; } temp = xmalloc(sizeof(t_connection)); temp->socket.tcp_sock = tsock; temp->socket.tcp_addr = addr; temp->socket.tcp_port = port; temp->socket.udp_sock = usock; temp->socket.udp_addr = addr; /* same for now but client can request it to be different */ temp->socket.local_addr = local_addr; temp->socket.local_port = local_port; temp->socket.real_local_addr = real_local_addr; temp->socket.real_local_port = real_local_port; temp->socket.udp_port = port; temp->socket.fdw_idx = -1; temp->protocol.class = conn_class_init; temp->protocol.state = conn_state_initial; temp->protocol.sessionkey = ((unsigned int)rand())^((unsigned int)now+(unsigned int)real_local_port); temp->protocol.sessionnum = connarray_add_conn(temp); temp->protocol.secret = ((unsigned int)rand())^(totalcount+((unsigned int)now)); temp->protocol.flags = MF_PLUG; temp->protocol.latency = 0; temp->protocol.chat.dnd = NULL; temp->protocol.chat.away = NULL; temp->protocol.chat.ignore_list = NULL; temp->protocol.chat.ignore_count = 0; temp->protocol.chat.quota.totcount = 0; temp->protocol.chat.quota.list = list_create(); temp->protocol.client.versionid = 0; temp->protocol.client.gameversion = 0; temp->protocol.client.checksum = 0; temp->protocol.client.archtag = 0; temp->protocol.client.clienttag = 0; temp->protocol.client.clientver = NULL; temp->protocol.client.gamelang = 0; temp->protocol.client.country = NULL; temp->protocol.client.tzbias = 0; temp->protocol.client.host = NULL; temp->protocol.client.user = NULL; temp->protocol.client.clientexe = NULL; temp->protocol.client.owner = NULL; temp->protocol.client.cdkey = NULL; temp->protocol.client.versioncheck = NULL; temp->protocol.account = NULL; temp->protocol.chat.channel = NULL; temp->protocol.chat.last_message = now; temp->protocol.chat.lastsender = NULL; temp->protocol.chat.irc.ircline = NULL; temp->protocol.chat.irc.ircping = 0; temp->protocol.chat.irc.ircpass = NULL; temp->protocol.chat.tmpOP_channel = NULL; temp->protocol.chat.tmpVOICE_channel = NULL; temp->protocol.game = NULL; temp->protocol.queues.outqueue = NULL; temp->protocol.queues.outsize = 0; temp->protocol.queues.outsizep = 0; temp->protocol.queues.inqueue = NULL; temp->protocol.queues.insize = 0; temp->protocol.loggeduser = NULL; temp->protocol.d2.realm = NULL; rcm_regref_init(&temp->protocol.d2.realm_regref,&conn_set_realm_cb,temp); temp->protocol.d2.character = NULL; temp->protocol.d2.realminfo = NULL; temp->protocol.d2.charname = NULL; temp->protocol.w3.w3_playerinfo = NULL; temp->protocol.w3.routeconn = NULL; temp->protocol.w3.anongame = NULL; temp->protocol.w3.anongame_search_starttime = 0; temp->protocol.bound = NULL; elist_init(&temp->protocol.timers); temp->protocol.wol.ingame = 0; temp->protocol.wol.codepage = 0; temp->protocol.wol.locale = 0; temp->protocol.wol.gameType = 0; temp->protocol.wol.apgar = NULL; temp->protocol.wol.gameOptions = NULL; temp->protocol.cr_time = now; temp->protocol.passfail_count = 0; temp->protocol.cflags = 0; list_prepend_data(conn_head,temp); eventlog(eventlog_level_info,__FUNCTION__,"[%d][%d] sessionkey=0x%08x sessionnum=0x%08x",temp->socket.tcp_sock,temp->socket.udp_sock,temp->protocol.sessionkey,temp->protocol.sessionnum); return temp; } extern t_anongame * conn_create_anongame(t_connection *c) { t_anongame * temp; int i; if(c->protocol.w3.anongame) { eventlog(eventlog_level_error,__FUNCTION__,"anongame already allocated"); return c->protocol.w3.anongame; } temp = xmalloc(sizeof(t_anongame)); temp->count = 0; temp->id = 0; temp->tid = 0; for (i=0; i < ANONGAME_MAX_GAMECOUNT/2; i++) temp->tc[i] = NULL; temp->race = 0; temp->playernum = 0; temp->handle = 0; temp->addr = 0; temp->loaded = 0; temp->joined = 0; temp->map_prefs = 0xffffffff; temp->type = 0; temp->gametype = 0; temp->queue = 0; temp->info = NULL; c->protocol.w3.anongame = temp; return temp; } extern t_anongame * conn_get_anongame(t_connection *c) { if(!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.w3.anongame; } extern void conn_destroy_anongame(t_connection *c) { t_anongame * a; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!(a = c->protocol.w3.anongame)) { eventlog(eventlog_level_error,__FUNCTION__,"NULL anongame"); return; } // delete reference to this connection if(a->info) { a->info->player[a->playernum-1] = NULL; if(--(a->info->currentplayers) == 0) anongameinfo_destroy(a->info); } // [quetzal] 20020824 // unqueue from anongame search list, // if we got AT game, unqueue entire team. if (anongame_arranged(a->queue)) { anongame_unqueue(a->tc[0], a->queue); } else { anongame_unqueue(c, a->queue); } xfree(c->protocol.w3.anongame); c->protocol.w3.anongame = NULL; } extern void conn_destroy(t_connection * c, t_elem ** elem, int conn_or_dead_list) { char const * classstr; t_elem * curr; if (c == NULL) { eventlog(eventlog_level_error, "conn_destroy", "got NULL connection"); return; } classstr = conn_class_get_str(c->protocol.class); if (list_remove_data(conn_head,c,(conn_or_dead_list)?&curr:elem)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); return; } if (c->protocol.class==conn_class_d2cs_bnetd) { t_realm * realm; realm=conn_get_realm(c); if (realm) realm_deactive(realm); else { eventlog(eventlog_level_error,__FUNCTION__,"could not find realm for d2cs connection"); } } else if (c->protocol.class == conn_class_w3route && c->protocol.w3.routeconn && c->protocol.w3.routeconn->protocol.w3.anongame) { anongame_stats(c); conn_destroy_anongame(c->protocol.w3.routeconn); // [zap-zero] destroy anongame too when game connection is invalid } if (c->protocol.d2.realm) { realm_add_player_number(c->protocol.d2.realm,-1); realm_put(c->protocol.d2.realm,&c->protocol.d2.realm_regref); } /* free the memory with user quota */ { t_qline * qline; LIST_TRAVERSE(c->protocol.chat.quota.list,curr) { qline = elem_get_data(curr); xfree(qline); list_remove_elem(c->protocol.chat.quota.list,&curr); } list_destroy(c->protocol.chat.quota.list); } /* if this user in a channel, notify everyone that the user has left */ if (c->protocol.chat.channel) channel_del_connection(c->protocol.chat.channel,c); if ((c->protocol.game) && (c->protocol.account)) { if (game_get_status(c->protocol.game)==game_status_started) { game_set_self_report(c->protocol.game,c->protocol.account,game_result_disconnect); game_set_report(c->protocol.game,c->protocol.account,"disconnect","disconnect"); } } conn_set_game(c,NULL,NULL,NULL,game_type_none,0); c->protocol.state = conn_state_empty; watchlist_del_all_events(c); timerlist_del_all_timers(c); clanmember_set_offline(c); if(c->protocol.account) watchlist_notify_event(c->protocol.account,NULL,c->protocol.client.clienttag,watch_event_logout); if (c->protocol.client.versioncheck) versioncheck_destroy((void *)c->protocol.client.versioncheck); /* avoid warning */ if (c->protocol.chat.lastsender) xfree((void *)c->protocol.chat.lastsender); /* avoid warning */ if (c->protocol.chat.away) xfree((void *)c->protocol.chat.away); /* avoid warning */ if (c->protocol.chat.dnd) xfree((void *)c->protocol.chat.dnd); /* avoid warning */ if (c->protocol.chat.tmpOP_channel) xfree((void *)c->protocol.chat.tmpOP_channel); /* avoid warning */ if (c->protocol.chat.tmpVOICE_channel) xfree((void *)c->protocol.chat.tmpVOICE_channel); /* avoid warning */ if (c->protocol.client.clientver) xfree((void *)c->protocol.client.clientver); /* avoid warning */ if (c->protocol.client.country) xfree((void *)c->protocol.client.country); /* avoid warning */ if (c->protocol.client.host) xfree((void *)c->protocol.client.host); /* avoid warning */ if (c->protocol.client.user) xfree((void *)c->protocol.client.user); /* avoid warning */ if (c->protocol.client.clientexe) xfree((void *)c->protocol.client.clientexe); /* avoid warning */ if (c->protocol.client.owner) xfree((void *)c->protocol.client.owner); /* avoid warning */ if (c->protocol.client.cdkey) xfree((void *)c->protocol.client.cdkey); /* avoid warning */ if (c->protocol.d2.realminfo) xfree((void *)c->protocol.d2.realminfo); /* avoid warning */ if (c->protocol.d2.charname) xfree((void *)c->protocol.d2.charname); /* avoid warning */ if (c->protocol.chat.irc.ircline) xfree((void *)c->protocol.chat.irc.ircline); /* avoid warning */ if (c->protocol.chat.irc.ircpass) xfree((void *)c->protocol.chat.irc.ircpass); /* avoid warning */ if (c->protocol.wol.apgar) xfree((void *)c->protocol.wol.apgar); /* avoid warning */ if (c->protocol.wol.gameOptions) xfree((void *)c->protocol.wol.gameOptions); /* avoid warning */ /* ADDED BY UNDYING SOULZZ 4/8/02 */ if (c->protocol.w3.w3_playerinfo) xfree((void *)c->protocol.w3.w3_playerinfo); /* avoid warning */ if (c->protocol.bound) c->protocol.bound->protocol.bound = NULL; if (c->protocol.chat.ignore_count>0) { if (!c->protocol.chat.ignore_list) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL ignore_list with ignore_count=%u",c->protocol.chat.ignore_count); } else { xfree(c->protocol.chat.ignore_list); } } if (c->protocol.account) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] \"%s\" logged out",c->socket.tcp_sock,conn_get_loggeduser(c)); //amadeo #ifdef WIN32_GUI guiOnUpdateUserList(); #endif if (prefs_get_sync_on_logoff()) { if (account_save(conn_get_account(c),FS_FORCE) < 0) eventlog(eventlog_level_error,__FUNCTION__,"cannot sync account (sync_on_logoff)"); } if (account_get_conn(c->protocol.account)==c) /* make sure you don't set this when allready on new conn (relogin with same account) */ account_set_conn(c->protocol.account,NULL); c->protocol.account = NULL; /* the account code will free the memory later */ } /* logged user is no longer only for logged in users */ if (c->protocol.loggeduser) xfree((void*)c->protocol.loggeduser); /* make sure the connection is closed */ if (c->socket.tcp_sock!=-1) { /* -1 means that the socket was already closed by conn_close() */ fdwatch_del_fd(c->socket.fdw_idx); psock_shutdown(c->socket.tcp_sock,PSOCK_SHUT_RDWR); psock_close(c->socket.tcp_sock); } /* clear out the packet queues */ if (c->protocol.queues.inqueue) packet_del_ref(c->protocol.queues.inqueue); queue_clear(&c->protocol.queues.outqueue); // [zap-zero] 20020601 if (c->protocol.w3.routeconn) { c->protocol.w3.routeconn->protocol.w3.routeconn = NULL; if(c->protocol.w3.routeconn->protocol.class == conn_class_w3route) conn_set_state(c->protocol.w3.routeconn, conn_state_destroy); } if(c->protocol.w3.anongame) conn_destroy_anongame(c); /* delete the conn from the dead list if its there, we dont check for error * because connections may be destroyed without first setting state to destroy */ if (conn_dead) list_remove_data(conn_dead, c, (conn_or_dead_list)?elem:&curr); connarray_del_conn(c->protocol.sessionnum); eventlog(eventlog_level_info,__FUNCTION__,"[%d] closed %s connection",c->socket.tcp_sock,classstr); xfree(c); } extern int conn_match(t_connection const * c, char const * username) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!username) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL username"); return -1; } if (!c->protocol.account) return 0; return account_match(c->protocol.account,username); } extern t_conn_class conn_get_class(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return conn_class_none; } return c->protocol.class; } extern void conn_set_class(t_connection * c, t_conn_class class) { t_timer_data data; unsigned long delta; t_conn_class oldclass; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (c->protocol.class==class) return; oldclass = c->protocol.class; c->protocol.class = class; switch(class) { case conn_class_bnet: if (prefs_get_udptest_port()!=0) conn_set_game_port(c,(unsigned short)prefs_get_udptest_port()); udptest_send(c); /* remove any init timers */ if (oldclass == conn_class_init) timerlist_del_all_timers(c); delta = prefs_get_latency(); data.n = delta; if (timerlist_add_timer(c,now+(time_t)delta,conn_test_latency,data)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add timer"); eventlog(eventlog_level_debug,__FUNCTION__,"added latency check timer"); break; case conn_class_w3route: delta = prefs_get_latency(); data.n = delta; if (timerlist_add_timer(c,now+(time_t)delta,conn_test_latency,data)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add timer"); break; case conn_class_bot: case conn_class_telnet: { t_packet * rpacket; if (class==conn_class_bot) { if ((delta = prefs_get_nullmsg())>0) { data.n = delta; if (timerlist_add_timer(c,now+(time_t)delta,conn_send_nullmsg,data)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not add timer"); } } /* remove any init timers */ if (oldclass == conn_class_init) timerlist_del_all_timers(c); conn_send_issue(c); if (!(rpacket = packet_create(packet_class_raw))) eventlog(eventlog_level_error,__FUNCTION__,"could not create rpacket"); else { packet_append_ntstring(rpacket,"Username: "); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } break; } default: /* remove any init timers */ if (oldclass == conn_class_init) timerlist_del_all_timers(c); break; } } extern t_conn_state conn_get_state(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return conn_state_empty; } return c->protocol.state; } extern void conn_set_state(t_connection * c, t_conn_state state) { t_elem * elem; if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return; } /* special case for destroying connections, add them to conn_dead list */ if (state == conn_state_destroy && c->protocol.state != conn_state_destroy) { if (!conn_dead) conn_dead = list_create(); list_append_data(conn_dead, c); } else if (state != conn_state_destroy && c->protocol.state == conn_state_destroy) if (list_remove_data(conn_dead, c, &elem)) { eventlog(eventlog_level_error, __FUNCTION__, "could not remove dead connection"); return; } c->protocol.state = state; } extern unsigned int conn_get_sessionkey(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.sessionkey; } extern unsigned int conn_get_sessionnum(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.sessionnum; } extern unsigned int conn_get_secret(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.secret; } extern unsigned int conn_get_addr(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->socket.tcp_addr; } extern unsigned short conn_get_port(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->socket.tcp_port; } extern unsigned int conn_get_local_addr(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->socket.local_addr; } extern unsigned short conn_get_local_port(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->socket.local_port; } extern unsigned int conn_get_real_local_addr(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->socket.real_local_addr; } extern unsigned short conn_get_real_local_port(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->socket.real_local_port; } extern unsigned int conn_get_game_addr(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->socket.udp_addr; } extern int conn_set_game_addr(t_connection * c, unsigned int game_addr) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } c->socket.udp_addr = game_addr; return 0; } extern unsigned short conn_get_game_port(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->socket.udp_port; } extern int conn_set_game_port(t_connection * c, unsigned short game_port) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } c->socket.udp_port = game_port; return 0; } extern void conn_set_host(t_connection * c, char const * host) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!host) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL host"); return; } if (c->protocol.client.host) xfree((void *)c->protocol.client.host); /* avoid warning */ c->protocol.client.host = xstrdup(host); } extern void conn_set_user(t_connection * c, char const * user) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!user) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL user"); return; } if (c->protocol.client.user) xfree((void *)c->protocol.client.user); /* avoid warning */ c->protocol.client.user = xstrdup(user); } extern void conn_set_owner(t_connection * c, char const * owner) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!owner) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL owner"); return; } if (c->protocol.client.owner) xfree((void *)c->protocol.client.owner); /* avoid warning */ c->protocol.client.owner = xstrdup(owner); } extern const char * conn_get_user(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.client.user; } extern const char * conn_get_owner(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.client.owner; } extern void conn_set_cdkey(t_connection * c, char const * cdkey) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!cdkey) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL cdkey"); return; } if (c->protocol.client.cdkey) xfree((void *)c->protocol.client.cdkey); /* avoid warning */ c->protocol.client.cdkey = xstrdup(cdkey); } extern char const * conn_get_clientexe(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } if (!c->protocol.client.clientexe) return ""; return c->protocol.client.clientexe; } extern void conn_set_clientexe(t_connection * c, char const * clientexe) { char const * temp; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!clientexe) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL clientexe"); return; } temp = xstrdup(clientexe); if (c->protocol.client.clientexe) xfree((void *)c->protocol.client.clientexe); /* avoid warning */ c->protocol.client.clientexe = temp; } extern char const * conn_get_clientver(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } if (!c->protocol.client.clientver) return ""; return c->protocol.client.clientver; } extern void conn_set_clientver(t_connection * c, char const * clientver) { char const * temp; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!clientver) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL clientver"); return; } temp = xstrdup(clientver); if (c->protocol.client.clientver) xfree((void *)c->protocol.client.clientver); /* avoid warning */ c->protocol.client.clientver = temp; } extern t_tag conn_get_archtag(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; /* unknown */ } return c->protocol.client.archtag; } extern void conn_set_archtag(t_connection * c, t_tag archtag) { char archtag_str[5]; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!tag_check_arch(archtag)) { eventlog(eventlog_level_error,__FUNCTION__,"got UNKNOWN archtag"); return; } if (c->protocol.client.archtag!=archtag) eventlog(eventlog_level_info,__FUNCTION__,"[%d] setting client arch to \"%s\"",conn_get_socket(c),tag_uint_to_str(archtag_str,archtag)); c->protocol.client.archtag = archtag; } extern t_tag conn_get_gamelang(t_connection const * c) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL connection"); return 0; } return c->protocol.client.gamelang; } extern void conn_set_gamelang(t_connection * c, t_tag gamelang) { char gamelang_str[5]; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!gamelang) return; /* only war3 & w3xp have gamelang */ if (!tag_check_gamelang(gamelang)) { eventlog(eventlog_level_error,__FUNCTION__,"got UNKNOWN gamelang"); return; } if (c->protocol.client.gamelang!=gamelang) eventlog(eventlog_level_info,__FUNCTION__,"[%d] setting client gamelang to \"%s\"",conn_get_socket(c),tag_uint_to_str(gamelang_str,gamelang)); c->protocol.client.gamelang = gamelang; } extern t_clienttag conn_get_clienttag(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return CLIENTTAG_UNKNOWN_UINT; } if (!c->protocol.client.clienttag) return CLIENTTAG_UNKNOWN_UINT; return c->protocol.client.clienttag; } extern t_clienttag conn_get_fake_clienttag(t_connection const * c) { char const * clienttag; t_account * account; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; /* unknown */ } account = conn_get_account(c); if (account) /* BITS remote connections don't need to have an account */ if ((clienttag = account_get_strattr(account,"BNET\\fakeclienttag"))) return tag_str_to_uint(clienttag); return c->protocol.client.clienttag; } extern void conn_set_clienttag(t_connection * c, t_clienttag clienttag) { char clienttag_str[5]; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!tag_check_client(clienttag)) { eventlog(eventlog_level_error,__FUNCTION__,"got UNKNOWN clienttag \"%s\"",tag_uint_to_str(clienttag_str,clienttag)); return; } if (c->protocol.client.clienttag!=clienttag) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] setting client type to \"%s\"",conn_get_socket(c),tag_uint_to_str(clienttag_str,clienttag)); c->protocol.client.clienttag = clienttag; if (c->protocol.chat.channel) channel_update_userflags(c); } } extern unsigned long conn_get_gameversion(t_connection const * c) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL connection"); return 0; } return c->protocol.client.gameversion; } extern int conn_set_gameversion(t_connection * c, unsigned long gameversion) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL connection"); return -1; } c->protocol.client.gameversion = gameversion; return 0; } extern unsigned long conn_get_checksum(t_connection const * c) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL connection"); return 0; } return c->protocol.client.checksum; } extern int conn_set_checksum(t_connection * c, unsigned long checksum) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL connection"); return -1; } c->protocol.client.checksum = checksum; return 0; } extern unsigned long conn_get_versionid(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.client.versionid; } extern int conn_set_versionid(t_connection * c, unsigned long versionid) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } c->protocol.client.versionid = versionid; return 0; } extern int conn_get_tzbias(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.client.tzbias; } extern void conn_set_tzbias(t_connection * c, int tzbias) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } c->protocol.client.tzbias = tzbias; } static void conn_set_account(t_connection * c, t_account * account) { t_connection * other; char const * tname; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return; } if ((other = connlist_find_connection_by_accountname((tname = account_get_name(account))))) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] forcing logout of previous login for \"%s\"",conn_get_socket(c),tname); conn_set_state(other, conn_state_destroy); } c->protocol.account = account; c->protocol.state = conn_state_loggedin; account_set_conn(account,c); { char const * flagstr; if ((flagstr = account_get_strattr(account,"BNET\\flags\\initial"))) conn_add_flags(c,strtoul(flagstr,NULL,0)); } account_set_ll_time(c->protocol.account,(unsigned int)now); account_set_ll_owner(c->protocol.account,c->protocol.client.owner); account_set_ll_clienttag(c->protocol.account,c->protocol.client.clienttag); account_set_ll_ip(c->protocol.account,addr_num_to_ip_str(c->socket.tcp_addr)); if (c->protocol.client.host) { xfree((void *)c->protocol.client.host); /* avoid warning */ c->protocol.client.host = NULL; } if (c->protocol.client.user) { xfree((void *)c->protocol.client.user); /* avoid warning */ c->protocol.client.user = NULL; } if (c->protocol.client.clientexe) { xfree((void *)c->protocol.client.clientexe); /* avoid warning */ c->protocol.client.clientexe = NULL; } if (c->protocol.client.owner) { xfree((void *)c->protocol.client.owner); /* avoid warning */ c->protocol.client.owner = NULL; } if (c->protocol.client.cdkey) { xfree((void *)c->protocol.client.cdkey); /* avoid warning */ c->protocol.client.cdkey = NULL; } clanmember_set_online(c); totalcount++; watchlist_notify_event(c->protocol.account,NULL,c->protocol.client.clienttag,watch_event_login); return; } extern void conn_login(t_connection *c, t_account *a, const char *loggeduser) { assert(c != NULL); assert(a != NULL); assert(loggeduser != NULL); conn_set_account(c,a); if (strcmp(conn_get_loggeduser(c),loggeduser)) conn_set_loggeduser(c,loggeduser); } extern t_account * conn_get_account(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.account; } extern int conn_set_loggeduser(t_connection * c, char const * username) { const char * temp; assert(c != NULL); assert(username != NULL); if (username[0]!='#') temp = xstrdup(username); else { unsigned int userid=0; str_to_uint(&username[1],&userid); if (userid!=0){ if (prefs_get_account_force_username()){ t_account* account = accountlist_find_account_by_uid(userid); temp = xstrdup(account_get_name(account)); } else{ char uid_string[USER_NAME_MAX]; sprintf(uid_string,"#%u",userid); temp = xstrdup(uid_string); } } else{ //theoretically this should never happen... eventlog(eventlog_level_error,__FUNCTION__,"got invalid numeric uid \"%s\"",username); // set value that would have been set prior to this bugfix... temp = xstrdup(username); } } if (c->protocol.loggeduser) xfree((void*)c->protocol.loggeduser); c->protocol.loggeduser = temp; return 0; } extern char const * conn_get_loggeduser(t_connection const * c) { assert(c != NULL); if (!c->protocol.loggeduser && c->protocol.account) return account_get_name(c->protocol.account); return c->protocol.loggeduser; } extern unsigned int conn_get_flags(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.flags; } extern int conn_set_flags(t_connection * c, unsigned int flags) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (flags!=c->protocol.flags) { c->protocol.flags = flags; if (c->protocol.chat.channel) channel_update_userflags(c); } return 0; } extern void conn_add_flags(t_connection * c, unsigned int flags) { unsigned int oldflags; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } oldflags = c->protocol.flags; c->protocol.flags |= flags; if (oldflags!=c->protocol.flags && c->protocol.chat.channel) channel_update_userflags(c); } extern void conn_del_flags(t_connection * c, unsigned int flags) { unsigned int oldflags; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } oldflags = c->protocol.flags; c->protocol.flags &= ~flags; if (oldflags!=c->protocol.flags && c->protocol.chat.channel) channel_update_userflags(c); } extern unsigned int conn_get_latency(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.latency; } extern void conn_set_latency(t_connection * c, unsigned int ms) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (c->protocol.latency != ms) { c->protocol.latency = ms; if (c->protocol.chat.channel) channel_update_latency(c); } } extern char const * conn_get_awaystr(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.chat.away; } extern int conn_set_awaystr(t_connection * c, char const * away) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (c->protocol.chat.away) xfree((void *)c->protocol.chat.away); /* avoid warning */ if (!away) c->protocol.chat.away = NULL; else c->protocol.chat.away = xstrdup(away); return 0; } extern char const * conn_get_dndstr(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.chat.dnd; } extern int conn_set_dndstr(t_connection * c, char const * dnd) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (c->protocol.chat.dnd) xfree((void *)c->protocol.chat.dnd); /* avoid warning */ if (!dnd) c->protocol.chat.dnd = NULL; else c->protocol.chat.dnd = xstrdup(dnd); return 0; } extern int conn_add_ignore(t_connection * c, t_account * account) { t_account * * newlist; t_connection *dest_c; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } newlist = xrealloc(c->protocol.chat.ignore_list,sizeof(t_account const *)*(c->protocol.chat.ignore_count+1)); newlist[c->protocol.chat.ignore_count++] = account; c->protocol.chat.ignore_list = newlist; dest_c = account_get_conn(account); if (dest_c) { t_message *message; message = message_create(message_type_userflags,dest_c,NULL,NULL); if (!message) return 0; message_send(message,c); message_destroy(message); } return 0; } extern int conn_del_ignore(t_connection * c, t_account const * account) { t_account * * newlist; t_account * temp; unsigned int i; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } for (i=0; iprotocol.chat.ignore_count; i++) if (c->protocol.chat.ignore_list[i]==account) break; if (i==c->protocol.chat.ignore_count) return -1; /* not in list */ /* swap entry to be deleted with last entry */ temp = c->protocol.chat.ignore_list[c->protocol.chat.ignore_count-1]; c->protocol.chat.ignore_list[c->protocol.chat.ignore_count-1] = c->protocol.chat.ignore_list[i]; c->protocol.chat.ignore_list[i] = temp; if (c->protocol.chat.ignore_count==1) /* some realloc()s are buggy */ { xfree(c->protocol.chat.ignore_list); newlist = NULL; } else newlist = xrealloc(c->protocol.chat.ignore_list,sizeof(t_account const *)*(c->protocol.chat.ignore_count-1)); c->protocol.chat.ignore_count--; c->protocol.chat.ignore_list = newlist; return 0; } extern int conn_add_watch(t_connection * c, t_account * account, t_clienttag clienttag) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (watchlist_add_events(c,account,clienttag,watch_event_login|watch_event_logout|watch_event_joingame|watch_event_leavegame)<0) return -1; return 0; } extern int conn_del_watch(t_connection * c, t_account * account, t_clienttag clienttag) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (watchlist_del_events(c,account,clienttag,watch_event_login|watch_event_logout|watch_event_joingame|watch_event_leavegame)<0) return -1; return 0; } extern int conn_check_ignoring(t_connection const * c, char const * me) { unsigned int i; t_account * temp; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!me || !(temp = accountlist_find_account(me))) return -1; if (c->protocol.chat.ignore_list) for (i=0; iprotocol.chat.ignore_count; i++) if (c->protocol.chat.ignore_list[i]==temp) return 1; return 0; } extern t_channel * conn_get_channel(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.chat.channel; } extern int conn_set_channel_var(t_connection * c, t_channel * channel) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } c->protocol.chat.channel = channel; return 0; } extern int conn_set_channel(t_connection * c, char const * channelname) { t_channel * channel; t_channel * oldchannel; t_account * acc; t_elem * curr; int clantag=0; t_clan * clan = NULL; t_clanmember * member = NULL; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } acc = c->protocol.account; if (!acc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (channelname) { unsigned int created; oldchannel=c->protocol.chat.channel; channel = channellist_find_channel_by_name(channelname,conn_get_country(c),realm_get_name(conn_get_realm(c))); if(channel && (channel == oldchannel)) return 0; if((strncasecmp(channelname, "clan ", 5)==0)&&(strlen(channelname)<10)) clantag = str_to_clantag(&channelname[5]); if ((clantag) && !((account_get_auth_admin(acc,channelname) == 1) || (account_get_auth_admin(acc,NULL) == 1))) { /* PELISH: Admins should be possible to join any channel */ clan = account_get_clan(acc); if ((!clan) || (clan_get_clantag(clan) != clantag)) { if (!channel) { char msgtemp[MAX_MESSAGE_LEN]; snprintf(msgtemp, sizeof(msgtemp), "Unable to join channel %s, there is no member of that clan in the channel!", channelname); message_send_text(c, message_type_error, c, msgtemp); if (conn_get_game(c) || c->protocol.chat.channel==NULL) { // FIXME: This is not tested to be according to battle.net!! // This is fix for empty clan channels with preventing to join CHANNEL_NAME_BANNED when is used _handle_join_command snprintf(msgtemp, sizeof(msgtemp), "You have been redirected to %s.", CHANNEL_NAME_BANNED); message_send_text(c, message_type_error, c, msgtemp); channel = channellist_find_channel_by_name(CHANNEL_NAME_BANNED,conn_get_country(c),realm_get_name(conn_get_realm(c))); } else return 0; } else { t_clan * ch_clan; if((ch_clan=clanlist_find_clan_by_clantag(clantag))&&(clan_get_channel_type(ch_clan)==1)) { message_send_text(c, message_type_error, c, "This is a private clan channel, unable to join!"); return 0; } } } else { if ((clan) && (clan_get_clantag(clan) == clantag) && (member = account_get_clanmember(acc))) { if (clanmember_get_status(member) >= CLAN_SHAMAN) /* PELISH: Giving tmpOP to SHAMAN and CHIEFTAIN on clanchannel */ conn_set_tmpOP_channel(c,channelname); } } } if (c->protocol.chat.channel) { channel_del_connection(c->protocol.chat.channel, c); c->protocol.chat.channel = NULL; } if (channel) { if (channel_check_banning(channel,c)) { message_send_text(c,message_type_error,c,"You are banned from that channel."); return -1; } if ((account_get_auth_admin(acc,NULL)!=1) && (account_get_auth_admin(acc,channelname)!=1) && (account_get_auth_operator(acc,NULL)!=1) && (account_get_auth_operator(acc,channelname)!=1) && (channel_get_max(channel) == 0)) { message_send_text(c,message_type_error,c,"That channel is for Admins/Operators only."); return -1; } if ((account_get_auth_admin(acc,NULL)!=1) && (account_get_auth_admin(acc,channelname)!=1) && (account_get_auth_operator(acc,NULL)!=1) && (account_get_auth_operator(acc,channelname)!=1) && (channel_get_max(channel) != -1) && (channel_get_curr(channel)>=channel_get_max(channel))) { message_send_text(c,message_type_error,c,"The channel is currently full."); return -1; } } if(conn_set_joingamewhisper_ack(c,0)<0) eventlog(eventlog_level_error,__FUNCTION__,"Unable to reset conn_set_joingamewhisper_ack flag"); if(conn_set_leavegamewhisper_ack(c,0)<0) eventlog(eventlog_level_error,__FUNCTION__,"Unable to reset conn_set_leavegamewhisper_ack flag"); /* if you're entering a channel, make sure they didn't exit a game without telling us */ if (c->protocol.game) { game_del_player(conn_get_game(c),c); c->protocol.game = NULL; } created = 0; if (!channel) { if(clantag) channel = channel_create(channelname,channelname,NULL,0,1,1,prefs_get_chanlog(), NULL, NULL, (prefs_get_maxusers_per_channel() > 0) ? prefs_get_maxusers_per_channel() : -1, 0, 1,0); else channel = channel_create(channelname,channelname,NULL,0,1,1,prefs_get_chanlog(), NULL, NULL, (prefs_get_maxusers_per_channel() > 0) ? prefs_get_maxusers_per_channel() : -1, 0, 0,0); if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create channel on join \"%s\"",conn_get_socket(c),channelname); return -1; } created = 1; } c->protocol.chat.channel=channel; if (channel_add_connection(channel,c)<0) { if (created) channel_destroy(channel,&curr); c->protocol.chat.channel = NULL; return -1; } eventlog(eventlog_level_info,__FUNCTION__,"[%d] joined channel \"%s\"",conn_get_socket(c),channel_get_name(c->protocol.chat.channel)); conn_send_welcome(c); if(c->protocol.chat.channel && (channel_get_flags(c->protocol.chat.channel) & channel_flags_thevoid)) message_send_text(c,message_type_info,c,"This channel does not have chat privileges."); if (clantag && clan && (clan_get_clantag(clan)==clantag)) { char msgtemp[MAX_MESSAGE_LEN]; sprintf(msgtemp,"%s",clan_get_motd(clan)); message_send_text(c,message_type_info,c,msgtemp); } if (channel_get_topic(channel_get_name(c->protocol.chat.channel)) && ((conn_get_class(c)!=conn_class_irc) || (conn_get_class(c)!=conn_class_wol))) { char msgtemp[MAX_MESSAGE_LEN]; sprintf(msgtemp,"%s topic: %s",channel_get_name(c->protocol.chat.channel),channel_get_topic(channel_get_name(c->protocol.chat.channel))); message_send_text(c,message_type_info,c,msgtemp); } if (c->protocol.chat.channel && (channel_get_flags(c->protocol.chat.channel) & channel_flags_moderated)) message_send_text(c,message_type_error,c,"This channel is moderated."); if(c->protocol.chat.channel!=oldchannel) clanmember_on_change_status_by_connection(c); } else { if (c->protocol.chat.channel) { channel_del_connection(c->protocol.chat.channel,c); c->protocol.chat.channel = NULL; } } return 0; } extern t_game * conn_get_game(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.game; } extern int conn_set_game(t_connection * c, char const * gamename, char const * gamepass, char const * gameinfo, t_game_type type, int version) /* * If game not exists (create) version != 0 (called in handle_bnet.c, function _client_startgameX()) * If game exists (join) version == 0 always (called in handle_bnet.c, function _client_joingame()) * If game exists (join) gameinfo == "" (called in handle_bnet.c, function _client_joingame()) * [KWS] */ { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (c->protocol.game) { if (gamename) { if (strcasecmp(gamename,game_get_name(c->protocol.game))) eventlog(eventlog_level_error,__FUNCTION__,"[%d] tried to join a new game \"%s\" while already in a game \"%s\"!",conn_get_socket(c),gamename,game_get_name(c->protocol.game)); else return 0; } game_del_player(conn_get_game(c),c); c->protocol.game = NULL; } if (gamename) { if (!(c->protocol.game = gamelist_find_game(gamename,c->protocol.client.clienttag,type)) /* do not allow creation of games with same name of same clienttag (yet) */ && !gamelist_find_game(gamename,c->protocol.client.clienttag,game_type_all)) { c->protocol.game = game_create(gamename,gamepass,gameinfo,type,version,c->protocol.client.clienttag,conn_get_gameversion(c)); if (c->protocol.game && conn_get_realm(c) && conn_get_charname(c)) { game_set_realmname(c->protocol.game,realm_get_name(conn_get_realm(c))); realm_add_game_number(conn_get_realm(c),1); send_d2cs_gameinforeq(c); } } if (c->protocol.game) { if (game_add_player(conn_get_game(c),gamepass,version,c)<0) { c->protocol.game = NULL; // bad password or version # return -1; } if (game_is_ladder(c->protocol.game)) { if (c == game_get_owner(c->protocol.game)) message_send_text(c,message_type_info,c,"Created ladder game"); else message_send_text(c,message_type_info,c,"Joined ladder game"); } } } else c->protocol.game = NULL; return 0; } extern unsigned int conn_get_tcpaddr(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->socket.tcp_addr; } extern t_packet * conn_get_in_queue(t_connection * c) { assert(c); return c->protocol.queues.inqueue; } extern void conn_put_in_queue(t_connection * c, t_packet * packet) { assert(c); c->protocol.queues.inqueue = packet; } extern unsigned int conn_get_in_size(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.queues.insize; } extern void conn_set_in_size(t_connection * c, unsigned int size) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } c->protocol.queues.insize = size; } extern unsigned int conn_get_out_size(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.queues.outsize; } extern void conn_set_out_size(t_connection * c, unsigned int size) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } c->protocol.queues.outsize = size; } extern int conn_push_outqueue(t_connection * c, t_packet * packet) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return -1; } if (!packet) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL packet"); return -1; } queue_push_packet((t_queue * *)&c->protocol.queues.outqueue, packet); if (!c->protocol.queues.outsizep++) fdwatch_update_fd(c->socket.fdw_idx, fdwatch_type_read | fdwatch_type_write); return 0; } extern t_packet * conn_peek_outqueue(t_connection * c) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return NULL; } return queue_peek_packet((t_queue const * const *)&c->protocol.queues.outqueue); } extern t_packet * conn_pull_outqueue(t_connection * c) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return NULL; } if (c->protocol.queues.outsizep) { if (!(--c->protocol.queues.outsizep)) fdwatch_update_fd(c->socket.fdw_idx, fdwatch_type_read); return queue_pull_packet((t_queue * *)&c->protocol.queues.outqueue); } return NULL; } extern char const * conn_get_username_real(t_connection const * c,char const * fn,unsigned int ln) { char const * result; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection (from %s:%u)",fn,ln); return NULL; } if(!c->protocol.account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account (from %s:%u)",fn,ln); return NULL; } result = account_get_name(c->protocol.account); if (result == NULL) eventlog(eventlog_level_error,__FUNCTION__,"returned previous error after being called by %s:%u",fn,ln); return result; } extern char const * conn_get_chatname(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } if ((c->protocol.class==conn_class_bnet) && c->protocol.bound) { if (c->protocol.d2.character) return character_get_name(c->protocol.d2.character); if (c->protocol.bound->protocol.d2.character) return character_get_name(c->protocol.bound->protocol.d2.character); eventlog(eventlog_level_error,__FUNCTION__,"[%d] got connection class %s bound to class %d without a character",conn_get_socket(c),conn_class_get_str(c->protocol.class),c->protocol.bound->protocol.class); } if (!c->protocol.account) return NULL; /* no name yet */ return conn_get_loggeduser(c); } extern int conn_unget_chatname(t_connection const * c, char const * name) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if ((c->protocol.class==conn_class_bnet) && c->protocol.bound) return 0; return 0; } extern char const * conn_get_chatcharname(t_connection const * c, t_connection const * dst) { char const * accname; char * chatcharname; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } if (!c->protocol.account) return NULL; /* no name yet */ /* for D2 Users */ accname = conn_get_loggeduser(c); if (!accname) return NULL; if (dst && dst->protocol.d2.charname) { const char *mychar; if (c->protocol.d2.charname) mychar = c->protocol.d2.charname; else mychar = ""; chatcharname = xmalloc(strlen(accname) + 2 + strlen(mychar)); sprintf(chatcharname, "%s*%s", mychar, accname); } else chatcharname = xstrdup(accname); return chatcharname; } extern int conn_unget_chatcharname(t_connection const * c, char const * name) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!name) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL name"); return -1; } xfree((void *)name); /* avoid warning */ return 0; } extern t_message_class conn_get_message_class(t_connection const * c, t_connection const * dst) { if (dst && dst->protocol.d2.charname) /* message to D2 user must be char*account */ return message_class_charjoin; return message_class_normal; } extern unsigned int conn_get_userid(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } if(!c->protocol.account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return 0; } return account_get_uid(c->protocol.account); } extern int conn_get_socket(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } return c->socket.tcp_sock; } extern int conn_get_game_socket(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } return c->socket.udp_sock; } extern int conn_set_game_socket(t_connection * c, int usock) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } c->socket.udp_sock = usock; return 0; } extern char const * conn_get_playerinfo(t_connection const * c) { t_account * account; static char playerinfo[MAX_PLAYERINFO_STR]; t_clienttag clienttag; char revtag[5]; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } if (!(account = conn_get_account(c))) { eventlog(eventlog_level_error,__FUNCTION__,"connection has no account"); return NULL; } if (!(clienttag = conn_get_fake_clienttag(c))) { eventlog(eventlog_level_error,__FUNCTION__,"connection has NULL fakeclienttag"); return NULL; } tag_uint_to_revstr(revtag,clienttag); if (clienttag==CLIENTTAG_BNCHATBOT_UINT) { strcpy(playerinfo,revtag); /* FIXME: what to return here? */ } else if ((clienttag==CLIENTTAG_STARCRAFT_UINT) || (clienttag==CLIENTTAG_BROODWARS_UINT)) { if (conn_get_versionid(c)<=0x000000c7) { sprintf(playerinfo,"%s %u %u %u %u %u", revtag, account_get_ladder_rating(account,clienttag,ladder_id_normal), account_get_ladder_rank(account,clienttag,ladder_id_normal), account_get_normal_wins(account,clienttag), 0,0); } else { sprintf(playerinfo,"%s %u %u %u %u %u %u %u %u %s", revtag, account_get_ladder_rating(account,clienttag,ladder_id_normal), account_get_ladder_rank(account,clienttag,ladder_id_normal), account_get_normal_wins(account,clienttag), 0,0, account_get_ladder_high_rating(account,clienttag,ladder_id_normal), 0,0, revtag); } } else if (clienttag==CLIENTTAG_SHAREWARE_UINT) { sprintf(playerinfo,"%s %u %u %u %u %u", revtag, account_get_ladder_rating(account,clienttag,ladder_id_normal), account_get_ladder_rank(account,clienttag,ladder_id_normal), account_get_normal_wins(account,clienttag), 0,0); } else if (clienttag==CLIENTTAG_DIABLORTL_UINT) { sprintf(playerinfo,"%s %u %u %u %u %u %u %u %u %u", revtag, account_get_normal_level(account,clienttag), account_get_normal_class(account,clienttag), account_get_normal_diablo_kills(account,clienttag), account_get_normal_strength(account,clienttag), account_get_normal_magic(account,clienttag), account_get_normal_dexterity(account,clienttag), account_get_normal_vitality(account,clienttag), account_get_normal_gold(account,clienttag), 0); } else if (clienttag==CLIENTTAG_DIABLOSHR_UINT) { sprintf(playerinfo,"%s %u %u %u %u %u %u %u %u %u", revtag, account_get_normal_level(account,clienttag), account_get_normal_class(account,clienttag), account_get_normal_diablo_kills(account,clienttag), account_get_normal_strength(account,clienttag), account_get_normal_magic(account,clienttag), account_get_normal_dexterity(account,clienttag), account_get_normal_vitality(account,clienttag), account_get_normal_gold(account,clienttag), 0); } else if (clienttag==CLIENTTAG_WARCIIBNE_UINT) { unsigned int a,b; a = account_get_ladder_rating(account,clienttag,ladder_id_normal); b = account_get_ladder_rating(account,clienttag,ladder_id_ironman); sprintf(playerinfo,"%s %u %u %u %u %u %u %u %u", revtag, a, account_get_ladder_rank(account,clienttag,ladder_id_normal), account_get_normal_wins(account,clienttag), 0, 0, (a>b) ? a : b, b, account_get_ladder_rank(account,clienttag,ladder_id_ironman)); } else if (clienttag==CLIENTTAG_DIABLO2DV_UINT || clienttag==CLIENTTAG_DIABLO2XP_UINT) { /* This sets portrait of character */ if (!conn_get_realm(c) || !conn_get_realminfo(c)) { strcpy(playerinfo,revtag); } else { strcpy(playerinfo,conn_get_realminfo(c)); } } else strcpy(playerinfo,revtag); /* open char */ return playerinfo; } extern int conn_set_playerinfo(t_connection const * c, char const * playerinfo) { t_clienttag clienttag; char clienttag_str[5]; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!playerinfo) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL playerinfo"); return -1; } clienttag = c->protocol.client.clienttag; if (clienttag==CLIENTTAG_DIABLORTL_UINT) { unsigned int level; unsigned int class; unsigned int diablo_kills; unsigned int strength; unsigned int magic; unsigned int dexterity; unsigned int vitality; unsigned int gold; if (sscanf(playerinfo,"LTRD %u %u %u %u %u %u %u %u %*u", &level, &class, &diablo_kills, &strength, &magic, &dexterity, &vitality, &gold)!=8) { eventlog(eventlog_level_error,__FUNCTION__,"got bad playerinfo"); return -1; } account_set_normal_level(conn_get_account(c),clienttag,level); account_set_normal_class(conn_get_account(c),clienttag,class); account_set_normal_diablo_kills(conn_get_account(c),clienttag,diablo_kills); account_set_normal_strength(conn_get_account(c),clienttag,strength); account_set_normal_magic(conn_get_account(c),clienttag,magic); account_set_normal_dexterity(conn_get_account(c),clienttag,dexterity); account_set_normal_vitality(conn_get_account(c),clienttag,vitality); account_set_normal_gold(conn_get_account(c),clienttag,gold); } else if (clienttag==CLIENTTAG_DIABLOSHR_UINT) { unsigned int level; unsigned int class; unsigned int diablo_kills; unsigned int strength; unsigned int magic; unsigned int dexterity; unsigned int vitality; unsigned int gold; if (sscanf(playerinfo,"RHSD %u %u %u %u %u %u %u %u %*u", &level, &class, &diablo_kills, &strength, &magic, &dexterity, &vitality, &gold)!=8) { eventlog(eventlog_level_error,__FUNCTION__,"got bad playerinfo"); return -1; } account_set_normal_level(conn_get_account(c),clienttag,level); account_set_normal_class(conn_get_account(c),clienttag,class); account_set_normal_diablo_kills(conn_get_account(c),clienttag,diablo_kills); account_set_normal_strength(conn_get_account(c),clienttag,strength); account_set_normal_magic(conn_get_account(c),clienttag,magic); account_set_normal_dexterity(conn_get_account(c),clienttag,dexterity); account_set_normal_vitality(conn_get_account(c),clienttag,vitality); account_set_normal_gold(conn_get_account(c),clienttag,gold); } else if (clienttag==CLIENTTAG_DIABLO2DV_UINT) { /* not much to do */ /* FIXME: get char name here? */ eventlog(eventlog_level_trace,__FUNCTION__,"[%d] playerinfo request for client \"%s\" playerinfo=\"%s\"",conn_get_socket(c),tag_uint_to_str(clienttag_str,clienttag),playerinfo); } else if (clienttag==CLIENTTAG_DIABLO2XP_UINT) { /* in playerinfo we get strings of the form "Realmname,charname" */ eventlog(eventlog_level_trace,__FUNCTION__,"[%d] playerinfo request for client \"%s\" playerinfo=\"%s\"",conn_get_socket(c),tag_uint_to_str(clienttag_str,clienttag),playerinfo); } else { eventlog(eventlog_level_warn,__FUNCTION__,"setting playerinfo for client \"%s\" not supported (playerinfo=\"%s\")",tag_uint_to_str(clienttag_str,clienttag),playerinfo); return -1; } return 0; } extern char const * conn_get_realminfo(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.d2.realminfo; } extern int conn_set_realminfo(t_connection * c, char const * realminfo) { char const * temp; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (realminfo) temp = xstrdup(realminfo); else temp = NULL; if (c->protocol.d2.realminfo) /* if it was set before, free it now */ xfree((void *)c->protocol.d2.realminfo); /* avoid warning */ c->protocol.d2.realminfo = temp; return 0; } extern char const * conn_get_charname(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.d2.charname; } extern int conn_set_charname(t_connection * c, char const * charname) { char const * temp; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (charname) temp = xstrdup(charname); else temp = charname; if (c->protocol.d2.charname) /* free it, if it was previously set */ xfree((void *)c->protocol.d2.charname); /* avoid warning */ c->protocol.d2.charname = temp; return 0; } extern int conn_set_idletime(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } c->protocol.chat.last_message = now; return 0; } extern unsigned int conn_get_idletime(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return (unsigned int)difftime(now,c->protocol.chat.last_message); } extern t_realm * conn_get_realm(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.d2.realm; } extern int conn_set_realm(t_connection * c, t_realm * realm) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (c->protocol.d2.realm) realm_put(c->protocol.d2.realm,&c->protocol.d2.realm_regref); if (!realm) c->protocol.d2.realm = NULL; else { c->protocol.d2.realm = realm_get(realm,&c->protocol.d2.realm_regref); eventlog(eventlog_level_debug,__FUNCTION__,"[%d] set to \"%s\"",conn_get_socket(c),realm_get_name(realm)); } return 0; } extern int conn_set_realm_cb(void *data, void *newref) { t_connection *c = (t_connection*)data; t_realm *newrealm = (t_realm*)newref; assert(c->protocol.d2.realm); /* this should never be NULL here */ /* we are removing a reference */ realm_put(c->protocol.d2.realm,&c->protocol.d2.realm_regref); if (newrealm) c->protocol.d2.realm = realm_get(newrealm,&c->protocol.d2.realm_regref); else { /* close the connection for players on unconfigured realms */ conn_set_state(c,conn_state_destroy); c->protocol.d2.realm = NULL; } return 0; } extern int conn_set_character(t_connection * c, t_character * character) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!character) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character"); return -1; } c->protocol.d2.character = character; return 0; } extern void conn_set_country(t_connection * c, char const * country) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!country) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL country"); return; } if (c->protocol.client.country) xfree((void *)c->protocol.client.country); /* avoid warning */ c->protocol.client.country = xstrdup(country); } extern char const * conn_get_country(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.client.country; } extern int conn_bind(t_connection * c1, t_connection * c2) { if (!c1) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!c2) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } c1->protocol.bound = c2; c2->protocol.bound = c1; return 0; } extern int conn_set_ircline(t_connection * c, char const * line) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!line) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL line"); return -1; } if (c->protocol.chat.irc.ircline) xfree((void *)c->protocol.chat.irc.ircline); /* avoid warning */ c->protocol.chat.irc.ircline = xstrdup(line); return 0; } extern char const * conn_get_ircline(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.chat.irc.ircline; } extern int conn_set_ircpass(t_connection * c, char const * pass) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (c->protocol.chat.irc.ircpass) xfree((void *)c->protocol.chat.irc.ircpass); /* avoid warning */ if (!pass) c->protocol.chat.irc.ircpass = NULL; else c->protocol.chat.irc.ircpass = xstrdup(pass); return 0; } extern char const * conn_get_ircpass(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.chat.irc.ircpass; } extern int conn_set_ircping(t_connection * c, unsigned int ping) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } c->protocol.chat.irc.ircping = ping; return 0; } extern unsigned int conn_get_ircping(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return c->protocol.chat.irc.ircping; } // NonReal extern int conn_get_welcomed(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return (c->protocol.cflags & conn_flags_welcomed); } // NonReal extern void conn_set_welcomed(t_connection * c, int welcomed) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } c->protocol.cflags |= conn_flags_welcomed; } /* ADDED BY UNDYING SOULZZ 4/7/02 */ extern int conn_set_w3_playerinfo( t_connection * c, const char * w3_playerinfo ) { const char * temp; if (!c) { eventlog(eventlog_level_error,__FUNCTION__, "got NULL connection"); return -1; } temp = xstrdup( w3_playerinfo ); if ( c->protocol.w3.w3_playerinfo ) xfree((void *)c->protocol.w3.w3_playerinfo); c->protocol.w3.w3_playerinfo = temp; return 1; } extern const char * conn_get_w3_playerinfo( t_connection * c ) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.w3.w3_playerinfo; } extern int conn_quota_exceeded(t_connection * con, char const * text) { t_qline * qline; t_elem * curr; if (!prefs_get_quota() || !conn_get_account(con) || (account_get_command_groups(conn_get_account(con)) & command_get_group("/admin-con"))) return 0; if (strlen(text)>prefs_get_quota_maxline()) { message_send_text(con,message_type_error,con,"Your line length quota has been exceeded!"); return 1; } LIST_TRAVERSE(con->protocol.chat.quota.list,curr) { qline = elem_get_data(curr); if (now>=qline->inf+(time_t)prefs_get_quota_time()) { /* these lines are at least quota_time old */ list_remove_elem(con->protocol.chat.quota.list,&curr); if (qline->count>con->protocol.chat.quota.totcount) eventlog(eventlog_level_error,__FUNCTION__,"qline->count=%u but con->protocol.chat.quota.totcount=%u",qline->count,con->protocol.chat.quota.totcount); con->protocol.chat.quota.totcount -= qline->count; xfree(qline); } else break; /* old items are first, so we know nothing else will match */ } qline = xmalloc(sizeof(t_qline)); qline->inf = now; /* set the moment */ if (strlen(text)>prefs_get_quota_wrapline()) /* round up on the divide */ qline->count = (strlen(text)+prefs_get_quota_wrapline()-1)/prefs_get_quota_wrapline(); else qline->count = 1; list_append_data(con->protocol.chat.quota.list,qline); con->protocol.chat.quota.totcount += qline->count; if (con->protocol.chat.quota.totcount>=prefs_get_quota_lines()) { message_send_text(con,message_type_error,con,"Your message quota has been exceeded!"); if (con->protocol.chat.quota.totcount>=prefs_get_quota_dobae()) { /* kick out the dobae user for violation of the quota rule */ conn_set_state(con,conn_state_destroy); if (con->protocol.chat.channel) channel_message_log(con->protocol.chat.channel,con,0,"DISCONNECTED FOR DOBAE ABUSE"); return 2; } return 1; } return 0; } extern int conn_set_lastsender(t_connection * c, char const * sender) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conection"); return -1; } if (c->protocol.chat.lastsender) xfree((void *)c->protocol.chat.lastsender); /* avoid warning */ if (!sender) { c->protocol.chat.lastsender = NULL; return 0; } c->protocol.chat.lastsender = xstrdup(sender); return 0; } extern char const * conn_get_lastsender(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.chat.lastsender; } extern t_versioncheck * conn_get_versioncheck(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.client.versioncheck; } extern int conn_set_versioncheck(t_connection * c, t_versioncheck * versioncheck) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!versioncheck) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL versioncheck"); return -1; } c->protocol.client.versioncheck = versioncheck; return 0; } extern int conn_get_echoback(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } return (c->protocol.cflags & conn_flags_echoback); } extern void conn_set_echoback(t_connection * c, int echoback) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (echoback) c->protocol.cflags |= conn_flags_echoback; else c->protocol.cflags &= ~conn_flags_echoback; } extern int conn_set_udpok(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!(c->protocol.cflags & conn_flags_udpok)) { c->protocol.cflags|= conn_flags_udpok; c->protocol.flags &= ~MF_PLUG; } return 0; } extern t_connection * conn_get_routeconn(t_connection const * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return c->protocol.w3.routeconn; } extern int conn_set_routeconn(t_connection * c, t_connection * rc) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conection"); return -1; } c->protocol.w3.routeconn = rc; return 0; } extern int conn_get_crtime(t_connection *c) { if (!c) { eventlog(eventlog_level_error, "conn_get_crtime", "got NULL connection"); return -1; } return c->protocol.cr_time; } extern int conn_set_joingamewhisper_ack(t_connection * c, unsigned int value) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__, "got NULL connection"); return -1; } if (value) c->protocol.cflags |= conn_flags_joingamewhisper; else c->protocol.cflags &= ~conn_flags_joingamewhisper; return 0; } extern int conn_get_joingamewhisper_ack(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__, "got NULL connection"); return -1; } return (c->protocol.cflags & conn_flags_joingamewhisper); } extern int conn_set_leavegamewhisper_ack(t_connection * c, unsigned int value) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__, "got NULL connection"); return -1; } if (value) c->protocol.cflags |= conn_flags_leavegamewhisper; else c->protocol.cflags &= ~conn_flags_leavegamewhisper; return 0; } extern int conn_get_leavegamewhisper_ack(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__, "got NULL connection"); return -1; } return (c->protocol.cflags & conn_flags_leavegamewhisper); } extern int conn_set_anongame_search_starttime(t_connection * c, time_t t) { if (c == NULL) { eventlog(eventlog_level_error, "conn_set_anongame_search_starttime", "got NULL connection"); return -1; } c->protocol.w3.anongame_search_starttime = t; return 0; } extern time_t conn_get_anongame_search_starttime(t_connection * c) { if (c == NULL) { eventlog(eventlog_level_error, "conn_set_anongame_search_starttime", "got NULL connection"); return ((time_t) 0); } return c->protocol.w3.anongame_search_starttime; } extern t_elist * conn_get_timer(t_connection *c) { if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return NULL; } return &c->protocol.timers; } extern int conn_add_fdwatch(t_connection *c, fdwatch_handler handle) { assert(c); c->socket.fdw_idx = fdwatch_add_fd(c->socket.tcp_sock, fdwatch_type_read, handle, c); return c->socket.fdw_idx; } extern int conn_get_user_count_by_clienttag(t_clienttag ct) { t_connection * conn; t_elem const * curr; int clienttagusers = 0; /* Get Number of Users for client tag specific */ LIST_TRAVERSE_CONST(connlist(),curr) { conn = elem_get_data(curr); if ( ( ct == conn->protocol.client.clienttag ) && ( conn->protocol.state == conn_state_loggedin ) ) clienttagusers++; } return clienttagusers; } extern int connlist_create(void) { conn_head = list_create(); connarray_create(); return 0; } extern int connlist_destroy(void) { if (conn_dead) list_destroy(conn_dead); conn_dead = NULL; connarray_destroy(); /* FIXME: if called with active connection, connection are not freed */ if (list_destroy(conn_head)<0) return -1; conn_head = NULL; return 0; } extern void connlist_reap(void) { t_elem *curr; t_connection *c; if (!conn_dead || !conn_head) return; LIST_TRAVERSE(conn_dead, curr) { c = (t_connection *)elem_get_data(curr); if (!c) eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in conn_dead list"); else conn_destroy(c,&curr,DESTROY_FROM_DEADLIST); /* also removes from conn_dead list and fdwatch */ } } extern t_list * connlist(void) { return conn_head; } extern t_connection * connlist_find_connection_by_accountname(char const * accountname) { t_account * temp; if (!accountname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL accountname"); return NULL; } if (!(temp = accountlist_find_account(accountname))) return NULL; return account_get_conn(temp); } extern t_connection * connlist_find_connection_by_account(t_account * account) { if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } return account_get_conn(account); } extern t_connection * connlist_find_connection_by_sessionkey(unsigned int sessionkey) { t_connection * c; t_elem const * curr; LIST_TRAVERSE_CONST(conn_head,curr) { c = elem_get_data(curr); if (c->protocol.sessionkey==sessionkey) return c; } return NULL; } extern t_connection * connlist_find_connection_by_sessionnum(unsigned int sessionnum) { return connarray_get_conn(sessionnum); } extern t_connection * connlist_find_connection_by_socket(int socket) { t_connection * c; t_elem const * curr; LIST_TRAVERSE_CONST(conn_head,curr) { c = elem_get_data(curr); if (c->socket.tcp_sock==socket) return c; } return NULL; } extern t_connection * connlist_find_connection_by_name(char const * name, t_realm * realm) { char charname[CHAR_NAME_LEN]; char const * temp; if (!name) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL name"); return NULL; } if (name[0]=='\0') { eventlog(eventlog_level_error,__FUNCTION__,"got empty name"); return NULL; } /* format: *username */ if (name[0]=='*') { name++; return connlist_find_connection_by_accountname(name); } /* If is charname@otherrealm or ch@rname@realm */ if ((temp=strrchr(name,'@'))) /* search from the right */ { unsigned int n; n = temp - name; if (n>=CHAR_NAME_LEN) { eventlog(eventlog_level_info,__FUNCTION__,"character name too long in \"%s\" (charname@otherrealm format)",name); return NULL; } strncpy(charname,name,n); charname[n] = '\0'; return connlist_find_connection_by_charname(name,temp + 1); } /* format: charname*username */ if ((temp=strchr(name,'*'))) { unsigned int n; n = temp - name; if (n>=CHAR_NAME_LEN) { eventlog(eventlog_level_info,__FUNCTION__,"character name too long in \"%s\" (charname*username format)",name); return NULL; } name = temp + 1; return connlist_find_connection_by_accountname(name); } /* format: charname (realm must be not NULL) */ if (realm) return connlist_find_connection_by_charname(name,realm_get_name(realm)); /* format: Simple username, clients with no realm, like starcraft or d2 open, * the format is the same of charname but is matched if realmname is NULL */ return connlist_find_connection_by_accountname(name); } extern t_connection * connlist_find_connection_by_charname(char const * charname, char const * realmname) { t_connection * c; t_elem const * curr; if (!realmname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realmname"); return NULL; } LIST_TRAVERSE_CONST(conn_head, curr) { c = elem_get_data(curr); if (!c) continue; if (!c->protocol.d2.charname) continue; if (!c->protocol.d2.realm) continue; if ((strcasecmp(c->protocol.d2.charname, charname)==0)&&(strcasecmp(realm_get_name(c->protocol.d2.realm),realmname)==0)) return c; } return NULL; } extern t_connection * connlist_find_connection_by_uid(unsigned int uid) { t_account * temp; if (!(temp = accountlist_find_account_by_uid(uid))) { return NULL; } return account_get_conn(temp); } extern int connlist_get_length(void) { return list_get_length(conn_head); } extern unsigned int connlist_login_get_length(void) { t_connection const * c; unsigned int count; t_elem const * curr; count = 0; LIST_TRAVERSE_CONST(conn_head,curr) { c = elem_get_data(curr); if ((c->protocol.state==conn_state_loggedin)&& ((c->protocol.class==conn_class_bnet)||(c->protocol.class==conn_class_bot)||(c->protocol.class==conn_class_telnet)||(c->protocol.class==conn_class_irc)||(c->protocol.class==conn_class_wol))) count++; } return count; } extern int connlist_total_logins(void) { return totalcount; } extern unsigned int connlist_count_connections(unsigned int addr) { t_connection * c; t_elem const * curr; unsigned int count; count = 0; LIST_TRAVERSE_CONST(conn_head,curr) { c = (t_connection *)elem_get_data(curr); if (c->socket.tcp_addr == addr) count++; } return count; } extern int conn_update_w3_playerinfo(t_connection * c) { t_account * account; t_clienttag clienttag; t_clan * user_clan; int clantag=0; unsigned int acctlevel; char tempplayerinfo[40]; char raceicon; /* appeared in 1.03 */ unsigned int raceiconnumber; unsigned int wins; char const * usericon; char clantag_str_tmp[5]; const char * clantag_str = NULL; char revtag[5]; char clienttag_str[5]; if (c == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return -1; } account = conn_get_account(c); if (account == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL account"); return -1; } strncpy(revtag, tag_uint_to_str(clienttag_str,conn_get_fake_clienttag(c)),5); revtag[4] = '\0'; strreverse(revtag); clienttag = c->protocol.client.clienttag; acctlevel = account_get_highestladderlevel(account,clienttag); account_get_raceicon(account, &raceicon, &raceiconnumber, &wins, clienttag); if((user_clan = account_get_clan(account)) != NULL) clantag = clan_get_clantag(user_clan); if(clantag) { sprintf(clantag_str_tmp, "%c%c%c%c", clantag&0xff, (clantag>>8)&0xff, (clantag>>16)&0xff, clantag>>24); clantag_str=clantag_str_tmp; while((* clantag_str) == 0) clantag_str++; } if(acctlevel == 0) { if(clantag) sprintf(tempplayerinfo, "%s %s 0 %s", revtag, revtag, clantag_str); else strcpy(tempplayerinfo, revtag); eventlog(eventlog_level_info,__FUNCTION__,"[%d] %s",conn_get_socket(c), revtag); } else { usericon = account_get_user_icon(account,clienttag); if (!usericon) { if(clantag) sprintf(tempplayerinfo, "%s %1u%c3W %u %s", revtag, raceiconnumber, raceicon, acctlevel, clantag_str); else sprintf(tempplayerinfo, "%s %1u%c3W %u", revtag, raceiconnumber, raceicon, acctlevel); eventlog(eventlog_level_info,__FUNCTION__,"[%d] %s using generated icon [%1u%c3W]",conn_get_socket(c), revtag, raceiconnumber, raceicon); } else { if(clantag) sprintf(tempplayerinfo, "%s %s %u %s",revtag, usericon, acctlevel, clantag_str); else sprintf(tempplayerinfo, "%s %s %u",revtag, usericon, acctlevel); eventlog(eventlog_level_info,__FUNCTION__,"[%d] %s using user-selected icon [%s]",conn_get_socket(c),revtag,usericon); } } conn_set_w3_playerinfo( c, tempplayerinfo ); return 0; } extern int conn_get_passfail_count (t_connection * c) { if (!c) { eventlog(eventlog_level_error, "conn_get_passfail_count", "got NULL connection"); return -1; } return c->protocol.passfail_count; } extern int conn_set_passfail_count (t_connection * c, unsigned int n) { if (c == NULL) { eventlog(eventlog_level_error, "conn_set_passfail_count", "got NULL connection"); return -1; } c->protocol.passfail_count = n; return 0; } extern int conn_increment_passfail_count (t_connection * c) { unsigned int count; if (prefs_get_passfail_count() > 0) { count = conn_get_passfail_count(c) + 1; if (count == prefs_get_passfail_count()) { ipbanlist_add(NULL, addr_num_to_ip_str(conn_get_addr(c)), now+(time_t)prefs_get_passfail_bantime()); eventlog(eventlog_level_info,__FUNCTION__,"[%d] failed password tries: %d (banned ip)",conn_get_socket(c), count); conn_set_state(c, conn_state_destroy); return -1; } else conn_set_passfail_count(c, count); } return 0; } extern int conn_set_tmpOP_channel(t_connection * c, char const * tmpOP_channel) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return -1; } if (c->protocol.chat.tmpOP_channel) { xfree((void *)c->protocol.chat.tmpOP_channel); c->protocol.chat.tmpOP_channel = NULL; } if (tmpOP_channel) c->protocol.chat.tmpOP_channel = xstrdup(tmpOP_channel); return 0; } extern char const * conn_get_tmpOP_channel(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return NULL; } return c->protocol.chat.tmpOP_channel; } extern int conn_set_tmpVOICE_channel(t_connection * c, char const * tmpVOICE_channel) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return -1; } if (c->protocol.chat.tmpVOICE_channel) { xfree((void *)c->protocol.chat.tmpVOICE_channel); c->protocol.chat.tmpVOICE_channel = NULL; } if (tmpVOICE_channel) c->protocol.chat.tmpVOICE_channel = xstrdup(tmpVOICE_channel); return 0; } extern char const * conn_get_tmpVOICE_channel(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return NULL; } return c->protocol.chat.tmpVOICE_channel; } static int connarray_create(void) { int i; t_conn_entry *curr; if (connarray) connarray_destroy(); connarray = xmalloc(sizeof(t_conn_entry) * fdw_maxcons); elist_init(&arrayflist); /* put all elements as free */ for(i = 0, curr = connarray; i < fdw_maxcons; i++, curr++) { elist_add_tail(&arrayflist,&curr->freelist); curr->c = NULL; } return 0; } static void connarray_destroy(void) { if (connarray) xfree((void*)connarray); connarray = NULL; } static t_connection *connarray_get_conn(unsigned index) { if (index >= fdw_maxcons) return NULL; return connarray[index].c; } static unsigned connarray_add_conn(t_connection *c) { t_conn_entry *curr; assert(c); assert(!elist_empty(&arrayflist)); curr = elist_entry(elist_next(&arrayflist),t_conn_entry,freelist); assert(curr->c == NULL); /* it should never be free and != NULL */ curr->c = c; elist_del(&curr->freelist); return (curr - connarray); /* return the array index */ } static void connarray_del_conn(unsigned index) { t_conn_entry *curr; if (index >= fdw_maxcons) return; curr = connarray + index; curr->c = NULL; elist_add_tail(&arrayflist,&curr->freelist); } /** * Westwood Online Extensions */ extern int conn_get_wol(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"get NULL conn"); return -1; } if (c->protocol.class==conn_class_wol) return 1; return 0; } extern void conn_wol_set_ingame(t_connection * c, int ingame) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"get NULL conn"); return; } if (ingame) c->protocol.wol.ingame = ingame; } extern int conn_wol_get_ingame(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"get NULL conn"); return -1; } return c->protocol.wol.ingame; } extern void conn_wol_set_apgar(t_connection * c, char const * apgar) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!apgar) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL WOL apgar"); return; } if (c->protocol.wol.apgar) xfree((void *)c->protocol.wol.apgar); /* avoid warning */ c->protocol.wol.apgar = xstrdup(apgar); } extern char const * conn_wol_get_apgar(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return NULL; } return c->protocol.wol.apgar; } extern void conn_wol_set_codepage(t_connection * c, int codepage) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return; } if (codepage) c->protocol.wol.codepage = codepage; } extern int conn_wol_get_codepage(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return -1; } return c->protocol.wol.codepage; } extern void conn_wol_set_locale(t_connection * c, int locale) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return; } if (locale) c->protocol.wol.locale = locale; } extern int conn_wol_get_locale(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return -1; } return c->protocol.wol.locale; } extern void conn_wol_set_game_type(t_connection * c, int gameType) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (gameType) c->protocol.wol.gameType = gameType; } extern int conn_wol_get_game_type(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return -1; } return c->protocol.wol.gameType; } extern void conn_wol_set_game_options(t_connection * c, char const * gameOptions) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (!gameOptions) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game options"); return; } if (c->protocol.wol.gameOptions) xfree((void *)c->protocol.wol.gameOptions); /* avoid warning */ c->protocol.wol.gameOptions = xstrdup(gameOptions); } extern char const * conn_wol_get_game_options(t_connection * c) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return NULL; } return c->protocol.wol.gameOptions; } pvpgn-1.8.5/src/bnetd/realm.h0000644000175000017500000000574011151345317015004 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_REALM_TYPES #define INCLUDED_REALM_TYPES #ifdef JUST_NEED_TYPES #include "common/addr.h" #include "connection.h" # include "common/rcm.h" #else #define JUST_NEED_TYPES #include "common/addr.h" #include "connection.h" # include "common/rcm.h" #undef JUST_NEED_TYPES #endif struct connection; typedef struct realm #ifdef REALM_INTERNAL_ACCESS { char const * name; char const * description; unsigned int sessionnum; unsigned int active; unsigned int ip; unsigned short port; unsigned int player_number; unsigned int game_number; int tcp_sock; struct connection * conn; t_rcm rcm; } #endif t_realm; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_REALM_PROTOS #define INCLUDED_REALM_PROTOS #define JUST_NEED_TYPES #include "common/list.h" #include "common/addr.h" #include "connection.h" #include "common/rcm.h" #undef JUST_NEED_TYPES extern char const * realm_get_name(t_realm const * realm) ; extern char const * realm_get_description(t_realm const * realm) ; extern unsigned short realm_get_port(t_realm const * realm) ; extern unsigned int realm_get_ip(t_realm const * realm) ; extern int realm_set_name(t_realm * realm, char const * name); extern unsigned int realm_get_active(t_realm const * realm); extern unsigned int realm_get_player_number(t_realm const * realm); extern int realm_add_player_number(t_realm * realm, int number); extern unsigned int realm_get_game_number(t_realm const * realm); extern int realm_add_game_number(t_realm * realm, int number); extern int realm_set_active(t_realm * realm, unsigned int active); extern int realm_active(t_realm * realm, struct connection * c); extern int realm_deactive(t_realm * realm); extern int realmlist_create(char const * filename); extern int realmlist_destroy(void); extern int realmlist_reload(char const * filename); extern t_realm * realmlist_find_realm(char const * realmname); extern t_realm * realmlist_find_realm_by_ip(unsigned long ip); /* ??? */ extern t_list * realmlist(void); extern struct connection * realm_get_conn(t_realm * realm); extern t_realm * realm_get(t_realm * realm, t_rcm_regref * regref); extern void realm_put(t_realm * realm, t_rcm_regref * regref); #endif #endif pvpgn-1.8.5/src/bnetd/handle_anongame.c0000644000175000017500000011704411151345317017000 0ustar aaronaaron/* * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "common/bn_type.h" #include "common/eventlog.h" #include "common/packet.h" #include "common/queue.h" #include "common/tag.h" #include "common/list.h" #include "common/util.h" #include "common/xalloc.h" #include "common/bnettime.h" #include "connection.h" #include "team.h" #include "account.h" #include "account_wrap.h" #include "channel.h" #include "anongame.h" #include "anongame_infos.h" #include "anongame_maplists.h" #include "handle_anongame.h" #include "tournament.h" #include "server.h" #include "clan.h" #include "common/setup_after.h" /* option - handling function */ /* 0x00 */ /* PG style search - handle_anongame_search() in anongame.c */ /* 0x01 */ /* server side packet sent from handle_anongame_search() in anongame.c */ /* 0x02 */ static int _client_anongame_infos(t_connection * c, t_packet const * const packet); /* 0x03 */ static int _client_anongame_cancel(t_connection * c); /* 0x04 */ static int _client_anongame_profile(t_connection * c, t_packet const * const packet); /* 0x05 */ /* AT style search - handle_anongame_search() in anongame.c */ /* 0x06 */ /* AT style search (Inviter) handle_anongame_search() in anongame.c */ /* 0x07 */ static int _client_anongame_tournament(t_connection * c, t_packet const * const packet); /* 0x08 */ static int _client_anongame_profile_clan(t_connection * c, t_packet const * const packet); /* 0x09 */ static int _client_anongame_get_icon(t_connection * c, t_packet const * const packet); /* 0x0A */ static int _client_anongame_set_icon(t_connection * c, t_packet const * const packet); /* misc functions used by _client_anongame_tournament() */ static unsigned int _tournament_time_convert(unsigned int time); /* and now the functions */ static int _client_anongame_profile_clan(t_connection * c, t_packet const * const packet) { t_packet * rpacket; int clantag; int clienttag; int count; int temp; t_clan * clan; unsigned char rescount; if (packet_get_size(packet)u.client_findanongame_profile_clan.clantag); clienttag = bn_int_get(packet->u.client_findanongame_profile_clan.clienttag); count = bn_int_get(packet->u.server_findanongame_profile_clan.count); clan = clanlist_find_clan_by_clantag(clantag); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket,sizeof(t_server_findanongame_profile_clan)); packet_set_type(rpacket,SERVER_FINDANONGAME_PROFILE_CLAN); bn_byte_set(&rpacket->u.server_findanongame_profile_clan.option,CLIENT_FINDANONGAME_PROFILE_CLAN); bn_int_set(&rpacket->u.server_findanongame_profile_clan.count,count); rescount = 0; if (!(clan)) { temp = 0; packet_append_data(rpacket,&temp,1); } else { temp = 0; packet_append_data(rpacket,&temp,1); /* need to add clan stuff here: format: bn_int ladder_tag (SNLC, 2NLC, 3NLC, 4NLC) bn_int wins bn_int losses bn_byte rank bn_byte progess bar bn_int xp bn_int rank bn_byte 0x06 <-- random + 5 races 6 times: bn_int wins bn_int losses */ } bn_byte_set(&rpacket->u.server_findanongame_profile_clan.rescount,rescount); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } static int _client_anongame_profile(t_connection * c, t_packet const * const packet) { t_packet * rpacket; char const * username; int Count, i; int temp; t_account * account; t_connection * dest_c; t_clienttag ctag; char clienttag_str[5]; t_list * teamlist; unsigned char teamcount; unsigned char *atcountp; t_elem * curr; t_team * team; t_bnettime bn_time; bn_long ltime; Count = bn_int_get(packet->u.client_findanongame.count); eventlog(eventlog_level_info,__FUNCTION__,"[%d] got a FINDANONGAME PROFILE packet",conn_get_socket(c)); if (!(username = packet_get_str_const(packet,sizeof(t_client_findanongame_profile),USER_NAME_MAX))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad FINDANONGAME_PROFILE (missing or too long username)",conn_get_socket(c)); return -1; } //If no account is found then break if (!(account = accountlist_find_account(username))) { eventlog(eventlog_level_error, __FUNCTION__, "Could not get account - PROFILE"); return -1; } if (!(dest_c = connlist_find_connection_by_accountname(username))) { eventlog(eventlog_level_debug, __FUNCTION__, "account is offline - try ll_clienttag"); if (!(ctag = account_get_ll_clienttag(account))) return -1; } else ctag = conn_get_clienttag(dest_c); eventlog(eventlog_level_info,__FUNCTION__,"Looking up %s's %s Stats.",username,tag_uint_to_str(clienttag_str,ctag)); if (account_get_ladder_level(account,ctag,ladder_id_solo)<=0 && account_get_ladder_level(account,ctag,ladder_id_team)<=0 && account_get_ladder_level(account,ctag,ladder_id_ffa)<=0 && account_get_teams(account)==NULL) { eventlog(eventlog_level_info,__FUNCTION__,"%s does not have WAR3 Stats.",username); if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket,sizeof(t_server_findanongame_profile2)); packet_set_type(rpacket,SERVER_FINDANONGAME_PROFILE); bn_byte_set(&rpacket->u.server_findanongame_profile2.option,CLIENT_FINDANONGAME_PROFILE); bn_int_set(&rpacket->u.server_findanongame_profile2.count,Count); bn_int_set(&rpacket->u.server_findanongame_profile2.icon,account_icon_to_profile_icon(account_get_user_icon(account,ctag),account,ctag)); bn_byte_set(&rpacket->u.server_findanongame_profile2.rescount,0); temp=0; packet_append_data(rpacket,&temp,2); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } else // If they do have a profile then: { int solowins=account_get_ladder_wins(account,ctag,ladder_id_solo); int sololoss=account_get_ladder_losses(account,ctag,ladder_id_solo); int soloxp=account_get_ladder_xp(account,ctag,ladder_id_solo); int sololevel=account_get_ladder_level(account,ctag,ladder_id_solo); int solorank=account_get_ladder_rank(account,ctag,ladder_id_solo); int teamwins=account_get_ladder_wins(account,ctag,ladder_id_team); int teamloss=account_get_ladder_losses(account,ctag,ladder_id_team); int teamxp=account_get_ladder_xp(account,ctag,ladder_id_team); int teamlevel=account_get_ladder_level(account,ctag,ladder_id_team); int teamrank=account_get_ladder_rank(account,ctag,ladder_id_team); int ffawins=account_get_ladder_wins(account,ctag,ladder_id_ffa); int ffaloss=account_get_ladder_losses(account,ctag,ladder_id_ffa); int ffaxp=account_get_ladder_xp(account,ctag,ladder_id_ffa); int ffalevel=account_get_ladder_level(account,ctag,ladder_id_ffa); int ffarank=account_get_ladder_rank(account,ctag,ladder_id_ffa); int humanwins=account_get_racewins(account,W3_RACE_HUMANS,ctag); int humanlosses=account_get_racelosses(account,W3_RACE_HUMANS,ctag); int orcwins=account_get_racewins(account,W3_RACE_ORCS,ctag); int orclosses=account_get_racelosses(account,W3_RACE_ORCS,ctag); int undeadwins=account_get_racewins(account,W3_RACE_UNDEAD,ctag); int undeadlosses=account_get_racelosses(account,W3_RACE_UNDEAD,ctag); int nightelfwins=account_get_racewins(account,W3_RACE_NIGHTELVES,ctag); int nightelflosses=account_get_racelosses(account,W3_RACE_NIGHTELVES,ctag); int randomwins=account_get_racewins(account,W3_RACE_RANDOM,ctag); int randomlosses=account_get_racelosses(account,W3_RACE_RANDOM,ctag); int tourneywins=account_get_racewins(account,W3_RACE_DEMONS,ctag); int tourneylosses=account_get_racelosses(account,W3_RACE_DEMONS,ctag); unsigned char rescount; if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket,sizeof(t_server_findanongame_profile2)); packet_set_type(rpacket,SERVER_FINDANONGAME_PROFILE); bn_byte_set(&rpacket->u.server_findanongame_profile2.option,CLIENT_FINDANONGAME_PROFILE); bn_int_set(&rpacket->u.server_findanongame_profile2.count,Count); //job count bn_int_set(&rpacket->u.server_findanongame_profile2.icon,account_icon_to_profile_icon(account_get_user_icon(account,ctag),account,ctag)); rescount = 0; if (sololevel > 0) { bn_int_set((bn_int*)&temp,0x534F4C4F); // SOLO backwards packet_append_data(rpacket,&temp,4); temp=0; bn_int_set((bn_int*)&temp,solowins); packet_append_data(rpacket,&temp,2); //SOLO WINS bn_int_set((bn_int*)&temp,sololoss); packet_append_data(rpacket,&temp,2); // SOLO LOSSES bn_int_set((bn_int*)&temp,sololevel); packet_append_data(rpacket,&temp,1); // SOLO LEVEL bn_int_set((bn_int*)&temp,account_get_profile_calcs(account,soloxp,sololevel)); packet_append_data(rpacket,&temp,1); // SOLO PROFILE CALC bn_int_set((bn_int *)&temp,soloxp); packet_append_data(rpacket,&temp,2); // SOLO XP bn_int_set((bn_int *)&temp,solorank); packet_append_data(rpacket,&temp,4); // SOLO LADDER RANK rescount++; } if (teamlevel > 0) { //below is for team records. Add this after 2v2,3v3,4v4 are done bn_int_set((bn_int*)&temp,0x5445414D); packet_append_data(rpacket,&temp,4); bn_int_set((bn_int*)&temp,teamwins); packet_append_data(rpacket,&temp,2); bn_int_set((bn_int*)&temp,teamloss); packet_append_data(rpacket,&temp,2); bn_int_set((bn_int*)&temp,teamlevel); packet_append_data(rpacket,&temp,1); bn_int_set((bn_int*)&temp,account_get_profile_calcs(account,teamxp,teamlevel)); packet_append_data(rpacket,&temp,1); bn_int_set((bn_int*)&temp,teamxp); packet_append_data(rpacket,&temp,2); bn_int_set((bn_int*)&temp,teamrank); packet_append_data(rpacket,&temp,4); //done of team game stats rescount++; } if (ffalevel > 0) { bn_int_set((bn_int*)&temp,0x46464120); packet_append_data(rpacket,&temp,4); bn_int_set((bn_int*)&temp,ffawins); packet_append_data(rpacket,&temp,2); bn_int_set((bn_int*)&temp,ffaloss); packet_append_data(rpacket,&temp,2); bn_int_set((bn_int*)&temp,ffalevel); packet_append_data(rpacket,&temp,1); bn_int_set((bn_int*)&temp,account_get_profile_calcs(account,ffaxp,ffalevel)); packet_append_data(rpacket,&temp,1); bn_int_set((bn_int*)&temp,ffaxp); packet_append_data(rpacket,&temp,2); bn_int_set((bn_int*)&temp,ffarank); packet_append_data(rpacket,&temp,4); //End of FFA Stats rescount++; } /* set result count */ bn_byte_set(&rpacket->u.server_findanongame_profile2.rescount,rescount); bn_int_set((bn_int*)&temp,0x06); //start of race stats packet_append_data(rpacket,&temp,1); bn_int_set((bn_int*)&temp,randomwins); packet_append_data(rpacket,&temp,2); //random wins bn_int_set((bn_int*)&temp,randomlosses); packet_append_data(rpacket,&temp,2); //random losses bn_int_set((bn_int*)&temp,humanwins); packet_append_data(rpacket,&temp,2); //human wins bn_int_set((bn_int*)&temp,humanlosses); packet_append_data(rpacket,&temp,2); //human losses bn_int_set((bn_int*)&temp,orcwins); packet_append_data(rpacket,&temp,2); //orc wins bn_int_set((bn_int*)&temp,orclosses); packet_append_data(rpacket,&temp,2); //orc losses bn_int_set((bn_int*)&temp,undeadwins); packet_append_data(rpacket,&temp,2); //undead wins bn_int_set((bn_int*)&temp,undeadlosses); packet_append_data(rpacket,&temp,2); //undead losses bn_int_set((bn_int*)&temp,nightelfwins); packet_append_data(rpacket,&temp,2); //elf wins bn_int_set((bn_int*)&temp,nightelflosses); packet_append_data(rpacket,&temp,2); //elf losses bn_int_set((bn_int*)&temp,tourneywins); packet_append_data(rpacket,&temp,2); //tourney wins bn_int_set((bn_int*)&temp,tourneylosses); packet_append_data(rpacket,&temp,2); //tourney losses //end of normal stats - Start of AT stats /* 1 byte team count place holder, set later */ packet_append_data(rpacket, &temp, 1); /* we need to store the AT team count but we dont know yet the no * of stored teams so we cache the pointer for later use */ atcountp = (unsigned char *)packet_get_raw_data(rpacket, packet_get_size(rpacket) - 1); teamlist = account_get_teams(account); teamcount = 0; if (teamlist) { int teamtype[] = {0, 0x32565332, 0x33565333, 0x34565334, 0x35565335, 0x36565336}; LIST_TRAVERSE(teamlist,curr) { if (!(team = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } if (team_get_clienttag(team) != ctag) continue; bn_int_set((bn_int*)&temp,teamtype[team_get_size(team)-1]); packet_append_data(rpacket,&temp,4); bn_int_set((bn_int*)&temp,team_get_wins(team)); //at team wins packet_append_data(rpacket,&temp,2); bn_int_set((bn_int*)&temp,team_get_losses(team)); //at team losses packet_append_data(rpacket,&temp,2); bn_int_set((bn_int*)&temp,team_get_level(team)); packet_append_data(rpacket,&temp,1); bn_int_set((bn_int*)&temp,account_get_profile_calcs(account,team_get_xp(team),team_get_level(team))); // xp bar calc packet_append_data(rpacket,&temp,1); bn_int_set((bn_int*)&temp,team_get_xp(team)); packet_append_data(rpacket,&temp,2); bn_int_set((bn_int*)&temp,team_get_rank(team)); //rank on AT ladder packet_append_data(rpacket,&temp,4); bn_time = time_to_bnettime(temp,team_get_lastgame(team)); bnettime_to_bn_long(bn_time,<ime); packet_append_data(rpacket,<ime,8); bn_int_set((bn_int*)&temp,team_get_size(team)-1); packet_append_data(rpacket,&temp,1); for (i=0; i=16)) break; } } *atcountp = (unsigned char)teamcount; conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); eventlog(eventlog_level_info,__FUNCTION__,"Sent %s's WAR3 Stats (including %d teams) to requestor.",username,teamcount); } return 0; } static int _client_anongame_cancel(t_connection * c) { t_packet * rpacket; t_connection * tc[ANONGAME_MAX_GAMECOUNT/2]; // [quetzal] 20020809 - added a_count, so we dont refer to already destroyed anongame t_anongame *a = conn_get_anongame(c); int a_count, i; eventlog(eventlog_level_info,__FUNCTION__,"[%d] got FINDANONGAME CANCEL packet", conn_get_socket(c)); if(!a) return -1; a_count = anongame_get_count(a); // anongame_unqueue(c, anongame_get_queue(a)); // -- already doing unqueue in conn_destroy_anongame for (i=0; i < ANONGAME_MAX_GAMECOUNT/2; i++) tc[i] = anongame_get_tc(a, i); for (i=0; i < ANONGAME_MAX_GAMECOUNT/2; i++) { if (tc[i] == NULL) continue; conn_set_routeconn(tc[i], NULL); conn_destroy_anongame(tc[i]); } if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket,sizeof(t_server_findanongame_playgame_cancel)); packet_set_type(rpacket,SERVER_FINDANONGAME_PLAYGAME_CANCEL); bn_byte_set(&rpacket->u.server_findanongame_playgame_cancel.cancel,SERVER_FINDANONGAME_CANCEL); bn_int_set(&rpacket->u.server_findanongame_playgame_cancel.count, a_count); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); return 0; } static int _client_anongame_get_icon(t_connection * c, t_packet const * const packet) { t_packet * rpacket; //BlacKDicK 04/20/2003 Need some huge re-work on this. { struct { char icon_code[4]; unsigned int portrait_code; char race; bn_short required_wins; char client_enabled; } tempicon; //FIXME: Add those to the prefs and also merge them on accoun_wrap; // FIXED BY DJP 07/16/2003 FOR 110 CHANGE ( TOURNEY & RACE WINS ) + Table_witdh short icon_req_race_wins; short icon_req_tourney_wins; int race[]={W3_RACE_RANDOM,W3_RACE_HUMANS,W3_RACE_ORCS,W3_RACE_UNDEAD,W3_RACE_NIGHTELVES,W3_RACE_DEMONS}; char race_char[6] ={'R','H','O','U','N','D'}; char icon_pos[5] ={'2','3','4','5','6',}; char table_width = 6; char table_height= 5; int i,j; char rico; unsigned int rlvl,rwins; t_clienttag clienttag; t_account * acc; char user_icon[5]; char const * uicon; clienttag = conn_get_clienttag(c); acc = conn_get_account(c); /* WAR3 uses a different table size, might change if blizzard add tournament support to RoC */ if (clienttag==CLIENTTAG_WARCRAFT3_UINT) { table_width = 5; table_height= 4; } eventlog(eventlog_level_info,__FUNCTION__,"[%d] got FINDANONGAME Get Icons packet",conn_get_socket(c)); if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } packet_set_size(rpacket, sizeof(t_server_findanongame_iconreply)); packet_set_type(rpacket, SERVER_FINDANONGAME_ICONREPLY); bn_int_set(&rpacket->u.server_findanongame_iconreply.count, bn_int_get(packet->u.client_findanongame_inforeq.count)); bn_byte_set(&rpacket->u.server_findanongame_iconreply.option, CLIENT_FINDANONGAME_GET_ICON); if ((uicon = account_get_user_icon(acc,clienttag))) { memcpy(&rpacket->u.server_findanongame_iconreply.curricon, uicon,4); } else { account_get_raceicon(acc,&rico,&rlvl,&rwins,clienttag); sprintf(user_icon,"%1d%c3W",rlvl,rico); memcpy(&rpacket->u.server_findanongame_iconreply.curricon,user_icon,4); } bn_byte_set(&rpacket->u.server_findanongame_iconreply.table_width, table_width); bn_byte_set(&rpacket->u.server_findanongame_iconreply.table_size, table_width*table_height); for (j=0;j=icon_req_race_wins) { tempicon.client_enabled=1; }else{ tempicon.client_enabled=0; } }else{ //Building the icon for the tourney icon_req_tourney_wins = anongame_infos_get_ICON_REQ_TOURNEY(j+1); bn_short_set(&tempicon.required_wins,icon_req_tourney_wins); if (account_get_racewins(acc,race[i],clienttag)>=icon_req_tourney_wins) { tempicon.client_enabled=1; }else{ tempicon.client_enabled=0;} } packet_append_data(rpacket, &tempicon, sizeof(tempicon)); } } //Go,go,go conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; } static int _client_anongame_set_icon(t_connection * c, t_packet const * const packet) { //BlacKDicK 04/20/2003 unsigned int desired_icon; char user_icon[5]; /*FIXME: In this case we do not get a 'count' but insted of it we get the icon that the client wants to set.'W3H2' for an example. For now it is ok, since they share the same position on the packet*/ desired_icon=bn_int_get(packet->u.client_findanongame.count); user_icon[4]=0; if (desired_icon==0){ strcpy(user_icon,"NULL"); eventlog(eventlog_level_info,__FUNCTION__,"[%d] Set icon packet to DEFAULT ICON [%4.4s]",conn_get_socket(c),user_icon); }else{ memcpy(user_icon,&desired_icon,4); eventlog(eventlog_level_info,__FUNCTION__,"[%d] Set icon packet to ICON [%s]",conn_get_socket(c),user_icon); } account_set_user_icon(conn_get_account(c),conn_get_clienttag(c),user_icon); //FIXME: Still need a way to 'refresh the user/channel' //_handle_rejoin_command(conn_get_account(c),""); /* ??? channel_update_userflags() */ conn_update_w3_playerinfo(c); channel_rejoin(c); return 0; } static int _client_anongame_infos(t_connection * c, t_packet const * const packet) { t_packet * rpacket; if (bn_int_get(packet->u.client_findanongame_inforeq.count) > 1) { /* reply with 0 entries found */ int temp = 0; if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } packet_set_size(rpacket, sizeof(t_server_findanongame_inforeply)); packet_set_type(rpacket, SERVER_FINDANONGAME_INFOREPLY); bn_byte_set(&rpacket->u.server_findanongame_inforeply.option, CLIENT_FINDANONGAME_INFOS); bn_int_set(&rpacket->u.server_findanongame_inforeply.count, bn_int_get(packet->u.client_findanongame_inforeq.count)); bn_byte_set(&rpacket->u.server_findanongame_inforeply.noitems, 0); packet_append_data(rpacket, &temp, 1); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } else { int i; int client_tag; int server_tag_count = 0; int client_tag_unk; int server_tag_unk; bn_int temp; char noitems; char * tmpdata; int tmplen; t_clienttag clienttag = conn_get_clienttag(c); char last_packet = 0x00; char other_packet = 0x01; char langstr[5]; t_gamelang gamelang = conn_get_gamelang(c); bn_int_tag_get((bn_int const *)&gamelang, langstr, 5); /* Send seperate packet for each item requested * sending all at once overloaded w3xp * [Omega] */ for (i=0;iu.client_findanongame_inforeq.noitems);i++){ noitems = 0; if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } /* Starting the packet stuff */ packet_set_size(rpacket, sizeof(t_server_findanongame_inforeply)); packet_set_type(rpacket, SERVER_FINDANONGAME_INFOREPLY); bn_byte_set(&rpacket->u.server_findanongame_inforeply.option, CLIENT_FINDANONGAME_INFOS); bn_int_set(&rpacket->u.server_findanongame_inforeply.count, 1); memcpy(&temp,(packet_get_data_const(packet,10+(i*8),4)),sizeof(int)); client_tag=bn_int_get(temp); memcpy(&temp,packet_get_data_const(packet,14+(i*8),4),sizeof(int)); client_tag_unk=bn_int_get(temp); switch (client_tag){ case CLIENT_FINDANONGAME_INFOTAG_URL: bn_int_set((bn_int*)&server_tag_unk,0xBF1F1047); packet_append_data(rpacket, "LRU\0" , 4); packet_append_data(rpacket, &server_tag_unk , 4); // FIXME: Maybe need do do some checks to avoid prefs empty strings. tmpdata = anongame_infos_data_get_url(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug,__FUNCTION__,"client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)",i,"CLIENT_FINDANONGAME_INFOTAG_URL",client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_MAP: bn_int_set((bn_int*)&server_tag_unk,0x70E2E0D5); packet_append_data(rpacket, "PAM\0" , 4); packet_append_data(rpacket, &server_tag_unk , 4); tmpdata = anongame_infos_data_get_map(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug,__FUNCTION__,"client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)",i,"CLIENT_FINDANONGAME_INFOTAG_MAP",client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_TYPE: bn_int_set((bn_int*)&server_tag_unk,0x7C87DEEE); packet_append_data(rpacket, "EPYT" , 4); packet_append_data(rpacket, &server_tag_unk , 4); tmpdata = anongame_infos_data_get_type(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug,__FUNCTION__,"client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)",i,"CLIENT_FINDANONGAME_INFOTAG_TYPE",client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_DESC: bn_int_set((bn_int*)&server_tag_unk,0xA4F0A22F); packet_append_data(rpacket, "CSED" , 4); packet_append_data(rpacket,&server_tag_unk,4); tmpdata = anongame_infos_data_get_desc(langstr, clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); eventlog(eventlog_level_debug,__FUNCTION__,"client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)",i,"CLIENT_FINDANONGAME_INFOTAG_DESC",client_tag_unk); noitems++; server_tag_count++; break; case CLIENT_FINDANONGAME_INFOTAG_LADR: bn_int_set((bn_int*)&server_tag_unk,0x3BADE25A); packet_append_data(rpacket, "RDAL" , 4); packet_append_data(rpacket, &server_tag_unk , 4); tmpdata = anongame_infos_data_get_ladr(langstr, clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug,__FUNCTION__,"client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)",i,"CLIENT_FINDANONGAME_INFOTAG_LADR",client_tag_unk); break; default: eventlog(eventlog_level_debug,__FUNCTION__,"unrec client_tag request tagid=(0x%01x) tag=(0x%04x)",i,client_tag); } //Adding a last padding null-byte if (server_tag_count == bn_byte_get(packet->u.client_findanongame_inforeq.noitems)) packet_append_data(rpacket, &last_packet, 1); /* only last packet in group gets 0x00 */ else packet_append_data(rpacket, &other_packet, 1); /* the rest get 0x01 */ //Go,go,go bn_byte_set(&rpacket->u.server_findanongame_inforeply.noitems, noitems); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } return 0; } /* tournament notice disabled at this time, but responce is sent to cleint */ static int _client_anongame_tournament(t_connection * c, t_packet const * const packet) { t_packet * rpacket; t_account * account = conn_get_account(c); t_clienttag clienttag = conn_get_clienttag(c); unsigned int start_prelim = tournament_get_start_preliminary(); unsigned int end_signup = tournament_get_end_signup(); unsigned int end_prelim = tournament_get_end_preliminary(); unsigned int start_r1 = tournament_get_start_round_1(); if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } packet_set_size(rpacket, sizeof(t_server_anongame_tournament_reply)); packet_set_type(rpacket, SERVER_FINDANONGAME_TOURNAMENT_REPLY); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.option, 7); bn_int_set(&rpacket->u.server_anongame_tournament_reply.count, bn_int_get(packet->u.client_anongame_tournament_request.count)); if ( !start_prelim || (end_signup <= now && tournament_user_signed_up(account) < 0) || tournament_check_client(clienttag) < 0) { /* No Tournament Notice */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.type, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown4, 0); bn_int_set( &rpacket->u.server_anongame_tournament_reply.timestamp, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown5, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.countdown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.wins, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.losses, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown3, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.selection, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (start_prelim>=now) { /* Tournament Notice */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.type, 1); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); /* random */ bn_int_set( &rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_prelim)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set( &rpacket->u.server_anongame_tournament_reply.countdown, start_prelim-now); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.wins, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.losses, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown3, 0x00); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (end_signup>=now) { /* Tournament Signup Notice - Play Game Active */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.type, 2); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown4, 0x0828); /* random */ bn_int_set( &rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(end_signup)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set( &rpacket->u.server_anongame_tournament_reply.countdown, end_signup-now); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown3, 0x08); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (end_prelim>=now) { /* Tournament Prelim Period - Play Game Active */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.type, 3); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown4, 0x0828); /* random */ bn_int_set( &rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(end_prelim)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set( &rpacket->u.server_anongame_tournament_reply.countdown, end_prelim-now); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown3, 0x08); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (start_r1>=now && (tournament_get_game_in_progress()) ) { /* Prelim Period Over - Shows user stats (not all prelim games finished) */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.type, 4); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); /* random */ bn_int_set( &rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_r1)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set( &rpacket->u.server_anongame_tournament_reply.countdown, start_r1-now); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown2, 0); /* 00 00 */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown3, 0x08); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (!(tournament_get_in_finals_status(account))) { /* Prelim Period Over - user did not make finals - Shows user stats */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.type, 5); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown4, 0); bn_int_set( &rpacket->u.server_anongame_tournament_reply.timestamp, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown5, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.countdown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.nulltag, 0); } /* cycle through [type-6] & [type-7] packets * * use [type-6] to show client "eliminated" or "continue" * timestamp , countdown & round number (of next round) must be set if clinet continues * * use [type-7] to make cleint wait for 44FF packet option 1 to start game (A guess, not tested) * * not sure if there is overall winner packet sent at end of last final round */ else if ( (0) ) { /* User in finals - Shows user stats and start of next round*/ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.type, 6); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); bn_int_set( &rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_r1)); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set( &rpacket->u.server_anongame_tournament_reply.countdown, start_r1-now); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown2, 0x0000); /* 00 00 */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.wins, 4); /* round number */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.losses, 0); /* 0 = continue , 1= eliminated */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); /* number of rounds in finals */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if ( (0) ) { /* user waiting for match to be made */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.type, 7); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown4, 0); bn_int_set( &rpacket->u.server_anongame_tournament_reply.timestamp, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown5, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.countdown, 0); bn_short_set( &rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.wins, 1); /* round number */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.losses, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); /* number of finals */ bn_byte_set( &rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set( &rpacket->u.server_anongame_tournament_reply.nulltag, 0); } conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); return 0; } static unsigned int _tournament_time_convert(unsigned int time) { /* it works, don't ask me how */ /* some time drift reportd by testers */ unsigned int tmp1, tmp2, tmp3; tmp1 = time-1059179400; /* 0x3F21CB88 */ tmp2 = tmp1*0.59604645; tmp3 = tmp2+3276999960U; /*eventlog(eventlog_level_trace,__FUNCTION__,"time: 0x%08x, tmp1: 0x%08x, tmp2 0x%08x, tmp3 0x%08x",time,tmp1,tmp2,tmp3);*/ return tmp3; } extern int handle_anongame_packet(t_connection * c, t_packet const * const packet) { switch (bn_byte_get(packet->u.client_anongame.option)) { case CLIENT_FINDANONGAME_PROFILE: return _client_anongame_profile(c, packet); case CLIENT_FINDANONGAME_CANCEL: return _client_anongame_cancel(c); case CLIENT_FINDANONGAME_SEARCH: case CLIENT_FINDANONGAME_AT_INVITER_SEARCH: case CLIENT_FINDANONGAME_AT_SEARCH: return handle_anongame_search(c, packet); /* located in anongame.c */ case CLIENT_FINDANONGAME_GET_ICON: return _client_anongame_get_icon(c, packet); case CLIENT_FINDANONGAME_SET_ICON: return _client_anongame_set_icon(c, packet); case CLIENT_FINDANONGAME_INFOS: return _client_anongame_infos(c, packet); case CLIENT_ANONGAME_TOURNAMENT: return _client_anongame_tournament(c, packet); case CLIENT_FINDANONGAME_PROFILE_CLAN: return _client_anongame_profile_clan(c, packet); default: eventlog(eventlog_level_error,__FUNCTION__,"got unhandled option %d",bn_byte_get(packet->u.client_findanongame.option)); return -1; } } pvpgn-1.8.5/src/bnetd/irc.c0000644000175000017500000010312011151345317014443 0ustar aaronaaron/* * Copyright (C) 2001 Marco Ziech (mmz@gmx.net) * Copyright (C) 2005 Bryan Biedenkapp (gatekeep@gmail.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strdup.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "common/irc_protocol.h" #include "common/packet.h" #include "common/eventlog.h" #include "connection.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/addr.h" #include "common/version.h" #include "common/queue.h" #include "common/list.h" #include "common/bnethash.h" #include "common/bnethashconv.h" #include "common/tag.h" #include "message.h" #include "account.h" #include "account_wrap.h" #include "channel.h" #include "irc.h" #include "prefs.h" #include "server.h" #include "tick.h" #include "message.h" #include "command_groups.h" #include "common/util.h" #include "common/xalloc.h" #include "common/setup_after.h" typedef struct { char const * nick; char const * user; char const * host; } t_irc_message_from; static char ** irc_split_elems(char * list, int separator, int ignoreblank); static int irc_unget_elems(char ** elems); static char * irc_message_preformat(t_irc_message_from const * from, char const * command, char const * dest, char const * text); extern int irc_send_cmd(t_connection * conn, char const * command, char const * params) { t_packet * p; char data[MAX_IRC_MESSAGE_LEN+1]; int len; char const * ircname = server_get_hostname(); char const * nick; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!command) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command"); return -1; } if (!(p = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return -1; } nick = conn_get_loggeduser(conn); if (!nick) nick = ""; /* snprintf isn't portable -> check message length first */ if (params) { len = 1+strlen(ircname)+1+strlen(command)+1+strlen(nick)+1+strlen(params)+2; if (len > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len); return -1; } else sprintf(data,":%s %s %s %s\r\n",ircname,command,nick,params); } else { len = 1+strlen(ircname)+1+strlen(command)+1+strlen(nick)+1+2; if (len > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len); return -1; } else sprintf(data,":%s %s %s\r\n",ircname,command,nick); } packet_set_size(p,0); packet_append_data(p,data,len); // eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data); conn_push_outqueue(conn,p); packet_del_ref(p); return 0; } extern int irc_send(t_connection * conn, int code, char const * params) { char temp[4]; /* '000\0' */ if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if ((code>999)||(code<0)) { /* more than 3 digits or negative */ eventlog(eventlog_level_error,__FUNCTION__,"invalid message code (%d)",code); return -1; } sprintf(temp,"%03u",code); return irc_send_cmd(conn,temp,params); } extern int irc_send_cmd2(t_connection * conn, char const * prefix, char const * command, char const * postfix, char const * comment) { t_packet * p; char data[MAX_IRC_MESSAGE_LEN+1]; int len; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!prefix) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL prefix"); return -1; } if (!command) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command"); return -1; } if (!postfix) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL postfix"); return -1; } if (!(p = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return -1; } if (comment) { len = 1+strlen(prefix)+1+strlen(command)+1+strlen(postfix)+2+strlen(comment)+1+2; if (len > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len); return -1; } else sprintf(data,":%s %s %s :%s\r\n",prefix,command,postfix,comment); } else { len = 1+strlen(prefix)+1+strlen(command)+1+strlen(postfix)+1+2; if (len > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len); return -1; } else sprintf(data,":%s %s %s\r\n",prefix,command,postfix); } packet_set_size(p,0); packet_append_data(p,data,len); // eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data); conn_push_outqueue(conn,p); packet_del_ref(p); return 0; } extern int irc_send_ping(t_connection * conn) { t_packet * p; char data[MAX_IRC_MESSAGE_LEN]; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if((conn_get_wol(conn) == 1)) return 0; if (!(p = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return -1; } conn_set_ircping(conn,get_ticks()); if (conn_get_state(conn)==conn_state_bot_username) sprintf(data,"PING :%u\r\n",conn_get_ircping(conn)); /* Undernet doesn't reveal the servername yet ... neither do we */ else if ((6+strlen(server_get_hostname())+2+1)<=MAX_IRC_MESSAGE_LEN) sprintf(data,"PING :%s\r\n",server_get_hostname()); else eventlog(eventlog_level_error,__FUNCTION__,"maximum message length exceeded"); eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data); packet_set_size(p,0); packet_append_data(p,data,strlen(data)); conn_push_outqueue(conn,p); packet_del_ref(p); return 0; } extern int irc_send_pong(t_connection * conn, char const * params) { t_packet * p; char data[MAX_IRC_MESSAGE_LEN]; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if ((1+strlen(server_get_hostname())+1+4+1+strlen(server_get_hostname())+((params)?(2+strlen(params)):(0))+2+1) > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"max message length exceeded"); return -1; } if (!(p = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return -1; } if (params) sprintf(data,":%s PONG %s :%s\r\n",server_get_hostname(),server_get_hostname(),params); else sprintf(data,":%s PONG %s\r\n",server_get_hostname(),server_get_hostname()); eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data); packet_set_size(p,0); packet_append_data(p,data,strlen(data)); conn_push_outqueue(conn,p); packet_del_ref(p); return 0; } extern int irc_authenticate(t_connection * conn, char const * passhash) { t_hash h1; t_hash h2; t_account * a; char const * temphash; char const * username; char temp[MAX_IRC_MESSAGE_LEN]; char const * tempapgar; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } if (!passhash) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL passhash"); return 0; } username = conn_get_loggeduser(conn); if (!username) { /* redundant sanity check */ eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn->protocol.loggeduser"); return 0; } a = accountlist_find_account(username); if (!a) { irc_send_cmd(conn,"NOTICE",":Authentication failed."); /* user does not exist */ return 0; } if (connlist_find_connection_by_account(a) && prefs_get_kick_old_login()==0) { snprintf(temp, sizeof(temp), "%s :Account is already in use!",conn_get_loggeduser(conn)); irc_send(conn,ERR_NICKNAMEINUSE,temp); } else if (account_get_auth_lock(a)==1) { irc_send_cmd(conn,"NOTICE",":Authentication rejected (account is locked) "); } else { if((conn_get_wol(conn) == 1)) { temphash = account_get_wol_apgar(a); tempapgar = conn_wol_get_apgar(conn); if(temphash == NULL) { account_set_wol_apgar(a,tempapgar); temphash = account_get_wol_apgar(a); } if(tempapgar == NULL) { irc_send(conn,RPL_BAD_LOGIN,":Authentication failed."); /* bad APGAR */ conn_increment_passfail_count(conn); return 0; } if(strcmp(temphash,tempapgar) == 0) { conn_set_clienttag(conn,CLIENTTAG_WWOL_UINT); /* WWOL hope here is ok */ conn_login(conn,a,username); conn_set_state(conn,conn_state_loggedin); return 1; } else { irc_send(conn,RPL_BAD_LOGIN,":Authentication failed."); /* bad APGAR */ conn_increment_passfail_count(conn); return 0; } } hash_set_str(&h1,passhash); temphash = account_get_pass(a); hash_set_str(&h2,temphash); if (hash_eq(h1,h2)) { conn_set_clienttag(conn,CLIENTTAG_IIRC_UINT); /* IIRC hope here is ok */ conn_login(conn,a,username); conn_set_state(conn,conn_state_loggedin); irc_send_cmd(conn,"NOTICE",":Authentication successful. You are now logged in."); return 1; } else { irc_send_cmd(conn,"NOTICE",":Authentication failed."); /* wrong password */ conn_increment_passfail_count(conn); } } return 0; } extern int irc_welcome(t_connection * conn) { char temp[MAX_IRC_MESSAGE_LEN]; time_t temptime; char const * tempname; char const * temptimestr; char const * filename; FILE *fp; char * line, * formatted_line; char send_line[MAX_IRC_MESSAGE_LEN]; char motd_failed = 0; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } tempname = conn_get_loggeduser(conn); if ((34+strlen(tempname)+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,":Welcome to the %s IRC Network %s",prefs_get_irc_network_name(), tempname); else sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_WELCOME,temp); if ((14+strlen(server_get_hostname())+10+strlen(PVPGN_SOFTWARE" "PVPGN_VERSION)+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,":Your host is %s, running "PVPGN_SOFTWARE" "PVPGN_VERSION,server_get_hostname()); else sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_YOURHOST,temp); temptime = server_get_starttime(); /* FIXME: This should be build time */ temptimestr = ctime(&temptime); if ((25+strlen(temptimestr)+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,":This server was created %s",temptimestr); /* FIXME: is ctime() portable? */ else sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_CREATED,temp); /* we don't give mode information on MYINFO we give it on ISUPPORT */ if ((strlen(server_get_hostname())+7+strlen(PVPGN_SOFTWARE" "PVPGN_VERSION)+9+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,"%s "PVPGN_SOFTWARE" "PVPGN_VERSION" - -",server_get_hostname()); else sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_MYINFO,temp); if((conn_get_wol(conn) == 1)) sprintf(temp,"NICKLEN=%d TOPICLEN=%d CHANNELLEN=%d PREFIX="CHANNEL_PREFIX" CHANTYPES="CHANNEL_TYPE" NETWORK=%s IRCD="PVPGN_SOFTWARE, WOL_NICKNAME_LEN, MAX_TOPIC_LEN, CHANNEL_NAME_LEN, prefs_get_irc_network_name()); else sprintf(temp,"NICKLEN=%d TOPICLEN=%d CHANNELLEN=%d PREFIX="CHANNEL_PREFIX" CHANTYPES="CHANNEL_TYPE" NETWORK=%s IRCD="PVPGN_SOFTWARE, CHAR_NAME_LEN, MAX_TOPIC_LEN, CHANNEL_NAME_LEN, prefs_get_irc_network_name()); if((strlen(temp))<=MAX_IRC_MESSAGE_LEN) irc_send(conn,RPL_ISUPPORT,temp); else { sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_ISUPPORT,temp); } if ((3+strlen(server_get_hostname())+22+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,":- %s, "PVPGN_SOFTWARE" "PVPGN_VERSION", built on %s",server_get_hostname(),temptimestr); else sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_MOTDSTART,temp); if ((filename = prefs_get_motdfile())) { if ((fp = fopen(filename,"r"))) { while ((line=file_get_line(fp))) { if ((formatted_line = message_format_line(conn,line))) { formatted_line[0]=' '; sprintf(send_line,":-%s",formatted_line); irc_send(conn,RPL_MOTD,send_line); xfree(formatted_line); } } file_get_line(NULL); // clear file_get_line buffer fclose(fp); } else motd_failed = 1; } else motd_failed = 1; if (motd_failed) { irc_send(conn,RPL_MOTD,":- Failed to load motd, sending default motd "); irc_send(conn,RPL_MOTD,":- ====================================================== "); irc_send(conn,RPL_MOTD,":- http://www.pvpgn.org "); irc_send(conn,RPL_MOTD,":- ====================================================== "); } irc_send(conn,RPL_ENDOFMOTD,":End of /MOTD command"); irc_send_cmd(conn,"NOTICE",":This is an experimental service."); conn_set_state(conn,conn_state_bot_password); if (conn_get_ircpass(conn)) { irc_send_cmd(conn,"NOTICE",":Trying to authenticate with PASS ..."); irc_authenticate(conn,conn_get_ircpass(conn)); } else { irc_send_cmd(conn,"NOTICE",":No PASS command received. Please identify yourself by /msg NICKSERV identify ."); } return 0; } /* Channel name conversion rules: */ /* Not allowed in IRC (RFC2812): NUL, BELL, CR, LF, ' ', ':' and ','*/ /* ' ' -> '_' */ /* '_' -> '%_' */ /* '%' -> '%%' */ /* '\b' -> '%b' */ /* '\n' -> '%n' */ /* '\r' -> '%r' */ /* ':' -> '%=' */ /* ',' -> '%-' */ /* In IRC a channel can be specified by '#'+channelname or '!'+channelid */ extern char const * irc_convert_channel(t_channel const * channel) { char const * bname; static char out[CHANNEL_NAME_LEN]; unsigned int outpos; int i; if (!channel) return "*"; memset(out,0,sizeof(out)); out[0] = '#'; outpos = 1; bname = channel_get_name(channel); for (i=0; bname[i]!='\0'; i++) { if (bname[i]==' ') { out[outpos++] = '_'; } else if (bname[i]=='_') { out[outpos++] = '%'; out[outpos++] = '_'; } else if (bname[i]=='%') { out[outpos++] = '%'; out[outpos++] = '%'; } else if (bname[i]=='\b') { out[outpos++] = '%'; out[outpos++] = 'b'; } else if (bname[i]=='\n') { out[outpos++] = '%'; out[outpos++] = 'n'; } else if (bname[i]=='\r') { out[outpos++] = '%'; out[outpos++] = 'r'; } else if (bname[i]==':') { out[outpos++] = '%'; out[outpos++] = '='; } else if (bname[i]==',') { out[outpos++] = '%'; out[outpos++] = '-'; } else { out[outpos++] = bname[i]; } if ((outpos+2)>=(sizeof(out))) { sprintf(out,"!%u",channel_get_channelid(channel)); return out; } } return out; } extern char const * irc_convert_ircname(char const * pircname) { static char out[CHANNEL_NAME_LEN]; unsigned int outpos; int special; int i; char const * ircname = pircname + 1; if (!ircname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ircname"); return NULL; } outpos = 0; memset(out,0,sizeof(out)); special = 0; if (pircname[0]=='!') { t_channel * channel; channel = channellist_find_channel_bychannelid(atoi(ircname)); if (channel) return channel_get_name(channel); else return NULL; } else if (pircname[0]!='#') { return NULL; } for (i=0; ircname[i]!='\0'; i++) { if (ircname[i]=='_') { out[outpos++] = ' '; } else if (ircname[i]=='%') { if (special) { out[outpos++] = '%'; special = 0; } else { special = 1; } } else if (special) { if (ircname[i]=='_') { out[outpos++] = '_'; } else if (ircname[i]=='b') { out[outpos++] = '\b'; } else if (ircname[i]=='n') { out[outpos++] = '\n'; } else if (ircname[i]=='r') { out[outpos++] = '\r'; } else if (ircname[i]=='=') { out[outpos++] = ':'; } else if (ircname[i]=='-') { out[outpos++] = ','; } else { /* maybe it's just a typo :) */ out[outpos++] = '%'; out[outpos++] = ircname[i]; } } else { out[outpos++] = ircname[i]; } if ((outpos+2)>=(sizeof(out))) { return NULL; } } return out; } /* splits an string list into its elements */ /* (list will be modified) */ static char ** irc_split_elems(char * list, int separator, int ignoreblank) { int i; int count; char ** out; if (!list) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL list"); return NULL; } for (count=0,i=0;list[i]!='\0';i++) { if (list[i]==separator) { count++; if (ignoreblank) { /* ignore more than one separators "in a row" */ while ((list[i+1]!='\0')&&(list[i]==separator)) i++; } } } count++; /* count separators -> we have one more element ... */ /* we also need a terminating element */ out = xmalloc((count+1)*sizeof(char *)); out[0] = list; if (count>1) { for (i=1;inick)||(!from->user)||(!from->host)) { eventlog(eventlog_level_error,__FUNCTION__,"got malformed from"); return NULL; } myfrom = xmalloc(strlen(from->nick)+1+strlen(from->user)+1+strlen(from->host)+1); /* nick + "!" + user + "@" + host + "\0" */ sprintf(myfrom,"%s!%s@%s",from->nick,from->user,from->host); } else myfrom = xstrdup(server_get_hostname()); if (dest) mydest = dest; if (text) mytext = text; len = 1+strlen(myfrom)+1+ strlen(command)+1+ strlen(mydest)+1+ 1+strlen(mytext)+1; msg = xmalloc(len); sprintf(msg,":%s\n%s\n%s\n%s",myfrom,command,mydest,mytext); xfree(myfrom); return msg; } extern int irc_message_postformat(t_packet * packet, t_connection const * dest) { int len; /* the four elements */ char * e1; char * e1_2; char * e2; char * e3; char * e4; char const * tname = NULL; char const * toname = "AUTH"; /* fallback name */ if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (!dest) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dest"); return -1; } e1 = packet_get_raw_data(packet,0); e2 = strchr(e1,'\n'); if (!e2) { eventlog(eventlog_level_warn,__FUNCTION__,"malformed message (e2 missing)"); return -1; } *e2++ = '\0'; e3 = strchr(e2,'\n'); if (!e3) { eventlog(eventlog_level_warn,__FUNCTION__,"malformed message (e3 missing)"); return -1; } *e3++ = '\0'; e4 = strchr(e3,'\n'); if (!e4) { eventlog(eventlog_level_warn,__FUNCTION__,"malformed message (e4 missing)"); return -1; } *e4++ = '\0'; if (prefs_get_hide_addr() && !(account_get_command_groups(conn_get_account(dest)) & command_get_group("/admin-addr"))) { e1_2 = strchr(e1,'@'); if (e1_2) { *e1_2++ = '\0'; } } else e1_2 = NULL; if (e3[0]=='\0') { /* fill in recipient */ if ((tname = conn_get_chatname(dest))) toname = tname; } else toname = e3; if (strcmp(toname,"\r")==0) { toname = ""; /* HACK: the target field is really empty */ } len = (strlen(e1)+1+strlen(e2)+1+strlen(toname)+1+strlen(e4)+2+1); if (len<=MAX_IRC_MESSAGE_LEN) { char msg[MAX_IRC_MESSAGE_LEN+1]; if (e1_2) sprintf(msg,"%s@hidden %s %s %s\r\n",e1,e2,toname,e4); else sprintf(msg,"%s %s %s %s\r\n",e1,e2,toname,e4); eventlog(eventlog_level_debug,__FUNCTION__,"sent \"%s\"",msg); packet_set_size(packet,0); packet_append_data(packet,msg,strlen(msg)); if (tname) conn_unget_chatname(dest,tname); return 0; } else { /* FIXME: split up message? */ eventlog(eventlog_level_warn,__FUNCTION__,"maximum IRC message length exceeded"); if (tname) conn_unget_chatname(dest,tname); return -1; } } extern int irc_message_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags) { char * msg; char const * ctag; t_irc_message_from from; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } msg = NULL; if (me) ctag = clienttag_uint_to_str(conn_get_clienttag(me)); else ctag = clienttag_uint_to_str(CLIENTTAG_IIRC_UINT); switch (type) { /* case message_type_adduser: this is sent manually in handle_irc */ case message_type_adduser: /* when we do it somewhere else, then we can also make sure to not get our logs spammed */ break; case message_type_join: from.nick = conn_get_chatname(me); from.user = ctag; from.host = addr_num_to_ip_str(conn_get_addr(me)); if((conn_get_wol(me) == 1)) { char temp[MAX_IRC_MESSAGE_LEN]; memset(temp,0,sizeof(temp)); /** * For WOL the channel JOIN output must be like the following: * user!WWOL@hostname JOIN :clanID,longIP channelName */ sprintf(temp,":0,%u",conn_get_addr(me)); msg = irc_message_preformat(&from,"JOIN",temp,irc_convert_channel(conn_get_channel(me))); } else msg = irc_message_preformat(&from,"JOIN","\r",irc_convert_channel(conn_get_channel(me))); conn_unget_chatname(me,from.nick); break; case message_type_part: from.nick = conn_get_chatname(me); from.user = ctag; from.host = addr_num_to_ip_str(conn_get_addr(me)); msg = irc_message_preformat(&from,"PART","\r",irc_convert_channel(conn_get_channel(me))); conn_unget_chatname(me,from.nick); break; case message_type_talk: case message_type_whisper: { char const * dest; char temp[MAX_IRC_MESSAGE_LEN]; if (me) { from.nick = conn_get_chatname(me); from.host = addr_num_to_ip_str(conn_get_addr(me)); } else { from.nick = server_get_hostname(); from.host = server_get_hostname(); } from.user = ctag; if (type==message_type_talk) dest = irc_convert_channel(conn_get_channel(me)); /* FIXME: support more channels and choose right one! */ else dest = ""; /* will be replaced with username in postformat */ sprintf(temp,":%s",text); msg = irc_message_preformat(&from,"PRIVMSG",dest,temp); if (me) conn_unget_chatname(me,from.nick); } break; case message_type_emote: { char const * dest; char temp[MAX_IRC_MESSAGE_LEN]; /* "\001ACTION " + text + "\001" + \0 */ if ((8+strlen(text)+1+1)<=MAX_IRC_MESSAGE_LEN) { sprintf(temp,":\001ACTION %s\001",text); } else { sprintf(temp,":\001ACTION (maximum message length exceeded)\001"); } from.nick = conn_get_chatname(me); from.user = ctag; from.host = addr_num_to_ip_str(conn_get_addr(me)); /* FIXME: also supports whisper emotes? */ dest = irc_convert_channel(conn_get_channel(me)); /* FIXME: support more channels and choose right one! */ msg = irc_message_preformat(&from,"PRIVMSG",dest,temp); conn_unget_chatname(me,from.nick); } break; case message_type_broadcast: case message_type_info: case message_type_error: { char temp[MAX_IRC_MESSAGE_LEN]; sprintf(temp,":%s",text); if ((type==message_type_info || type==message_type_error) && (conn_get_wol(dst) == 1)) msg = irc_message_preformat(NULL,"PAGE",NULL,temp); else msg = irc_message_preformat(NULL,"NOTICE",NULL,temp); } break; case message_type_channel: /* ignore it */ break; case message_type_userflags: /* ignore it */ break; case message_type_mode: from.nick = conn_get_chatname(me); from.user = ctag; from.host = addr_num_to_ip_str(conn_get_addr(me)); msg = irc_message_preformat(&from,"MODE","\r",text); conn_unget_chatname(me,from.nick); break; case message_type_notice: { char temp[MAX_IRC_MESSAGE_LEN]; sprintf(temp,":%s",text); if (me && conn_get_chatname(me)) { from.nick = conn_get_chatname(me); from.host = addr_num_to_ip_str(conn_get_addr(me)); from.user = ctag; msg = irc_message_preformat(&from,"NOTICE","",temp); }else{ msg = irc_message_preformat(NULL,"NOTICE","",temp); } } break; /** * Westwood Online Extensions */ case message_wol_joingame: from.nick = conn_get_chatname(me); from.user = ctag; from.host = addr_num_to_ip_str(conn_get_addr(me)); msg = irc_message_preformat(&from,"JOINGAME",text,"\r"); conn_unget_chatname(me,from.nick); break; case message_wol_gameopt_owner: from.nick = conn_get_chatname(me); from.user = ctag; from.host = addr_num_to_ip_str(conn_get_addr(me)); msg = irc_message_preformat(&from,"GAMEOPT",irc_convert_channel(conn_get_channel(me)),text); conn_unget_chatname(me,from.nick); break; case message_wol_gameopt_join: from.nick = conn_get_chatname(me); from.user = ctag; from.host = addr_num_to_ip_str(conn_get_addr(me)); msg = irc_message_preformat(&from,"GAMEOPT",channel_wol_get_game_owner(conn_get_channel(me)),text); conn_unget_chatname(me,from.nick); break; case message_wol_start_game: from.nick = conn_get_chatname(me); from.user = ctag; from.host = addr_num_to_ip_str(conn_get_addr(me)); msg = irc_message_preformat(&from,"STARTG","u",text); conn_unget_chatname(me,from.nick); break; case message_wol_page: from.nick = conn_get_chatname(me); from.user = ctag; from.host = addr_num_to_ip_str(conn_get_addr(me)); msg = irc_message_preformat(&from,"PAGE","u",text); conn_unget_chatname(me,from.nick); break; default: eventlog(eventlog_level_warn,__FUNCTION__,"%d not yet implemented",type); return -1; } if (msg) { packet_append_string(packet,msg); xfree(msg); return 0; } return -1; } extern int irc_send_rpl_namreply(t_connection * c, t_channel const * channel) { char temp[MAX_IRC_MESSAGE_LEN]; char const * ircname; int first = 1; t_connection * m; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } memset(temp,0,sizeof(temp)); ircname = irc_convert_channel(channel); if (!ircname) { eventlog(eventlog_level_error,__FUNCTION__,"channel has NULL ircname"); return -1; } /* '@' = secret; '*' = private; '=' = public */ if ((1+1+strlen(ircname)+2+1)<=MAX_IRC_MESSAGE_LEN) { sprintf(temp,"%c %s :",((channel_get_permanent(channel))?('='):('*')),ircname); } else { eventlog(eventlog_level_warn,__FUNCTION__,"maximum message length exceeded"); return -1; } /* FIXME: Add per user flags (@(op) and +(voice))*/ for (m = channel_get_first(channel);m;m = channel_get_next()) { char const * name = conn_get_chatname(m); char flg[5] = ""; unsigned int flags; if (!name) continue; flags = conn_get_flags(m); if (flags & MF_BLIZZARD) strcat(flg,"@"); else if ((flags & MF_BNET) || (flags & MF_GAVEL)) strcat(flg,"%"); else if (flags & MF_VOICE) strcat(flg,"+"); if ((strlen(temp)+((!first)?(1):(0))+strlen(flg)+strlen(name)+1)<=sizeof(temp)) { if (!first) strcat(temp," "); if((conn_get_wol(c) == 1)) { char _temp[MAX_IRC_MESSAGE_LEN]; if ((channel_wol_get_game_owner(channel) != NULL) && (strcmp(channel_wol_get_game_owner(channel),name) == 0)) { strcat(temp,"@"); } snprintf(_temp,sizeof(_temp),"%s,0,%u",name,conn_get_addr(m)); strcat(temp,_temp); } else { strcat(temp,flg); strcat(temp,name); } first = 0; } conn_unget_chatname(m,name); } irc_send(c,RPL_NAMREPLY,temp); return 0; } static int irc_who_connection(t_connection * dest, t_connection * c) { t_account * a; char const * tempuser; char const * tempowner; char const * tempname; char const * tempip; char const * tempflags = "@"; /* FIXME: that's dumb */ char temp[MAX_IRC_MESSAGE_LEN]; char const * tempchannel; if (!dest) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL destination"); return -1; } if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } a = conn_get_account(c); if (!(tempuser = clienttag_uint_to_str(conn_get_clienttag(c)))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag (tempuser)"); return -1; } if (!(tempowner = account_get_ll_owner(a))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ll_owner (tempowner)"); return -1; } if (!(tempname = conn_get_username(c))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL username (tempname)"); return -1; } if (!(tempip = addr_num_to_ip_str(conn_get_addr(c)))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL addr (tempip)"); return -1; } if (!(tempchannel = irc_convert_channel(conn_get_channel(c)))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel (tempchannel)"); return -1; } if ((strlen(tempchannel)+1+strlen(tempuser)+1+strlen(tempip)+1+strlen(server_get_hostname())+1+strlen(tempname)+1+1+strlen(tempflags)+4+strlen(tempowner)+1)>MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_info,__FUNCTION__,"WHO reply too long - skip"); return -1; } else sprintf(temp,"%s %s %s %s %s %c%s :0 %s",tempchannel,tempuser,tempip,server_get_hostname(),tempname,'H',tempflags,tempowner); irc_send(dest,RPL_WHOREPLY,temp); return 0; } extern int irc_who(t_connection * c, char const * name) { /* FIXME: support wildcards! */ if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!name) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL name"); return -1; } if ((name[0]=='#')||(name[0]=='&')||(name[0]=='!')) { /* it's a channel */ t_connection * info; t_channel * channel; char const * ircname; ircname = irc_convert_ircname(name); channel = channellist_find_channel_by_name(ircname,NULL,NULL); if (!channel) { char temp[MAX_IRC_MESSAGE_LEN]; if ((strlen(":No such channel")+1+strlen(name)+1)<=MAX_IRC_MESSAGE_LEN) { sprintf(temp,":No such channel %s",name); irc_send(c,ERR_NOSUCHCHANNEL,temp); } else { irc_send(c,ERR_NOSUCHCHANNEL,":No such channel"); } return 0; } for (info = channel_get_first(channel);info;info = channel_get_next()) { irc_who_connection(c,info); } } else { /* it's just one user */ t_connection * info; if ((info = connlist_find_connection_by_accountname(name))) return irc_who_connection(c,info); } return 0; } pvpgn-1.8.5/src/bnetd/output.c0000644000175000017500000001252211151345317015233 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "output.h" #include "prefs.h" #include "connection.h" #include "game.h" #include "ladder.h" #include "server.h" #include "channel.h" #include "account.h" #include "common/util.h" #include "common/bnettime.h" #include "common/eventlog.h" #include "common/list.h" #include "common/proginfo.h" #include "compat/strerror.h" #include "common/xalloc.h" #include "common/tag.h" char * status_filename; int output_standard_writer(FILE * fp); /* * Initialisation Output * */ extern void output_init(void) { eventlog(eventlog_level_info,__FUNCTION__,"initializing output file"); if (prefs_get_XML_status_output()) status_filename = create_filename(prefs_get_outputdir(),"server",".xml"); // WarCraft III else status_filename = create_filename(prefs_get_outputdir(),"server",".dat"); // WarCraft III return; } /* * Write Functions * */ static int _glist_cb_xml(t_game *game, void *data) { char clienttag_str[5]; fprintf((FILE*)data,"\t\t%s%s\n",game_get_name(game),tag_uint_to_str(clienttag_str,game_get_clienttag(game))); return 0; } static int _glist_cb_simple(t_game *game, void *data) { static int number; char clienttag_str[5]; if (!data) { number = 1; return 0; } fprintf((FILE*)data,"game%d=%s,%s\n",number,tag_uint_to_str(clienttag_str,game_get_clienttag(game)),game_get_name(game)); number++; return 0; } int output_standard_writer(FILE * fp) { t_elem const *curr; t_connection *conn; t_channel const *channel; char const *channel_name; int number; char clienttag_str[5]; if (prefs_get_XML_status_output()) { fprintf(fp,"\n\n"); fprintf(fp,"\t\t%s\n",PVPGN_VERSION); fprintf(fp,"\t\t%s\n",seconds_to_timestr(server_get_uptime())); fprintf(fp,"\t\t\n"); fprintf(fp,"\t\t%d\n",connlist_login_get_length()); LIST_TRAVERSE_CONST(connlist(),curr) { conn = elem_get_data(curr); if (conn_get_account(conn)) fprintf(fp,"\t\t%s%s%s\n",conn_get_username(conn),tag_uint_to_str(clienttag_str,conn_get_clienttag(conn)),conn_get_clientver(conn)); } fprintf(fp,"\t\t\n"); fprintf(fp,"\t\t\n"); fprintf(fp,"\t\t%d\n",gamelist_get_length()); gamelist_traverse(_glist_cb_xml,fp); fprintf(fp,"\t\t\n"); fprintf(fp,"\t\t\n"); fprintf(fp,"\t\t%d\n",channellist_get_length()); LIST_TRAVERSE_CONST(channellist(),curr) { channel = elem_get_data(curr); channel_name = channel_get_name(channel); fprintf(fp,"\t\t%s\n",channel_name); } fprintf(fp,"\t\t\n"); fprintf(fp,"\n"); return 0; } else { fprintf(fp,"[STATUS]\nVersion=%s\nUptime=%s\nGames=%d\nUsers=%d\nChannels=%d\nUserAccounts=%d\n",PVPGN_VERSION,seconds_to_timestr(server_get_uptime()),gamelist_get_length(),connlist_login_get_length(),channellist_get_length(),accountlist_get_length()); // Status fprintf(fp,"[CHANNELS]\n"); number=1; LIST_TRAVERSE_CONST(channellist(),curr) { channel = elem_get_data(curr); channel_name = channel_get_name(channel); fprintf(fp,"channel%d=%s\n",number,channel_name); number++; } fprintf(fp,"[GAMES]\n"); _glist_cb_simple(NULL,NULL); /* init number */ gamelist_traverse(_glist_cb_simple,fp); fprintf(fp,"[USERS]\n"); number=1; LIST_TRAVERSE_CONST(connlist(),curr) { conn = elem_get_data(curr); if (conn_get_account(conn)) { fprintf(fp,"user%d=%s,%s\n",number,tag_uint_to_str(clienttag_str,conn_get_clienttag(conn)),conn_get_username(conn)); number++; } } return 0; } } extern int output_write_to_file(void) { FILE * fp; if (!status_filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(fp = fopen(status_filename,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for writing (fopen: %s)",status_filename,pstrerror(errno)); return -1; } output_standard_writer(fp); fclose(fp); return 0; } extern void output_dispose_filename(void) { if (status_filename) xfree(status_filename); } pvpgn-1.8.5/src/bnetd/handle_d2cs.h0000644000175000017500000000177511151345317016056 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_HANDLE_D2CS_H #define INCLUDED_HANDLE_D2CS_H extern int handle_d2cs_packet(t_connection * c, t_packet const * packet); extern int handle_d2cs_init(t_connection * c); extern int send_d2cs_gameinforeq(t_connection * c); #endif pvpgn-1.8.5/src/bnetd/autoupdate.c0000644000175000017500000001503111151345317016044 0ustar aaronaaron/* * Copyright (C) 2000 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 2002 Gianluigi Tiesi (sherpya@netfarm.it) * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define AUTOUPDATE_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/strtoul.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strchr.h" #include "compat/strdup.h" #include #include "compat/strerror.h" #include "common/eventlog.h" #include "common/list.h" #include "common/util.h" #include "common/proginfo.h" #include "common/tag.h" #include "common/xalloc.h" #include "autoupdate.h" #include "common/setup_after.h" static t_list * autoupdate_head=NULL; static FILE * fp = NULL; /* * Open the autoupdate configuration file, create a linked list of the * clienttag and the update file for it. The format of the file is: * archtagclienttagversiontagupdate file * * Comments begin with # and are ignored. * * The server assumes that the update file is in the "files" directory * so do not include "/" in the filename - it won't be sent * (because it is a security risk). */ extern int autoupdate_load(char const * filename) { unsigned int line; unsigned int pos; char * buff; char * temp; char const * archtag; char const * clienttag; char const * mpqfile; char const * versiontag; t_autoupdate * entry; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return -1; } autoupdate_head = list_create(); for (line=1; (buff = file_get_line(fp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if ((temp = strrchr(buff,'#'))) { unsigned int len; unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } /* FIXME: use next_token instead of strtok */ if (!(archtag = strtok(buff, " \t"))) { /* strtok modifies the string it is passed */ eventlog(eventlog_level_error,__FUNCTION__,"missing archtag on line %u of file \"%s\"",line,filename); continue; } if (!(clienttag = strtok(NULL," \t"))) { eventlog(eventlog_level_error,__FUNCTION__,"missing clienttag on line %u of file \"%s\"",line,filename); continue; } if (!(versiontag = strtok(NULL, " \t"))) { eventlog(eventlog_level_error,__FUNCTION__,"missing versiontag on line %u of file \"%s\"",line,filename); continue; } if (!(mpqfile = strtok(NULL," \t"))) { eventlog(eventlog_level_error,__FUNCTION__,"missing mpqfile on line %u of file \"%s\"",line,filename); continue; } entry = xmalloc(sizeof(t_autoupdate)); if (!tag_check_arch((entry->archtag = tag_str_to_uint(archtag)))) { eventlog(eventlog_level_error,__FUNCTION__,"got unknown archtag"); xfree(entry); continue; } if (!tag_check_client((entry->clienttag = tag_str_to_uint(clienttag)))) { eventlog(eventlog_level_error,__FUNCTION__,"got unknown clienttag"); xfree(entry); continue; } entry->versiontag = xstrdup(versiontag); entry->mpqfile = xstrdup(mpqfile); eventlog(eventlog_level_debug,__FUNCTION__,"update '%s' version '%s' with file %s",clienttag,versiontag,mpqfile); list_append_data(autoupdate_head,entry); } file_get_line(NULL); // clear file_get_line buffer fclose(fp); return 0; } /* * Free up all of the elements in the linked list */ extern int autoupdate_unload(void) { if (autoupdate_head) { t_elem * curr; t_autoupdate * entry; LIST_TRAVERSE(autoupdate_head,curr) { if (!(entry = elem_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); else { xfree((void *)entry->versiontag); /* avoid warning */ xfree((void *)entry->mpqfile); /* avoid warning */ xfree(entry); } list_remove_elem(autoupdate_head,&curr); } if (list_destroy(autoupdate_head)<0) return -1; autoupdate_head = NULL; } return 0; } /* * Check to see if an update exists for the clients version * return file name if there is one * retrun NULL if no update exists */ extern char * autoupdate_check(t_tag archtag, t_tag clienttag, t_tag gamelang, char const * versiontag) { if (autoupdate_head) { t_elem const * curr; t_autoupdate * entry; char * temp; LIST_TRAVERSE_CONST(autoupdate_head,curr) { if (!(entry = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if (entry->archtag != archtag) continue; if (entry->clienttag != clienttag) continue; if (strcmp(entry->versiontag, versiontag) != 0) continue; /* if we have a gamelang then add it to the mpq file name */ if ((gamelang) && // so far only WAR3 uses gamelang specific MPQs! ((clienttag == CLIENTTAG_WARCRAFT3_UINT) || (clienttag == CLIENTTAG_WAR3XP_UINT))){ char gltag[5]; char * tempmpq; char * extention; tag_uint_to_str(gltag,gamelang); tempmpq = xstrdup(entry->mpqfile); temp = xmalloc(strlen(tempmpq)+6); extention = strrchr(tempmpq,'.'); *extention = '\0'; extention++; sprintf(temp, "%s_%s.%s", tempmpq, gltag, extention); xfree((void *)tempmpq); return temp; } temp = xstrdup(entry->mpqfile); return temp; } } return NULL; } pvpgn-1.8.5/src/bnetd/account_wrap.h0000644000175000017500000003540711151345317016374 0ustar aaronaaron/* * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_ACCOUNT_WRAP_PROTOS #define INCLUDED_ACCOUNT_WRAP_PROTOS #define JUST_NEED_TYPES #include "account.h" #include "connection.h" #include "character.h" #include "common/bnettime.h" #include "ladder.h" #include "game.h" #include "common/tag.h" #undef JUST_NEED_TYPES /* convenience functions */ extern unsigned int account_get_numattr_real(t_account * account, char const * key, char const * fn, unsigned int ln); #define account_get_numattr(A,K) account_get_numattr_real(A,K,__FILE__,__LINE__) extern int account_set_numattr(t_account * account, char const * key, unsigned int val); extern int account_get_boolattr_real(t_account * account, char const * key, char const * fn, unsigned int ln); #define account_get_boolattr(A,K) account_get_boolattr_real(A,K,__FILE__,__LINE__) extern int account_set_boolattr(t_account * account, char const * key, int val); extern char const * account_get_pass(t_account * account); extern int account_set_pass(t_account * account, char const * passhash1); /* authorization */ extern int account_get_auth_admin(t_account * account, char const * channelname); extern int account_set_auth_admin(t_account * account, char const * channelname, int val); extern int account_get_auth_announce(t_account * account); extern int account_get_auth_botlogin(t_account * account); extern int account_get_auth_bnetlogin(t_account * account); extern int account_get_auth_operator(t_account * account, char const * channelname); extern int account_set_auth_operator(t_account * account, char const * channelname, int val); extern int account_get_auth_voice(t_account * account, char const * channelname); extern int account_set_auth_voice(t_account * account, char const * channelname, int val); extern int account_get_auth_changepass(t_account * account); extern int account_get_auth_changeprofile(t_account * account); extern int account_get_auth_createnormalgame(t_account * account); extern int account_get_auth_joinnormalgame(t_account * account); extern int account_get_auth_createladdergame(t_account * account); extern int account_get_auth_joinladdergame(t_account * account); extern int account_get_auth_lock(t_account * account); extern int account_set_auth_lock(t_account * account, int val); /* profile */ extern char const * account_get_sex(t_account * account); /* the profile attributes are updated directly in bnetd.c */ extern char const * account_get_age(t_account * account); extern char const * account_get_loc(t_account * account); extern char const * account_get_desc(t_account * account); /* last login */ extern unsigned int account_get_ll_time(t_account * account); extern int account_set_ll_time(t_account * account, unsigned int t); extern char const * account_get_ll_user(t_account * account); extern int account_set_ll_user(t_account * account, char const * user); extern t_clienttag account_get_ll_clienttag(t_account * account); extern int account_set_ll_clienttag(t_account * account, t_clienttag clienttag); extern char const * account_get_ll_owner(t_account * account); extern int account_set_ll_owner(t_account * account, char const * owner); extern char const * account_get_ll_ip(t_account * account); extern int account_set_ll_ip(t_account * account, char const * ip); /* normal stats */ extern unsigned int account_get_normal_wins(t_account * account, t_clienttag clienttag); extern int account_inc_normal_wins(t_account * account, t_clienttag clienttag); extern int account_set_normal_wins(t_account * account, t_clienttag clienttag, unsigned wins); extern unsigned int account_get_normal_losses(t_account * account, t_clienttag clienttag); extern int account_inc_normal_losses(t_account * account, t_clienttag clienttag); extern int account_set_normal_losses(t_account * account, t_clienttag clienttag, unsigned losses); extern unsigned int account_get_normal_draws(t_account * account, t_clienttag clienttag); extern int account_inc_normal_draws(t_account * account, t_clienttag clienttag); extern unsigned int account_get_normal_disconnects(t_account * account, t_clienttag clienttag); extern int account_inc_normal_disconnects(t_account * account, t_clienttag clienttag); extern int account_set_normal_disconnects(t_account * account, t_clienttag clienttag,unsigned discs); extern int account_set_normal_last_time(t_account * account, t_clienttag clienttag, t_bnettime t); extern int account_set_normal_last_result(t_account * account, t_clienttag clienttag, char const * result); /* ladder stats (active) */ extern unsigned int account_get_ladder_active_wins(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_active_wins(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int wins); extern unsigned int account_get_ladder_active_losses(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_active_losses(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int losses); extern unsigned int account_get_ladder_active_draws(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_active_draws(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int draws); extern unsigned int account_get_ladder_active_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_active_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int disconnects); extern unsigned int account_get_ladder_active_rating(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_active_rating(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int rating); extern int account_get_ladder_active_rank(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_active_rank(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int rank); extern char const * account_get_ladder_active_last_time(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_active_last_time(t_account * account, t_clienttag clienttag, t_ladder_id id, t_bnettime t); /* ladder stats (current) */ extern unsigned int account_get_ladder_wins(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_inc_ladder_wins(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_wins(t_account * account, t_clienttag clienttag, t_ladder_id id,unsigned wins); extern unsigned int account_get_ladder_losses(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_inc_ladder_draws(t_account * account, t_clienttag clienttag, t_ladder_id id); extern unsigned int account_get_ladder_draws(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_inc_ladder_losses(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_losses(t_account * account, t_clienttag clienttag, t_ladder_id id,unsigned losses); extern unsigned int account_get_ladder_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_inc_ladder_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id,unsigned discs); extern unsigned int account_get_ladder_rating(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_rating(t_account * account, t_clienttag clienttag, t_ladder_id id,unsigned rating); extern int account_adjust_ladder_rating(t_account * account, t_clienttag clienttag, t_ladder_id id, int delta); extern int account_get_ladder_rank(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_rank(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int rank); extern unsigned int account_get_ladder_high_rating(t_account * account, t_clienttag clienttag, t_ladder_id id); extern unsigned int account_get_ladder_high_rank(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_last_time(t_account * account, t_clienttag clienttag, t_ladder_id id, t_bnettime t); extern char const * account_get_ladder_last_time(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_last_result(t_account * account, t_clienttag clienttag, t_ladder_id id, char const * result); /* Diablo normal stats */ extern unsigned int account_get_normal_level(t_account * account, t_clienttag clienttag); extern int account_set_normal_level(t_account * account, t_clienttag clienttag, unsigned int level); extern unsigned int account_get_normal_class(t_account * account, t_clienttag clienttag); extern int account_set_normal_class(t_account * account, t_clienttag clienttag, unsigned int class); extern unsigned int account_get_normal_diablo_kills(t_account * account, t_clienttag clienttag); extern int account_set_normal_diablo_kills(t_account * account, t_clienttag clienttag, unsigned int diablo_kills); extern unsigned int account_get_normal_strength(t_account * account, t_clienttag clienttag); extern int account_set_normal_strength(t_account * account, t_clienttag clienttag, unsigned int strength); extern unsigned int account_get_normal_magic(t_account * account, t_clienttag clienttag); extern int account_set_normal_magic(t_account * account, t_clienttag clienttag, unsigned int magic); extern unsigned int account_get_normal_dexterity(t_account * account, t_clienttag clienttag); extern int account_set_normal_dexterity(t_account * account, t_clienttag clienttag, unsigned int dexterity); extern unsigned int account_get_normal_vitality(t_account * account, t_clienttag clienttag); extern int account_set_normal_vitality(t_account * account, t_clienttag clienttag, unsigned int vitality); extern unsigned int account_get_normal_gold(t_account * account, t_clienttag clienttag); extern int account_set_normal_gold(t_account * account, t_clienttag clienttag, unsigned int gold); /* Diablo II closed characters */ extern char const * account_get_closed_characterlist(t_account * account, t_clienttag clienttag, char const * realmname); extern int account_set_closed_characterlist(t_account * account, t_clienttag clienttag, char const * charlist); extern int account_add_closed_character(t_account * account, t_clienttag clienttag, t_character * ch); extern int account_check_closed_character(t_account * account, t_clienttag clienttag, char const * realmname, char const * charname); extern int account_set_friend( t_account * account, int friendnum, unsigned int frienduid ); extern unsigned int account_get_friend( t_account * account, int friendnum); extern int account_get_friendcount( t_account * account ); extern int account_add_friend( t_account * my_acc, t_account * facc ); extern int account_remove_friend( t_account * account, int friendnum ); extern int account_remove_friend2( t_account * account, const char * friend ); extern char const * race_get_str(unsigned int race); extern int account_set_admin( t_account * account ); extern int account_set_demoteadmin( t_account * account ); extern unsigned int account_get_command_groups(t_account * account); extern int account_set_command_groups(t_account * account, unsigned int groups); extern int account_set_w3pgrace( t_account * account, t_clienttag clienttag, unsigned int race); extern int account_get_w3pgrace( t_account * account, t_clienttag clienttag ); extern void account_get_raceicon(t_account * account, char * raceicon, unsigned int * raceiconnumber, unsigned int * wins,t_clienttag clienttag); //Used to call the save stats for all opponents extern int account_set_saveladderstats(t_account *a, unsigned int gametype, t_game_result result, unsigned int opponlevel,t_clienttag clienttag); extern int account_inc_racewins( t_account * account, unsigned int intrace, t_clienttag clienttag); extern int account_get_racewins( t_account * account, unsigned int intrace, t_clienttag clienttag); extern int account_inc_racelosses( t_account * account, unsigned int intrace, t_clienttag clienttag); extern int account_get_racelosses( t_account * account, unsigned int intrace, t_clienttag clienttag); extern int account_update_xp(t_account * account, t_clienttag clienttag, t_game_result gameresult, unsigned int opponlevel,int * xp_diff,t_ladder_id id); extern int account_get_ladder_xp(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_xp(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int xp); extern int account_get_ladder_level(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_ladder_level(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int level); extern int account_adjust_ladder_level(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int account_set_currentatteam(t_account * account, unsigned int teamcount); extern int account_get_currentatteam(t_account * account); extern int account_get_highestladderlevel(t_account * account,t_clienttag clienttag); //func will compare levels for AT, Solo/Team Ladder and out the higest level of the 3 // Determines the length of XP bar in profiles screen extern int account_get_profile_calcs(t_account * account, int xp, unsigned int level); extern unsigned int account_get_icon_profile(t_account * account,t_clienttag clienttag); extern int account_set_user_icon( t_account * account, t_clienttag clienttag,char const * usericon); extern char const * account_get_user_icon( t_account * account, t_clienttag clienttag ); extern unsigned int account_icon_to_profile_icon(char const * icon,t_account * account, t_clienttag ctag); extern char const * account_icon_default(t_account * account, t_clienttag clienttag); extern int account_is_operator_or_admin(t_account * account, char const * channel); extern int account_set_email(t_account * account, char const * email); extern char const * account_get_email(t_account * account); /** * Westwood Online Extensions */ extern char const * account_get_wol_apgar(t_account * account); extern int account_set_wol_apgar(t_account * account, char const * apgar); #endif #endif pvpgn-1.8.5/src/bnetd/command_groups.c0000644000175000017500000001064711151345317016716 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define COMMAND_GROUPS_INTERNAL_ACCESS #include "common/setup_before.h" #include #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "common/eventlog.h" #include "common/list.h" #include "compat/strerror.h" #include "prefs.h" #include "common/util.h" #include "common/xalloc.h" #include "command_groups.h" #include "common/setup_after.h" //#define COMMANDGROUPSDEBUG 1 static t_list * command_groups_head=NULL; static FILE * fp = NULL; extern int command_groups_load(char const * filename) { unsigned int line; unsigned int pos; char * buff; char * temp; char const * command; unsigned int group; t_command_groups * entry; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return -1; } command_groups_head = list_create(); for (line=1; (buff = file_get_line(fp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if ((temp = strrchr(buff,'#'))) { unsigned int len; unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } if (!(temp = strtok(buff," \t"))) { /* strtok modifies the string it is passed */ eventlog(eventlog_level_error,__FUNCTION__,"missing group on line %u of file \"%s\"",line,filename); continue; } if (str_to_uint(temp,&group)<0) { eventlog(eventlog_level_error,__FUNCTION__,"group '%s' not a valid group (1-8)",temp); continue; } if (group == 0 || group > 8) { eventlog(eventlog_level_error,__FUNCTION__,"group '%u' not within groups limits (1-8)",group); continue; } while ((command = strtok(NULL," \t"))) { entry = xmalloc(sizeof(t_command_groups)); entry->group = 1 << (group-1); entry->command = xstrdup(command); list_append_data(command_groups_head,entry); #ifdef COMMANDGROUPSDEBUG eventlog(eventlog_level_info,__FUNCTION__,"Added command: %s - with group %u",entry->command,entry->group); #endif } } file_get_line(NULL); // clear file_get_line buffer fclose(fp); return 0; } extern int command_groups_unload(void) { t_elem * curr; t_command_groups * entry; if (command_groups_head) { LIST_TRAVERSE(command_groups_head,curr) { if (!(entry = elem_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); else { xfree(entry->command); xfree(entry); } list_remove_elem(command_groups_head,&curr); } list_destroy(command_groups_head); command_groups_head = NULL; } return 0; } extern unsigned int command_get_group(char const * command) { t_elem const * curr; t_command_groups * entry; if (command_groups_head) { LIST_TRAVERSE(command_groups_head,curr) { if (!(entry = elem_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); else if (!(strcmp(entry->command,command))) return entry->group; } } return 0; } extern int command_groups_reload(char const * filename) { command_groups_unload(); return command_groups_load(filename); } pvpgn-1.8.5/src/bnetd/prefs.h0000644000175000017500000001740411151345317015023 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 1999 Mark Baysinger (mbaysing@ucsd.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_PREFS_TYPES #define INCLUDED_PREFS_TYPES #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_PREFS_PROTOS #define INCLUDED_PREFS_PROTOS extern int prefs_load(char const * filename); extern void prefs_unload(void); extern char const * prefs_get_storage_path(void) ; extern char const * prefs_get_filedir(void) ; extern char const * prefs_get_logfile(void) ; extern char const * prefs_get_loglevels(void) ; extern char const * prefs_get_motdfile(void) ; extern char const * prefs_get_newsfile(void) ; extern char const * prefs_get_adfile(void) ; extern char const * prefs_get_topicfile(void) ; extern char const * prefs_get_DBlayoutfile(void) ; extern unsigned int prefs_get_user_sync_timer(void) ; extern unsigned int prefs_get_user_flush_timer(void) ; extern unsigned int prefs_get_user_step(void) ; extern char const * prefs_get_hostname(void) ; extern char const * prefs_get_servername(void) ; extern unsigned int prefs_get_track(void) ; extern char const * prefs_get_location(void) ; extern char const * prefs_get_description(void) ; extern char const * prefs_get_url(void) ; extern char const * prefs_get_contact_name(void) ; extern char const * prefs_get_contact_email(void) ; extern unsigned int prefs_get_latency(void) ; extern unsigned int prefs_get_irc_latency(void) ; extern unsigned int prefs_get_shutdown_delay(void) ; extern unsigned int prefs_get_shutdown_decr(void) ; extern unsigned int prefs_get_allow_new_accounts(void) ; extern unsigned int prefs_get_max_accounts(void) ; extern unsigned int prefs_get_kick_old_login(void) ; extern char const * prefs_get_channelfile(void) ; extern unsigned int prefs_get_ask_new_channel(void) ; extern unsigned int prefs_get_hide_pass_games(void) ; extern unsigned int prefs_get_hide_started_games(void) ; extern unsigned int prefs_get_hide_temp_channels(void) ; extern unsigned int prefs_get_hide_addr(void) ; extern unsigned int prefs_get_enable_conn_all(void) ; extern unsigned int prefs_get_extra_commands(void) ; extern unsigned int prefs_get_udptest_port(void) ; extern char const * prefs_get_reportdir(void) ; extern unsigned int prefs_get_report_all_games(void) ; extern unsigned int prefs_get_report_diablo_games(void) ; extern char const * prefs_get_pidfile(void) ; extern char const * prefs_get_iconfile(void) ; extern char const * prefs_get_war3_iconfile(void) ; extern char const * prefs_get_star_iconfile(void) ; extern char const * prefs_get_tosfile(void) ; extern char const * prefs_get_mpqauthfile(void) ; extern char const * prefs_get_mpqfile(void) ; extern char const * prefs_get_trackserv_addrs(void) ; extern char const * prefs_get_bnetdserv_addrs(void) ; extern char const * prefs_get_irc_addrs(void) ; extern char const * prefs_get_w3route_addr(void) ; extern unsigned int prefs_get_use_keepalive(void) ; extern char const * prefs_get_ipbanfile(void) ; extern unsigned int prefs_get_discisloss(void) ; extern char const * prefs_get_helpfile(void) ; extern char const * prefs_get_fortunecmd(void) ; extern char const * prefs_get_transfile(void) ; extern unsigned int prefs_get_chanlog(void) ; extern char const * prefs_get_chanlogdir(void) ; extern unsigned int prefs_get_quota(void) ; extern unsigned int prefs_get_quota_lines(void) ; extern unsigned int prefs_get_quota_time(void) ; extern unsigned int prefs_get_quota_wrapline(void) ; extern unsigned int prefs_get_quota_maxline(void) ; extern unsigned int prefs_get_ladder_init_rating(void) ; extern unsigned int prefs_get_quota_dobae(void) ; extern char const * prefs_get_realmfile(void) ; extern char const * prefs_get_issuefile(void) ; extern char const * prefs_get_effective_user(void) ; extern char const * prefs_get_effective_group(void) ; extern unsigned int prefs_get_nullmsg(void) ; extern unsigned int prefs_get_mail_support(void) ; extern unsigned int prefs_get_mail_quota(void) ; extern char const * prefs_get_maildir(void) ; extern char const * prefs_get_log_notice(void) ; extern unsigned int prefs_get_savebyname(void) ; extern unsigned int prefs_get_skip_versioncheck(void) ; extern unsigned int prefs_get_allow_bad_version(void) ; extern unsigned int prefs_get_allow_unknown_version(void) ; extern char const * prefs_get_versioncheck_file(void) ; extern unsigned int prefs_allow_d2cs_setname(void) ; extern unsigned int prefs_get_d2cs_version(void) ; extern unsigned int prefs_get_hashtable_size(void) ; extern char const * prefs_get_telnet_addrs(void) ; extern unsigned int prefs_get_ipban_check_int(void) ; extern char const * prefs_get_version_exeinfo_match(void) ; extern unsigned int prefs_get_version_exeinfo_maxdiff(void) ; extern unsigned int prefs_get_max_concurrent_logins(void) ; /* ADDED BY UNDYING SOULZZ 4/9/02 */ extern unsigned int prefs_get_identify_timeout_secs(void) ; extern char const * prefs_get_server_info(void) ; /* [zap-zero] 20020616 */ extern char const * prefs_get_mysql_host(void) ; extern char const * prefs_get_mysql_account(void) ; extern char const * prefs_get_mysql_password(void) ; extern char const * prefs_get_mysql_sock(void) ; extern char const * prefs_get_mysql_dbname(void) ; extern unsigned int prefs_get_mysql_persistent(void) ; extern char const * prefs_get_mapsfile(void) ; extern char const * prefs_get_xplevel_file(void) ; extern char const * prefs_get_xpcalc_file(void) ; extern int prefs_get_initkill_timer(void) ; //aaron extern int prefs_get_war3_ladder_update_secs(void) ; extern int prefs_get_output_update_secs(void) ; extern char const * prefs_get_ladderdir(void) ; extern char const * prefs_get_outputdir(void) ; extern int prefs_get_XML_output_ladder(void) ; extern int prefs_get_XML_status_output(void) ; extern char const * prefs_get_account_allowed_symbols(void) ; extern unsigned int prefs_get_account_force_username(void); extern char const * prefs_get_command_groups_file(void) ; extern char const * prefs_get_tournament_file(void) ; extern char const * prefs_get_aliasfile(void) ; extern char const * prefs_get_anongame_infos_file(void) ; extern unsigned int prefs_get_max_conns_per_IP(void) ; extern int prefs_get_max_friends(void) ; extern unsigned int prefs_get_clan_newer_time(void) ; extern unsigned int prefs_get_clan_max_members(void) ; extern unsigned int prefs_get_clan_channel_default_private(void) ; extern unsigned int prefs_get_passfail_count(void) ; extern unsigned int prefs_get_passfail_bantime(void) ; extern unsigned int prefs_get_maxusers_per_channel(void) ; extern char const * prefs_get_supportfile(void); extern char const * prefs_get_allowed_clients(void); extern char const * prefs_get_ladder_games(void); extern char const * prefs_get_ladder_prefix(void); extern unsigned int prefs_get_max_connections(void); extern unsigned int prefs_get_sync_on_logoff(void); extern char const * prefs_get_irc_network_name(void); /** * Westwood Online Extensions */ extern char const * prefs_get_wol_addrs(void); extern char const * prefs_get_wol_timezone(void); extern char const * prefs_get_wol_longitude(void); extern char const * prefs_get_wol_latitude(void); #endif #endif pvpgn-1.8.5/src/bnetd/clan.c0000644000175000017500000010061711151345317014613 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define CLAN_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strrchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include "compat/pdir.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include "common/eventlog.h" #include "common/packet.h" #include "common/bnet_protocol.h" #include "common/tag.h" #include "common/util.h" #include "common/bnettime.h" #include "common/eventlog.h" #include "common/list.h" #include "common/proginfo.h" #include "common/bn_type.h" #include "common/xalloc.h" #include "connection.h" #include "anongame.h" #include "prefs.h" #include "friends.h" #include "game.h" #include "clan.h" #include "account.h" #include "channel.h" #include "anongame.h" #include "storage.h" #include "server.h" #include "compat/uint.h" #include "common/setup_after.h" static t_list *clanlist_head = NULL; int max_clanid = 0; /* callback function for storage use */ static int _cb_load_clans(void *clan) { if (clanlist_add_clan(clan) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "failed to add clan to clanlist"); return -1; } if (((t_clan *) clan)->clanid > max_clanid) max_clanid = ((t_clan *) clan)->clanid; return 0; } /* ** Packet Management */ extern int clan_send_packet_to_online_members(t_clan * clan, t_packet * packet) { t_elem *curr; if (!clan) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } if (!packet) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL packet"); return -1; } LIST_TRAVERSE(clan->members, curr) { t_clanmember * member; t_clienttag clienttag; t_connection * conn; if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list"); continue; } if (!(conn = clanmember_get_conn(member))) continue; // not online if (!(clienttag = conn_get_clienttag(conn))) { eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag"); continue; } if ((clienttag != CLIENTTAG_WARCRAFT3_UINT ) && (clienttag != CLIENTTAG_WAR3XP_UINT)) continue; // online but wrong client conn_push_outqueue(conn, packet); } return 0; } extern int clan_send_status_window_on_create(t_clan * clan) { t_packet * rpacket; t_elem *curr; if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } if ((rpacket = packet_create(packet_class_bnet))) { char channelname[10]; if (clan->clantag) sprintf(channelname, "Clan %c%c%c%c", (clan->clantag >> 24), (clan->clantag >> 16) & 0xff, (clan->clantag >> 8) & 0xff, clan->clantag & 0xff); else { sprintf(channelname, "Clans"); eventlog(eventlog_level_error,__FUNCTION__,"clan has NULL clantag"); } packet_set_size(rpacket, sizeof(t_server_w3xp_clan_clanack)); packet_set_type(rpacket, SERVER_W3XP_CLAN_CLANACK); bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.unknow1, 0); bn_int_set(&rpacket->u.server_w3xp_clan_clanack.clantag, clan->clantag); LIST_TRAVERSE(clan->members, curr) { t_clanmember * member; t_clienttag clienttag; t_connection * conn; if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list"); continue; } if (!(conn = clanmember_get_conn(member))) continue; // not online; if (!(clienttag = conn_get_clienttag(conn))) { eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag"); continue; } if ((clienttag != CLIENTTAG_WARCRAFT3_UINT) && (clienttag != CLIENTTAG_WAR3XP_UINT)) continue; // online but wrong client if (conn_get_channel(conn)) { conn_update_w3_playerinfo(conn); channel_set_userflags(conn); if (conn_set_channel(conn, channelname) < 0) conn_set_channel(conn, CHANNEL_NAME_BANNED); /* should not fail */ } bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.status, member->status); conn_push_outqueue(conn, rpacket); } packet_del_ref(rpacket); } return 0; } extern int clan_close_status_window_on_disband(t_clan * clan) { t_packet * rpacket; t_elem *curr; if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_w3xp_clanquitnotify)); packet_set_type(rpacket, SERVER_W3XP_CLANQUITNOTIFY); bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.status, SERVER_W3XP_CLANQUITNOTIFY_STATUS_REMOVED_FROM_CLAN); LIST_TRAVERSE(clan->members, curr) { t_clanmember * member; t_clienttag clienttag; t_connection * conn; if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list"); continue; } if (!(conn = clanmember_get_conn(member))) continue; // not online; if (!(clienttag = conn_get_clienttag(conn))) { eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag"); continue; } if ((clienttag != CLIENTTAG_WARCRAFT3_UINT) && (clienttag != CLIENTTAG_WAR3XP_UINT)) continue; // online but wrong client conn_push_outqueue(conn, rpacket); conn_update_w3_playerinfo(conn); } packet_del_ref(rpacket); } return 0; } extern int clan_send_status_window(t_connection * c) { t_packet * rpacket; t_account *acc; t_clanmember *member; t_clienttag clienttag; t_clan * clan; if (!(acc = conn_get_account(c))) return 0; if (!(member = account_get_clanmember(acc))) return 0; if (!(clan = member->clan)) { eventlog(eventlog_level_error,__FUNCTION__,"member has NULL clan"); return -1; } if (!(clan->clantag)) { eventlog(eventlog_level_error,__FUNCTION__,"clan has NULL clantag"); return -1; } if (!(clienttag = conn_get_clienttag(c))) { eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag"); return -1; } if ((clienttag != CLIENTTAG_WARCRAFT3_UINT) && (clienttag != CLIENTTAG_WAR3XP_UINT)) return 0; if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_w3xp_clan_clanack)); packet_set_type(rpacket, SERVER_W3XP_CLAN_CLANACK); bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.unknow1, 0); bn_int_set(&rpacket->u.server_w3xp_clan_clanack.clantag, member->clan->clantag); bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.status, member->status); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } extern int clan_close_status_window(t_connection * c) { t_packet * rpacket; t_clienttag clienttag; if (!(clienttag = conn_get_clienttag(c))) { eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag"); return -1; } if ((clienttag != CLIENTTAG_WARCRAFT3_UINT) && (clienttag != CLIENTTAG_WAR3XP_UINT)) return 0; if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_w3xp_clanquitnotify)); packet_set_type(rpacket, SERVER_W3XP_CLANQUITNOTIFY); bn_byte_set(&rpacket->u.server_w3xp_clanquitnotify.status, SERVER_W3XP_CLANQUITNOTIFY_STATUS_REMOVED_FROM_CLAN); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } extern int clan_send_memberlist(t_connection * c, t_packet const *const packet) { t_packet * rpacket; t_elem *curr; char const *username; t_clanmember *member; t_clan *clan; t_account *account; int count = 0; char tmpstr[2]; const char *append_str; if (!(account = conn_get_account(c))) return -1; if (!(clan = account_get_clan(account))) return -1; if ((rpacket = packet_create(packet_class_bnet))) { t_account * memberacc; packet_set_size(rpacket, sizeof(t_server_w3xp_clanmemberlist_reply)); packet_set_type(rpacket, SERVER_W3XP_CLANMEMBERLIST_REPLY); bn_int_set(&rpacket->u.server_w3xp_clanmemberlist_reply.count, bn_int_get(packet->u.client_w3xp_clanmemberlist_req.count)); LIST_TRAVERSE(clan->members, curr) { if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL element in list"); continue; } if (!(memberacc = member->memberacc)) { eventlog(eventlog_level_error,__FUNCTION__,"member has NULL account"); continue; } username = account_get_name(memberacc); packet_append_string(rpacket, username); tmpstr[0] = member->status; append_str = clanmember_get_online_status(member, &tmpstr[1]); packet_append_data(rpacket, tmpstr, 2); if (append_str) packet_append_string(rpacket, append_str); else packet_append_string(rpacket, ""); count++; } bn_byte_set(&rpacket->u.server_w3xp_clanmemberlist_reply.member_count, count); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } return -1; } extern int clan_save_motd_chg(t_connection * c, t_packet const *const packet) { t_account *account; char const *motd; int offset; t_clan *clan; if ((account = conn_get_account(c)) == NULL) return -1; if ((clan = account_get_clan(account)) == NULL) return -1; offset = sizeof(packet->u.client_w3xp_clan_motdchg); motd = packet_get_str_const(packet, offset, CLAN_MOTD_MAX); eventlog(eventlog_level_trace, __FUNCTION__, "[%d] got W3XP_CLAN_MOTDCHG packet : %s", conn_get_socket(c), motd); if (clan_set_motd(clan, motd) != 0) { eventlog(eventlog_level_error, __FUNCTION__, "Failed to set clan motd."); return -1; } clan->modified = 1; return 0; } extern int clan_send_motd_reply(t_connection * c, t_packet const *const packet) { t_packet * rpacket; t_account *account; t_clan *clan; if ((account = conn_get_account(c)) == NULL) return -1; if ((clan = account_get_clan(account)) == NULL) return -1; if (clan->clan_motd == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "Failed to get clan motd."); return -1; } if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_w3xp_clan_motdreply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_MOTDREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_motdreply.count, bn_int_get(packet->u.client_w3xp_clan_motdreq.count)); bn_int_set(&rpacket->u.server_w3xp_clan_motdreply.unknow1, SERVER_W3XP_CLAN_MOTDREPLY_UNKNOW1); packet_append_string(rpacket, clan->clan_motd); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; } /* ** String / Function Management */ extern int clan_get_possible_member(t_connection * c, t_packet const *const packet) { t_packet * rpacket; t_channel *channel; t_connection *conn; char const *username; t_account * account; int friend_count = 0; int clantag; clantag = bn_int_get(packet->u.client_w3xp_clan_createreq.clantag); if ((rpacket = packet_create(packet_class_bnet)) == NULL) { return -1; } packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createreply)); packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEREPLY); bn_int_set(&rpacket->u.server_w3xp_clan_createreply.count, bn_int_get(packet->u.client_w3xp_clan_createreq.count)); if (clanlist_find_clan_by_clantag(clantag) != NULL) { bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.check_result, SERVER_W3XP_CLAN_CREATEREPLY_CHECK_ALLREADY_IN_USE); bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.friend_count, 0); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } if ((account = conn_get_account(c)) && (account_get_clan(account) != NULL || account_get_creating_clan(account) != NULL)) { bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.check_result, SERVER_W3XP_CLAN_CREATEREPLY_CHECK_EXCEPTION); bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.friend_count, 0); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.check_result, SERVER_W3XP_CLAN_CREATEREPLY_CHECK_OK); channel = conn_get_channel(c); if (channel_get_permanent(channel)) { /* If not in a private channel, retreive number of mutual friend connected */ t_list *flist = account_get_friends(conn_get_account(c)); t_elem const *curr; t_friend *fr; LIST_TRAVERSE_CONST(flist, curr) { if ((fr = elem_get_data(curr)) != NULL) { t_account *fr_acc = friend_get_account(fr); t_clienttag clienttag; if (fr->mutual && ((conn = connlist_find_connection_by_account(fr_acc)) != NULL) && (conn_get_channel(conn) == channel) && (!account_get_clan(fr_acc)) && (!account_get_creating_clan(fr_acc)) && (clienttag = conn_get_clienttag(conn)) && ((clienttag == CLIENTTAG_WAR3XP_UINT) || (clienttag == CLIENTTAG_WARCRAFT3_UINT)) && (username = account_get_name(fr_acc))) { friend_count++; packet_append_string(rpacket, username); } } } } else { /* If in a private channel, retreive all users in the channel */ for (conn = channel_get_first(channel); conn; conn = channel_get_next()) { t_account * acc; t_clienttag clienttag; if ((conn != c) && (acc = conn_get_account(conn)) && (!account_get_clan(acc)) && (!account_get_creating_clan(acc)) && (clienttag = conn_get_clienttag(conn)) && ((clienttag == CLIENTTAG_WAR3XP_UINT) || (clienttag == CLIENTTAG_WARCRAFT3_UINT)) && (username = conn_get_username(conn))) { friend_count++; packet_append_string(rpacket, username); } } } bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.friend_count, friend_count); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } extern int clanmember_on_change_status(t_clanmember * member) { t_packet * rpacket; if (member == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember"); return -1; } if (member->clan == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } if ((rpacket = packet_create(packet_class_bnet)) != NULL) { char tmpstr[2]; const char *append_str; packet_set_size(rpacket, sizeof(t_server_w3xp_clanmemberupdate)); packet_set_type(rpacket, SERVER_W3XP_CLANMEMBERUPDATE); packet_append_string(rpacket, account_get_name(member->memberacc)); tmpstr[0] = member->status; append_str = clanmember_get_online_status(member, &tmpstr[1]); packet_append_data(rpacket, tmpstr, 2); if (append_str) packet_append_string(rpacket, append_str); else packet_append_string(rpacket, ""); clan_send_packet_to_online_members(member->clan, rpacket); packet_del_ref(rpacket); } return 0; } extern int clanmember_on_change_status_by_connection(t_connection * conn) { t_packet * rpacket; t_account *acc; t_clanmember *member; if (!(conn)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL conn"); return -1; } if ((acc = conn_get_account(conn)) == NULL) return -1; if ((member = account_get_clanmember(acc)) == NULL) return -1; if (member->clan == NULL) return -1; if ((rpacket = packet_create(packet_class_bnet)) != NULL) { char tmpstr[2]; const char *append_str; packet_set_size(rpacket, sizeof(t_server_w3xp_clanmemberupdate)); packet_set_type(rpacket, SERVER_W3XP_CLANMEMBERUPDATE); packet_append_string(rpacket, account_get_name(acc)); tmpstr[0] = member->status; append_str = clanmember_get_online_status_by_connection(conn, &tmpstr[1]); packet_append_data(rpacket, tmpstr, 2); if (append_str) packet_append_string(rpacket, append_str); else packet_append_string(rpacket, ""); clan_send_packet_to_online_members(member->clan, rpacket); packet_del_ref(rpacket); } return 0; } extern int clan_unload_members(t_clan * clan) { t_elem *curr; t_clanmember *member; if (clan->members) { LIST_TRAVERSE(clan->members, curr) { if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } list_remove_elem(clan->members, &curr); xfree((void *) member); } if (list_destroy(clan->members) < 0) return -1; clan->members = NULL; } return 0; } extern int clan_remove_all_members(t_clan * clan) { t_elem *curr; t_clanmember *member; if (clan->members) { LIST_TRAVERSE(clan->members, curr) { if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } if (member->memberacc != NULL) account_set_clanmember(member->memberacc, NULL); list_remove_elem(clan->members, &curr); xfree((void *) member); } if (list_destroy(clan->members) < 0) return -1; clan->members = NULL; } return 0; } extern int clanlist_remove_clan(t_clan * clan) { t_elem * elem; if (clan == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "get NULL clan"); return -1; } if (list_remove_data(clanlist_head, clan, &elem) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "could not delete clan entry"); return -1; } return 0; } extern int clan_remove(int clantag) { return storage->remove_clan(clantag); } extern int clan_save(t_clan * clan) { if (clan->created <= 0) { if (now - clan->creation_time > 120) { clanlist_remove_clan(clan); clan_destroy(clan); } return 0; } storage->write_clan(clan); clan->modified = 0; return 0; } extern t_list *clanlist(void) { return clanlist_head; } extern int clanlist_add_clan(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } if (!(clan->clanid)) clan->clanid = ++max_clanid; list_append_data(clanlist_head, clan); return clan->clanid; } int clanlist_load(void) { // make sure to unload previous clanlist before loading again if (clanlist_head) clanlist_unload(); clanlist_head = list_create(); storage->load_clans(_cb_load_clans); return 0; } extern int clanlist_save(void) { t_elem *curr; t_clan *clan; if (clanlist_head) { LIST_TRAVERSE(clanlist_head, curr) { if (!(clan = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } if (clan->modified) clan_save(clan); } } return 0; } extern int clanlist_unload(void) { t_elem *curr; t_clan *clan; if (clanlist_head) { LIST_TRAVERSE(clanlist_head, curr) { if (!(clan = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } if (clan->clanname) xfree((void *) clan->clanname); if (clan->clan_motd) xfree((void *) clan->clan_motd); clan_unload_members(clan); xfree((void *) clan); list_remove_elem(clanlist_head, &curr); } if (list_destroy(clanlist_head) < 0) return -1; clanlist_head = NULL; } return 0; } extern t_clan *clanlist_find_clan_by_clanid(int cid) { t_elem *curr; t_clan *clan; if (clanlist_head) { LIST_TRAVERSE(clanlist_head, curr) { if (!(clan = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } eventlog(eventlog_level_error, __FUNCTION__, "trace %d", clan->clanid); if (clan->created && (clan->clanid == cid)) return clan; } } return NULL; } extern t_clan *clanlist_find_clan_by_clantag(int clantag) { t_elem *curr; t_clan *clan; if (clantag == 0) return NULL; if (clanlist_head) { LIST_TRAVERSE(clanlist_head, curr) { if (!(clan = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } if (clan->created && (clan->clantag == clantag)) return clan; } } return NULL; } extern t_clanmember *clan_find_member(t_clan * clan, t_account * memberacc) { t_clanmember *member; t_elem *curr; if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return NULL; } if (!(clan->members)) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL clan->members"); return NULL; } LIST_TRAVERSE(clan->members, curr) { if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL element in list"); return NULL; } if (member->memberacc == memberacc) return member; } return NULL; } extern t_clanmember *clan_find_member_by_name(t_clan * clan, char const *membername) { t_clanmember *member; t_elem *curr; if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return NULL; } if (!(clan->members)) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL clan->members"); return NULL; } LIST_TRAVERSE(clan->members, curr) { if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL element in list"); return NULL; } if (strcasecmp(account_get_name(member->memberacc), membername) == 0) return member; } return NULL; } extern t_clanmember *clan_find_member_by_uid(t_clan * clan, unsigned int memberuid) { t_clanmember *member; t_elem *curr; if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return NULL; } if (!(clan->members)) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL clan->members"); return NULL; } LIST_TRAVERSE(clan->members, curr) { if (!(member = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL element in list"); return NULL; } if (account_get_uid(member->memberacc) == memberuid) return member; } return NULL; } extern t_account *clanmember_get_account(t_clanmember * member) { if (!(member)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember"); return NULL; } return (t_account *) member->memberacc; } extern int clanmember_set_account(t_clanmember * member, t_account * memberacc) { if (!(member)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember"); return -1; } member->memberacc = memberacc; return 0; } extern t_connection *clanmember_get_conn(t_clanmember * member) { t_account * account; if (!(member)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember"); return NULL; } if (!(account = member->memberacc)) { eventlog(eventlog_level_error,__FUNCTION__,"member as NULL account"); return NULL; } return account_get_conn(account); } extern char clanmember_get_status(t_clanmember * member) { if (!(member)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember"); return 0; } if ((member->status == CLAN_NEW) && (now - member->join_time > prefs_get_clan_newer_time() * 3600)) { member->status = CLAN_PEON; member->clan->modified = 1; #ifdef WITH_SQL member->modified = 1; #endif } return member->status; } extern int clanmember_set_status(t_clanmember * member, char status) { if (!(member)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember"); return -1; } if (member->status != status) { member->status = status; member->clan->modified = 1; #ifdef WITH_SQL member->modified = 1; #endif } return 0; } extern time_t clanmember_get_join_time(t_clanmember * member) { if (!(member)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember"); return 0; } return member->join_time; } extern t_clan *clanmember_get_clan(t_clanmember * member) { if (!(member)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember"); return 0; } return member->clan; } extern const char *clanmember_get_online_status(t_clanmember * member, char *status) { return clanmember_get_online_status_by_connection(clanmember_get_conn(member), status); } extern const char *clanmember_get_online_status_by_connection(t_connection * conn, char *status) { if (conn && (conn_get_state(conn)!=conn_state_empty)) { t_game *game; t_channel *channel; if ((game = conn_get_game(conn)) != NULL) { if (game_get_flag(game) == game_flag_private) (*status) = SERVER_W3XP_CLAN_MEMBER_PRIVATE_GAME; else (*status) = SERVER_W3XP_CLAN_MEMBER_GAME; return game_get_name(game); } if ((channel = conn_get_channel(conn)) != NULL) { (*status) = SERVER_W3XP_CLAN_MEMBER_CHANNEL; return channel_get_name(channel); } (*status) = SERVER_W3XP_CLAN_MEMBER_ONLINE; } else (*status) = SERVER_W3XP_CLAN_MEMBER_OFFLINE; return NULL; } extern int clanmember_set_online(t_connection * c) { t_clanmember *member; t_account *acc; if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return -1; } if ((acc = conn_get_account(c)) && (member = account_get_clanmember(acc))) { clanmember_on_change_status(member); } return 0; } extern int clanmember_set_offline(t_connection * c) { t_clanmember *member; t_account *acc; if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); return -1; } if ((acc = conn_get_account(c)) && (member = account_get_clanmember_forced(acc))) { clanmember_on_change_status(member); } return 0; } extern int clan_get_created(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } return clan->created; } extern int clan_set_created(t_clan * clan, int created) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } clan->created = created; return 0; } extern char clan_get_modified(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } return clan->modified; } extern int clan_set_modified(t_clan * clan, char modified) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } clan->modified = modified; return 0; } extern char clan_get_channel_type(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } return clan->channel_type; } extern int clan_set_channel_type(t_clan * clan, char channel_type) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } clan->channel_type = channel_type; return 0; } extern t_list *clan_get_members(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return NULL; } return clan->members; } extern char const *clan_get_name(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return NULL; } return clan->clanname; } extern int clan_get_clantag(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return 0; } return clan->clantag; } extern char const *clan_get_motd(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return NULL; } return clan->clan_motd; } extern int clan_set_motd(t_clan * clan, const char *motd) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } if (!(motd)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL motd"); return -1; } else { if (clan->clan_motd) xfree((void *) clan->clan_motd); clan->clan_motd = xstrdup(motd); } return 0; } extern unsigned int clan_get_clanid(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return 0; } return clan->clanid; } extern int clan_set_creation_time(t_clan * clan, time_t c_time) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return -1; } clan->creation_time = c_time; return 0; } extern time_t clan_get_creation_time(t_clan * clan) { if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return 0; } return clan->creation_time; } extern t_clanmember *clan_add_member(t_clan * clan, t_account * memberacc, char status) { t_clanmember *member; if (!(clan)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan"); return NULL; } if (!(clan->members)) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL clan->members"); return NULL; } member = xmalloc(sizeof(t_clanmember)); member->memberacc = memberacc; member->status = status; member->join_time = now; member->clan = clan; #ifdef WITH_SQL member->modified = 1; #endif list_append_data(clan->members, member); account_set_clanmember(memberacc, member); clan->modified = 1; return member; } extern int clan_remove_member(t_clan * clan, t_clanmember * member) { t_elem * elem; if (!member) return -1; if (list_remove_data(clan->members, member, &elem) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "could not remove member"); return -1; } if (member->memberacc != NULL) { account_set_clanmember(member->memberacc, NULL); storage->remove_clanmember(account_get_uid(member->memberacc)); } xfree((void *) member); clan->modified = 1; return 0; } extern t_clan *clan_create(t_account * chieftain_acc, int clantag, const char *clanname, const char *motd) { t_clan *clan; t_clanmember *member; clan = xmalloc(sizeof(t_clan)); member = xmalloc(sizeof(t_clanmember)); if (!(clanname)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanname"); xfree((void *) clan); xfree((void *) member); return NULL; } clan->clanname = xstrdup(clanname); if (!(motd)) clan->clan_motd = xstrdup("This is a newly created clan"); else clan->clan_motd = xstrdup(motd); clan->creation_time = now; clan->clantag = clantag; clan->clanid = ++max_clanid; clan->created = 0; clan->modified = 1; clan->channel_type = prefs_get_clan_channel_default_private(); clan->members = list_create(); member->memberacc = chieftain_acc; member->status = CLAN_CHIEFTAIN; member->join_time = clan->creation_time; member->clan = clan; #ifdef WITH_SQL member->modified = 1; #endif list_append_data(clan->members, member); account_set_clanmember(chieftain_acc, member); return clan; } extern int clan_destroy(t_clan * clan) { if (!clan) return 0; if (clan->clanname) xfree((void *) clan->clanname); if (clan->clan_motd) xfree((void *) clan->clan_motd); clan_remove_all_members(clan); xfree((void *) clan); return 0; } extern int clan_get_member_count(t_clan * clan) { t_elem *curr; int count = 0; LIST_TRAVERSE(clan->members, curr) { if ((elem_get_data(curr)) != NULL) count++; } return count; } extern int str_to_clantag(const char *str) { int clantag = 0; if (!str) return 0; if (str[0]) { clantag = str[0] << 24; if (str[1]) { clantag += str[1] << 16; if (str[2]) { clantag += str[2] << 8; if (str[3]) clantag += str[3]; } } } return clantag; } pvpgn-1.8.5/src/bnetd/adbanner.h0000644000175000017500000000360611151345317015455 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_ADBANNER_TYPES #define INCLUDED_ADBANNER_TYPES #include "common/tag.h" typedef struct adbanner #ifdef ADBANNER_INTERNAL_ACCESS { unsigned int id; unsigned int extensiontag; unsigned int delay; /* in seconds */ unsigned int next; /* adid or 0 */ char const * filename; char const * link; t_clienttag client; } #endif t_adbanner; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_ADBANNER_PROTOS #define INCLUDED_ADBANNER_PROTOS #define JUST_NEED_TYPES #include "connection.h" #undef JUST_NEED_TYPES extern t_adbanner * adbanner_pick(t_connection const * c, unsigned int prev_id); extern t_adbanner * adbanner_get(t_connection const * c, unsigned int id); extern unsigned int adbanner_get_id(t_adbanner const * ad); extern unsigned int adbanner_get_extensiontag(t_adbanner const * ad); extern char const * adbanner_get_filename(t_adbanner const * ad); extern char const * adbanner_get_link(t_adbanner const * ad); extern t_clienttag adbanner_get_client(t_adbanner const * ad); extern int adbannerlist_create(char const * filename); extern int adbannerlist_destroy(void); #endif #endif pvpgn-1.8.5/src/bnetd/storage.c0000644000175000017500000000536711151345317015350 0ustar aaronaaron/* * Copyright (C) 2002,2003 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "compat/strcasecmp.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "storage.h" #include "storage_file.h" #ifdef WITH_SQL #include "storage_sql.h" #include "storage_sql2.h" #endif #include "compat/strdup.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" t_storage *storage = NULL; extern int storage_init(const char *spath) { char *temp, *p; int res; char dstr[256]; if (spath == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL spath"); return -1; } temp = xstrdup(spath); if ((p = strchr(spath, ':')) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "malformed storage_path , driver not found"); xfree((void*)temp); return -1; } strcpy(dstr, "file"); #ifdef WITH_SQL strcat(dstr, ", sql"); strcat(dstr, ", sql2"); #endif eventlog(eventlog_level_info, __FUNCTION__, "initializing storage layer (available drivers: %s)", dstr); *p = '\0'; if (strcasecmp(spath, "file") == 0) { storage = &storage_file; res = storage->init(p + 1); if (!res) eventlog(eventlog_level_info, __FUNCTION__, "using file storage driver"); } #ifdef WITH_SQL else if (strcasecmp(spath, "sql") == 0) { storage = &storage_sql; res = storage->init(p + 1); if (!res) eventlog(eventlog_level_info, __FUNCTION__, "using sql storage driver"); } else if (strcasecmp(spath, "sql2") == 0) { storage = &storage_sql2; res = storage->init(p + 1); if (!res) eventlog(eventlog_level_info, __FUNCTION__, "using sql2 storage driver"); } #endif else { eventlog(eventlog_level_fatal, __FUNCTION__, "no known driver specified (%s)", spath); res = -1; } xfree((void*)temp); return res; } extern void storage_close(void) { storage->close(); } pvpgn-1.8.5/src/bnetd/attrgroup.c0000644000175000017500000002577411151345317015737 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_ASSERT_H # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "common/eventlog.h" #include "common/flags.h" #include "common/xalloc.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #define ATTRGROUP_INTERNAL_ACCESS #include "attr.h" #include "attrgroup.h" #include "attrlayer.h" #include "storage.h" #include "prefs.h" #include "server.h" #include "common/setup_after.h" static inline void attrgroup_set_accessed(t_attrgroup *attrgroup) { FLAG_SET(&attrgroup->flags, ATTRGROUP_FLAG_ACCESSED); attrgroup->lastaccess = now; } static inline void attrgroup_clear_accessed(t_attrgroup *attrgroup) { FLAG_CLEAR(&attrgroup->flags, ATTRGROUP_FLAG_ACCESSED); } static inline void attrgroup_set_dirty(t_attrgroup *attrgroup) { if (FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_DIRTY)) return; attrgroup->dirtytime = now; FLAG_SET(&attrgroup->flags, ATTRGROUP_FLAG_DIRTY); attrlayer_add_dirtylist(&attrgroup->dirtylist); } static inline void attrgroup_clear_dirty(t_attrgroup *attrgroup) { if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_DIRTY)) return; FLAG_CLEAR(&attrgroup->flags, ATTRGROUP_FLAG_DIRTY); attrlayer_del_dirtylist(&attrgroup->dirtylist); } static inline void attrgroup_set_loaded(t_attrgroup *attrgroup) { if (FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED)) return; FLAG_SET(&attrgroup->flags, ATTRGROUP_FLAG_LOADED); attrlayer_add_loadedlist(&attrgroup->loadedlist); } static inline void attrgroup_clear_loaded(t_attrgroup *attrgroup) { if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED)) return; /* clear this because they are not valid if attrgroup is unloaded */ attrgroup_clear_dirty(attrgroup); attrgroup_clear_accessed(attrgroup); FLAG_CLEAR(&attrgroup->flags, ATTRGROUP_FLAG_LOADED); attrlayer_del_loadedlist(&attrgroup->loadedlist); } static t_attrgroup * attrgroup_create(void) { t_attrgroup *attrgroup; attrgroup = xmalloc(sizeof(t_attrgroup)); hlist_init(&attrgroup->list); attrgroup->storage = NULL; attrgroup->flags = ATTRGROUP_FLAG_NONE; attrgroup->lastaccess = 0; attrgroup->dirtytime = 0; elist_init(&attrgroup->loadedlist); elist_init(&attrgroup->dirtylist); return attrgroup; } extern t_attrgroup * attrgroup_create_storage(t_storage_info *storage) { t_attrgroup *attrgroup; attrgroup = attrgroup_create(); attrgroup->storage = storage; return attrgroup; } extern t_attrgroup * attrgroup_create_newuser(const char *name) { t_attrgroup *attrgroup; t_storage_info *stmp; stmp = storage->create_account(name); if (!stmp) { eventlog(eventlog_level_error,__FUNCTION__,"failed to add user '%s' to storage", name); return NULL; } attrgroup = attrgroup_create_storage(stmp); /* new accounts are born loaded */ attrgroup_set_loaded(attrgroup); return attrgroup; } extern t_attrgroup * attrgroup_create_nameuid(const char *name, unsigned uid) { t_storage_info *info; t_attrgroup *attrgroup; info = storage->read_account(name,uid); if (!info) return NULL; attrgroup = attrgroup_create_storage(info); return attrgroup; } extern int attrgroup_destroy(t_attrgroup *attrgroup) { if (!attrgroup) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup"); return -1; } attrgroup_unload(attrgroup); if (attrgroup->storage) storage->free_info(attrgroup->storage); xfree(attrgroup); return 0; } extern int attrgroup_save(t_attrgroup *attrgroup, int flags) { if (!attrgroup) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup"); return -1; } if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED)) return 0; if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_DIRTY)) return 0; if (!FLAG_ISSET(flags, FS_FORCE) && now - attrgroup->dirtytime < prefs_get_user_sync_timer()) return 0; assert(attrgroup->storage); storage->write_attrs(attrgroup->storage, &attrgroup->list); attrgroup_clear_dirty(attrgroup); return 1; } extern int attrgroup_flush(t_attrgroup *attrgroup, int flags) { t_attr *attr; t_hlist *curr, *save; if (!attrgroup) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup"); return -1; } if (!FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED)) return 0; if (!FLAG_ISSET(flags, FS_FORCE) && FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_ACCESSED) && now - attrgroup->lastaccess < prefs_get_user_flush_timer()) return 0; /* sync data to disk if dirty */ attrgroup_save(attrgroup,FS_FORCE); hlist_for_each_safe(curr,&attrgroup->list,save) { attr = hlist_entry(curr,t_attr,link); attr_destroy(attr); } hlist_init(&attrgroup->list); /* reset list */ attrgroup_clear_loaded(attrgroup); return 1; } static int _cb_load_attr(const char *key, const char *val, void *data) { t_attrgroup *attrgroup = (t_attrgroup *)data; return attrgroup_set_attr(attrgroup, key, val); } extern int attrgroup_load(t_attrgroup *attrgroup) { assert(attrgroup); assert(attrgroup->storage); if (FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_LOADED)) /* already done */ return 0; if (FLAG_ISSET(attrgroup->flags, ATTRGROUP_FLAG_DIRTY)) { /* if not loaded, how dirty ? */ eventlog(eventlog_level_error, __FUNCTION__, "can't load modified account"); return -1; } attrgroup_set_loaded(attrgroup); if (storage->read_attrs(attrgroup->storage, _cb_load_attr, attrgroup)) { eventlog(eventlog_level_error, __FUNCTION__, "got error loading attributes"); return -1; } attrgroup_clear_dirty(attrgroup); return 0; } extern int attrgroup_unload(t_attrgroup *attrgroup) { attrgroup_flush(attrgroup,FS_FORCE); return 0; } typedef struct { void *data; t_attr_cb cb; } t_attr_cb_data; static int _cb_read_accounts(t_storage_info *info, void *data) { t_attrgroup *attrgroup; t_attr_cb_data *cbdata = (t_attr_cb_data*)data; attrgroup = attrgroup_create_storage(info); return cbdata->cb(attrgroup,cbdata->data); } extern int attrgroup_read_accounts(int flag, t_attr_cb cb, void *data) { t_attr_cb_data cbdata; cbdata.cb = cb; cbdata.data = data; return storage->read_accounts(flag, _cb_read_accounts, &cbdata); } static const char *attrgroup_escape_key(const char *key) { const char *newkey, *newkey2; char *tmp; newkey = key; if (!strncasecmp(key,"DynKey",6)) { /* OLD COMMENT, MIGHT NOT BE VALID ANYMORE * Recent Starcraft clients seems to query DynKey\*\1\rank instead of * Record\*\1\rank. So replace Dynkey with Record for key lookup. */ tmp = xstrdup(key); strncpy(tmp,"Record",6); newkey = tmp; } else if (!strncmp(key,"Star",4)) { /* OLD COMMENT * Starcraft clients query Star instead of STAR on logon screen. */ tmp = xstrdup(key); strncpy(tmp,"STAR",4); newkey = tmp; } if (newkey != key) { newkey2 = storage->escape_key(newkey); if (newkey2 != newkey) { xfree((void*)newkey); newkey = newkey2; } } else newkey = storage->escape_key(key); return newkey; } static t_attr *attrgroup_find_attr(t_attrgroup *attrgroup, const char *pkey[], int escape) { const char *val; t_hlist *curr, *last, *last2; t_attr *attr; assert(attrgroup); assert(pkey); assert(*pkey); /* trigger loading of attributes if not loaded already */ if (attrgroup_load(attrgroup)) return NULL; /* eventlog happens earlier */ /* only if the callers tell us to */ if (escape) *pkey = attrgroup_escape_key(*pkey); /* we are doing attribute lookup so we are accessing it */ attrgroup_set_accessed(attrgroup); last = &attrgroup->list; last2 = NULL; hlist_for_each(curr,&attrgroup->list) { attr = hlist_entry(curr, t_attr, link); if (!strcasecmp(attr_get_key(attr),*pkey)) { val = attr_get_val(attr); /* key found, promote it so it's found faster next time */ hlist_promote(curr, last, last2); break; } last2 = last; last = curr; } if (curr == &attrgroup->list) { /* no key found in cached list */ attr = (t_attr*)storage->read_attr(attrgroup->storage, *pkey); if (attr) hlist_add(&attrgroup->list, &attr->link); } /* "attr" here can either have a proper value found in the cached list, or * a value returned by storage->read_attr, or NULL */ return attr; } /* low-level get attr, receives a flag to tell if it needs to escape key */ static const char *attrgroup_get_attrlow(t_attrgroup *attrgroup, const char *key, int escape) { const char *val = NULL; const char *newkey = key; t_attr *attr; /* no need to check for attrgroup, key */ attr = attrgroup_find_attr(attrgroup, &newkey, escape); if (attr) val = attr_get_val(attr); if (!val && attrgroup != attrlayer_get_defattrgroup()) val = attrgroup_get_attrlow(attrlayer_get_defattrgroup(), newkey, 0); if (newkey != key) xfree((void*)newkey); return val; } extern const char *attrgroup_get_attr(t_attrgroup *attrgroup, const char *key) { if (!attrgroup) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup"); return NULL; } if (!key) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL key"); return NULL; } return attrgroup_get_attrlow(attrgroup, key, 1); } extern int attrgroup_set_attr(t_attrgroup *attrgroup, const char *key, const char *val) { t_attr *attr; const char *newkey = key; if (!attrgroup) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL attrgroup"); return -1; } if (!key) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL key"); return -1; } attr = attrgroup_find_attr(attrgroup, &newkey, 1); if (attr) { if (attr_get_val(attr) == val || (attr_get_val(attr) && val && !strcmp(attr_get_val(attr), val))) goto out; /* no need to modify anything, values are the same */ /* new value for existent key, replace the old one */ attr_set_val(attr, val); } else { /* unknown key so add new attr */ attr = attr_create(newkey, val); hlist_add(&attrgroup->list, &attr->link); } /* we have modified this attr and attrgroup */ attr_set_dirty(attr); attrgroup_set_dirty(attrgroup); out: if (newkey != key) xfree((void*)newkey); return 0; } pvpgn-1.8.5/src/bnetd/timer.h0000644000175000017500000000474311151345317015026 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_TIMER_TYPES #define INCLUDED_TIMER_TYPES #ifdef JUST_NEED_TYPES # ifdef TIME_WITH_SYS_TIME # include # include # else # if HAVE_SYS_TIME_H # include # else # include # endif # endif # include "connection.h" #else # define JUST_NEED_TYPES # ifdef TIME_WITH_SYS_TIME # include # include # else # if HAVE_SYS_TIME_H # include # else # include # endif # endif # include "connection.h" # undef JUST_NEED_TYPES #endif #include "common/elist.h" typedef union { unsigned long n; void * p; } t_timer_data; typedef void (* t_timer_cb)(t_connection * owner, time_t when, t_timer_data data); typedef struct timer_struct #ifdef TIMER_INTERNAL_ACCESS { t_connection * owner; /* who to notify */ time_t when; /* when the timer expires */ t_timer_cb cb; /* what to call */ t_timer_data data; /* data argument */ t_elist owners; /* list to the setup timers of same owner */ t_elist timers; /* timers list, used for final cleaning */ } #endif t_timer; #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_TIMER_PROTOS #define INCLUDED_TIMER_PROTOS #define JUST_NEED_TYPES #ifdef TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include "connection.h" #undef JUST_NEED_TYPES extern int timerlist_create(void); extern int timerlist_destroy(void); extern int timerlist_add_timer(t_connection * owner, time_t when, t_timer_cb cb, t_timer_data data); extern int timerlist_del_all_timers(t_connection * owner); extern int timerlist_check_timers(time_t when); #endif #endif pvpgn-1.8.5/src/bnetd/helpfile.h0000644000175000017500000000210011151345317015457 0ustar aaronaaron/* * Copyright (C) 2000 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef INCLUDED_HELPFILE_H #define INCLUDED_HELPFILE_H #ifndef JUST_NEED_TYPES #define JUST_NEED_TYPES #include "connection.h" #undef JUST_NEED_TYPES extern int helpfile_init(char const * filename); extern int helpfile_unload(void); extern int handle_help_command(t_connection *, char const *); #endif #endif pvpgn-1.8.5/src/bnetd/file.h0000644000175000017500000000223411151345317014616 0ustar aaronaaron/* * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_FILE_PROTOS #define INCLUDED_FILE_PROTOS #define JUST_NEED_TYPES #include "common/bn_type.h" #undef JUST_NEED_TYPES extern int file_to_mod_time(char const * rawname, bn_long * modtime); extern int file_send(t_connection * c, char const * rawname, unsigned int adid, unsigned int etag, unsigned int startoffset, int need_header); #endif #endif pvpgn-1.8.5/src/bnetd/anongame.c0000644000175000017500000020143411151345317015462 0ustar aaronaaron/* * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef WIN32 # include "compat/socket.h" /* is this needed */ #endif #include "compat/strdup.h" #include "common/packet.h" #include "common/eventlog.h" #include "common/tag.h" #include "team.h" #include "account.h" #include "account_wrap.h" #include "connection.h" #include "common/queue.h" #include "prefs.h" #include "common/bn_type.h" #include "common/list.h" #include "common/addr.h" #include "common/xalloc.h" #include "versioncheck.h" #include "anongame.h" #include "tournament.h" #include "timer.h" #include "ladder.h" #include "server.h" #include "anongame_maplists.h" #include "anongame_gameresult.h" #include "common/trans.h" #include "common/setup_after.h" #define MAX_LEVEL 100 /* [quetzal] 20020827 - this one get modified by anongame_queue player when there're enough * players and map has been chosen based on their preferences. otherwise its NULL */ static char *mapname = NULL; static int players[ANONGAME_TYPES] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static t_connection *player[ANONGAME_TYPES][ANONGAME_MAX_GAMECOUNT]; /* [quetzal] 20020815 - queue to hold matching players */ static t_list *matchlists[ANONGAME_TYPES][MAX_LEVEL]; long average_anongame_search_time = 30; unsigned int anongame_search_count = 0; /**********************************************************************************/ static t_connection *_connlist_find_connection_by_uid(int uid); static char const *_conn_get_versiontag(t_connection * c); static int _anongame_gametype_to_queue(int type, int gametype); static int _anongame_level_by_queue(t_connection * c, int queue); static char *_get_map_from_prefs(int queue, t_uint32 cur_prefs, t_clienttag clienttag); static unsigned int _anongame_get_gametype_tab(int queue); static int _anongame_totalplayers(int queue); static int _anongame_totalteams(int queue); static int _handle_anongame_search(t_connection * c, t_packet const *packet); static int _anongame_queue(t_connection * c, int queue, t_uint32 map_prefs); static int _anongame_compare_level(void const *a, void const *b); static int _anongame_order_queue(int queue); static int _anongame_match(t_connection * c, int queue); static int _anongame_search_found(int queue); /**********************************************************************************/ static t_connection *_connlist_find_connection_by_uid(int uid) { return connlist_find_connection_by_account(accountlist_find_account_by_uid(uid)); } static char const *_conn_get_versiontag(t_connection * c) { return versioncheck_get_versiontag(conn_get_versioncheck(c)); } /**********/ static char const *_anongame_queue_to_string(int queue) { switch (queue) { case ANONGAME_TYPE_1V1: return "PG 1v1"; case ANONGAME_TYPE_2V2: return "PG 2v2"; case ANONGAME_TYPE_3V3: return "PG 3v3"; case ANONGAME_TYPE_4V4: return "PG 4v4"; case ANONGAME_TYPE_SMALL_FFA: return "PG SFFA"; case ANONGAME_TYPE_AT_2V2: return "AT 2v2"; case ANONGAME_TYPE_TEAM_FFA: return "AT TFFA"; case ANONGAME_TYPE_AT_3V3: return "AT 3v3"; case ANONGAME_TYPE_AT_4V4: return "AT 4v4"; case ANONGAME_TYPE_TY: return "TOURNEY"; case ANONGAME_TYPE_5V5: return "PG 5v5"; case ANONGAME_TYPE_6V6: return "PG 6v6"; case ANONGAME_TYPE_2V2V2: return "PG 2v2v2"; case ANONGAME_TYPE_3V3V3: return "PG 3v3v3"; case ANONGAME_TYPE_4V4V4: return "PG 4v4v4"; case ANONGAME_TYPE_2V2V2V2: return "PG 2v2v2v2"; case ANONGAME_TYPE_3V3V3V3: return "PG 3v3v3v3"; case ANONGAME_TYPE_AT_2V2V2: return "AT 2v2v2"; default: eventlog(eventlog_level_error, __FUNCTION__, "invalid queue number %d", queue); return "error"; } } static int _anongame_gametype_to_queue(int type, int gametype) { switch (type) { case 0: /* PG */ switch (gametype) { case 0: return ANONGAME_TYPE_1V1; case 1: return ANONGAME_TYPE_2V2; case 2: return ANONGAME_TYPE_3V3; case 3: return ANONGAME_TYPE_4V4; case 4: return ANONGAME_TYPE_SMALL_FFA; case 5: return ANONGAME_TYPE_5V5; case 6: return ANONGAME_TYPE_6V6; case 7: return ANONGAME_TYPE_2V2V2; case 8: return ANONGAME_TYPE_3V3V3; case 9: return ANONGAME_TYPE_4V4V4; case 10: return ANONGAME_TYPE_2V2V2V2; case 11: return ANONGAME_TYPE_3V3V3V3; default: eventlog(eventlog_level_error, __FUNCTION__, "invalid PG game type: %d", gametype); return -1; } case 1: /* AT */ switch (gametype) { case 0: return ANONGAME_TYPE_AT_2V2; case 2: return ANONGAME_TYPE_AT_3V3; case 3: return ANONGAME_TYPE_AT_4V4; case 4: return ANONGAME_TYPE_AT_2V2V2; default: eventlog(eventlog_level_error, __FUNCTION__, "invalid AT game type: %d", gametype); return -1; } case 2: /* TY */ return ANONGAME_TYPE_TY; default: eventlog(eventlog_level_error, __FUNCTION__, "invalid type: %d", type); return -1; } } static int _anongame_level_by_queue(t_connection * c, int queue) { t_clienttag ct = conn_get_clienttag(c); switch (queue) { case ANONGAME_TYPE_1V1: return account_get_ladder_level(conn_get_account(c), ct, ladder_id_solo); case ANONGAME_TYPE_2V2: case ANONGAME_TYPE_3V3: case ANONGAME_TYPE_4V4: case ANONGAME_TYPE_5V5: case ANONGAME_TYPE_6V6: case ANONGAME_TYPE_2V2V2: case ANONGAME_TYPE_3V3V3: case ANONGAME_TYPE_4V4V4: case ANONGAME_TYPE_2V2V2V2: case ANONGAME_TYPE_3V3V3V3: return account_get_ladder_level(conn_get_account(c), ct, ladder_id_ffa); case ANONGAME_TYPE_SMALL_FFA: case ANONGAME_TYPE_TEAM_FFA: return account_get_ladder_level(conn_get_account(c), ct, ladder_id_ffa); case ANONGAME_TYPE_AT_2V2: case ANONGAME_TYPE_AT_3V3: case ANONGAME_TYPE_AT_4V4: case ANONGAME_TYPE_AT_2V2V2: return 0; case ANONGAME_TYPE_TY: /* set to ((wins * 3) + ties - losses) ie. prelim score */ return tournament_get_player_score(conn_get_account(c)); default: eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue); return -1; } } static char *_get_map_from_prefs(int queue, t_uint32 cur_prefs, t_clienttag clienttag) { int i, j = 0; char *default_map, *selected; char *res_maps[32]; char clienttag_str[5]; if (clienttag == CLIENTTAG_WARCRAFT3_UINT) default_map = "Maps\\(8)PlainsOfSnow.w3m"; else if (clienttag == CLIENTTAG_WAR3XP_UINT) default_map = "Maps\\(8)PlainsOfSnow.w3m"; else { eventlog(eventlog_level_error, __FUNCTION__, "invalid clienttag : %s", tag_uint_to_str(clienttag_str,clienttag)); return "Maps\\(8)PlainsOfSnow.w3m"; } for (i = 0; i < 32; i++) res_maps[i] = NULL; for (i = 0; i < 32; i++) { if (cur_prefs & 1) res_maps[j++] = maplists_get_map(queue, clienttag, i + 1); cur_prefs >>= 1; } i = rand() % j; if (res_maps[i]) selected = res_maps[i]; else selected = default_map; eventlog(eventlog_level_trace, __FUNCTION__, "got map %s from prefs", selected); return selected; } static unsigned int _anongame_get_gametype_tab(int queue) { /* dizzy: this changed in 1.05 */ switch (queue) { case ANONGAME_TYPE_1V1: return SERVER_ANONGAME_SOLO_STR; case ANONGAME_TYPE_2V2: case ANONGAME_TYPE_3V3: case ANONGAME_TYPE_4V4: case ANONGAME_TYPE_5V5: case ANONGAME_TYPE_6V6: case ANONGAME_TYPE_2V2V2: case ANONGAME_TYPE_3V3V3: case ANONGAME_TYPE_4V4V4: case ANONGAME_TYPE_2V2V2V2: case ANONGAME_TYPE_3V3V3V3: return SERVER_ANONGAME_TEAM_STR; case ANONGAME_TYPE_SMALL_FFA: return SERVER_ANONGAME_SFFA_STR; case ANONGAME_TYPE_TEAM_FFA: return 0; /* Team FFA is no longer supported */ case ANONGAME_TYPE_AT_2V2: return SERVER_ANONGAME_AT2v2_STR; case ANONGAME_TYPE_AT_3V3: return SERVER_ANONGAME_AT3v3_STR; case ANONGAME_TYPE_AT_4V4: return SERVER_ANONGAME_AT4v4_STR; case ANONGAME_TYPE_AT_2V2V2: return SERVER_ANONGAME_AT2v2_STR; /* fixme */ case ANONGAME_TYPE_TY: return SERVER_ANONGAME_TY_STR; default: eventlog(eventlog_level_error, __FUNCTION__, "invalid queue (%d)", queue); return 0; } } static int _anongame_totalplayers(int queue) { switch (queue) { case ANONGAME_TYPE_1V1: return 2; case ANONGAME_TYPE_2V2: case ANONGAME_TYPE_AT_2V2: case ANONGAME_TYPE_SMALL_FFA: /* fixme: total players not always 4 */ return 4; case ANONGAME_TYPE_3V3: case ANONGAME_TYPE_AT_3V3: case ANONGAME_TYPE_2V2V2: case ANONGAME_TYPE_AT_2V2V2: return 6; case ANONGAME_TYPE_4V4: case ANONGAME_TYPE_AT_4V4: case ANONGAME_TYPE_TEAM_FFA: case ANONGAME_TYPE_2V2V2V2: return 8; case ANONGAME_TYPE_3V3V3: return 9; case ANONGAME_TYPE_5V5: return 10; case ANONGAME_TYPE_6V6: case ANONGAME_TYPE_4V4V4: case ANONGAME_TYPE_3V3V3V3: return 12; case ANONGAME_TYPE_TY: return tournament_get_totalplayers(); default: eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue); return 0; } } static int _anongame_totalteams(int queue) { /* dont forget to change this if you make some game type with more teams */ #define ANONGAME_MAX_TEAMS 4 switch (queue) { case ANONGAME_TYPE_1V1: case ANONGAME_TYPE_SMALL_FFA: return 0; case ANONGAME_TYPE_2V2: case ANONGAME_TYPE_3V3: case ANONGAME_TYPE_4V4: case ANONGAME_TYPE_5V5: case ANONGAME_TYPE_6V6: case ANONGAME_TYPE_AT_2V2: case ANONGAME_TYPE_AT_3V3: case ANONGAME_TYPE_AT_4V4: return 2; case ANONGAME_TYPE_2V2V2: case ANONGAME_TYPE_3V3V3: case ANONGAME_TYPE_4V4V4: case ANONGAME_TYPE_AT_2V2V2: return 3; case ANONGAME_TYPE_TEAM_FFA: /* not even used */ case ANONGAME_TYPE_2V2V2V2: case ANONGAME_TYPE_3V3V3V3: return 4; case ANONGAME_TYPE_TY: return 2; /* fixme: does not support 2v2v2 - tournament_get_totalteams() */ default: eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue); return 0; } } /**********/ static int _handle_anongame_search(t_connection * c, t_packet const *packet) { int i, j, temp, set = 1; t_packet *rpacket; t_connection *tc[6]; t_anongame *a, *ta; t_uint8 teamsize = 0; t_uint8 option = bn_byte_get(packet->u.client_findanongame.option); if (!(a = conn_get_anongame(c))) { if (!(a = conn_create_anongame(c))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] conn_create_anongame failed", conn_get_socket(c)); return -1; } } conn_set_anongame_search_starttime(c, now); switch (option) { case CLIENT_FINDANONGAME_AT_INVITER_SEARCH: a->count = bn_int_get(packet->u.client_findanongame_at_inv.count); a->id = bn_int_get(packet->u.client_findanongame_at_inv.id); a->tid = bn_int_get(packet->u.client_findanongame_at_inv.tid); a->race = bn_int_get(packet->u.client_findanongame_at_inv.race); a->map_prefs = bn_int_get(packet->u.client_findanongame_at_inv.map_prefs); a->type = bn_byte_get(packet->u.client_findanongame_at_inv.type); a->gametype = bn_byte_get(packet->u.client_findanongame_at_inv.gametype); teamsize = bn_byte_get(packet->u.client_findanongame_at_inv.teamsize); break; case CLIENT_FINDANONGAME_AT_SEARCH: a->count = bn_int_get(packet->u.client_findanongame_at.count); a->id = bn_int_get(packet->u.client_findanongame_at.id); a->tid = bn_int_get(packet->u.client_findanongame_at.tid); a->race = bn_int_get(packet->u.client_findanongame_at.race); teamsize = bn_byte_get(packet->u.client_findanongame_at.teamsize); break; case CLIENT_FINDANONGAME_SEARCH: a->count = bn_int_get(packet->u.client_findanongame.count); a->id = bn_int_get(packet->u.client_findanongame.id); a->race = bn_int_get(packet->u.client_findanongame.race); a->map_prefs = bn_int_get(packet->u.client_findanongame.map_prefs); a->type = bn_byte_get(packet->u.client_findanongame.type); a->gametype = bn_byte_get(packet->u.client_findanongame.gametype); break; default: eventlog(eventlog_level_error, __FUNCTION__, "invalid search option (%d)", option); return -1; } if (option != CLIENT_FINDANONGAME_AT_SEARCH) if ((a->queue = _anongame_gametype_to_queue(a->type, a->gametype)) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "invalid queue: %d", a->queue); return -1; } account_set_w3pgrace(conn_get_account(c), conn_get_clienttag(c), a->race); /* send search reply to client */ if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_anongame_search_reply)); packet_set_type(rpacket, SERVER_ANONGAME_SEARCH_REPLY); bn_byte_set(&rpacket->u.server_anongame_search_reply.option, SERVER_FINDANONGAME_SEARCH); bn_int_set(&rpacket->u.server_anongame_search_reply.count, a->count); bn_int_set(&rpacket->u.server_anongame_search_reply.reply, 0); temp = (int) average_anongame_search_time; packet_append_data(rpacket, &temp, 2); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); /* end search reply */ switch (option) { case CLIENT_FINDANONGAME_AT_INVITER_SEARCH: for (i = 0; i < teamsize; i++) { /* assign player conns to tc[] array */ if (!(tc[i] = _connlist_find_connection_by_uid(bn_int_get(packet->u.client_findanongame_at_inv.info[i])))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(tc[i])); return -1; } } for (i = 0; i < teamsize; i++) { /* assign info from inviter to other team players */ if (!(ta = conn_get_anongame(tc[i]))) { if (!(ta = conn_create_anongame(tc[i]))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] conn_create_anongame failed", conn_get_socket(tc[i])); return -1; } } for (j = 0; j < teamsize; j++) /* add each players conn to each anongame struct */ ta->tc[j] = tc[j]; ta->type = a->type; ta->gametype = a->gametype; ta->queue = a->queue; ta->map_prefs = a->map_prefs; if (ta->tid != a->tid) set = 0; } if (!set) /* check if search packet has been recieved from each team member */ return 0; break; case CLIENT_FINDANONGAME_AT_SEARCH: for (i = 0; i < teamsize; i++) { /* assign player conns to tc[] array */ if (!(tc[i] = _connlist_find_connection_by_uid(bn_int_get(packet->u.client_findanongame_at.info[i])))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(tc[i])); return -1; } } for (i = 0; i < teamsize; i++) { /* check if search packet has been recieved from each team member */ if (!(ta = conn_get_anongame(tc[i]))) return 0; if (ta->tid != a->tid) return 0; } break; case CLIENT_FINDANONGAME_SEARCH: tc[0] = c; a->tc[0] = c; break; default: eventlog(eventlog_level_error, __FUNCTION__, "invalid search option (%d)", option); return -1; } if (_anongame_queue(tc[0], a->queue, a->map_prefs) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "queue failed"); return -1; } _anongame_match(c, a->queue); /* if enough players are queued send found packet */ if (players[a->queue] == _anongame_totalplayers(a->queue)) if (_anongame_search_found(a->queue) < 0) return -1; return 0; } static int _anongame_queue(t_connection * c, int queue, t_uint32 map_prefs) { int level; t_matchdata *md; if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection"); } if (queue >= ANONGAME_TYPES) { eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue); return -1; } level = _anongame_level_by_queue(c, queue); if (!matchlists[queue][level]) matchlists[queue][level] = list_create(); md = xmalloc(sizeof(t_matchdata)); md->c = c; md->map_prefs = map_prefs; md->versiontag = _conn_get_versiontag(c); list_append_data(matchlists[queue][level], md); return 0; } static int _anongame_compare_level(void const *a, void const *b) { t_connection *ca = *(t_connection * const *) a; t_connection *cb = *(t_connection * const *) b; int level_a = _anongame_level_by_queue(ca, anongame_get_queue(conn_get_anongame(ca))); int level_b = _anongame_level_by_queue(cb, anongame_get_queue(conn_get_anongame(cb))); return (level_a > level_b) ? -1 : ((level_a < level_b) ? 1 : 0); } static int _anongame_order_queue(int queue) { if (_anongame_totalteams(queue) != 0 && !anongame_arranged(queue)) { /* no need to reorder 1v1, sffa, or AT queues */ int i, j; t_connection *temp; int level[ANONGAME_MAX_TEAMS]; int teams = _anongame_totalteams(queue); /* number of teams */ int ppt = players[queue] / teams; /* players per team */ for (i = 0; i < ANONGAME_MAX_TEAMS; i++) level[i] = 0; for (i = 0; i < ppt - 1; i++) { /* loop through the number of players per team */ for (j = 0; j < teams; j++) { level[j] = level[j] + _anongame_level_by_queue(player[queue][i * ppt + j], queue); } if (teams == 2) { /* 1 >= 2 */ if (level[i * teams] >= level[i * teams + 1]) { temp = player[queue][(i + 1) * teams]; player[queue][(i + 1) * teams] = player[queue][(i + 1) * teams + 1]; player[queue][(i + 1) * teams + 1] = temp; } /* 2 >= 1 */ else if (level[i * teams + 1] >= level[i * teams]) { ; /* nothing to do */ } } /* end 2 teams */ else if (teams == 3) { /* 1 >= 2 >= 3 */ if (level[i * 3] >= level[i * 3 + 1] && level[i * 3 + 1] >= level[i * 3 + 2]) { temp = player[queue][(i + 1) * 3]; player[queue][(i + 1) * 3] = player[queue][(i + 1) * 3 + 2]; player[queue][(i + 1) * 3 + 2] = temp; } /* 1 >= 3 >= 2 */ else if (level[i * 3] >= level[i * 3 + 2] && level[i * 3 + 2] >= level[i * 3 + 1]) { temp = player[queue][(i + 1) * 3]; player[queue][(i + 1) * 3] = player[queue][(i + 1) * 3 + 2]; player[queue][(i + 1) * 3 + 2] = player[queue][(i + 1) * 3 + 1]; player[queue][(i + 1) * 3 + 1] = temp; } /* 2 >= 1 >= 3 */ else if (level[i * 3 + 1] >= level[i * 3] && level[i * 3] >= level[i * 3 + 2]) { temp = player[queue][(i + 1) * 3]; player[queue][(i + 1) * 3] = player[queue][(i + 1) * 3 + 1]; player[queue][(i + 1) * 3 + 1] = player[queue][(i + 1) * 3 + 2]; player[queue][(i + 1) * 3 + 2] = temp; } /* 2 >= 3 >= 1 */ else if (level[i * 3 + 1] >= level[i * 3 + 2] && level[i * 3 + 2] >= level[i * 3]) { temp = player[queue][(i + 1) * 3 + 1]; player[queue][(i + 1) * 3 + 1] = player[queue][(i + 1) * 3 + 2]; player[queue][(i + 1) * 3 + 2] = temp; } /* 3 >= 1 >= 2 */ else if (level[i * 3 + 2] >= level[i * 3] && level[i * 3] >= level[i * 3 + 1]) { temp = player[queue][(i + 1) * 3]; player[queue][(i + 1) * 3] = player[queue][(i + 1) * 3 + 1]; player[queue][(i + 1) * 3 + 1] = temp; } /* 3 >= 2 >= 1 */ else if (level[i * 3 + 2] >= level[i * 3 + 1] && level[i * 3 + 1] >= level[i * 3]) { ; /* nothing to do */ } } /* end 3 teams */ else if (teams == 4) { /* 1234 */ if (level[i * 4] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 3]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; temp = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = temp; } /* 1243 */ else if (level[i * 4] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 3] >= level[i * 4 + 2]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = temp; } /* 1324 */ else if (level[i * 4] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 3]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; } /* 1342 */ else if (level[i * 4] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 1]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = temp; } /* 1423 */ else if (level[i * 4] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = temp; } /* 1432 */ else if (level[i * 4] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 1]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = temp; } /* 2134 */ else if (level[i * 4 + 1] >= level[i * 4] && level[i * 4] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 3]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; } /* 2143 */ else if (level[i * 4 + 1] >= level[i * 4] && level[i * 4] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 2]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = temp; temp = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; } /* 2314 */ else if (level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4] && level[i * 4] >= level[i * 4 + 3]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = temp; } /* 2341 */ else if (level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4]) { temp = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; } /* 2413 */ else if (level[i * 4 + 1] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4] && level[i * 4] >= level[i * 4 + 2]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = temp; } /* 2431 */ else if (level[i * 4 + 1] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4]) { temp = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = temp; } /* 3124 */ else if (level[i * 4 + 2] >= level[i * 4] && level[i * 4] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 3]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; } /* 3142 */ else if (level[i * 4 + 2] >= level[i * 4] && level[i * 4] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 1]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = temp; } /* 3214 */ else if (level[i * 4 + 2] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4] && level[i * 4] >= level[i * 4 + 3]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; } /* 3241 */ else if (level[i * 4 + 2] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4]) { temp = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; } /* 3412 */ else if (level[i * 4 + 2] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4] && level[i * 4] >= level[i * 4 + 1]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = temp; temp = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; } /* 3421 */ else if (level[i * 4 + 2] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4]) { temp = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3]; player[queue][(i + 1) * 4 + 3] = temp; } /* 4123 */ else if (level[i * 4 + 3] >= level[i * 4] && level[i * 4] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = temp; } /* 4132 */ else if (level[i * 4 + 3] >= level[i * 4] && level[i * 4] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 1]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = temp; } /* 4213 */ else if (level[i * 4 + 3] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4] && level[i * 4] >= level[i * 4 + 2]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = temp; } /* 4231 */ else if (level[i * 4 + 3] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4]) { temp = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2]; player[queue][(i + 1) * 4 + 2] = temp; } /* 4312 */ else if (level[i * 4 + 3] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4] && level[i * 4] >= level[i * 4 + 1]) { temp = player[queue][(i + 1) * 4]; player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1]; player[queue][(i + 1) * 4 + 1] = temp; } /* 4321 */ else if (level[i * 4 + 3] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4]) { ; /* nothing to do */ } } /* end 4 teams */ } /* end ppt loop */ } /* end "if" statement */ return 0; } static int _anongame_match(t_connection * c, int queue) { int level = _anongame_level_by_queue(c, queue); int delta = 0; int i; t_matchdata *md; t_elem *curr; int diff; t_anongame *a = conn_get_anongame(c); t_uint32 cur_prefs = a->map_prefs; t_connection *inv_c[ANONGAME_MAX_TEAMS]; int maxlevel, minlevel; int teams = 0; players[queue] = 0; eventlog(eventlog_level_trace, __FUNCTION__, "[%d] matching started for level %d player in queue %d", conn_get_socket(c), level, queue); diff = war3_get_maxleveldiff(); maxlevel = level + diff; minlevel = (level - diff < 0) ? 0 : level - diff; while (abs(delta) < (diff + 1)) { if ((level + delta <= maxlevel) && (level + delta >= minlevel)) { eventlog(eventlog_level_trace, __FUNCTION__, "Traversing level %d players", level + delta); LIST_TRAVERSE(matchlists[queue][level + delta], curr) { md = elem_get_data(curr); if (md->versiontag && _conn_get_versiontag(c) && !strcmp(md->versiontag, _conn_get_versiontag(c)) && (cur_prefs & md->map_prefs)) { /* set maxlevel and minlevel to keep all players within 6 levels */ maxlevel = (level + delta + diff < maxlevel) ? level + delta + diff : maxlevel; minlevel = (level + delta - diff > minlevel) ? level + delta - diff : minlevel; cur_prefs &= md->map_prefs; /* AT match */ if (anongame_arranged(queue)) { /* set the inv_c for unqueueing later */ inv_c[teams] = md->c; a = conn_get_anongame(md->c); /* add all the players on the team to player[][] */ for (i = 0; i < _anongame_totalplayers(queue) / _anongame_totalteams(queue); i++) { player[queue][teams + i * _anongame_totalteams(queue)] = a->tc[i]; players[queue]++; } teams++; /* check for enough players */ if (players[queue] == _anongame_totalplayers(queue)) { /* unqueue just the single team entry */ for (i = 0; i < teams; i++) anongame_unqueue(inv_c[i], queue); mapname = _get_map_from_prefs(queue, cur_prefs, conn_get_clienttag(c)); return 0; } /* PG match */ } else { player[queue][players[queue]++] = md->c; if (players[queue] == _anongame_totalplayers(queue)) { /* first sort queue by level */ qsort(player[queue], players[queue], sizeof(t_connection *), _anongame_compare_level); /* next call reodering function */ _anongame_order_queue(queue); /* unqueue players */ for (i = 0; i < players[queue]; i++) anongame_unqueue(player[queue][i], queue); mapname = _get_map_from_prefs(queue, cur_prefs, conn_get_clienttag(c)); return 0; } } } } } if (delta <= 0 || level - delta < 0) delta = abs(delta) + 1; else delta = -delta; if (level + delta > MAX_LEVEL) delta = -delta; if (level + delta < 0) break; /* cant really happen */ } eventlog(eventlog_level_trace, __FUNCTION__, "[%d] Matching finished, not enough players (found %d)", conn_get_socket(c), players[queue]); mapname = NULL; return 0; } static int w3routeip = -1; /* changed by dizzy to show the w3routeshow addr if available */ static unsigned short w3routeport = BNETD_W3ROUTE_PORT; static int _anongame_search_found(int queue) { t_packet *rpacket; t_anongameinfo *info; t_anongame *a; int i, j; t_saf_pt2 *pt2; /* FIXME: maybe periodically lookup w3routeaddr to support dynamic ips? * (or should dns lookup be even quick enough to do it everytime?) */ if (w3routeip == -1) { t_addr *routeraddr; routeraddr = addr_create_str(prefs_get_w3route_addr(), 0, BNETD_W3ROUTE_PORT); if (!routeraddr) { eventlog(eventlog_level_error, __FUNCTION__, "error getting w3route_addr"); return -1; } w3routeip = addr_get_ip(routeraddr); w3routeport = addr_get_port(routeraddr); addr_destroy(routeraddr); } info = anongameinfo_create(_anongame_totalplayers(queue)); if (!info) { eventlog(eventlog_level_error, __FUNCTION__, "anongameinfo_create failed"); return -1; } /* create data to be appended to end of packet */ pt2 = xmalloc(sizeof(t_saf_pt2)); bn_int_set(&pt2->unknown1, 0xFFFFFFFF); bn_int_set(&pt2->anongame_string, _anongame_get_gametype_tab(queue)); bn_byte_set(&pt2->totalplayers, _anongame_totalplayers(queue)); bn_byte_set(&pt2->totalteams, _anongame_totalteams(queue)); /* 1v1 & sffa are set to zero in _anongame_totalteams() */ bn_short_set(&pt2->unknown2, 0); bn_byte_set(&pt2->visibility, 2); /* visibility. 0x01 - dark 0x02 - default */ bn_byte_set(&pt2->unknown3, 2); /* send found packet to each of the players */ for (i = 0; i < players[queue]; i++) { if (!(a = conn_get_anongame(player[queue][i]))) { eventlog(eventlog_level_error, __FUNCTION__, "no anongame struct for queued player"); xfree(pt2); return -1; } a->info = info; a->playernum = i + 1; for (j = 0; j < players[queue]; j++) { a->info->player[j] = player[queue][j]; a->info->account[j] = conn_get_account(player[queue][j]); } if (!(rpacket = packet_create(packet_class_bnet))) { xfree(pt2); return -1; } packet_set_size(rpacket, sizeof(t_server_anongame_found)); packet_set_type(rpacket, SERVER_ANONGAME_FOUND); bn_byte_set(&rpacket->u.server_anongame_found.option, 1); bn_int_set(&rpacket->u.server_anongame_found.count, a->count); bn_int_set(&rpacket->u.server_anongame_found.unknown1, 0); { /* trans support */ unsigned int w3ip = w3routeip; unsigned short w3port = w3routeport; trans_net(conn_get_addr(player[queue][i]), &w3ip, &w3port); /* if ip to send is 0.0.0.0 (which will not work anyway) try * to guess the reachable IP of pvpgn by using the local * endpoing address of the bnet class connection */ if (!w3ip) w3ip = conn_get_real_local_addr(player[queue][i]); bn_int_nset(&rpacket->u.server_anongame_found.ip, w3ip); bn_short_set(&rpacket->u.server_anongame_found.port, w3port); } bn_byte_set(&rpacket->u.server_anongame_found.unknown2, i + 1); bn_byte_set(&rpacket->u.server_anongame_found.unknown3, queue); bn_short_set(&rpacket->u.server_anongame_found.unknown4, 0); bn_int_set(&rpacket->u.server_anongame_found.id, 0xdeadbeef); bn_byte_set(&rpacket->u.server_anongame_found.unknown5, 6); bn_byte_set(&rpacket->u.server_anongame_found.type, a->type); bn_byte_set(&rpacket->u.server_anongame_found.gametype, a->gametype); packet_append_string(rpacket, mapname); packet_append_data(rpacket, pt2, sizeof(t_saf_pt2)); conn_push_outqueue(player[queue][i], rpacket); packet_del_ref(rpacket); } /* clear queue */ players[queue] = 0; xfree(pt2); return 0; } /**********************************************************************************/ /* external functions */ /**********************************************************************************/ extern int anongame_matchlists_create() { int i, j; for (i = 0; i < ANONGAME_TYPES; i++) { for (j = 0; j < MAX_LEVEL; j++) { matchlists[i][j] = NULL; } } return 0; } extern int anongame_matchlists_destroy() { int i, j; for (i = 0; i < ANONGAME_TYPES; i++) { for (j = 0; j < MAX_LEVEL; j++) { if (matchlists[i][j]) { list_destroy(matchlists[i][j]); } } } return 0; } /**********/ extern int handle_anongame_search(t_connection * c, t_packet const *packet) { return _handle_anongame_search(c, packet); } extern int anongame_unqueue(t_connection * c, int queue) { int i; t_elem *curr; t_matchdata *md; if (queue < 0) { eventlog(eventlog_level_error, __FUNCTION__, "got negative queue id (%d)", queue); return -1; } if (queue >= ANONGAME_TYPES) { eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue); return -1; } if (conn_get_anongame_search_starttime(c) != ((time_t) 0)) { average_anongame_search_time *= anongame_search_count; average_anongame_search_time += (long) difftime(time(NULL), conn_get_anongame_search_starttime(c)); anongame_search_count++; average_anongame_search_time /= anongame_search_count; if (anongame_search_count > 20000) anongame_search_count = anongame_search_count / 2; /* to prevent an overflow of the average time */ conn_set_anongame_search_starttime(c, ((time_t) 0)); } for (i = 0; i < MAX_LEVEL; i++) { if (matchlists[queue][i] == NULL) continue; LIST_TRAVERSE(matchlists[queue][i], curr) { md = elem_get_data(curr); if (md->c == c) { eventlog(eventlog_level_trace, __FUNCTION__, "unqueued player [%d] level %d", conn_get_socket(c), i); list_remove_elem(matchlists[queue][i], &curr); xfree(md); return 0; } } } /* Output error to log for PG queues, AT players are queued with single * entry. Because anongame_unqueue() is called for each player, only the first * time called will the team be removed, the rest are therefore not an error. * [Omega] */ if (anongame_arranged(queue) == 0) { eventlog(eventlog_level_trace, __FUNCTION__, "[%d] player not found in \"%s\" queue", conn_get_socket(c), _anongame_queue_to_string(queue)); return -1; } return 0; } /**********/ extern char anongame_arranged(int queue) { switch (queue) { case ANONGAME_TYPE_AT_2V2: case ANONGAME_TYPE_AT_3V3: case ANONGAME_TYPE_AT_4V4: case ANONGAME_TYPE_AT_2V2V2: return 1; case ANONGAME_TYPE_TY: return tournament_is_arranged(); default: return 0; } } extern int anongame_evaluate_results(t_anongame * anongame) { int i, j, number; int wins[ANONGAME_MAX_GAMECOUNT]; int losses[ANONGAME_MAX_GAMECOUNT]; int result; t_anongame_gameresult *results; t_anongameinfo *anoninfo = anongame->info; for (i = 0; i < ANONGAME_MAX_GAMECOUNT; i++) { wins[i] = 0; losses[i] = 0; } for (i = 0; i < anongame_get_totalplayers(anongame); i++) { if ((results = anoninfo->results[i])) { for (j = 0; j < gameresult_get_number_of_results(results); j++) { number = gameresult_get_player_number(results, j) - 1; result = gameresult_get_player_result(results, j); if ((result == W3_GAMERESULT_WIN)) wins[number]++; if ((result == W3_GAMERESULT_LOSS)) losses[number]++; } } } for (i = 0; i < anongame_get_totalplayers(anongame); i++) { if ((wins[i] > losses[i])) { if ((anoninfo->result[i] != W3_GAMERESULT_WIN)) { eventlog(eventlog_level_trace, __FUNCTION__, "player %d reported DISC/LOSS for self, but others agree on WIN", i + 1); anoninfo->result[i] = W3_GAMERESULT_WIN; } } else { if ((anoninfo->result[i] != W3_GAMERESULT_LOSS)) { eventlog(eventlog_level_trace, __FUNCTION__, "player %d reported DISC/WIN for self, but others agree on LOSS", i + 1); anoninfo->result[i] = W3_GAMERESULT_LOSS; } } } return 0; } extern int anongame_stats(t_connection * c) { int i; int wins = 0, losses = 0, discs = 0; t_connection *gamec = conn_get_routeconn(c); t_anongame *a = conn_get_anongame(gamec); int tp = anongame_get_totalplayers(a); int oppon_level[ANONGAME_MAX_GAMECOUNT]; t_uint8 gametype = a->queue; t_uint8 plnum = a->playernum; t_clienttag ct = conn_get_clienttag(c); int tt = _anongame_totalteams(gametype); /* do nothing till all other players have w3route conn closed */ for (i = 0; i < tp; i++) if (i + 1 != plnum && a->info->player[i]) if (conn_get_routeconn(a->info->player[i])) return 0; anongame_evaluate_results(a); /* count wins, losses, discs */ for (i = 0; i < tp; i++) { if (a->info->result[i] == W3_GAMERESULT_WIN) wins++; else if (a->info->result[i] == W3_GAMERESULT_LOSS) losses++; else discs++; } /* do some sanity checking (hack prevention) */ switch (gametype) { case ANONGAME_TYPE_SMALL_FFA: if (wins != 1) { eventlog(eventlog_level_info, __FUNCTION__, "bogus game result: wins != 1 in small ffa game"); return -1; } break; case ANONGAME_TYPE_TEAM_FFA: if (!discs && wins != 2) { eventlog(eventlog_level_info, __FUNCTION__, "bogus game result: wins != 2 in team ffa game"); return -1; } break; default: if (!discs && wins > losses) { eventlog(eventlog_level_info, __FUNCTION__, "bogus game result: wins > losses"); return -1; } break; } /* prevent users from getting loss if server is shutdown (does not prevent errors from crash) - [Omega] */ /* also discard games with no winners at all (i.e. games where game host disc'ed and so all players do) */ if (!wins) return -1; /* according to zap, order of players in anongame is: * for PG: t1_p1, t2_p1, t1_p2, t2_p2, ... * for AT: t1_p1, t1_p2, ..., t2_p1, t2_p2, ... * * (Not True.. follows same order as PG) * 4v4 = t1_p1, t2_p1, t1_p2, t2_p2, t1_p3, t2_p3, t1_p4, t2_p4 * 3v3v3 = t1_p1, t2_p1, t3_p1, t1_p2, t2_p2, t3_p2, t1_p3, t2_p3, t3_p3 * 2v2v2v2 = t1_p1, t2_p1, t3_p1, t4_p1, t1_p2, t2_p2, t3_p2, t4_p2 */ /* opponent level calculation has to be done here, because later on, the level of other players * may allready be modified */ for (i = 0; i < tp; i++) { int j, k, l; t_account *oacc; oppon_level[i] = 0; switch (gametype) { case ANONGAME_TYPE_TY: /* FIXME-TY: ADD TOURNAMENT STATS RECORDING (this part not required?) */ break; case ANONGAME_TYPE_1V1: oppon_level[i] = account_get_ladder_level(a->info->account[(i + 1) % tp], ct, ladder_id_solo); break; case ANONGAME_TYPE_SMALL_FFA: /* oppon_level = average level of all other players */ for (j = 0; j < tp; j++) if (i != j) oppon_level[i] += account_get_ladder_level(a->info->account[j], ct, ladder_id_ffa); oppon_level[i] /= (tp - 1); break; case ANONGAME_TYPE_AT_2V2: case ANONGAME_TYPE_AT_3V3: case ANONGAME_TYPE_AT_4V4: oacc = a->info->account[(i + 1) % tp]; oppon_level[i] = team_get_level(account_find_team_by_teamid(oacc, account_get_currentatteam(oacc))); break; case ANONGAME_TYPE_AT_2V2V2: oacc = a->info->account[(i + 1) % tp]; oppon_level[i] = team_get_level(account_find_team_by_teamid(oacc, account_get_currentatteam(oacc))); oacc = a->info->account[(i + 2) % tp]; oppon_level[i] = team_get_level(account_find_team_by_teamid(oacc, account_get_currentatteam(oacc))); oppon_level[i] /= 2; break; default: /* oppon_level = average level of all opponents * this should work for all PG team games * [Omega] */ k = i + 1; for (j = 0; j < (tp / tt); j++) { for (l = 0; l < (tt - 1); l++) { oppon_level[i] += account_get_ladder_level(a->info->account[k % tp], ct, ladder_id_team); k++; } k++; } oppon_level[i] /= (tp / tt * (tt - 1)); } } for (i = 0; i < tp; i++) { t_account *acc; t_team *team; unsigned int currteam; int result = a->info->result[i]; if (result == -1) result = W3_GAMERESULT_LOSS; acc = a->info->account[i]; switch (gametype) { case ANONGAME_TYPE_TY: if (result == W3_GAMERESULT_WIN) tournament_add_stat(acc, 1); if (result == W3_GAMERESULT_LOSS) tournament_add_stat(acc, 2); /* FIXME-TY: how to do ties? */ break; case ANONGAME_TYPE_AT_2V2: case ANONGAME_TYPE_AT_3V3: case ANONGAME_TYPE_AT_4V4: case ANONGAME_TYPE_AT_2V2V2: if ((currteam = account_get_currentatteam(acc))) { team = account_find_team_by_teamid(acc, currteam); team_set_saveladderstats(team, gametype, result, oppon_level[i], ct); } break; case ANONGAME_TYPE_1V1: case ANONGAME_TYPE_2V2: case ANONGAME_TYPE_3V3: case ANONGAME_TYPE_4V4: case ANONGAME_TYPE_SMALL_FFA: case ANONGAME_TYPE_5V5: case ANONGAME_TYPE_6V6: case ANONGAME_TYPE_2V2V2: case ANONGAME_TYPE_3V3V3: case ANONGAME_TYPE_4V4V4: case ANONGAME_TYPE_2V2V2V2: case ANONGAME_TYPE_3V3V3V3: if (result == W3_GAMERESULT_WIN) account_set_saveladderstats(acc, gametype, game_result_win, oppon_level[i], ct); if (result == W3_GAMERESULT_LOSS) account_set_saveladderstats(acc, gametype, game_result_loss, oppon_level[i], ct); break; default: break; } } /* aaron: now update war3 ladders */ ladder_update_all_accounts(); return 1; } /**********/ extern t_anongameinfo *anongameinfo_create(int totalplayers) { t_anongameinfo *temp; int i; temp = xmalloc(sizeof(t_anongameinfo)); temp->totalplayers = temp->currentplayers = totalplayers; for (i = 0; i < ANONGAME_MAX_GAMECOUNT; i++) { temp->player[i] = NULL; temp->account[i] = NULL; temp->result[i] = -1; /* consider DISC default */ temp->results[i] = NULL; } return temp; } extern void anongameinfo_destroy(t_anongameinfo * i) { int j; if (!i) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongameinfo"); return; } for (j = 0; j < ANONGAME_MAX_GAMECOUNT; j++) if (i->results[j]) gameresult_destroy(i->results[j]); xfree(i); } /**********/ extern t_anongameinfo *anongame_get_info(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return NULL; } return a->info; } extern int anongame_get_currentplayers(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } if (!a->info) { eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo"); return 0; } return a->info->currentplayers; } extern int anongame_get_totalplayers(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } if (!a->info) { eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo"); return 0; } return a->info->totalplayers; } extern t_connection *anongame_get_player(t_anongame * a, int plnum) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return NULL; } if (!a->info) { eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo"); return NULL; } if (plnum < 0 || plnum > 7 || plnum >= a->info->totalplayers) { eventlog(eventlog_level_error, __FUNCTION__, "invalid plnum: %d", plnum); return NULL; } return a->info->player[plnum]; } extern int anongame_get_count(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->count; } extern t_uint32 anongame_get_id(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->id; } extern t_connection *anongame_get_tc(t_anongame * a, int tpnumber) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->tc[tpnumber]; } extern t_uint32 anongame_get_race(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->race; } extern t_uint32 anongame_get_handle(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->handle; } extern unsigned int anongame_get_addr(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->addr; } extern char anongame_get_loaded(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->loaded; } extern char anongame_get_joined(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->joined; } extern t_uint8 anongame_get_playernum(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->playernum; } extern t_uint8 anongame_get_queue(t_anongame * a) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return 0; } return a->queue; } /**********/ extern void anongame_set_result(t_anongame * a, int result) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return; } if (!a->info) { eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo"); return; } if (a->playernum < 1 || a->playernum > ANONGAME_MAX_GAMECOUNT) { eventlog(eventlog_level_error, __FUNCTION__, "invalid playernum: %d", a->playernum); return; } a->info->result[a->playernum - 1] = result; } extern void anongame_set_gameresults(t_anongame * a, t_anongame_gameresult * results) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return; } if (!a->info) { eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo"); return; } if (a->playernum < 1 || a->playernum > ANONGAME_MAX_GAMECOUNT) { eventlog(eventlog_level_error, __FUNCTION__, "invalid playernum: %d", a->playernum); return; } a->info->results[a->playernum - 1] = results; } extern void anongame_set_handle(t_anongame * a, t_uint32 h) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return; } a->handle = h; } extern void anongame_set_addr(t_anongame * a, unsigned int addr) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return; } a->addr = addr; } extern void anongame_set_loaded(t_anongame * a, char loaded) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return; } a->loaded = loaded; } extern void anongame_set_joined(t_anongame * a, char joined) { if (!a) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame"); return; } a->joined = joined; } /**********/ /* move to own .c/.h file for handling w3route connections */ extern int handle_w3route_packet(t_connection * c, t_packet const *const packet) { /* [smith] 20030427 fixed Big-Endian/Little-Endian conversion (Solaris bug) then * use packet_append_data for append platform dependent data types - like * "int", cos this code was broken for BE platforms. it's rewriten in platform * independent style whis usege bn_int and other bn_* like datatypes and * fuctions for wor with datatypes - bn_int_set(), what provide right * byteorder, not depended on LE/BE * fixed broken htonl() conversion for BE platforms - change it to * bn_int_nset(). i hope it's worked on intel too %) */ t_packet *rpacket; t_connection *gamec; char const *username; t_anongame *a = NULL; t_uint8 gametype, plnum; int tp, i; if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL packet", conn_get_socket(c)); return -1; } if (packet_get_class(packet) != packet_class_w3route) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad packet (class %d)", conn_get_socket(c), packet_get_class(packet)); return -1; } if (conn_get_state(c) != conn_state_connected) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] not connected", conn_get_socket(c)); return -1; } /* init route connection */ if (packet_get_type(packet) == CLIENT_W3ROUTE_REQ) { t_connection *oldc; eventlog(eventlog_level_trace, __FUNCTION__, "[%d] sizeof t_client_w3route_req %d", conn_get_socket(c), sizeof(t_client_w3route_req)); username = packet_get_str_const(packet, sizeof(t_client_w3route_req), USER_NAME_MAX); eventlog(eventlog_level_info, __FUNCTION__, "[%d] got username '%s'", conn_get_socket(c), username); gamec = connlist_find_connection_by_accountname(username); if (!gamec) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] no game connection found for this w3route connection; closing", conn_get_socket(c)); conn_set_state(c, conn_state_destroy); return 0; } if (!(a = conn_get_anongame(gamec))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] no anongame struct for game connection", conn_get_socket(c)); conn_set_state(c, conn_state_destroy); return 0; } if (bn_int_get((unsigned char const *) packet->u.data + sizeof(t_client_w3route_req) + strlen(username) + 2) != anongame_get_id(a)) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] client sent wrong id for user '%s', closing connection", conn_get_socket(c), username); conn_set_state(c, conn_state_destroy); return 0; } oldc = conn_get_routeconn(gamec); if (oldc) { conn_set_routeconn(oldc, NULL); conn_set_state(oldc, conn_state_destroy); } if (conn_set_routeconn(c, gamec) < 0 || conn_set_routeconn(gamec, c) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] conn_set_routeconn failed", conn_get_socket(c)); return -1; } /* set clienttag for w3route connections; we can do conn_get_clienttag() on them */ conn_set_clienttag(c, conn_get_clienttag(gamec)); anongame_set_addr(a, bn_int_get((unsigned char const *) packet->u.data + sizeof(t_client_w3route_req) + strlen(username) + 2 + 12)); anongame_set_joined(a, 0); anongame_set_loaded(a, 0); anongame_set_result(a, -1); anongame_set_gameresults(a, NULL); anongame_set_handle(a, bn_int_get(packet->u.client_w3route_req.handle)); if (!(rpacket = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c)); return -1; } packet_set_size(rpacket, sizeof(t_server_w3route_ack)); packet_set_type(rpacket, SERVER_W3ROUTE_ACK); bn_byte_set(&rpacket->u.server_w3route_ack.unknown1, 7); bn_short_set(&rpacket->u.server_w3route_ack.unknown2, 0); bn_int_set(&rpacket->u.server_w3route_ack.unknown3, SERVER_W3ROUTE_ACK_UNKNOWN3); bn_short_set(&rpacket->u.server_w3route_ack.unknown4, 0xcccc); bn_byte_set(&rpacket->u.server_w3route_ack.playernum, anongame_get_playernum(a)); bn_short_set(&rpacket->u.server_w3route_ack.unknown5, 0x0002); bn_short_set(&rpacket->u.server_w3route_ack.port, conn_get_port(c)); bn_int_nset(&rpacket->u.server_w3route_ack.ip, conn_get_addr(c)); bn_int_set(&rpacket->u.server_w3route_ack.unknown7, 0); bn_int_set(&rpacket->u.server_w3route_ack.unknown8, 0); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; } else { gamec = conn_get_routeconn(c); if (gamec) a = conn_get_anongame(gamec); } if (!gamec) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] no game connection found for this w3route connection", conn_get_socket(c)); return 0; } if (!a) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] no anongame struct found for this w3route connection", conn_get_socket(c)); return 0; } gametype = anongame_get_queue(a); plnum = anongame_get_playernum(a); tp = anongame_get_totalplayers(a); /* handle these packets _before_ checking for routeconn of other players */ switch (packet_get_type(packet)) { case CLIENT_W3ROUTE_ECHOREPLY: return 0; case CLIENT_W3ROUTE_CONNECTED: return 0; case CLIENT_W3ROUTE_GAMERESULT: case CLIENT_W3ROUTE_GAMERESULT_W3XP: { /* insert reading of whole packet into t_gameresult */ t_anongame_gameresult *gameresult; int result; t_timer_data data; t_anongameinfo *inf = anongame_get_info(a); t_connection *ac; data.p = NULL; if (!(gameresult = anongame_gameresult_parse(packet))) result = -1; else /* own result is always stored as first result */ result = gameresult_get_player_result(gameresult, 0); eventlog(eventlog_level_trace, __FUNCTION__, "[%d] got W3ROUTE_GAMERESULT: %08x", conn_get_socket(c), result); if (!inf) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] NULL anongameinfo", conn_get_socket(c)); return -1; } anongame_set_gameresults(a, gameresult); anongame_set_result(a, result); conn_set_state(c, conn_state_destroy); /* activate timers on open w3route connectons */ if (result == W3_GAMERESULT_WIN) { for (i = 0; i < tp; i++) { if (anongame_get_player(a, i)) { ac = conn_get_routeconn(anongame_get_player(a, i)); if (ac) { /* 300 seconds or 5 minute timer */ timerlist_add_timer(ac, now + (time_t) 300, conn_shutdown, data); eventlog(eventlog_level_trace, __FUNCTION__, "[%d] started timer to close w3route", conn_get_socket(ac)); } } } } return 0; } } for (i = 0; i < tp; i++) if (i + 1 != plnum && anongame_get_player(a, i)) if (!conn_get_routeconn(anongame_get_player(a, i)) || !conn_get_anongame(anongame_get_player(a, i))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] not all players have w3route connections up yet", conn_get_socket(c)); return 0; } /* handle these packets _after_ checking for routeconns of other players */ switch (packet_get_type(packet)) { case CLIENT_W3ROUTE_LOADINGDONE: eventlog(eventlog_level_trace, __FUNCTION__, "[%d] got LOADINGDONE, playernum: %d", conn_get_socket(c), plnum); anongame_set_loaded(a, 1); for (i = 0; i < tp; i++) { if (!anongame_get_player(a, i)) /* ignore disconnected players */ continue; if (!(rpacket = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c)); return -1; } packet_set_size(rpacket, sizeof(t_server_w3route_loadingack)); packet_set_type(rpacket, SERVER_W3ROUTE_LOADINGACK); bn_byte_set(&rpacket->u.server_w3route_loadingack.playernum, plnum); conn_push_outqueue(conn_get_routeconn(anongame_get_player(a, i)), rpacket); packet_del_ref(rpacket); } /* have all players loaded? */ for (i = 0; i < tp; i++) if (i + 1 != plnum && anongame_get_player(a, i) && !anongame_get_loaded(conn_get_anongame(anongame_get_player(a, i)))) return 0; for (i = 0; i < tp; i++) { if (!anongame_get_player(a, i)) continue; if (!(rpacket = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c)); return -1; } packet_set_size(rpacket, sizeof(t_server_w3route_ready)); packet_set_type(rpacket, SERVER_W3ROUTE_READY); bn_byte_set(&rpacket->u.server_w3route_host.unknown1, 0); conn_push_outqueue(conn_get_routeconn(anongame_get_player(a, i)), rpacket); packet_del_ref(rpacket); } break; case CLIENT_W3ROUTE_ABORT: eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got W3ROUTE_ABORT", conn_get_socket(c)); break; default: eventlog(eventlog_level_trace, __FUNCTION__, "[%d] default: got packet type: %04x", conn_get_socket(c), packet_get_type(packet)); } return 0; } extern int handle_anongame_join(t_connection * c) { t_anongame *a, *ja, *oa; t_connection *jc, *o; t_packet *rpacket; int tp, level; char gametype; t_account *acct; t_clienttag ct = conn_get_clienttag(c); static t_server_w3route_playerinfo2 pl2; static t_server_w3route_levelinfo2 li2; static t_server_w3route_playerinfo_addr pl_addr; int i, j; if (!c) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(c)); return -1; } if (!(conn_get_routeconn(c))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] no route connection", conn_get_socket(c)); return -1; } if (!(a = conn_get_anongame(c))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] no anongame struct", conn_get_socket(c)); return -1; } anongame_set_joined(a, 1); gametype = anongame_get_queue(a); tp = anongame_get_totalplayers(a); /* wait till all players have w3route conns */ for (i = 0; i < tp; i++) if (anongame_get_player(a, i) && (!conn_get_routeconn(anongame_get_player(a, i)) || !conn_get_anongame(anongame_get_player(a, i)) || !anongame_get_joined(conn_get_anongame(anongame_get_player(a, i))))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] not all players have joined game BNet yet", conn_get_socket(c)); return 0; } /* then send each player info about all others */ for (j = 0; j < tp; j++) { jc = anongame_get_player(a, j); if (!jc) /* ignore disconnected players */ continue; ja = conn_get_anongame(jc); /* send a playerinfo packet for this player to each other player */ for (i = 0; i < tp; i++) { if (i + 1 != anongame_get_playernum(ja)) { eventlog(eventlog_level_trace, __FUNCTION__, "i = %d", i); if (!(o = anongame_get_player(ja, i))) { eventlog(eventlog_level_warn, __FUNCTION__, "[%d] player %d disconnected, ignoring", conn_get_socket(c), i); continue; } if (!(rpacket = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c)); return -1; } packet_set_size(rpacket, sizeof(t_server_w3route_playerinfo)); packet_set_type(rpacket, SERVER_W3ROUTE_PLAYERINFO); if (!(oa = conn_get_anongame(o))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] no anongame struct of player %d", conn_get_socket(c), i); return -1; } bn_int_set(&rpacket->u.server_w3route_playerinfo.handle, anongame_get_handle(oa)); bn_byte_set(&rpacket->u.server_w3route_playerinfo.playernum, anongame_get_playernum(oa)); packet_append_string(rpacket, conn_get_username(o)); /* playerinfo2 */ bn_byte_set(&pl2.unknown1, 8); bn_int_set(&pl2.id, anongame_get_id(oa)); bn_int_set(&pl2.race, anongame_get_race(oa)); packet_append_data(rpacket, &pl2, sizeof(pl2)); /* external addr */ bn_short_set(&pl_addr.unknown1, 2); { /* trans support */ unsigned short port = conn_get_game_port(o); unsigned int addr = conn_get_game_addr(o); trans_net(conn_get_game_addr(jc), &addr, &port); bn_short_nset(&pl_addr.port, port); bn_int_nset(&pl_addr.ip, addr); } bn_int_set(&pl_addr.unknown2, 0); bn_int_set(&pl_addr.unknown3, 0); packet_append_data(rpacket, &pl_addr, sizeof(pl_addr)); /* local addr */ bn_short_set(&pl_addr.unknown1, 2); bn_short_nset(&pl_addr.port, conn_get_game_port(o)); bn_int_set(&pl_addr.ip, anongame_get_addr(oa)); bn_int_set(&pl_addr.unknown2, 0); bn_int_set(&pl_addr.unknown3, 0); packet_append_data(rpacket, &pl_addr, sizeof(pl_addr)); conn_push_outqueue(conn_get_routeconn(jc), rpacket); packet_del_ref(rpacket); } } /* levelinfo */ if (!(rpacket = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c)); return -1; } packet_set_size(rpacket, sizeof(t_server_w3route_levelinfo)); packet_set_type(rpacket, SERVER_W3ROUTE_LEVELINFO); bn_byte_set(&rpacket->u.server_w3route_levelinfo.numplayers, anongame_get_currentplayers(a)); for (i = 0; i < tp; i++) { if (!anongame_get_player(ja, i)) continue; bn_byte_set(&li2.plnum, i + 1); bn_byte_set(&li2.unknown1, 3); switch (gametype) { case ANONGAME_TYPE_1V1: level = account_get_ladder_level(conn_get_account(anongame_get_player(ja, i)), ct, ladder_id_solo); break; case ANONGAME_TYPE_SMALL_FFA: case ANONGAME_TYPE_TEAM_FFA: level = account_get_ladder_level(conn_get_account(anongame_get_player(ja, i)), ct, ladder_id_ffa); break; case ANONGAME_TYPE_AT_2V2: case ANONGAME_TYPE_AT_3V3: case ANONGAME_TYPE_AT_4V4: case ANONGAME_TYPE_AT_2V2V2: acct = conn_get_account(anongame_get_player(ja, i)); level = team_get_level(account_find_team_by_teamid(acct, account_get_currentatteam(acct))); break; case ANONGAME_TYPE_TY: level = 0; /* FIXME-TY: WHAT TO DO HERE */ break; default: level = account_get_ladder_level(conn_get_account(anongame_get_player(ja, i)), ct, ladder_id_team); break; } /* first anongame shows level 0 as level 1 */ bn_byte_set(&li2.level, level ? level : 1); bn_short_set(&li2.unknown2, 0); packet_append_data(rpacket, &li2, sizeof(li2)); } conn_push_outqueue(conn_get_routeconn(jc), rpacket); packet_del_ref(rpacket); /* startgame1 */ if (!(rpacket = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c)); return -1; } packet_set_size(rpacket, sizeof(t_server_w3route_startgame1)); packet_set_type(rpacket, SERVER_W3ROUTE_STARTGAME1); conn_push_outqueue(conn_get_routeconn(jc), rpacket); packet_del_ref(rpacket); /* startgame2 */ if (!(rpacket = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c)); return -1; } packet_set_size(rpacket, sizeof(t_server_w3route_startgame2)); packet_set_type(rpacket, SERVER_W3ROUTE_STARTGAME2); conn_push_outqueue(conn_get_routeconn(jc), rpacket); packet_del_ref(rpacket); } return 0; } pvpgn-1.8.5/src/bnetd/anongame_infos.h0000644000175000017500000001157511151345317016672 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_ANONGAME_INFOS_TYPES #define INCLUDED_ANONGAME_INFOS_TYPES #ifdef JUST_NEED_TYPES #include "common/list.h" #else #define JUST_NEED_TYPES #include "common/list.h" #undef JUST_NEED_TYPES #endif #define anongame_infos_URL_count 14 typedef enum { URL_server, URL_player, URL_tourney, URL_clan, URL_ladder_PG_1v1, URL_ladder_PG_ffa, URL_ladder_PG_team, URL_ladder_AT_2v2, URL_ladder_AT_3v3, URL_ladder_AT_4v4, URL_ladder_clan_1v1, URL_ladder_clan_2v2, URL_ladder_clan_3v3, URL_ladder_clan_4v4 } t_anongame_infos_URLs; #define anongame_infos_DESC_count 38 typedef enum { ladder_PG_1v1_desc, ladder_PG_ffa_desc, ladder_PG_team_desc, ladder_AT_2v2_desc, ladder_AT_3v3_desc, ladder_AT_4v4_desc, ladder_clan_1v1_desc, ladder_clan_2v2_desc, ladder_clan_3v3_desc, ladder_clan_4v4_desc, gametype_1v1_short, gametype_1v1_long, gametype_2v2_short, gametype_2v2_long, gametype_3v3_short, gametype_3v3_long, gametype_4v4_short, gametype_4v4_long, gametype_ffa_short, gametype_ffa_long, gametype_2v2v2_short, gametype_2v2v2_long, gametype_sffa_short, gametype_sffa_long, gametype_tffa_short, gametype_tffa_long, gametype_3v3v3_short, gametype_3v3v3_long, gametype_4v4v4_short, gametype_4v4v4_long, gametype_2v2v2v2_short, gametype_2v2v2v2_long, gametype_3v3v3v3_short, gametype_3v3v3v3_long, gametype_5v5_short, gametype_5v5_long, gametype_6v6_short, gametype_6v6_long } t_anongame_infos_DESCs; typedef struct { char * langID; char ** descs; } t_anongame_infos_DESC; #define anongame_infos_THUMBSDOWN_count 17 typedef enum { PG_1v1, PG_2v2, PG_3v3, PG_4v4, PG_ffa, AT_2v2, AT_3v3, AT_4v4, PG_2v2v2, AT_ffa, PG_5v5, PG_6v6, PG_3v3v3, PG_4v4v4, PG_2v2v2v2, PG_3v3v3v3, AT_2v2v2 } t_anongame_infos_THUMBDOWNs; #define anongame_infos_ICON_REQ_count 14 typedef enum { ICON_REQ_WAR3_Level1, ICON_REQ_WAR3_Level2, ICON_REQ_WAR3_Level3, ICON_REQ_WAR3_Level4, ICON_REQ_W3XP_Level1, ICON_REQ_W3XP_Level2, ICON_REQ_W3XP_Level3, ICON_REQ_W3XP_Level4, ICON_REQ_W3XP_Level5, ICON_REQ_TRNY_Level1, ICON_REQ_TRNY_Level2, ICON_REQ_TRNY_Level3, ICON_REQ_TRNY_Level4, ICON_REQ_TRNY_Level5 } t_anongame_infos_ICON_REQs; typedef struct { char * langID; char * desc_data; char * ladr_data; char * desc_comp_data; char * ladr_comp_data; int desc_len; int ladr_len; int desc_comp_len; int ladr_comp_len; } t_anongame_infos_data_lang; typedef struct { char * langID; char * url_comp_data; char * url_comp_data_115; char * map_comp_data; char * type_comp_data; char * desc_comp_data; char * ladr_comp_data; int url_comp_len; int url_comp_len_115; int map_comp_len; int type_comp_len; int desc_comp_len; int ladr_comp_len; } t_anongame_infos_data; typedef struct { char ** anongame_infos_URL; t_anongame_infos_DESC * anongame_infos_DESC; /* for default DESC */ t_list * anongame_infos_DESC_list; /* for localized DESC's */ char anongame_infos_THUMBSDOWN[anongame_infos_THUMBSDOWN_count]; int anongame_infos_ICON_REQ[anongame_infos_ICON_REQ_count]; t_anongame_infos_data * anongame_infos_data_war3; t_anongame_infos_data * anongame_infos_data_w3xp; t_list * anongame_infos_data_lang_war3; t_list * anongame_infos_data_lang_w3xp; } t_anongame_infos; #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_ANONGAME_INFOS_PROTOS #define INCLUDED_ANONGAME_INFOS_PROTOS #define JUST_NEED_TYPES #include "common/tag.h" #undef JUST_NEED_TYPES extern int anongame_infos_load(char const * filename); extern int anongame_infos_unload(void); extern char anongame_infos_get_thumbsdown(int queue); extern short anongame_infos_get_ICON_REQ(int Level,t_clienttag clienttag); extern short anongame_infos_get_ICON_REQ_TOURNEY(int Level); extern char * anongame_infos_data_get_url(t_clienttag clienttag, int versionid, int * len); extern char * anongame_infos_data_get_map(t_clienttag clienttag, int versionid, int * len); extern char * anongame_infos_data_get_type(t_clienttag clienttag, int versionid, int * len); extern char * anongame_infos_data_get_desc(char const * langID, t_clienttag clienttag, int versionid, int * len); extern char * anongame_infos_data_get_ladr(char const * langID, t_clienttag clienttag, int versionid, int * len); #endif #endif pvpgn-1.8.5/src/bnetd/file_cdb.c0000644000175000017500000002000311151345317015413 0ustar aaronaaron/* * Copyright (C) 2003,2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include #ifdef HAVE_LIMITS_H # include #endif #include "compat/char_bit.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include "compat/strerror.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_UNISTD_H # include #else # ifdef WIN32 # include # endif #endif #include "compat/pdir.h" #include "common/eventlog.h" #include "prefs.h" #include "common/util.h" #include "common/field_sizes.h" #include "common/bnethash.h" #include "common/introtate.h" #define CLAN_INTERNAL_ACCESS #include "account.h" #include "common/hashtable.h" #include "storage.h" #include "storage_file.h" #include "common/list.h" #include "common/xalloc.h" #include "connection.h" #include "watch.h" #include "clan.h" #undef CLAN_INTERNAL_ACCESS #include "common/tag.h" #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #include "tinycdb/cdb.h" #include "common/elist.h" #include "attr.h" #include "common/setup_after.h" /* cdb file storage API functions */ static int cdb_read_attrs(const char *filename, t_read_attr_func cb, void *data); static t_attr * cdb_read_attr(const char *filename, const char *key); static int cdb_write_attrs(const char *filename, const t_hlist *attributes); /* file_engine struct populated with the functions above */ t_file_engine file_cdb = { cdb_read_attr, cdb_read_attrs, cdb_write_attrs }; /* start of actual cdb file storage code */ //#define CDB_ON_DEMAND 1 static int cdb_write_attrs(const char *filename, const t_hlist *attributes) { FILE *cdbfile; t_hlist *curr; t_attr *attr; struct cdb_make cdbm; if ((cdbfile = fopen(filename, "w+b")) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "unable to open file \"%s\" for writing ",filename); return -1; } cdb_make_start(&cdbm, cdbfile); hlist_for_each(curr,attributes) { attr = hlist_entry(curr, t_attr, link); if (attr_get_key(attr) && attr_get_val(attr)) { if (strncmp("BNET\\CharacterDefault\\", attr_get_key(attr), 20) == 0) { eventlog(eventlog_level_debug, __FUNCTION__, "skipping attribute key=\"%s\"",attr_get_key(attr)); } else { eventlog(eventlog_level_debug, __FUNCTION__, "saving attribute key=\"%s\" val=\"%s\"",attr_get_key(attr),attr_get_val(attr)); if (cdb_make_add(&cdbm, attr_get_key(attr), strlen(attr_get_key(attr)), attr_get_val(attr), strlen(attr_get_val(attr)))<0) { eventlog(eventlog_level_error, __FUNCTION__, "got error on cdb_make_add ('%s' = '%s')", attr_get_key(attr), attr_get_val(attr)); cdb_make_finish(&cdbm); /* try to bail out nicely */ fclose(cdbfile); return -1; } } } else eventlog(eventlog_level_error, __FUNCTION__,"could not save attribute key=\"%s\"",attr_get_key(attr)); attr_clear_dirty(attr); } if (cdb_make_finish(&cdbm)<0) { eventlog(eventlog_level_error, __FUNCTION__, "got error on cdb_make_finish"); fclose(cdbfile); return -1; } if (fclose(cdbfile)<0) { eventlog(eventlog_level_error, __FUNCTION__, "got error on fclose()"); return -1; } return 0; } #ifndef CDB_ON_DEMAND /* code adapted from tinycdb-0.73/cdb.c */ static int fget(FILE * fd, unsigned char *b, cdbi_t len, cdbi_t *posp, cdbi_t limit) { if (posp && limit - *posp < len) { eventlog(eventlog_level_error, __FUNCTION__, "invalid cdb database format"); return -1; } if (fread(b, 1, len, fd) != len) { if (ferror(fd)) { eventlog(eventlog_level_error, __FUNCTION__, "got error reading from db file"); return -1; } eventlog(eventlog_level_error, __FUNCTION__, "unable to read from cdb file, incomplete file"); return -1; } if (posp) *posp += len; return 0; } static const char * fcpy(FILE *fd, cdbi_t len, cdbi_t *posp, cdbi_t limit, unsigned char * buf) { static char *str; static unsigned strl; unsigned int res = 0, no = 0; if (strl < len + 1) { char *tmp; tmp = xmalloc(len + 1); if (str) xfree((void*)str); str = tmp; strl = len + 1; } while(len - res > 0) { if (len > 2048) no = 2048; else no = len; if (fget(fd, buf, no, posp, limit)) return NULL; memmove(str + res, buf, no); res += no; } if (res > strl - 1) { eventlog(eventlog_level_error, __FUNCTION__, "BUG, this should not happen"); return NULL; } str[res] = '\0'; return str; } static int cdb_read_attrs(const char *filename, t_read_attr_func cb, void *data) { cdbi_t eod, klen, vlen; cdbi_t pos = 0; const char *key; const char *val; unsigned char buf[2048]; FILE *f; if ((f = fopen(filename, "rb")) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got error opening file '%s'", filename); return -1; } if (fget(f, buf, 2048, &pos, 2048)) goto err_fd; eod = cdb_unpack(buf); while(pos < eod) { if (fget(f, buf, 8, &pos, eod)) goto err_fd; klen = cdb_unpack(buf); vlen = cdb_unpack(buf + 4); if ((key = fcpy(f, klen, &pos, eod, buf)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "error reading attribute key"); goto err_fd; } key = xstrdup(key); if ((val = fcpy(f, vlen, &pos, eod, buf)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "error reading attribute val"); goto err_key; } // eventlog(eventlog_level_trace, __FUNCTION__, "read atribute : '%s' -> '%s'", key, val); if (cb(key, val, data)) eventlog(eventlog_level_error, __FUNCTION__, "got error from callback on account file '%s'", filename); xfree((void *)key); } fclose(f); return 0; err_key: xfree((void *)key); err_fd: fclose(f); return -1; } #else /* CDB_ON_DEMAND */ static int cdb_read_attrs(const char *filename, t_read_attr_func cb, void *data) { return 0; } #endif static t_attr * cdb_read_attr(const char *filename, const char *key) { #ifdef CDB_ON_DEMAND FILE *cdbfile; t_attr *attr; char *val; unsigned vlen = 1; // eventlog(eventlog_level_trace, __FUNCTION__, "reading key '%s'", key); if ((cdbfile = fopen(filename, "rb")) == NULL) { // eventlog(eventlog_level_debug, __FUNCTION__, "unable to open file \"%s\" for reading ",filename); return NULL; } if (cdb_seek(cdbfile, key, strlen(key), &vlen) <= 0) { // eventlog(eventlog_level_debug, __FUNCTION__, "could not find key '%s'", key); fclose(cdbfile); return NULL; } /* FIXME: use attr_* API */ attr = xmalloc(sizeof(t_attr)); attr->key = xstrdup(key); val = xmalloc(vlen + 1); cdb_bread(cdbfile, val, vlen); fclose(cdbfile); val[vlen] = '\0'; attr->val = val; attr->dirty = 0; // eventlog(eventlog_level_trace, __FUNCTION__, "read key '%s' value '%s'", attr->key, attr->val); return attr; #else return NULL; #endif } pvpgn-1.8.5/src/bnetd/ladder_calc.c0000644000175000017500000004062211151345317016112 0ustar aaronaaron/* * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999,2000 D.Moreaux (vapula@linuxbe.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "account.h" #include "account_wrap.h" #include "common/eventlog.h" #include "game.h" #include "common/tag.h" #include "ladder.h" #include "ladder_calc.h" #include "common/xalloc.h" #include "common/setup_after.h" static double probability(unsigned int a, unsigned int b) ; static int coefficient(t_account * account, t_clienttag clienttag, t_ladder_id id); static double two_player(unsigned int *rating); static double three_player(unsigned int *rating); static double four_player(unsigned int *rating); static double five_player(unsigned int *rating); static double five_f1(int a, int b, int c, int d, int e) ; static double five_f2(int a, int b, int c) ; static double six_player(unsigned int *rating); static double six_f1(int a, int b, int c, int d, int e, int f) ; static double six_f2(int a, int b, int c, int d, int e, int f) ; static double six_f3(int a, int b, int c, int d) ; static double seven_player(unsigned int *rating); static double seven_f1(int a, int b, int c, int d, int e, int f, int g) ; static double seven_f2(int a, int b, int c, int d, int e, int f, int g) ; static double eight_player(unsigned int *rating); static double eight_f1(int a, int b, int c, int d, int e, int f, int g) ; static double eight_f2(int a, int b, int c, int d, int e, int f, int g) ; static double eight_f3(int a, int b, int c, int d, int e) ; /* * Compute probability of winning using the Elo system * * The formula is: * * D = rating(player a) - rating(player b) * * 1 * Pwin(D) = ------------------ * -(D / 400) * 1 + 10 */ static double probability(unsigned int a, unsigned int b) { double i, j; i = (((double)a) - ((double)b)) / 400.0; j = pow(10.0,-i); return (1.0 / (1.0+j)); } /* * This is the coefficient k which is meant to enhance the * effect of the Elo system where more experienced players * will gain fewer points when playing against newbies, and * newbies will gain massive points if they win against an * experienced player. It also helps stabilize a player's * rating after they have played 30 games or so. * * K=50 for new players * K=30 for players who have played 30 or more ladder games * K=20 for players who have attained a rating of 2400 or higher */ static int coefficient(t_account * account, t_clienttag clienttag, t_ladder_id id) { int const total_ladder_games=account_get_ladder_wins(account,clienttag,id) + account_get_ladder_losses(account,clienttag,id) + account_get_ladder_disconnects(account,clienttag,id); if (total_ladder_games < 30) return 50; if (account_get_ladder_rating(account,clienttag,id) < 2400) return 30; return 20; } /* * The Elo system only handles 2 players, these functions extend * the calculation to different numbers of players as if they were * in a tournament. It turns out the math for this is really ugly, * so we have hardcoded the equations for every number of players. */ static double two_player(unsigned int *rating) { unsigned int a,b; double ab; a = rating[0]; b = rating[1]; ab = probability(a,b); return ab; } static double three_player(unsigned int *rating) { unsigned int a,b,c; double ab,ac,bc,cb; a = rating[0]; b = rating[1]; c = rating[2]; ab = probability(a,b); ac = probability(a,c); bc = probability(b,c); cb = 1.0 - bc; return (2*(ab*ac)+(bc*ab)+(cb*ac))/3; } static double four_player(unsigned int *rating) { unsigned int a,b,c,d; double ab,ac,ad,bc,bd,cb,cd,db,dc; a = rating[0]; b = rating[1]; c = rating[2]; d = rating[3]; ab = probability(a,b); ac = probability(a,c); ad = probability(a,d); bc = probability(b,c); bd = probability(b,d); cd = probability(c,d); cb = 1.0 - bc; db = 1.0 - bd; dc = 1.0 - cd; return (ab*ac*(cd+bd)+ac*ad*(db+cb)+ab*ad*(dc+bc))/3; } /* [Denis MOREAUX , 10 Apr 2000] * * C D E A D E The winner may be in the * A B C E B C A E 2 players or the 3 players * A C B A group. In either case, a * A A second player must be choosen * to be either the one playing * against A in the 2-players subtree or being the winner * of the 2-player subtree if A is in the 3-players subtree. */ static double five_player(unsigned int *rating) { unsigned int a,b,c,d,e; a = rating[0]; b = rating[1]; c = rating[2]; d = rating[3]; e = rating[4]; return (five_f1(a,b,c,d,e)+five_f1(a,c,d,e,b)+ five_f1(a,d,e,b,c)+five_f1(a,e,b,c,d))/30; } /* [Denis MOREAUX , 10 Apr 2000 * * Two cases to treat : AB-CDE and BC-ADE. * in both cases, A win against B. * In the first case, A win over the winner of a 3-players game * (3 possible winners). * In the second case, B win over one of the three other and A is in * the 3-players game. */ static double five_f1(int a, int b, int c, int d, int e) { double ab,ac,ad,ae,bc,bd,be; ab = probability(a,b); ac = probability(a,c); ad = probability(a,d); ae = probability(a,e); bc = probability(b,c); bd = probability(b,d); be = probability(b,e); return ab*(ac*five_f2(c,d,e)+ad*five_f2(d,e,c)+ae*five_f2(e,c,d)+ bc*five_f2(a,d,e)+bd*five_f2(a,c,e)+be*five_f2(a,c,d)); } static double five_f2(int a, int b, int c) { double ab,ac,bc,cb; ab = probability(a,b); ac = probability(a,c); bc = probability(b,c); cb = 1.0 - bc; return (2*(ab*ac)+bc*ab+cb*ac); } static double six_player(unsigned int *rating) { unsigned int a,b,c,d,e,f; a = rating[0]; b = rating[1]; c = rating[2]; d = rating[3]; e = rating[4]; f = rating[5]; /* A B C D * A C E F * A E * A */ return (six_f1(a,b,c,d,e,f)+ /* A is in group of 4 */ six_f1(a,b,c,e,d,f)+ six_f1(a,b,e,d,c,f)+ six_f1(a,e,c,d,b,f)+ six_f1(a,b,c,f,d,e)+ six_f1(a,b,f,d,c,e)+ six_f1(a,f,c,d,b,e)+ six_f1(a,e,f,b,c,d)+ six_f1(a,e,f,c,b,d)+ six_f1(a,e,f,d,b,c)+ six_f2(a,b,c,d,e,f)+ /* A is in group of 2 */ six_f2(a,c,b,d,e,f)+ six_f2(a,d,b,c,e,f)+ six_f2(a,e,b,c,d,f)+ six_f2(a,f,b,c,d,e))/45; } /* ABCD = group of 4, EF = group of 2, A must win */ /* D.Moreaux, 10 Apr 2000: changed double to int for the parameters */ static double six_f1(int a, int b, int c, int d, int e, int f) { double ab,ac,ad,bc,bd,cb,cd,db,dc,ef,fe,ae,af; ab = probability(a,b); ac = probability(a,c); ad = probability(a,d); ae = probability(a,e); af = probability(a,f); bc = probability(b,c); bd = probability(b,d); cd = probability(c,d); ef = probability(e,f); cb = 1.0 - bc; db = 1.0 - bd; dc = 1.0 - cd; fe = 1.0 - ef; return (ab*ac*(cd+bd)+ac*ad*(db+cb)+ab*ad*(dc+bc))*(ef*ae+fe*af); } /* AB is group of 2, CDEF is group of 4, A must win */ static double six_f2(int a, int b, int c, int d, int e, int f) { double ab,ac,ad,ae,af; ab = probability(a,b); ac = probability(a,c); ad = probability(a,d); ae = probability(a,e); af = probability(a,f); return (six_f3(c,d,e,f)*ab*ac+ six_f3(d,c,e,f)*ab*ad+ six_f3(e,c,d,f)*ab*ae+ six_f3(f,c,d,e)*ab*af); } /* ABCD is group of 4, A win */ static double six_f3(int a, int b, int c, int d) { double ab,ac,ad,bc,bd,cb,cd,db,dc; ab = probability(a,b); ac = probability(a,c); ad = probability(a,d); bc = probability(b,c); bd = probability(b,d); cd = probability(c,d); cb = 1.0 - bc; db = 1.0 - bd; dc = 1.0 - cd; return (ab*ac*(cd+bd)+ac*ad*(db+cb)+ab*ad*(dc+bc)); } static double seven_player(unsigned int *rating) { unsigned int a,b,c,d,e,f,g; a = rating[0]; b = rating[1]; c = rating[2]; d = rating[3]; e = rating[4]; f = rating[5]; g = rating[6]; return (seven_f1(a,b,c,d,e,f,g)+seven_f1(a,c,b,d,e,f,g)+ seven_f1(a,d,c,b,e,f,g)+seven_f1(a,e,c,d,b,f,g)+ seven_f1(a,f,c,d,e,b,g)+seven_f1(a,g,c,d,e,f,b))/45; } static double seven_f1(int a, int b, int c, int d, int e, int f, int g) { return seven_f2(a,b,c,d,e,f,g)+seven_f2(a,b,d,c,e,f,g)+ seven_f2(a,b,e,d,c,f,g)+seven_f2(a,b,f,d,e,c,g)+ seven_f2(a,b,g,d,e,f,c); } static double seven_f2(int a, int b, int c, int d, int e, int f, int g) { double ab,ac,ad,ae,af,ag,bc,bd,be,bf,bg,cd,ce,cf,cg; double de,df,dg,ed,ef,eg,fd,fe,fg,gd,ge,gf; ab = probability(a,b); ac = probability(a,c); ad = probability(a,d); ae = probability(a,e); af = probability(a,f); ag = probability(a,g); bc = probability(b,c); bd = probability(b,d); be = probability(b,e); bf = probability(b,f); bg = probability(b,g); cd = probability(c,d); ce = probability(c,e); cf = probability(c,f); cg = probability(c,g); de = probability(d,e); df = probability(d,f); dg = probability(d,g); ef = probability(e,f); eg = probability(e,g); fg = probability(f,g); ed = 1.0 - de; fd = 1.0 - df; gd = 1.0 - dg; fe = 1.0 - ef; ge = 1.0 - eg; gf = 1.0 - fg; return ab*( (ac+bc)* (ad*(de*df*(fg+eg)+df*dg*(ge+fe)+de*dg*(gf+ef))+ /* 4:d win */ ae*(ed*ef*(fg+dg)+ef*eg*(gd+fd)+ed*eg*(gf+df))+ /* 4:e win */ af*(fe*fd*(dg+eg)+fd*fg*(ge+de)+fe*fg*(gd+ed))+ /* 4:f win */ ag*(ge*gf*(fd+ed)+gf*gd*(de+fe)+ge*gd*(df+ef)))+ /* 4:g win */ bc* ((bd+cd)*(ae*af*(fg+eg)+af*ag*(ge+fe)+ae*ag*(gf+ef))+ /* 3:d */ (be+ce)*(ad*af*(fg+dg)+af*ag*(ad+ad)+ad*ag*(gf+df))+ /* 3:e */ (bf+cf)*(ae*ad*(dg+eg)+ad*ag*(ge+de)+ae*ag*(gd+ed))+ /* 3:f */ (bg+cg)*(ae*af*(fd+ed)+af*ad*(de+fe)+ae*ad*(df+ef)))); /* 3:g */ } static double eight_player(unsigned int *rating) { unsigned int a,b,c,d,e,f,g,h; double ab,ac,ad,ae,af,ag,ah; a = rating[0]; b = rating[1]; c = rating[2]; d = rating[3]; e = rating[4]; f = rating[5]; g = rating[6]; h = rating[7]; ab = probability(a,b); ac = probability(a,c); ad = probability(a,d); ae = probability(a,e); af = probability(a,f); ag = probability(a,g); ah = probability(a,h); /* First against A may be one from seven */ return (eight_f1(a,c,d,e,f,g,h)*ab+ eight_f1(a,b,d,e,f,g,h)*ac+ eight_f1(a,b,c,e,f,g,h)*ad+ eight_f1(a,b,c,d,f,g,h)*ae+ eight_f1(a,b,c,d,e,g,h)*af+ eight_f1(a,b,c,d,e,f,h)*ag+ eight_f1(a,b,c,d,e,f,g)*ah)/315; } static double eight_f1(int a, int b, int c, int d, int e, int f, int g) { /* The winner of the second group, who'll then play against A, may be one from six possible players */ return eight_f2(a,b,c,d,e,f,g)+ eight_f2(a,c,b,d,e,f,g)+ eight_f2(a,d,b,c,e,f,g)+ eight_f2(a,e,b,c,d,f,g)+ eight_f2(a,f,b,c,d,e,g)+ eight_f2(a,g,b,c,d,e,f); } static double eight_f2(int a, int b, int c, int d, int e, int f, int g) { double ab,bc,bd,be,bf,bg; ab = probability(a,b); bc = probability(b,c); bd = probability(b,d); be = probability(b,e); bf = probability(b,f); bg = probability(b,g); /* There are 5 player who may play against the 3rd. The third (b) will win over them and lose against a */ return ab*(eight_f3(a,d,e,f,g)*bc+ eight_f3(a,c,e,f,g)*bd+ eight_f3(a,c,d,f,g)*be+ eight_f3(a,c,d,e,g)*bf+ eight_f3(a,c,d,e,f)*bg); } /* D.Moreaux, 10 Apr 2000: changed double to int for the parameters */ static double eight_f3(int a, int b, int c, int d, int e) { double ab,ac,ad,ae,bc,bd,be,cb,cd,ce,db,dc,de,eb,ec,ed; ab = probability(a,b); ac = probability(a,c); ad = probability(a,d); ae = probability(a,e); bc = probability(b,c); bd = probability(b,d); be = probability(b,e); cd = probability(c,d); ce = probability(c,e); de = probability(d,e); cb = 1.0 - bc; db = 1.0 - bd; dc = 1.0 - cd; eb = 1.0 - be; ec = 1.0 - ce; ed = 1.0 - de; /* expansion then factorisation (this function is called 210 times) * gain 4 func_call * 24 * * 30 probability */ return (bc*de+be*dc)*((ab-ad)*bd+ad)+ (bd*ce+be*cd)*((ab-ac)*bc+ac)+ (cb*de+db*ce)*((ac-ad)*cd+ad)+ (cd*eb+cb*ed)*((ac-ae)*ce+ae)+ (dc*eb+db*ec)*((ad-ae)*de+ae)+ (bd*ec+bc*ed)*((ae-ab)*eb+ab); } /* Determine changes in ratings due to game results. */ extern int ladder_calc_info(t_clienttag clienttag, t_ladder_id id, unsigned int count, t_account * * players, t_game_result * results, t_ladder_info * info) { unsigned int curr; unsigned int *rating; unsigned int *sorted; if (!players) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL players"); return -1; } if (!results) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL results"); return -1; } if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } if (!info) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL info"); return -1; } rating = xmalloc(sizeof(unsigned int)*count); sorted = xmalloc(sizeof(unsigned int)*count); for (curr=0; curr fewer points added */ else delta = -fabs(k * prob); /* better the chance of winning -> more points subtracted */ eventlog(eventlog_level_debug,__FUNCTION__,"computed probability=%g, k=%g, deltar=%+g",prob,k,delta); info[curr].prob = prob; info[curr].k = (unsigned int)k; info[curr].adj = (int)delta; info[curr].oldrating = rating[curr]; info[curr].oldrank = account_get_ladder_rank(players[curr],clienttag,id); } xfree((void *)rating); xfree((void *)sorted); return 0; } pvpgn-1.8.5/src/bnetd/udptest_send.h0000644000175000017500000000201711151345317016377 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_UDPTEST_SEND_TYPES #define INCLUDED_UDPTEST_SEND_TYPES #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_UDPTEST_SEND_PROTOS #define INCLUDED_UDPTEST_SEND_PROTOS extern int udptest_send(t_connection const * c); #endif #endif pvpgn-1.8.5/src/bnetd/realm.c0000644000175000017500000003331411151345317014775 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define REALM_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strrchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include #include "compat/strerror.h" #include "common/eventlog.h" #include "common/list.h" #include "common/util.h" #include "common/addr.h" #include "common/xalloc.h" #include "connection.h" #include "common/rcm.h" #include "realm.h" #ifdef HAVE_ASSERT_H # include #endif #include "common/setup_after.h" static t_list * realmlist_head=NULL; static t_realm * realm_create(char const * name, char const * description, unsigned int ip, unsigned int port); static int realm_destroy(t_realm * realm); static t_realm * realm_create(char const * name, char const * description, unsigned int ip, unsigned int port) { t_realm * realm; if (!name) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL name"); return NULL; } if (!description) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL description"); return NULL; } realm = xmalloc(sizeof(t_realm)); realm->name = NULL; realm->description = NULL; if (realm_set_name(realm ,name)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to set name for realm"); xfree(realm); return NULL; } if (realm->description != NULL) xfree((void *)realm->description); realm->description = xstrdup(description); realm->ip = ip; realm->port = port; realm->conn = NULL; realm->active = 0; realm->player_number = 0; realm->game_number = 0; realm->sessionnum = 0; realm->tcp_sock = 0; rcm_init(&realm->rcm); eventlog(eventlog_level_info,__FUNCTION__,"created realm \"%s\"",name); return realm; } static int realm_destroy(t_realm * realm) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return -1; } if (realm->active) realm_deactive(realm); xfree((void *)realm->name); /* avoid warning */ xfree((void *)realm->description); /* avoid warning */ xfree((void *)realm); /* avoid warning */ return 0; } extern char const * realm_get_name(t_realm const * realm) { if (!realm) { return NULL; } return realm->name; } extern int realm_set_name(t_realm * realm, char const * name) { char const * temp; t_realm const * temprealm; if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return -1; } if (name && (temprealm=realmlist_find_realm(name))) { if (temprealm == realm) return 0; else { eventlog(eventlog_level_error,__FUNCTION__,"realm %s does already exist in list",name); return -1; } } if (name) temp=xstrdup(name); else temp = NULL; if (realm->name) xfree((void *)realm->name); /* avoid warning */ realm->name = temp; return 0; } extern char const * realm_get_description(t_realm const * realm) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return NULL; } return realm->description; } extern unsigned short realm_get_port(t_realm const * realm) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return 0; } return realm->port; } extern unsigned int realm_get_ip(t_realm const * realm) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return 0; } return realm->ip; } extern unsigned int realm_get_active(t_realm const * realm) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return 0; } return realm->active; } extern int realm_set_active(t_realm * realm, unsigned int active) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return -1; } realm->active=active; return 0; } extern unsigned int realm_get_player_number(t_realm const * realm) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return 0; } return realm->player_number; } extern int realm_add_player_number(t_realm * realm, int number) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return -1; } realm->player_number += number; return 0; } extern unsigned int realm_get_game_number(t_realm const * realm) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return 0; } return realm->game_number; } extern int realm_add_game_number(t_realm * realm, int number) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return -1; } realm->game_number += number; return 0; } extern int realm_active(t_realm * realm, t_connection * c) { if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return -1; } if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (realm->active) { eventlog(eventlog_level_debug,__FUNCTION__, "realm %s is already actived,destroy previous one",realm->name); realm_deactive(realm); } realm->active=1; realm->conn=c; conn_set_realm(c,realm); realm->sessionnum=conn_get_sessionnum(c); realm->tcp_sock=conn_get_socket(c); eventlog(eventlog_level_info,__FUNCTION__, "realm %s actived",realm->name); return 0; } extern int realm_deactive(t_realm * realm) { t_connection * c; if (!realm) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); return -1; } if (!realm->active) { eventlog(eventlog_level_error,__FUNCTION__,"realm %s is not actived",realm->name); return -1; } if ((c = realm_get_conn(realm))) conn_set_state(c,conn_state_destroy); realm->active=0; realm->sessionnum=0; realm->tcp_sock=0; /* realm->player_number=0; realm->game_number=0; */ eventlog(eventlog_level_info,__FUNCTION__, "realm %s deactived",realm->name); return 0; } t_list * realmlist_load(char const * filename) { FILE * fp; unsigned int line; unsigned int pos; unsigned int len; t_addr * raddr; char * temp, *temp2; char * buff; char * name; char * desc; t_realm * realm; t_list * list_head = NULL; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return NULL; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open realm file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return NULL; } list_head = list_create(); for (line=1; (buff = file_get_line(fp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if ((temp = strrchr(buff,'#'))) { unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } /* skip any separators */ for (temp = buff; *temp && (*temp == ' ' || *temp == '\t');temp++); if (*temp != '"') { eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no realmname)",line,filename); continue; } temp2 = temp + 1; /* find the next " */ for (temp = temp2; *temp && *temp != '"';temp++); if (*temp != '"' || temp == temp2) { eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no realmname)",line,filename); continue; } /* save the realmname */ *temp = '\0'; name = xstrdup(temp2); /* eventlog(eventlog_level_trace, __FUNCTION__,"found realmname: %s",name); */ /* skip any separators */ for(temp = temp + 1; *temp && (*temp == '\t' || *temp == ' ');temp++); if (*temp == '"') { /* we have realm description */ temp2 = temp + 1; /* find the next " */ for(temp = temp2;*temp && *temp != '"';temp++); if (*temp != '"' || temp == temp2) { eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no valid description)",line,filename); xfree(name); continue; } /* save the description */ *temp = '\0'; desc = xstrdup(temp2); /* eventlog(eventlog_level_trace, __FUNCTION__,"found realm desc: %s",desc); */ /* skip any separators */ for(temp = temp + 1; *temp && (*temp == ' ' || *temp == '\t');temp++); } else desc = xstrdup("\0"); temp2 = temp; /* find out where address ends */ for(temp = temp2 + 1; *temp && *temp != ' ' && *temp != '\t';temp++); if (*temp) *temp++ = '\0'; /* if is not the end of the file, end addr and move forward */ /* eventlog(eventlog_level_trace, __FUNCTION__,"found realm ip: %s",temp2); */ if (!(raddr = addr_create_str(temp2,0,BNETD_REALM_PORT))) /* 0 means "this computer" */ { eventlog(eventlog_level_error,__FUNCTION__,"invalid address value for field 3 on line %u in file \"%s\"",line,filename); xfree(name); xfree(desc); continue; } if (!(realm = realm_create(name,desc,addr_get_ip(raddr),addr_get_port(raddr)))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create realm"); addr_destroy(raddr); xfree(name); xfree(desc); continue; } addr_destroy(raddr); xfree(name); xfree(desc); list_prepend_data(list_head,realm); } file_get_line(NULL); // clear file_get_line buffer if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close realm file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno)); return list_head; } extern int realmlist_reload(char const * filename) { t_elem * new_curr; t_elem * old_curr; t_realm * new_realm; t_realm * old_realm; int match; t_list * newlist = NULL; t_list * oldlist = realmlist_head; realmlist_head = NULL; if (!(newlist = realmlist_load(filename))) return -1; LIST_TRAVERSE(oldlist,old_curr) { if (!(old_realm = elem_get_data(old_curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL elem in list"); continue; } match = 0; LIST_TRAVERSE(newlist,new_curr) { if (!(new_realm = elem_get_data(new_curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL elem in list"); continue; } if (!strcmp(old_realm->name,new_realm->name)) { match = 1; rcm_chref(&old_realm->rcm,new_realm); break; } } if (!match) rcm_chref(&old_realm->rcm,NULL); realm_destroy(old_realm); list_remove_elem(oldlist,&old_curr); } list_destroy(oldlist); realmlist_head = newlist; return 0; } extern int realmlist_create(char const * filename) { if (!(realmlist_head = realmlist_load(filename))) return -1; return 0; } extern int realmlist_unload(t_list * list_head) { t_elem * curr; t_realm * realm; if (list_head) { LIST_TRAVERSE(list_head,curr) { if (!(realm = elem_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL realm in list"); else realm_destroy(realm); list_remove_elem(list_head,&curr); } list_destroy(list_head); } return 0; } extern int realmlist_destroy() { int res; res = realmlist_unload(realmlist_head); realmlist_head = NULL; return res; } extern t_list * realmlist(void) { return realmlist_head; } extern t_realm * realmlist_find_realm(char const * realmname) { t_elem const * curr; t_realm * realm; if (!realmname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realmname"); return NULL; } LIST_TRAVERSE_CONST(realmlist_head,curr) { realm = elem_get_data(curr); if (strcasecmp(realm->name,realmname)==0) return realm; } return NULL; } extern t_realm * realmlist_find_realm_by_ip(unsigned long ip) { t_elem const * curr; t_realm * realm; LIST_TRAVERSE_CONST(realmlist_head,curr) { realm = elem_get_data(curr); if (realm->ip==ip) return realm; } return NULL; } extern t_connection * realm_get_conn(t_realm * realm) { assert(realm); return realm->conn; } extern t_realm * realm_get(t_realm * realm, t_rcm_regref * regref) { rcm_get(&realm->rcm,regref); return realm; } extern void realm_put(t_realm * realm, t_rcm_regref * regref) { rcm_put(&realm->rcm,regref); } pvpgn-1.8.5/src/bnetd/news.h0000644000175000017500000000271011151345317014652 0ustar aaronaaron/* * Copyright (C) 2000 Alexey Belyaev (spider@omskart.ru) * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_NEWS_TYPES #define INCLUDED_NEWS_TYPES #ifdef HAVE_TIME_H # include #endif #include "common/elist.h" #include "common/lstr.h" typedef struct news_index #ifdef NEWS_INTERNAL_ACCESS { time_t date; t_lstr body; t_elist list; } #endif t_news_index; typedef int (*t_news_cb)(time_t, t_lstr *, void *); #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef NEWS_INTERNAL_ACCESS #define NEWS_INTERNAL_ACCESS extern int news_load(const char *filename); extern int news_unload(void); extern unsigned int news_get_firstnews(void); extern unsigned int news_get_lastnews(void); extern void news_traverse(t_news_cb cb, void *data); #endif #endif pvpgn-1.8.5/src/bnetd/watch.h0000644000175000017500000000424611151345317015012 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_WATCH_TYPES #define INCLUDED_WATCH_TYPES #ifdef WATCH_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include "account.h" # include "connection.h" #else # define JUST_NEED_TYPES # include "account.h" # include "connection.h" # undef JUST_NEED_TYPES #endif #include "common/tag.h" #endif typedef enum { watch_event_login=1, watch_event_logout=2, watch_event_joingame=4, watch_event_leavegame=8 } t_watch_event; #ifdef WATCH_INTERNAL_ACCESS typedef struct { t_connection * owner; /* who to notify */ t_account * who; /* when this account */ t_watch_event what; /* does one of these things */ t_clienttag clienttag; } t_watch_pair; #endif #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_WATCH_PROTOS #define INCLUDED_WATCH_PROTOS #define JUST_NEED_TYPES #include "account.h" #include "connection.h" #undef JUST_NEED_TYPES extern int watchlist_create(void); extern int watchlist_destroy(void); extern int watchlist_add_events(t_connection * owner, t_account * who, t_clienttag clienttag, t_watch_event events); extern int watchlist_del_events(t_connection * owner, t_account * who, t_clienttag clienttag, t_watch_event events); extern int watchlist_del_all_events(t_connection * owner); extern int watchlist_del_by_account(t_account * account); extern int watchlist_notify_event(t_account * who, char const * gamename, t_clienttag clienttag, t_watch_event event); #endif #endif pvpgn-1.8.5/src/bnetd/anongame_maplists.c0000644000175000017500000002163011151345317017374 0ustar aaronaaron/* * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "common/packet.h" #include "common/tag.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "prefs.h" #include "anongame_maplists.h" #include "common/setup_after.h" #define MAXMAPS 100 #define MAXMAPS_PER_QUEUE 32 /* cannot be changed (map_prefs only supports 32 maps) */ /**********************************************************************************/ static char * maplist_war3[MAXMAPS]; static char * maplist_w3xp[MAXMAPS]; static int number_maps_war3 = 0; static int number_maps_w3xp = 0; static char maplists_war3[ANONGAME_TYPES][MAXMAPS_PER_QUEUE+1]; static char maplists_w3xp[ANONGAME_TYPES][MAXMAPS_PER_QUEUE+1]; static int _maplists_type_get_queue(const char * type); static char * _maplists_queue_get_type(int queue); static void _maplists_add_map(t_clienttag clienttag, char * mapname, int queue); /*****/ static char * queue_names[ANONGAME_TYPES] = { "1v1","2v2","3v3","4v4","sffa","at2v2","tffa","at3v3","at4v4", "TY", "5v5","6v6","2v2v2","3v3v3","4v4v4","2v2v2v2","3v3v3v3", "at2v2v2" }; /**********************************************************************************/ static int _maplists_type_get_queue(const char * type) { int i; for (i = 0; i < ANONGAME_TYPES; i++) if (strcmp(type, queue_names[i]) == 0) return i; return -1; } static char * _maplists_queue_get_type(int queue) { return queue_names[queue]; } static void _maplists_add_map(t_clienttag clienttag, char * mapname, int queue) { /* this function does two things * 1. adds the mapname to maplist for MAPS section * maplist[mapnumber] = mapname * number_maps = total maps held in maplist[] * 2. adds the mapnumber to maplists for TYPE section * maplists[queue][0] = number of maps for queue * maplists[queue][1..32] = mapnumber * ie. maplist[maplists[queue][1..32]] = mapname */ int in_list = 0; int j; char clienttag_str[5]; if (clienttag==CLIENTTAG_WARCRAFT3_UINT) { for (j = 0; j < number_maps_war3; j++) { if (strcmp(maplist_war3[j], mapname) == 0) { /* already in list */ in_list = 1; break; } } if (!in_list) maplist_war3[number_maps_war3++] = xstrdup(mapname); if (maplists_war3[queue][0] < MAXMAPS_PER_QUEUE) { maplists_war3[queue][0]++; maplists_war3[queue][(int)maplists_war3[queue][0]] = j; } else { eventlog(eventlog_level_error,__FUNCTION__, "cannot add map \"%s\" for gametype: %s (maxmaps per qametype: %d)", mapname, _maplists_queue_get_type(queue), MAXMAPS_PER_QUEUE); } } else if (clienttag==CLIENTTAG_WAR3XP_UINT) { for (j = 0; j < number_maps_w3xp; j++) { if (strcmp(maplist_w3xp[j], mapname) == 0) { /* already in list */ in_list = 1; break; } } if (!in_list) maplist_w3xp[number_maps_w3xp++] = xstrdup(mapname); if (maplists_w3xp[queue][0] < MAXMAPS_PER_QUEUE) { maplists_w3xp[queue][0]++; maplists_w3xp[queue][(int)maplists_w3xp[queue][0]] = j; } else { eventlog(eventlog_level_error,__FUNCTION__, "cannot add map \"%s\" for gametype: %s (maxmaps per qametype: %d)", mapname, _maplists_queue_get_type(queue), MAXMAPS_PER_QUEUE); } } else eventlog(eventlog_level_error,__FUNCTION__,"invalid clienttag: %s",tag_uint_to_str(clienttag_str,clienttag)); } /**********************************************************************************/ extern int anongame_maplists_create(void) { FILE *mapfd; char buffer[256]; int len, i, queue; char *p, *q, *r, *u; if (prefs_get_mapsfile() == NULL) { eventlog(eventlog_level_error, "anongame_maplists_create","invalid mapsfile, check your config"); return -1; } if ((mapfd = fopen(prefs_get_mapsfile(), "rt")) == NULL) { eventlog(eventlog_level_error, "anongame_maplists_create", "could not open mapsfile : \"%s\"", prefs_get_mapsfile()); return -1; } /* init the maps, they say static vars are 0-ed anyway but u never know :) */ for(i=0; i < ANONGAME_TYPES; i++) { maplists_war3[i][0] = 0; maplists_w3xp[i][0] = 0; } while(fgets(buffer, 256, mapfd)) { len = strlen(buffer); if (len < 1) continue; if (buffer[len-1] == '\n') { buffer[len-1] = '\0'; } /* search for comments and comment them out */ for(p = buffer; *p ; p++) if (*p == '#') { *p = '\0'; break; } /* skip spaces and/or tabs */ for(p = buffer; *p && ( *p == ' ' || *p == '\t' ); p++); /* p = clienttag */ if (*p == '\0') continue; /* find next delimiter */ for(q = p; *q && *q != ' ' && *q != '\t'; q++); if (*q == '\0' || q - p != 4) continue; /* clienttag needs to have 4 chars */ *q = '\0'; /* end of clienttag */ /* skip spaces and/or tabs */ for (q++ ; *q && ( *q == ' ' || *q == '\t'); q++); /* q = type */ if (*q == '\0') continue; /* find next delimiter */ for (r = q+1; *r && *r != ' ' && *r != '\t'; r++); *r = '\0'; /* end of type */ /* skip spaces and/or tabs */ for (r++ ; *r && ( *r == ' ' || *r == '\t'); r++); /* r = mapname */ if (*r == '\0') continue; if (*r!='\"') /* mapname without quotes */ /* find next delimiter */ for (u = r+1; *u && *u != ' ' && *u != '\t'; u++); else /* mapname with quotes */ { r++; /* skip quote */ for (u = r+1; *u && *u != '\"'; u++); /* find end quote or end of buffer */ if (*u!='\"') { eventlog(eventlog_level_error,__FUNCTION__,"missing \" at the end of the map name, presume it's ok anyway"); } } *u = '\0'; /* end of mapname */ if ((queue = _maplists_type_get_queue(q)) < 0) continue; /* invalid queue */ _maplists_add_map(tag_case_str_to_uint(p), r, queue); } fclose(mapfd); return 0; } /* used by the MAPS section */ extern int maplists_get_totalmaps(t_clienttag clienttag) { if (clienttag==CLIENTTAG_WARCRAFT3_UINT) return number_maps_war3; if (clienttag==CLIENTTAG_WAR3XP_UINT) return number_maps_w3xp; return 0; } extern void maplists_add_maps_to_packet(t_packet * packet, t_clienttag clienttag) { int i; if (clienttag==CLIENTTAG_WARCRAFT3_UINT) for (i = 0; i < number_maps_war3; i++) packet_append_string(packet, maplist_war3[i]); if (clienttag==CLIENTTAG_WAR3XP_UINT) for (i = 0; i < number_maps_w3xp; i++) packet_append_string(packet, maplist_w3xp[i]); } /* used by TYPE section */ extern int maplists_get_totalmaps_by_queue(t_clienttag clienttag, int queue) { if (clienttag==CLIENTTAG_WARCRAFT3_UINT) return maplists_war3[queue][0]; if (clienttag==CLIENTTAG_WAR3XP_UINT) return maplists_w3xp[queue][0]; return 0; } extern void maplists_add_map_info_to_packet(t_packet * rpacket, t_clienttag clienttag, int queue) { int i; if (clienttag==CLIENTTAG_WARCRAFT3_UINT) { for (i = 0; i < maplists_war3[queue][0] + 1; i++) packet_append_data(rpacket, &maplists_war3[queue][i], 1); } if (clienttag==CLIENTTAG_WAR3XP_UINT) { for (i = 0; i < maplists_w3xp[queue][0] + 1; i++) packet_append_data(rpacket, &maplists_w3xp[queue][i], 1); } } /* used by _get_map_from_prefs() */ extern char * maplists_get_map(int queue, t_clienttag clienttag, int mapnumber) { if (clienttag==CLIENTTAG_WARCRAFT3_UINT) return maplist_war3[(int)maplists_war3[queue][mapnumber]]; if (clienttag==CLIENTTAG_WAR3XP_UINT) return maplist_w3xp[(int)maplists_w3xp[queue][mapnumber]]; return NULL; } extern void anongame_maplists_destroy() { int i; for (i = 0; i < MAXMAPS; i++) { if (maplist_war3[i]) xfree((void *)maplist_war3[i]); if (maplist_w3xp[i]) xfree((void *)maplist_w3xp[i]); } } extern int anongame_add_tournament_map(t_clienttag clienttag, char * mapname) { _maplists_add_map(clienttag, mapname, ANONGAME_TYPE_TY); return 0; } extern void anongame_tournament_maplists_destroy(void) { return; /* nothing to destroy */ } pvpgn-1.8.5/src/bnetd/handle_init.h0000644000175000017500000000207211151345317016155 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_HANDLE_INIT_PROTOS #define INCLUDED_HANDLE_INIT_PROTOS #define JUST_NEED_TYPES #include "connection.h" #include "common/packet.h" #undef JUST_NEED_TYPES extern int handle_init_packet(t_connection * c, t_packet const * const packet); #endif #endif pvpgn-1.8.5/src/bnetd/game_conv.h0000644000175000017500000000332211151345317015634 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_GAME_CONV_PROTOS #define INCLUDED_GAME_CONV_PROTOS #define JUST_NEED_TYPES #include "game.h" #undef JUST_NEED_TYPES extern t_game_type bngreqtype_to_gtype(t_clienttag clienttag, unsigned short bngtype) ; extern t_game_type bngtype_to_gtype(t_clienttag clienttag, unsigned short bngtype) ; extern unsigned short gtype_to_bngtype(t_game_type gtype) ; extern t_game_option bngoption_to_goption(t_clienttag clienttag, t_game_type gtype, unsigned short bngoption) ; extern t_game_result bngresult_to_gresult(unsigned int bngresult) ; extern t_game_maptype bngmaptype_to_gmaptype(unsigned int bngmaptype) ; extern t_game_tileset bngtileset_to_gtileset(unsigned int bngtileset) ; extern t_game_speed bngspeed_to_gspeed(unsigned int bngspeed) ; extern t_game_difficulty bngdifficulty_to_gdifficulty(unsigned int bngdifficulty) ; extern int game_parse_info(t_game * game, char const * gameinfo); #endif #endif pvpgn-1.8.5/src/bnetd/sql_dbcreator.c0000644000175000017500000004725011151345317016525 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef WITH_SQL #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #define SQL_DBCREATOR_INTERNAL_ACCESS #include "sql_dbcreator.h" #undef SQL_DBCREATOR_INTERNAL_ACCESS #include "storage_sql.h" #include "common/eventlog.h" #include "common/util.h" #include "compat/strdup.h" #include "common/list.h" #include "common/xalloc.h" #include "common/xstr.h" #include "prefs.h" #include "common/setup_after.h" t_elem * curr_table = NULL; t_elem * curr_column = NULL; t_elem * curr_cmd = NULL; t_db_layout * db_layout; static void sql_escape_command(char *escape, const char *from, int len); t_column * create_column(char * name, char * value, char * mode, char * extra_cmd) { t_column * column; if (!(name)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL column name"); return NULL; } if (!(value)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL column value"); return NULL; } column = xmalloc(sizeof(t_column)); column->name = xstrdup(name); column->value = xstrdup(value); if (mode && extra_cmd) { column->mode = xstrdup(mode); column->extra_cmd = xstrdup(extra_cmd); } else { column->mode = NULL; column->extra_cmd = NULL; } return column; }; void dispose_column(t_column * column) { if (column) { if (column->name) xfree((void *)column->name); if (column->value) xfree((void *)column->value); if (column->mode) xfree((void *)column->mode); if (column->extra_cmd) xfree((void *)column->extra_cmd); xfree((void *)column); } } t_sqlcommand * create_sqlcommand(char * sql_command, char * mode, char * extra_cmd) { t_sqlcommand * sqlcommand; if (!(sql_command)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL sql_command"); return NULL; } sqlcommand = xmalloc(sizeof(t_sqlcommand)); sqlcommand->sql_command = xstrdup(sql_command); if (mode && extra_cmd) { sqlcommand->mode = xstrdup(mode); sqlcommand->extra_cmd = xstrdup(extra_cmd); } else { sqlcommand->mode = NULL; sqlcommand->extra_cmd = NULL; } return sqlcommand; } void dispose_sqlcommand(t_sqlcommand * sqlcommand) { if (sqlcommand) { if (sqlcommand->sql_command) xfree((void *)sqlcommand->sql_command); if (sqlcommand->mode) xfree((void *)sqlcommand->mode); if (sqlcommand->extra_cmd) xfree((void *)sqlcommand->extra_cmd); xfree(sqlcommand); } } t_table * create_table(char * name) { t_table * table; if (!(name)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL table name"); return NULL; } table = xmalloc(sizeof(t_table)); table->name = xstrdup(name); table->columns = list_create(); table->sql_commands = list_create(); return table; } void dispose_table(t_table * table) { t_elem * curr; t_column * column; t_sqlcommand * sql_command; if (table) { if (table->name) xfree((void *)table->name); // free list if (table->columns) { LIST_TRAVERSE(table->columns,curr) { if (!(column = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } dispose_column(column); list_remove_elem(table->columns,&curr); } list_destroy(table->columns); } if (table->sql_commands) { LIST_TRAVERSE(table->sql_commands,curr) { if (!(sql_command = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } dispose_sqlcommand(sql_command); list_remove_elem(table->sql_commands,&curr); } list_destroy(table->sql_commands); } xfree((void *)table); } } void table_add_column(t_table * table, t_column * column) { if ((table) && (column)) { list_append_data(table->columns,column); } } void table_add_sql_command(t_table * table, t_sqlcommand * sql_command) { if ((table) && (sql_command)) { list_append_data(table->sql_commands,sql_command); } } t_db_layout * create_db_layout() { t_db_layout * db_layout; db_layout = xmalloc(sizeof(t_db_layout)); db_layout->tables = list_create(); return db_layout; } void dispose_db_layout(t_db_layout * db_layout) { t_elem * curr; t_table * table; if (db_layout) { if (db_layout->tables) { LIST_TRAVERSE(db_layout->tables,curr) { if (!(table = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } dispose_table(table); list_remove_elem(db_layout->tables,&curr); } list_destroy(db_layout->tables); } xfree((void *)db_layout); } } void db_layout_add_table(t_db_layout * db_layout, t_table * table) { if ((db_layout) && (table)) { list_append_data(db_layout->tables,table); } } t_table * db_layout_get_first_table(t_db_layout * db_layout) { t_table * table; curr_column = NULL; if (!(db_layout)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL db_layout"); return NULL; } if (!(db_layout->tables)) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL db_layout->tables"); return NULL; } if (!(curr_table = list_get_first(db_layout->tables))) { eventlog(eventlog_level_error,__FUNCTION__,"db_layout has no tables"); return NULL; } if (!(table = elem_get_data(curr_table))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list"); return NULL; } return table; } t_table * db_layout_get_next_table(t_db_layout * db_layout) { t_table * table; curr_column = NULL; if (!(curr_table)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL curr_table"); return NULL; } if (!(curr_table = elem_get_next(db_layout->tables, curr_table))) return NULL; if (!(table = elem_get_data(curr_table))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list"); return NULL; } return table; } t_column * table_get_first_column(t_table * table) { t_column * column; if (!(table)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL table"); return NULL; } if (!(table->columns)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL table->columns"); return NULL; } if (!(curr_column = list_get_first(table->columns))) { eventlog(eventlog_level_error,__FUNCTION__,"table has no columns"); return NULL; } if (!(column = elem_get_data(curr_column))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list"); return NULL; } return column; } t_column * table_get_next_column(t_table * table) { t_column * column; if (!(curr_column)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL curr_column"); return NULL; } if (!(curr_column = elem_get_next(table->columns, curr_column))) return NULL; if (!(column = elem_get_data(curr_column))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list"); return NULL; } return column; } t_sqlcommand * table_get_first_sql_command(t_table * table) { t_sqlcommand * sql_command; if (!(table)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL table"); return NULL; } if (!(table->sql_commands)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL table->sql_commands"); return NULL; } if (!(curr_cmd = list_get_first(table->sql_commands))) { return NULL; } if (!(sql_command = elem_get_data(curr_cmd))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list"); return NULL; } return sql_command; } t_sqlcommand * table_get_next_sql_command(t_table * table) { t_sqlcommand * sql_command; if (!(curr_cmd)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL curr_cmd"); return NULL; } if (!(curr_cmd = elem_get_next(table->sql_commands, curr_cmd))) return NULL; if (!(sql_command = elem_get_data(curr_cmd))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list"); return NULL; } return sql_command; } int load_db_layout(char const * filename) { FILE * fp; int lineno; char * line = NULL; char * tmp = NULL; char * table = NULL; char * column = NULL; char * value = NULL; char * sqlcmd = NULL; char * sqlcmd_escaped = NULL; char * mode = NULL; char * extra_cmd = NULL; char * extra_cmd_escaped = NULL; t_table * _table = NULL; t_column * _column = NULL; t_sqlcommand * _sqlcommand = NULL; t_xstr * xstr = NULL; int prefix; if (!(filename)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"can't open sql_DB_layout file"); return -1; } if (!(db_layout = create_db_layout())) { eventlog(eventlog_level_error,__FUNCTION__,"failed to create db_layout"); fclose(fp); return -1; } for (lineno=1; (line = file_get_line(fp)) ; lineno++) { /* convert ${prefix} replacement variable */ prefix = 0; for(tmp = line;(tmp = strstr(line, "${prefix}")); line = tmp + 9 /* strlen("${prefix}") */) { *tmp = '\0'; if (!prefix) { prefix = 1; if (!xstr) xstr = xstr_alloc(); xstr_clear(xstr); } xstr_cat_str(xstr, line); xstr_cat_str(xstr, tab_prefix); } if (prefix) { /* append any reminder of the original string */ xstr_cat_str(xstr, line); line = (char*)xstr_get_str(xstr); } switch (line[0]) { case '[': table = &line[1]; if (!(tmp = strchr(table,']'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing ']' in line %i",lineno); continue; } tmp[0]='\0'; if (_table) db_layout_add_table(db_layout,_table); _table = create_table(table); break; case '"': if (!(_table)) { eventlog(eventlog_level_error,__FUNCTION__,"found a column without previous table in line %i",lineno); continue; } column = &line[1]; if (!(tmp = strchr(column,'"'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing '\"' at the end of column definition in line %i",lineno); continue; } tmp[0]='\0'; tmp++; if (!(tmp = strchr(tmp,'"'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing default value in line %i",lineno); continue; } value = ++tmp; if (!(tmp = strchr(value,'"'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing '\"' at the end of default value in line %i",lineno); continue; } tmp[0]='\0'; tmp++; mode = NULL; extra_cmd = NULL; extra_cmd_escaped = NULL; if ((mode = strchr(tmp,'&')) || (mode = strchr(tmp,'|'))) { if (mode[0] == mode[1]) { mode[2]='\0'; tmp=mode+3; if (!(tmp = strchr(tmp,'"'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing starting '\"' in extra sql_command on line %i",lineno); continue; } extra_cmd = ++tmp; if (!(tmp = strchr(extra_cmd,'"'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing ending '\"' in extra sql_command on line %i",lineno); continue; } tmp[0]='\0'; } else { eventlog(eventlog_level_error,__FUNCTION__,"missing or non-matching secondary character in combination logic on line %i",lineno); continue; } } if (extra_cmd) { extra_cmd_escaped = xmalloc(strlen(extra_cmd) * 2); sql_escape_command(extra_cmd_escaped, extra_cmd, strlen(extra_cmd)); } _column = create_column(column,value,mode,extra_cmd_escaped); if (extra_cmd_escaped) xfree(extra_cmd_escaped); table_add_column(_table,_column); _column = NULL; break; case ':': if (!(_table)) { eventlog(eventlog_level_error,__FUNCTION__,"found a sql_command without previous table in line %i",lineno); continue; } if (line[1]!='"') { eventlog(eventlog_level_error,__FUNCTION__,"missing starting '\"' in sql_command definition on line %i",lineno); continue; } sqlcmd = &line[2]; if (!(tmp = strchr(sqlcmd,'"'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing ending '\"' in sql_command definition on line %i",lineno); continue; } tmp[0]='\0'; tmp++; mode = NULL; extra_cmd = NULL; extra_cmd_escaped = NULL; if ((mode = strchr(tmp,'&')) || (mode = strchr(tmp,'|'))) { if (mode[0] == mode[1]) { mode[2]='\0'; tmp=mode+3; if (!(tmp = strchr(tmp,'"'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing starting '\"' in extra sql_command on line %i",lineno); continue; } extra_cmd = ++tmp; if (!(tmp = strchr(extra_cmd,'"'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing ending '\"' in extra sql_command on line %i",lineno); continue; } tmp[0]='\0'; } else { eventlog(eventlog_level_error,__FUNCTION__,"missing or non-matching secondary character in combination logic on line %i",lineno); continue; } } sqlcmd_escaped = xmalloc(strlen(sqlcmd) * 2); sql_escape_command(sqlcmd_escaped, sqlcmd, strlen(sqlcmd)); if (extra_cmd) { extra_cmd_escaped = xmalloc(strlen(extra_cmd) * 2); sql_escape_command(extra_cmd_escaped, extra_cmd, strlen(extra_cmd)); } _sqlcommand = create_sqlcommand(sqlcmd_escaped,mode,extra_cmd_escaped); xfree(sqlcmd_escaped); if (extra_cmd_escaped) xfree(extra_cmd_escaped); table_add_sql_command(_table,_sqlcommand); _sqlcommand = NULL; break; case '#': break; default: eventlog(eventlog_level_error,__FUNCTION__,"illegal starting symbol at line %i",lineno); } } if (_table) db_layout_add_table(db_layout,_table); if (xstr) xstr_free(xstr); file_get_line(NULL); // clear file_get_line buffer fclose(fp); return 0; } int sql_dbcreator(t_sql_engine * sql) { t_table * table; t_column * column; char _column[1024]; char query[1024]; t_sqlcommand * sqlcmd; load_db_layout(prefs_get_DBlayoutfile()); eventlog(eventlog_level_info, __FUNCTION__,"Creating missing tables and columns (if any)"); for (table = db_layout_get_first_table(db_layout);table;table = db_layout_get_next_table(db_layout)) { column = table_get_first_column(table); sprintf(query,"CREATE TABLE %s (%s default %s)",table->name,column->name,column->value); //create table if missing if (!(sql->query(query))) { eventlog(eventlog_level_info,__FUNCTION__,"added missing table %s to DB",table->name); eventlog(eventlog_level_info,__FUNCTION__,"added missing column %s to table %s",column->name,table->name); } for (;column;column = table_get_next_column(table)) { sprintf(query,"ALTER TABLE %s ADD %s DEFAULT %s",table->name,column->name,column->value); if (!(sql->query(query))) { eventlog(eventlog_level_info,__FUNCTION__,"added missing column %s to table %s",column->name,table->name); if ((column->mode != NULL) && (strcmp(column->mode,"&&") == 0)) { if (!(sql->query(column->extra_cmd))) { eventlog(eventlog_level_info,__FUNCTION__,"sucessfully issued: %s %s",column->mode, column->extra_cmd); } } /* sscanf(column->name,"%s",_column); sprintf(query,"ALTER TABLE %s ALTER %s SET DEFAULT %s",table->name,_column,column->value); // If failed, try alternate language. (From ZSoft for sql_odbc.) if(sql->query(query)) { sprintf(query,"ALTER TABLE %s ADD DEFAULT %s FOR %s",table->name,column->value,_column); sql->query(query); } // ALTER TABLE BNET add default 'false' for auth_admin; */ } else { if ((column->mode != NULL) && (strcmp(column->mode,"||") == 0)) { if (!(sql->query(column->extra_cmd))) { eventlog(eventlog_level_info,__FUNCTION__,"sucessfully issued: %s %s",column->mode, column->extra_cmd); } } } } for (sqlcmd = table_get_first_sql_command(table);sqlcmd;sqlcmd = table_get_next_sql_command(table)) { if (!(sql->query(sqlcmd->sql_command))) { eventlog(eventlog_level_info,__FUNCTION__,"sucessfully issued: %s",sqlcmd->sql_command); if ((sqlcmd->mode != NULL) && (strcmp(sqlcmd->mode,"&&") == 0)) { if (!(sql->query(sqlcmd->extra_cmd))) { eventlog(eventlog_level_info,__FUNCTION__,"sucessfully issued: %s %s",sqlcmd->mode, sqlcmd->extra_cmd); } } } else { if ((sqlcmd->mode != NULL) && (strcmp(sqlcmd->mode,"||") == 0)) { if (!(sql->query(sqlcmd->extra_cmd))) { eventlog(eventlog_level_info,__FUNCTION__,"sucessfully issued: %s %s",sqlcmd->mode, sqlcmd->extra_cmd); } } } } column = table_get_first_column(table); sscanf(column->name,"%s",_column); //get column name without format infos sprintf(query,"INSERT INTO %s (%s) VALUES (%s)",table->name,_column,column->value); if (!(sql->query(query))) { eventlog(eventlog_level_info,__FUNCTION__,"added missing default account to table %s",table->name); } } dispose_db_layout(db_layout); eventlog(eventlog_level_info,__FUNCTION__,"finished adding missing tables and columns"); return 0; } static void sql_escape_command(char *escape, const char *from, int len) { if (from != NULL && len != 0) /* make sure we have a command */ { char * tmp1 = xstrdup(from); /* copy of 'from' */ char * tmp2 = escape; char * tmp3 = NULL; /* begining of string to be escaped */ char * tmp4 = xmalloc(strlen(tmp1) * 2); /* escaped string */ unsigned int i,j; /* eventlog(eventlog_level_trace,__FUNCTION__,"COMMAND: %s",tmp1); */ for (i=0; tmp1[i] && i < len; i++, tmp2++) { *tmp2 = tmp1[i]; /* copy 'from' to 'escape' */ if (tmp1[i] == '\'') /* check if we find a string by checking for a single quote (') */ { tmp3 = &tmp1[++i]; /* set tmp3 to the begining of the string to be escaped */ for(; tmp1[i] && tmp1[i] != '\'' && i < len; i++); /* find the end of the string to be escaped */ tmp1[i] = '\0'; /* set end of string with null terminator */ /* eventlog(eventlog_level_trace,__FUNCTION__,"STRING: %s",tmp3); */ sql->escape_string(tmp4, tmp3, strlen(tmp3)); /* escape the string */ /* eventlog(eventlog_level_trace,__FUNCTION__,"ESCAPE STRING: %s",tmp4); */ for (j=0, tmp2++; tmp4[j]; j++, tmp2++) *tmp2 = tmp4[j]; /* add 'escaped string' to 'escape' */ *tmp2 = '\''; /* add single quote to end after adding 'escaped string' */ } } *tmp2 = '\0'; /* eventlog(eventlog_level_trace,__FUNCTION__,"ESCAPED COMMAND: %s",escape); */ xfree(tmp1); xfree(tmp4); } } #endif /* WITH_SQL */ pvpgn-1.8.5/src/bnetd/ipban.h0000644000175000017500000000474011151345317014774 0ustar aaronaaron/* * Copyright (C) 2000 Gediminas (gugini@fortas.ktu.lt) * Copyright (C) 2002 Bart³omiej Butyn (bartek@milc.com.pl) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_IPBAN_TYPES #define INCLUDED_IPBAN_TYPES #ifdef IPBAN_INTERNAL_ACCESS #define MAX_FUNC_LEN 10 #define MAX_IP_STR 32 #define MAX_TIME_STR 9 #define IPBAN_FUNC_ADD 1 #define IPBAN_FUNC_DEL 2 #define IPBAN_FUNC_LIST 3 #define IPBAN_FUNC_CHECK 4 #define IPBAN_FUNC_HELP 5 #define IPBAN_FUNC_UNKNOWN 6 typedef enum { ipban_type_exact, /* 192.168.0.10 */ ipban_type_wildcard, /* 192.168.*.* */ ipban_type_range, /* 192.168.0.10-192.168.0.25 */ ipban_type_netmask, /* 192.168.0.0/255.255.0.0 */ ipban_type_prefix /* 192.168.0.0/16 */ } t_ipban_type; typedef struct ipban_entry_struct { char * info1; /* third octet */ char * info2; /* third octet */ char * info3; /* third octet */ char * info4; /* fourth octet */ int type; time_t endtime; } t_ipban_entry; #endif #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_IPBAN_PROTOS #define INCLUDED_IPBAN_PROTOS #define JUST_NEED_TYPES #include "connection.h" #undef JUST_NEED_TYPES extern int ipbanlist_create(void); extern int ipbanlist_destroy(void); extern int ipbanlist_load(char const * filename); extern int ipbanlist_save(char const * filename); extern int ipbanlist_check(char const * addr); extern int ipbanlist_add(t_connection * c, char const * cp, time_t endtime); extern int ipbanlist_unload_expired(void); extern time_t ipbanlist_str_to_time_t(t_connection * c, char const * timestr); extern int handle_ipban_command(t_connection * c, char const * text); #endif #endif pvpgn-1.8.5/src/bnetd/handle_bot.h0000644000175000017500000000206711151345317016002 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_HANDLE_BOT_PROTOS #define INCLUDED_HANDLE_BOT_PROTOS #define JUST_NEED_TYPES #include "connection.h" #include "common/packet.h" #undef JUST_NEED_TYPES extern int handle_bot_packet(t_connection * c, t_packet const * const packet); #endif #endif pvpgn-1.8.5/src/bnetd/sql_odbc.h0000644000175000017500000000173411151345317015471 0ustar aaronaaron/* * Copyright (C) 2005 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SQL_ODBC_PROTOS #define INCLUDED_SQL_ODBC_PROTOS #define JUST_NEED_TYPES # include "sql_common.h" #undef JUST_NEED_TYPES extern t_sql_engine sql_odbc; #endif /* INCLUDED_SQL_ODBC_PROTOS */ pvpgn-1.8.5/src/bnetd/clan.h0000644000175000017500000001315611151345317014621 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_CLAN_TYPES #define INCLUDED_CLAN_TYPES #ifdef JUST_NEED_TYPES # include "common/bn_type.h" #else # define JUST_NEED_TYPES # include "common/bn_type.h" # undef JUST_NEED_TYPES #endif #ifdef CLAN_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include # include "common/list.h" #else # define JUST_NEED_TYPES # include # include "common/list.h" # undef JUST_NEED_TYPES #endif #endif typedef struct clan #ifdef CLAN_INTERNAL_ACCESS { unsigned int clanid; int clantag; char const *clanname; time_t creation_time; char const *clan_motd; t_list *members; int created; /* --by Soar on create, set it to -count of invited members, each accept packet will inc it by 1, when it is increased to 0, means that all invited members have accepted, then clan will be created and set this value to 1 */ char modified; char channel_type; /* 0--public 1--private */ } #endif t_clan; typedef struct _clanmember #ifdef CLAN_INTERNAL_ACCESS { void *memberacc; char status; time_t join_time; t_clan * clan; #ifdef WITH_SQL char modified; #endif } #endif t_clanmember; #define CLAN_CHIEFTAIN 0x04 #define CLAN_SHAMAN 0x03 #define CLAN_GRUNT 0x02 #define CLAN_PEON 0x01 #define CLAN_NEW 0x00 #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_CLAN_PROTOS #define INCLUDED_CLAN_PROTOS #define JUST_NEED_TYPES #include "common/list.h" #undef JUST_NEED_TYPES extern t_list *clanlist(void); extern int clanlist_load(void); extern int clanlist_save(void); extern int clanlist_unload(void); extern int clanlist_remove_clan(t_clan * clan); extern int clanlist_add_clan(t_clan * clan); extern t_clan *clanlist_find_clan_by_clanid(int cid); extern t_clan *clanlist_find_clan_by_clantag(int clantag); extern t_account *clanmember_get_account(t_clanmember * member); extern int clanmember_set_account(t_clanmember * member, t_account * memberacc); extern t_connection *clanmember_get_conn(t_clanmember * member); extern char clanmember_get_status(t_clanmember * member); extern int clanmember_set_status(t_clanmember * member, char status); extern time_t clanmember_get_join_time(t_clanmember * member); extern t_clan * clanmember_get_clan(t_clanmember * member); extern int clanmember_set_online(t_connection * c); extern int clanmember_set_offline(t_connection * c); extern const char *clanmember_get_online_status(t_clanmember * member, char *status); extern int clanmember_on_change_status(t_clanmember * member); extern const char *clanmember_get_online_status_by_connection(t_connection * conn, char *status); extern int clanmember_on_change_status_by_connection(t_connection * conn); extern t_clan *clan_create(t_account * chieftain_acc, int clantag, const char *clanname, const char *motd); extern int clan_destroy(t_clan * clan); extern int clan_unload_members(t_clan * clan); extern int clan_remove_all_members(t_clan * clan); extern int clan_save(t_clan * clan); extern int clan_remove(int clantag); extern int clan_get_created(t_clan * clan); extern int clan_set_created(t_clan * clan, int created); extern char clan_get_modified(t_clan * clan); extern int clan_set_modified(t_clan * clan, char modified); extern char clan_get_channel_type(t_clan * clan); extern int clan_set_channel_type(t_clan * clan, char channel_type); extern t_list *clan_get_members(t_clan * clan); extern char const *clan_get_name(t_clan * clan); extern int clan_get_clantag(t_clan * clan); extern char const *clan_get_motd(t_clan * clan); extern int clan_set_motd(t_clan * clan, const char *motd); extern unsigned int clan_get_clanid(t_clan * clan); extern int clan_set_creation_time(t_clan * clan, time_t c_time); extern time_t clan_get_creation_time(t_clan * clan); extern int clan_get_member_count(t_clan * clan); extern t_clanmember *clan_add_member(t_clan * clan, t_account * memberacc, char status); extern int clan_remove_member(t_clan * clan, t_clanmember * member); extern t_clanmember *clan_find_member(t_clan * clan, t_account * memberacc); extern t_clanmember *clan_find_member_by_name(t_clan * clan, char const *membername); extern t_clanmember *clan_find_member_by_uid(t_clan * clan, unsigned int memberuid); extern int clan_send_packet_to_online_members(t_clan * clan, t_packet * packet); extern int clan_get_possible_member(t_connection * c, t_packet const *const packet); extern int clan_send_status_window(t_connection * c); extern int clan_send_status_window_on_create(t_clan * clan); extern int clan_close_status_window(t_connection * c); extern int clan_close_status_window_on_disband(t_clan * clan); extern int clan_send_memberlist(t_connection * c, t_packet const *const packet); extern int clan_change_member_status(t_connection * c, t_packet const *const packet); extern int clan_send_motd_reply(t_connection * c, t_packet const *const packet); extern int clan_save_motd_chg(t_connection * c, t_packet const *const packet); extern int str_to_clantag(const char *str); #endif #endif pvpgn-1.8.5/src/bnetd/mail.h0000644000175000017500000000462711151345317014631 0ustar aaronaaron/* * Copyright (C) 2001 Dizzy * Copyright (C) 2004 Donny Redmond (dredmond@linuxmail.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef INCLUDED_MAIL_TYPES #define INCLUDED_MAIL_TYPES #define MAX_FUNC_LEN 10 #define MAX_MAIL_QUOTA 10 #define MAIL_FUNC_SEND 1 #define MAIL_FUNC_READ 2 #define MAIL_FUNC_DELETE 3 #define MAIL_FUNC_HELP 4 #define MAIL_FUNC_UNKNOWN 5 #ifdef MAIL_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # ifdef TIME_WITH_SYS_TIME # include # include # else # ifdef HAVE_SYS_TIME_H # include # else # include # endif # endif # ifdef HAVE_SYS_TYPES_H # include # endif # include "compat/pdir.h" #else # define JUST_NEED_TYPES # ifdef TIME_WITH_SYS_TIME # include # include # else # ifdef HAVE_SYS_TIME_H # include # else # include # endif # endif # ifdef HAVE_SYS_TYPES_H # include # endif # include "compat/pdir.h" # undef JUST_NEED_TYPES #endif typedef enum { mbox_mode_read = 0x01, mbox_mode_write = 0x02 } t_mbox_mode; typedef struct mailbox_struct { t_pdir * maildir; unsigned int uid; char * path; } t_mailbox; typedef struct mail_struct { char * sender; char * message; time_t timestamp; } t_mail; typedef struct maillist_struct { int idx; char * sender; time_t timestamp; struct maillist_struct * next; } t_maillist; #endif #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_MAIL_PROTOS #define INCLUDED_MAIL_PROTOS #define JUST_NEED_TYPES #include "connection.h" #undef JUST_NEED_TYPES extern int handle_mail_command(t_connection *, char const *); extern char const * check_mail(t_connection const * c); #endif #endif pvpgn-1.8.5/src/bnetd/message.c0000644000175000017500000013204011151345317015315 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2001,2002 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define MESSAGE_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #ifdef HAVE_UNISTD_H # include #endif #include "compat/gethostname.h" #include #include "compat/strerror.h" #include "connection.h" #include "common/bn_type.h" #include "common/queue.h" #include "common/packet.h" #include "common/bot_protocol.h" #include "common/bnet_protocol.h" #include "common/field_sizes.h" #include "common/eventlog.h" #include "common/list.h" #include "common/util.h" #include "common/version.h" #include "common/addr.h" #include "account.h" #include "account_wrap.h" #include "game.h" #include "channel.h" #include "channel_conv.h" #include "command.h" #include "irc.h" #include "message.h" #include "mail.h" #include "prefs.h" #include "common/tag.h" #include "common/xalloc.h" #include "common/setup_after.h" static int message_telnet_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags); static int message_bot_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags); static int message_bnet_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags); static t_packet * message_cache_lookup(t_message * message, t_connection *dst, unsigned int flags); static char const * message_type_get_str(t_message_type type) { switch (type) { case message_type_adduser: return "adduser"; case message_type_join: return "join"; case message_type_part: return "part"; case message_type_whisper: return "whisper"; case message_type_talk: return "talk"; case message_type_broadcast: return "broadcast"; case message_type_channel: return "channel"; case message_type_userflags: return "userflags"; case message_type_whisperack: return "whisperack"; case message_type_friendwhisperack: //[zap-zero] 20020518 return "friendwhisperack"; case message_type_channelfull: return "channelfull"; case message_type_channeldoesnotexist: return "channeldoesnotexist"; case message_type_channelrestricted: return "channelrestricted"; case message_type_info: return "info"; case message_type_error: return "error"; case message_type_emote: return "emote"; case message_type_uniqueid: return "uniqueid"; case message_type_mode: return "mode"; case message_type_notice: return "notice"; case message_type_null: return "null"; default: return "UNKNOWN"; } } /* make sure none of the expanded format symbols is longer than this (with null) */ #define MAX_INC 64 extern char * message_format_line(t_connection const * c, char const * in) { char * out; unsigned int inpos; unsigned int outpos; unsigned int outlen=MAX_INC; unsigned int inlen; char clienttag_str[5]; out = xmalloc(outlen+1); inlen = strlen(in); out[0] = 'I'; for (inpos=0,outpos=1; inpos=outlen) { char * newout; outlen += MAX_INC; newout = xrealloc(out,outlen); out = newout; } } out[outpos] = '\0'; return out; } static int message_telnet_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags) { char * msgtemp; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } switch (type) { case message_type_uniqueid: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } msgtemp = xmalloc(strlen(text)+32); sprintf(msgtemp,"Your unique name: %s\r\n",text); break; case message_type_adduser: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(strlen(tname)+32); sprintf(msgtemp,"[%s is here]\r\n",tname); conn_unget_chatcharname(me,tname); } break; case message_type_join: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(strlen(tname)+32); sprintf(msgtemp,"[%s enters]\r\n",tname); conn_unget_chatcharname(me,tname); } break; case message_type_part: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(strlen(tname)+32); sprintf(msgtemp,"[%s leaves]\r\n",tname); conn_unget_chatcharname(me,tname); } break; case message_type_whisper: case message_type_notice: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ { char const * tname; char const * newtext; if (me) tname = conn_get_chatcharname(me, dst); else tname = prefs_get_servername(); if ((newtext = escape_chars(text,strlen(text)))) { msgtemp = xmalloc(strlen(tname)+8+strlen(newtext)+4); sprintf(msgtemp," %s\r\n",tname,newtext); xfree((void *)newtext); /* avoid warning */ } else { msgtemp = xmalloc(16+strlen(tname)); sprintf(msgtemp," \r\n",tname); } if (me) conn_unget_chatcharname(me,tname); } break; case message_type_talk: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ { char const * tname; char const * newtext; if (me) tname = conn_get_chatcharname(me, dst); else tname = prefs_get_servername(); if ((newtext = escape_chars(text,strlen(text)))) { msgtemp = xmalloc(strlen(tname)+4+strlen(newtext)+4); sprintf(msgtemp,"<%s> %s\r\n",tname,newtext); xfree((void *)newtext); /* avoid warning */ } else { msgtemp = xmalloc(strlen(tname)+8); sprintf(msgtemp,"<%s> \r\n",tname); } if (me) conn_unget_chatcharname(me,tname); } break; case message_type_broadcast: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ { char const * newtext; if ((newtext = escape_chars(text,strlen(text)))) { msgtemp = xmalloc(16+strlen(newtext)+4); sprintf(msgtemp,"Broadcast: %s\r\n",newtext); /* FIXME: show source? */ xfree((void *)newtext); /* avoid warning */ } else { msgtemp = xmalloc(16); sprintf(msgtemp,"Broadcast: \r\n"); /* FIXME: show source? */ } } break; case message_type_channel: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } msgtemp = xmalloc(strlen(text)+32); sprintf(msgtemp,"Joining channel: \"%s\"\r\n",text); break; case message_type_userflags: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } msgtemp = xstrdup(""); break; case message_type_whisperack: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } { char const * tname; char const * newtext; tname = conn_get_chatcharname(me, dst); if ((newtext = escape_chars(text,strlen(text)))) { msgtemp = xmalloc(strlen(tname)+8+strlen(newtext)+4); sprintf(msgtemp," %s\r\n",tname,newtext); xfree((void *)newtext); /* avoid warning */ } else { msgtemp = xmalloc(strlen(tname)+8+strlen(text)+4); sprintf(msgtemp," %s\r\n",tname,text); } conn_unget_chatcharname(me,tname); } break; case message_type_friendwhisperack: // [zap-zero] 20020518 if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } { char const * newtext; if ((newtext = escape_chars(text,strlen(text)))) { msgtemp = xmalloc(14+8+strlen(newtext)+4); sprintf(msgtemp," %s\r\n",newtext); xfree((void *)newtext); /* avoid warning */ } else { msgtemp = xmalloc(14+8+strlen(text)+4); sprintf(msgtemp," %s\r\n",text); } } break; case message_type_channelfull: /* FIXME */ msgtemp = xstrdup(""); break; case message_type_channeldoesnotexist: /* FIXME */ msgtemp = xstrdup(""); break; case message_type_channelrestricted: /* FIXME */ msgtemp = xstrdup(""); break; case message_type_info: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } { char const * newtext; if ((newtext = escape_chars(text,strlen(text)))) { msgtemp = xmalloc(strlen(newtext)+4); sprintf(msgtemp,"%s\r\n",newtext); xfree((void *)newtext); /* avoid warning */ } else { msgtemp = xmalloc(strlen(text)+4); sprintf(msgtemp,"%s\r\n",text); } } break; case message_type_error: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } { char const * newtext; if ((newtext = escape_chars(text,strlen(text)))) { msgtemp = xmalloc(8+strlen(newtext)+4); sprintf(msgtemp,"ERROR: %s\r\n",newtext); xfree((void *)newtext); /* avoid warning */ } else { msgtemp = xmalloc(8+strlen(text)+4); sprintf(msgtemp,"ERROR: %s\r\n",text); } } break; case message_type_emote: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ { char const * tname; char const * newtext; tname = conn_get_chatcharname(me, dst); if ((newtext = escape_chars(text,strlen(text)))) { msgtemp = xmalloc(strlen(tname)+4+strlen(newtext)+4); sprintf(msgtemp,"<%s %s>\r\n",tname,newtext); xfree((void *)newtext); /* avoid warning */ } else { msgtemp = xmalloc(strlen(tname)+4+strlen(text)+4); sprintf(msgtemp,"<%s %s>\r\n",tname,text); } conn_unget_chatcharname(me,tname); } break; case message_type_mode: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } { char const * tname; tname = conn_get_chatcharname(me,dst); msgtemp = xmalloc(strlen(tname)+32); sprintf(msgtemp,"%s change mode: %s\r\n",tname,text); conn_unget_chatcharname(me,tname); } default: eventlog(eventlog_level_error,__FUNCTION__,"got bad message type %d",(int)type); return -1; } { int retval; retval = packet_append_ntstring(packet,msgtemp); xfree(msgtemp); return retval; } } static int message_bot_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags) { char * msgtemp; char clienttag_str[5]; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } /* special-case the login banner so it doesn't have numbers * at the start of each line */ if (me && conn_get_state(me)!=conn_state_loggedin && conn_get_state(me)!=conn_state_destroy && type!=message_type_null) /* this does not apply for NULL messages */ { if (!text) { #if 0 /* battle.net actually sends them during login */ if (type==message_type_null) return 0; /* don't display null messages during the login */ #endif eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for non-loggedin state"); return -1; } msgtemp = xmalloc(strlen(text)+4); sprintf(msgtemp,"%s\r\n",text); } else switch (type) { case message_type_null: msgtemp = xmalloc(32); sprintf(msgtemp,"%u %s\r\n",EID_NULL,"NULL"); break; case message_type_uniqueid: /* FIXME: need to send this for some bots, also needed to support guest accounts */ if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } msgtemp = xmalloc(strlen(text)+32); sprintf(msgtemp,"%u %s %s\r\n",EID_UNIQUENAME,"NAME",text); break; case message_type_adduser: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(32+strlen(tname)+32); sprintf(msgtemp,"%u %s %s %04x [%s]\r\n",EID_SHOWUSER,"USER",tname,conn_get_flags(me)|dstflags,tag_uint_to_str(clienttag_str,conn_get_fake_clienttag(me))); conn_unget_chatcharname(me,tname); } break; case message_type_join: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(32+strlen(tname)+32); sprintf(msgtemp,"%u %s %s %04x [%s]\r\n",EID_JOIN,"JOIN",tname,conn_get_flags(me)|dstflags,tag_uint_to_str(clienttag_str,conn_get_fake_clienttag(me))); conn_unget_chatcharname(me,tname); } break; case message_type_part: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(32+strlen(tname)+32); sprintf(msgtemp,"%u %s %s %04x\r\n",EID_LEAVE,"LEAVE",tname,conn_get_flags(me)|dstflags); conn_unget_chatcharname(me,tname); } break; case message_type_whisper: case message_type_notice: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ { char const * tname; if (me) tname = conn_get_chatcharname(me, dst); else tname = prefs_get_servername(); msgtemp = xmalloc(32+strlen(tname)+32+strlen(text)); sprintf(msgtemp,"%u %s %s %04x \"%s\"\r\n",EID_WHISPER,"WHISPER",tname,me?conn_get_flags(me)|dstflags:dstflags,text); if (me) conn_unget_chatcharname(me,tname); } break; case message_type_talk: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(32+strlen(tname)+32+strlen(text)); sprintf(msgtemp,"%u %s %s %04x \"%s\"\r\n",EID_TALK,"TALK",tname,conn_get_flags(me)|dstflags,text); conn_unget_chatcharname(me,tname); } break; case message_type_broadcast: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ msgtemp = xmalloc(32+32+strlen(text)); sprintf(msgtemp,"%u %s \"%s\"\r\n",EID_BROADCAST,"_",text); /* FIXME: what does this look like on Battle.net? */ break; case message_type_channel: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } msgtemp = xmalloc(32+strlen(text)); sprintf(msgtemp,"%u %s \"%s\"\r\n",EID_CHANNEL,"CHANNEL",text); break; case message_type_userflags: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(32+strlen(tname)+16); sprintf(msgtemp,"%u %s %s %04x\r\n",EID_USERFLAGS,"USER",tname,conn_get_flags(me)|dstflags); conn_unget_chatcharname(me,tname); } break; case message_type_whisperack: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(32+strlen(tname)+32+strlen(text)); sprintf(msgtemp,"%u %s %s %04x \"%s\"\r\n",EID_WHISPERSENT,"WHISPER",tname,conn_get_flags(me)|dstflags,text); conn_unget_chatcharname(me,tname); } break; case message_type_friendwhisperack: // [zap-zero] 20020518 if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } { msgtemp = xmalloc(32+16+32+strlen(text)); sprintf(msgtemp,"%u %s \"your friends\" %04x \"%s\"\r\n",EID_WHISPERSENT,"WHISPER",conn_get_flags(me)|dstflags,text); } break; case message_type_channelfull: msgtemp = xmalloc(32); sprintf(msgtemp,"%u \r\n",EID_CHANNELFULL); /* FIXME */ break; case message_type_channeldoesnotexist: msgtemp = xmalloc(32); sprintf(msgtemp,"%u \r\n",EID_CHANNELDOESNOTEXIST); /* FIXME */ break; case message_type_channelrestricted: msgtemp = xmalloc(32); sprintf(msgtemp,"%u \r\n",EID_CHANNELRESTRICTED); /* FIXME */ break; case message_type_info: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } msgtemp = xmalloc(32+16+strlen(text)); sprintf(msgtemp,"%u %s \"%s\"\r\n",EID_INFO,"INFO",text); break; case message_type_error: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } msgtemp = xmalloc(32+16+strlen(text)); sprintf(msgtemp,"%u %s \"%s\"\r\n",EID_ERROR,"ERROR",text); break; case message_type_emote: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ { char const * tname; tname = conn_get_chatcharname(me, dst); msgtemp = xmalloc(32+strlen(tname)+32+strlen(text)); sprintf(msgtemp,"%u %s %s %04x \"%s\"\r\n",EID_EMOTE,"EMOTE",tname,conn_get_flags(me)|dstflags,text); conn_unget_chatcharname(me,tname); } break; default: eventlog(eventlog_level_error,__FUNCTION__,"got bad message type %d",(int)type); return -1; } if (strlen(msgtemp)>MAX_MESSAGE_LEN) msgtemp[MAX_MESSAGE_LEN] = '\0'; /* now truncate to max size */ { int retval; retval = packet_append_ntstring(packet,msgtemp); xfree(msgtemp); return retval; } } static int message_bnet_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (text && text[0]=='\0') text = " "; /* empty messages crash some clients, just send whitespace */ packet_set_size(packet,sizeof(t_server_message)); packet_set_type(packet,SERVER_MESSAGE); bn_int_set(&packet->u.server_message.player_ip,SERVER_MESSAGE_PLAYER_IP_DUMMY); bn_int_nset(&packet->u.server_message.account_num,SERVER_MESSAGE_ACCOUNT_NUM); bn_int_set(&packet->u.server_message.reg_auth,SERVER_MESSAGE_REG_AUTH); switch (type) { case message_type_adduser: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_ADDUSER); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; char const * playerinfo; tname = conn_get_chatcharname(me, dst); packet_append_string(packet,tname); conn_unget_chatcharname(me,tname); if ((conn_get_clienttag(me) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(me) == CLIENTTAG_WAR3XP_UINT)) playerinfo = conn_get_w3_playerinfo(me); else playerinfo = conn_get_playerinfo(me); if (playerinfo == NULL) { playerinfo = ""; } packet_append_string(packet,playerinfo); } break; case message_type_join: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_JOIN); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; char const * playerinfo; tname = conn_get_chatcharname(me, dst); packet_append_string(packet,tname); conn_unget_chatcharname(me,tname); if ((conn_get_clienttag(me) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(me) == CLIENTTAG_WAR3XP_UINT)) playerinfo = conn_get_w3_playerinfo(me); else playerinfo = conn_get_playerinfo(me); if (playerinfo == NULL) { playerinfo = ""; } packet_append_string(packet, playerinfo); } break; case message_type_part: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_PART); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; tname = conn_get_chatcharname(me, dst); packet_append_string(packet,tname); conn_unget_chatcharname(me,tname); packet_append_string(packet,""); } break; case message_type_whisper: case message_type_notice: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_WHISPER); bn_int_set(&packet->u.server_message.flags,me?conn_get_flags(me)|dstflags:dstflags); bn_int_set(&packet->u.server_message.latency,me?conn_get_latency(me):0); if (me) { char const * tname; tname = conn_get_chatcharname(me, dst); packet_append_string(packet,tname); conn_unget_chatcharname(me,tname); } else packet_append_string(packet,prefs_get_servername()); packet_append_string(packet,text); break; case message_type_talk: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_TALK); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; tname = conn_get_chatcharname(me, dst); packet_append_string(packet,tname); conn_unget_chatcharname(me,tname); packet_append_string(packet,text); } break; case message_type_broadcast: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_BROADCAST); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; tname = conn_get_chatcharname(me, dst); packet_append_string(packet,tname); conn_unget_chatcharname(me,tname); packet_append_string(packet,text); } break; case message_type_channel: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_CHANNEL); { t_channel const * channel; if (!(channel = conn_get_channel(me))) bn_int_set(&packet->u.server_message.flags,0); else bn_int_set(&packet->u.server_message.flags,cflags_to_bncflags(channel_get_flags(channel))); } bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; tname = conn_get_chatname(me); packet_append_string(packet,tname); conn_unget_chatname(me,tname); packet_append_string(packet,text); } break; case message_type_userflags: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_USERFLAGS); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; char const * playerinfo; tname = conn_get_chatcharname(me, dst); packet_append_string(packet,tname); conn_unget_chatcharname(me,tname); if ((conn_get_clienttag(me) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(me) == CLIENTTAG_WAR3XP_UINT)) playerinfo = conn_get_w3_playerinfo(me); else playerinfo = conn_get_playerinfo(me); if (playerinfo == NULL) { playerinfo = ""; } packet_append_string(packet, playerinfo); } break; case message_type_whisperack: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_WHISPERACK); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; tname = conn_get_chatcharname(me, dst); packet_append_string(packet,tname); conn_unget_chatcharname(me,tname); packet_append_string(packet,text); } break; case message_type_friendwhisperack: // [zap-zero] 20020518 if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_WHISPERACK); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { packet_append_string(packet,"your friends"); packet_append_string(packet,text); } break; case message_type_channelfull: /* FIXME */ bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_CHANNELFULL); bn_int_set(&packet->u.server_message.flags,0); bn_int_set(&packet->u.server_message.latency,0); packet_append_string(packet,""); packet_append_string(packet,""); break; case message_type_channeldoesnotexist: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_CHANNELDOESNOTEXIST); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; tname = conn_get_chatname(me); packet_append_string(packet,tname); conn_unget_chatname(me,tname); packet_append_string(packet,text); } break; case message_type_channelrestricted: /* FIXME */ bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_CHANNELRESTRICTED); bn_int_set(&packet->u.server_message.flags,0); bn_int_set(&packet->u.server_message.latency,0); packet_append_string(packet,""); packet_append_string(packet,""); break; case message_type_info: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_INFO); bn_int_set(&packet->u.server_message.flags,0); bn_int_set(&packet->u.server_message.latency,0); packet_append_string(packet,""); packet_append_string(packet,text); break; case message_type_error: if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_ERROR); bn_int_set(&packet->u.server_message.flags,0); bn_int_set(&packet->u.server_message.latency,0); packet_append_string(packet,""); packet_append_string(packet,text); break; case message_type_emote: if (!me) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type)); return -1; } if (!text) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type)); return -1; } if (dstflags&MF_X) return -1; /* player is ignored */ bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_EMOTE); bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags); bn_int_set(&packet->u.server_message.latency,conn_get_latency(me)); { char const * tname; tname = conn_get_chatcharname(me, dst); packet_append_string(packet,tname); conn_unget_chatcharname(me,tname); packet_append_string(packet,text); } break; default: eventlog(eventlog_level_error,__FUNCTION__,"got bad message type %d",(int)type); return -1; } return 0; } extern t_message * message_create(t_message_type type, t_connection * src, t_connection * dst, char const * text) { t_message * message; message = xmalloc(sizeof(t_message)); message->num_cached = 0; message->packets = NULL; message->classes = NULL; message->dstflags = NULL; message->mclasses = NULL; message->type = type; message->src = src; message->dst = dst; message->text = text; return message; } extern int message_destroy(t_message * message) { unsigned int i; if (!message) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL message"); return -1; } for (i=0; inum_cached; i++) if (message->packets[i]) packet_del_ref(message->packets[i]); if (message->packets) xfree(message->packets); if (message->classes) xfree(message->classes); if (message->dstflags) xfree(message->dstflags); if (message->mclasses) xfree(message->mclasses); xfree(message); return 0; } static t_packet * message_cache_lookup(t_message * message, t_connection *dst, unsigned int dstflags) { unsigned int i; t_packet * packet; t_message_class mclass; t_conn_class class; if (!message) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL message"); return NULL; } class = conn_get_class(dst); mclass = conn_get_message_class(message->src, dst); for (i=0; inum_cached; i++) if (message->classes[i]==class && message->dstflags[i]==dstflags && message->mclasses[i]==mclass) return message->packets[i]; { t_packet * * temp_packets; t_conn_class * temp_classes; unsigned int * temp_dstflags; t_message_class *temp_mclasses; if (!message->packets) temp_packets = xmalloc(sizeof(t_packet *)*(message->num_cached+1)); else temp_packets = xrealloc(message->packets,sizeof(t_packet *)*(message->num_cached+1)); if (!message->classes) temp_classes = xmalloc(sizeof(t_conn_class)*(message->num_cached+1)); else temp_classes = xrealloc(message->classes,sizeof(t_conn_class)*(message->num_cached+1)); if (!message->dstflags) temp_dstflags = xmalloc(sizeof(unsigned int)*(message->num_cached+1)); else temp_dstflags = xrealloc(message->dstflags,sizeof(unsigned int)*(message->num_cached+1)); if (!message->mclasses) temp_mclasses = xmalloc(sizeof(t_message_class)*(message->num_cached+1)); else temp_mclasses = xrealloc(message->mclasses,sizeof(t_message_class)*(message->num_cached+1)); message->packets = temp_packets; message->classes = temp_classes; message->dstflags = temp_dstflags; message->mclasses = temp_mclasses; } switch (class) { case conn_class_telnet: if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return NULL; } if (message_telnet_format(packet,message->type,message->src,message->dst,message->text,dstflags)<0) { packet_del_ref(packet); packet = NULL; /* we can cache the NULL too */ } break; case conn_class_bot: if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return NULL; } if (message_bot_format(packet,message->type,message->src,message->dst,message->text,dstflags)<0) { packet_del_ref(packet); packet = NULL; /* we can cache the NULL too */ } break; case conn_class_bnet: if (!(packet = packet_create(packet_class_bnet))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return NULL; } if (message_bnet_format(packet,message->type,message->src,dst,message->text,dstflags)<0) { packet_del_ref(packet); packet = NULL; /* we can cache the NULL too */ } break; case conn_class_irc: case conn_class_wol: if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return NULL; } /* irc_message_format() is in irc.c */ if (irc_message_format(packet,message->type,message->src,message->dst,message->text,dstflags)<0) { packet_del_ref(packet); packet = NULL; /* we can cache the NULL too */ } break; case conn_class_init: case conn_class_file: case conn_class_d2cs_bnetd: case conn_class_w3route: packet = NULL; break; /* cache the NULL but dont send any error, * this are normal connections */ default: eventlog(eventlog_level_error,__FUNCTION__,"unsupported connection class %d",(int)class); packet = NULL; /* we can cache the NULL too */ } message->num_cached++; message->packets[i] = packet; message->classes[i] = class; message->dstflags[i] = dstflags; message->mclasses[i] = mclass; return packet; } extern int message_send(t_message * message, t_connection * dst) { t_packet * packet; unsigned int dstflags; if (!message) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL message"); return -1; } if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst connection"); return -1; } dstflags = 0; if (message->src) { char const * tname; if ((tname = conn_get_chatname(message->src)) && conn_check_ignoring(dst,tname)==1) { conn_unget_chatname(message->src,tname); dstflags |= MF_X; } if (tname) conn_unget_chatname(message->src,tname); } if (!(packet = message_cache_lookup(message,dst,dstflags))) return -1; /* FIXME: this is not needed now, message has dst */ if ((conn_get_class(dst)==conn_class_irc)||(conn_get_class(dst)==conn_class_wol)) { /* HACK: IRC message always need the recipient and are therefore bad to cache. */ /* So we only cache a pseudo packet and convert it to a real packet later ... */ packet = packet_duplicate(packet); /* we want to modify packet so we have to create a copy ... */ if (irc_message_postformat(packet,dst)<0) { packet_del_ref(packet); /* we don't need the previously created copy anymore ... */ return -1; } } conn_push_outqueue(dst,packet); if ((conn_get_class(dst)==conn_class_irc)||(conn_get_class(dst)==conn_class_wol)) packet_del_ref(packet); /* we don't need the previously created copy anymore ... */ return 0; } extern int message_send_all(t_message * message) { t_connection * c; t_elem const * curr; int rez; if (!message) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL message"); return -1; } rez = -1; LIST_TRAVERSE_CONST(connlist(),curr) { c = elem_get_data(curr); if (message_send(message,c)==0) rez = 0; } return rez; } extern int message_send_text(t_connection * dst, t_message_type type, t_connection * src, char const * text) { t_message * message; int rez; if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!(message = message_create(type,src,dst,text))) return -1; rez = message_send(message,dst); message_destroy(message); return rez; } extern int message_send_admins(t_connection * src, t_message_type type, char const * text) { t_elem const * curr; t_connection * tc; int counter = 0; LIST_TRAVERSE_CONST(connlist(),curr) { tc = elem_get_data(curr); if (!tc) continue; if (account_get_auth_admin(conn_get_account(tc),NULL)==1 && tc != src) { message_send_text(tc,type,src,text); counter++; } } return counter; } extern int message_send_formatted(t_connection * dst, char const * text) { char * line; if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!(line = message_format_line(dst,text))) { eventlog(eventlog_level_error,__FUNCTION__,"could not format input text \"%s\"",text); return -1; } /* caller beware: empty messages can crash Blizzard clients */ switch (line[0]) { case 'C': if (line[1]=='/') handle_command(dst,&line[1]); else if (conn_get_channel(dst) && !conn_quota_exceeded(dst,&line[1])) channel_message_send(conn_get_channel(dst),message_type_talk,dst,&line[1]); break; case 'B': message_send_text(dst,message_type_broadcast,dst,&line[1]); break; case 'E': message_send_text(dst,message_type_error,dst,&line[1]); break; case 'M': message_send_text(dst,message_type_talk,dst,&line[1]); break; case 'T': message_send_text(dst,message_type_emote,dst,&line[1]); break; case 'I': case 'W': message_send_text(dst,message_type_info,dst,&line[1]); break; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown message type '%c'",line[0]); xfree(line); return -1; } xfree(line); return 0; } extern int message_send_file(t_connection * dst, FILE * fd) { char * buff; if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!fd) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL fd"); return -1; } while ((buff = file_get_line(fd))) { message_send_formatted(dst,buff); } file_get_line(NULL); // clear file_get_line buffer return 0; } pvpgn-1.8.5/src/bnetd/attrlayer.h0000644000175000017500000000300611151345317015704 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __ATTRLAYER_H_INCLUDED__ #define __ATTRLAYER_H_INCLUDED__ #include "common/elist.h" #include "attrgroup.h" /* flags controlling flush/save operations */ #define FS_NONE 0 #define FS_FORCE 1 /* force save/flush no matter of time */ #define FS_ALL 2 /* save/flush all, not in steps */ extern int attrlayer_init(void); extern int attrlayer_cleanup(void); extern int attrlayer_load_default(void); extern int attrlayer_save(int flags); extern int attrlayer_flush(int flags); extern t_attrgroup * attrlayer_get_defattrgroup(void); extern void attrlayer_add_loadedlist(t_elist *what); extern void attrlayer_del_loadedlist(t_elist *what); extern void attrlayer_add_dirtylist(t_elist *what); extern void attrlayer_del_dirtylist(t_elist *what); #endif /* __ATTRLAYER_H_INCLUDED__ */ pvpgn-1.8.5/src/bnetd/ladder_binary.c0000644000175000017500000001406611151345317016477 0ustar aaronaaron/* * Copyright (C) 2003 Aaron * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define BINARY_LADDER_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "errno.h" #include "compat/strerror.h" #include "account.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "ladder_binary.h" #include "ladder.h" #include "prefs.h" #include "common/setup_after.h" static void dispose_filename(const char * filename) { if (filename) xfree((void*)filename); } static const char * binary_ladder_type_to_filename(t_binary_ladder_types type) { switch (type) { case WAR3_SOLO: return "WAR3_SOLO"; case WAR3_TEAM: return "WAR3_TEAM"; case WAR3_FFA : return "WAR3_FFA"; case WAR3_AT : return "WAR3_AT"; case W3XP_SOLO: return "W3XP_SOLO"; case W3XP_TEAM: return "W3XP_TEAM"; case W3XP_FFA : return "W3XP_FFA"; case W3XP_AT : return "W3XP_AT"; case STAR_AR : return "STAR_AR"; case STAR_AW : return "STAR_AW"; case STAR_AG : return "STAR_AG"; case STAR_CR : return "STAR_CR"; case STAR_CW : return "STAR_CW"; case STAR_CG : return "STAR_CG"; case SEXP_AR : return "SEXP_AR"; case SEXP_AW : return "SEXP_AW"; case SEXP_AG : return "SEXP_AG"; case SEXP_CR : return "SEXP_CR"; case SEXP_CW : return "SEXP_CW"; case SEXP_CG : return "SEXP_CG"; case W2BN_AR : return "W2BN_AR"; case W2BN_AW : return "W2BN_AW"; case W2BN_AG : return "W2BN_AG"; case W2BN_CR : return "W2BN_CR"; case W2BN_CW : return "W2BN_CW"; case W2BN_CG : return "W2BN_CG"; case W2BN_ARI : return "W2BN_ARI"; case W2BN_AWI : return "W2BN_AWI"; case W2BN_AGI : return "W2BN_AGI"; case W2BN_CRI : return "W2BN_CRI"; case W2BN_CWI : return "W2BN_CWI"; case W2BN_CGI : return "W2BN_CGI"; default: eventlog(eventlog_level_error,__FUNCTION__,"got invalid binary ladder type"); return NULL; } } extern int binary_ladder_save(t_binary_ladder_types type, unsigned int paracount, t_cb_get_from_ladder _cb_get_from_ladder) { int results[10]; int rank = 1; const char * ladder_name; const char * filename; int checksum, count; FILE * fp; if ((!(ladder_name = binary_ladder_type_to_filename(type))) || (!(filename = create_filename(prefs_get_ladderdir(),ladder_name,"_LADDER")))) { eventlog(eventlog_level_error,__FUNCTION__,"NULL filename - aborting"); return -1; } if (!(fp = fopen(filename,"wb"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for writing (fopen: %s)",filename,pstrerror(errno)); dispose_filename(filename); return -1; } results[0] = magick; fwrite(results,sizeof(int),1,fp); //write the magick int as header checksum = 0; while ((*_cb_get_from_ladder)(type,rank,results)!=-1) { fwrite(results,sizeof(int),paracount,fp); for (count=0;count #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/strtoul.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_MKTIME # ifdef TIME_WITH_SYS_TIME # include # include # else # ifdef HAVE_SYS_TIME_H # include # else # include # endif # endif #endif #ifdef HAVE_ASSERT_H # include #endif #include "compat/strchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include #include #include "compat/strerror.h" #include "common/eventlog.h" #include "common/list.h" #include "common/util.h" #include "common/proginfo.h" #include "common/token.h" #include "common/field_sizes.h" #include "prefs.h" #include "versioncheck.h" #include "common/tag.h" #include "common/xalloc.h" #include "common/setup_after.h" static t_list * versioninfo_head=NULL; static t_versioncheck dummyvc={ "A=42 B=42 C=42 4 A=A^S B=B^B C=C^C A=A^S", "IX86ver1.mpq", "NoVC" }; static int versioncheck_compare_exeinfo(t_parsed_exeinfo * pattern, t_parsed_exeinfo * match); extern t_versioncheck * versioncheck_create(t_tag archtag, t_tag clienttag) { t_elem const * curr; t_versioninfo * vi; t_versioncheck * vc; char archtag_str[5]; char clienttag_str[5]; LIST_TRAVERSE_CONST(versioninfo_head,curr) { if (!(vi = elem_get_data(curr))) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"version list contains NULL item"); continue; } eventlog(eventlog_level_debug,__FUNCTION__,"version check entry archtag=%s, clienttag=%s", tag_uint_to_str(archtag_str,vi->archtag), tag_uint_to_str(clienttag_str,vi->clienttag)); if (vi->archtag != archtag) continue; if (vi->clienttag != clienttag) continue; /* FIXME: randomize the selection if more than one match */ vc = xmalloc(sizeof(t_versioncheck)); vc->eqn = xstrdup(vi->eqn); vc->mpqfile = xstrdup(vi->mpqfile); vc->versiontag = xstrdup(tag_uint_to_str(clienttag_str,clienttag)); return vc; } /* * No entries in the file that match, return the dummy because we have to send * some equation and auth mpq to the client. The client is not going to pass the * validation later unless skip_versioncheck or allow_unknown_version is enabled. */ return &dummyvc; } extern int versioncheck_destroy(t_versioncheck * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return -1; } if (vc==&dummyvc) return 0; xfree((void *)vc->versiontag); xfree((void *)vc->mpqfile); xfree((void *)vc->eqn); xfree(vc); return 0; } extern int versioncheck_set_versiontag(t_versioncheck * vc, char const * versiontag) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return -1; } if (!versiontag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL versiontag"); return -1; } if (vc->versiontag!=NULL) xfree((void *)vc->versiontag); vc->versiontag = xstrdup(versiontag); return 0; } extern char const * versioncheck_get_versiontag(t_versioncheck const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return NULL; } return vc->versiontag; } extern char const * versioncheck_get_mpqfile(t_versioncheck const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return NULL; } return vc->mpqfile; } extern char const * versioncheck_get_eqn(t_versioncheck const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return NULL; } return vc->eqn; } t_parsed_exeinfo * parse_exeinfo(char const * exeinfo) { t_parsed_exeinfo * parsed_exeinfo; if (!exeinfo) { return NULL; } parsed_exeinfo = xmalloc(sizeof(t_parsed_exeinfo)); parsed_exeinfo->exe = xstrdup(exeinfo); parsed_exeinfo->time = 0; parsed_exeinfo->size = 0; if (strcmp(prefs_get_version_exeinfo_match(),"parse")==0) { #ifdef HAVE_MKTIME struct tm t1; char *exe; char mask[MAX_EXEINFO_STR+1]; char * marker; int size; char time_invalid = 0; if ((exeinfo[0]=='\0') || //happens when using war3-noCD and having deleted war3.org (strcmp(exeinfo,"badexe")==0)) //happens when AUTHREQ had no owner/exeinfo entry { xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); eventlog(eventlog_level_error,__FUNCTION__,"found empty exeinfo"); return NULL; } memset(&t1,0,sizeof(t1)); t1.tm_isdst = -1; exeinfo = strreverse((char *)exeinfo); if (!(marker = strchr(exeinfo,' '))) { xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); return NULL; } for (; marker[0]==' ';marker++); if (!(marker = strchr(marker,' '))) { xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); return NULL; } for (; marker[0]==' ';marker++); if (!(marker = strchr(marker,' '))) { xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); return NULL; } for (; marker[0]==' ';marker++); marker--; marker[0] = '\0'; marker++; exe = xstrdup(marker); xfree((void *)parsed_exeinfo->exe); parsed_exeinfo->exe = strreverse((char *)exe); exeinfo = strreverse((char *)exeinfo); sprintf(mask,"%%02u/%%02u/%%u %%02u:%%02u:%%02u %%u"); if (sscanf(exeinfo,mask,&t1.tm_mon,&t1.tm_mday,&t1.tm_year,&t1.tm_hour,&t1.tm_min,&t1.tm_sec,&size)!=7) { if (sscanf(exeinfo,"%*s %*s %u",&size) != 1) { eventlog(eventlog_level_warn,__FUNCTION__,"parser error while parsing pattern \"%s\"",exeinfo); xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); return NULL; /* neq */ } time_invalid=1; } /* Now we have a Y2K problem :) Thanks for using a 2 digit decimal years, Blizzard. */ /* 00-79 -> 2000-2079 * * 80-99 -> 1980-1999 * * 100+ unchanged */ if (t1.tm_year<80) t1.tm_year = t1.tm_year + 100; if (time_invalid) parsed_exeinfo->time = -1; else parsed_exeinfo->time = mktime(&t1); parsed_exeinfo->size = size; #else eventlog(eventlog_level_error,__FUNCTION__,"Your system does not support mktime(). Please select another exeinfo matching method."); return NULL; #endif } return parsed_exeinfo; } #define safe_toupper(X) (islower((int)X)?toupper((int)X):(X)) /* This implements some dumb kind of pattern matching. Any '?' * signs in the pattern are treated as "don't care" signs. This * means that it doesn't matter what's on this place in the match. */ //static int versioncheck_compare_exeinfo(char const * pattern, char const * match) static int versioncheck_compare_exeinfo(t_parsed_exeinfo * pattern, t_parsed_exeinfo * match) { assert(pattern); assert(match); if (!strcasecmp(prefs_get_version_exeinfo_match(),"none")) return 0; /* ignore exeinfo */ if (strlen(pattern->exe)!=strlen(match->exe)) return 1; /* neq */ if (strcmp(prefs_get_version_exeinfo_match(),"exact")==0) { return strcasecmp(pattern->exe,match->exe); } else if (strcmp(prefs_get_version_exeinfo_match(),"exactcase")==0) { return strcmp(pattern->exe,match->exe); } else if (strcmp(prefs_get_version_exeinfo_match(),"wildcard")==0) { unsigned int i; for (i=0;iexe);i++) if ((pattern->exe[i]!='?')&& /* out "don't care" sign */ (safe_toupper(pattern->exe[i])!=safe_toupper(match->exe[i]))) return 1; /* neq */ return 0; /* ok */ } else if (strcmp(prefs_get_version_exeinfo_match(),"parse")==0) { if (strcasecmp(pattern->exe,match->exe)!=0) { eventlog(eventlog_level_trace,__FUNCTION__,"filename differs"); return 1; /* neq */ } if (pattern->size!=match->size) { eventlog(eventlog_level_trace,__FUNCTION__,"size differs"); return 1; /* neq */ } if ((pattern->time!=-1) && prefs_get_version_exeinfo_maxdiff() && (abs(pattern->time-match->time)>(signed)prefs_get_version_exeinfo_maxdiff())) { eventlog(eventlog_level_trace,__FUNCTION__,"time differs by %i",abs(pattern->time-match->time)); return 1; } return 0; /* ok */ } else { eventlog(eventlog_level_error,__FUNCTION__,"unknown version exeinfo match method \"%s\"",prefs_get_version_exeinfo_match()); return -1; /* neq/fail */ } } void free_parsed_exeinfo(t_parsed_exeinfo * parsed_exeinfo) { if (parsed_exeinfo) { if (parsed_exeinfo->exe) xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); } } extern int versioncheck_validate(t_versioncheck * vc, t_tag archtag, t_tag clienttag, char const * exeinfo, unsigned long versionid, unsigned long gameversion, unsigned long checksum) { t_elem const * curr; t_versioninfo * vi; int badexe,badcs; t_parsed_exeinfo * parsed_exeinfo; if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return -1; } badexe=badcs = 0; parsed_exeinfo = parse_exeinfo(exeinfo); LIST_TRAVERSE_CONST(versioninfo_head,curr) { if (!(vi = elem_get_data(curr))) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"version list contains NULL item"); continue; } if (vi->archtag != archtag) continue; if (vi->clienttag != clienttag) continue; if (strcmp(vi->eqn,vc->eqn)!=0) continue; if (strcmp(vi->mpqfile,vc->mpqfile)!=0) continue; if (vi->versionid && vi->versionid != versionid) continue; if (vi->gameversion && vi->gameversion != gameversion) continue; if ((!(parsed_exeinfo)) || (vi->parsed_exeinfo && (versioncheck_compare_exeinfo(vi->parsed_exeinfo,parsed_exeinfo) != 0))) { /* * Found an entry matching but the exeinfo doesn't match. * We need to rember this because if no other matching versions are found * we will return badversion. */ badexe = 1; } else badexe = 0; if (vi->checksum && vi->checksum != checksum) { /* * Found an entry matching but the checksum doesn't match. * We need to rember this because if no other matching versions are found * we will return badversion. */ badcs = 1; } else badcs = 0; if (vc->versiontag) xfree((void *)vc->versiontag); vc->versiontag = xstrdup(vi->versiontag); if (badexe || badcs) continue; /* Ok, version and checksum matches or exeinfo/checksum are disabled * anyway we have found a complete match */ eventlog(eventlog_level_info,__FUNCTION__,"got a matching entry: %s",vc->versiontag); free_parsed_exeinfo(parsed_exeinfo); return 1; } if (badcs) /* A match was found but the checksum was different */ { eventlog(eventlog_level_info,__FUNCTION__,"bad checksum, closest match is: %s",vc->versiontag); free_parsed_exeinfo(parsed_exeinfo); return -1; } if (badexe) /* A match was found but the exeinfo string was different */ { eventlog(eventlog_level_info,__FUNCTION__,"bad exeinfo, closest match is: %s",vc->versiontag); free_parsed_exeinfo(parsed_exeinfo); return -1; } /* No match in list */ eventlog(eventlog_level_info,__FUNCTION__,"no match in list, setting to: %s",vc->versiontag); free_parsed_exeinfo(parsed_exeinfo); return 0; } extern int versioncheck_load(char const * filename) { FILE * fp; unsigned int line; unsigned int pos; char * buff; char * temp; char const * eqn; char const * mpqfile; char const * archtag; char const * clienttag; char const * exeinfo; char const * versionid; char const * gameversion; char const * checksum; char const * versiontag; t_versioninfo * vi; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(versioninfo_head = list_create())) { eventlog(eventlog_level_error,__FUNCTION__,"could create list"); return -1; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); list_destroy(versioninfo_head); versioninfo_head = NULL; return -1; } line = 1; for (; (buff = file_get_line(fp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if ((temp = strrchr(buff,'#'))) { unsigned int len; unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } if (!(eqn = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing eqn near line %u of file \"%s\"",line,filename); continue; } line++; if (!(mpqfile = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing mpqfile near line %u of file \"%s\"",line,filename); continue; } line++; if (!(archtag = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing archtag near line %u of file \"%s\"",line,filename); continue; } line++; if (!(clienttag = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing clienttag near line %u of file \"%s\"",line,filename); continue; } line++; if (!(exeinfo = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing exeinfo near line %u of file \"%s\"",line,filename); continue; } line++; if (!(versionid = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing versionid near line %u of file \"%s\"",line,filename); continue; } line++; if (!(gameversion = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing gameversion near line %u of file \"%s\"",line,filename); continue; } line++; if (!(checksum = next_token(buff,&pos))) { eventlog(eventlog_level_error,__FUNCTION__,"missing checksum near line %u of file \"%s\"",line,filename); continue; } line++; if (!(versiontag = next_token(buff,&pos))) { versiontag = NULL; } vi = xmalloc(sizeof(t_versioninfo)); vi->eqn = xstrdup(eqn); vi->mpqfile = xstrdup(mpqfile); if (strlen(archtag)!=4) { eventlog(eventlog_level_error,__FUNCTION__,"invalid arch tag on line %u of file \"%s\"",line,filename); xfree((void *)vi->mpqfile); /* avoid warning */ xfree((void *)vi->eqn); /* avoid warning */ xfree(vi); continue; } if (!tag_check_arch((vi->archtag = tag_str_to_uint(archtag)))) { eventlog(eventlog_level_error,__FUNCTION__,"got unknown archtag \"%s\"",archtag); xfree((void *)vi->mpqfile); /* avoid warning */ xfree((void *)vi->eqn); /* avoid warning */ xfree(vi); continue; } if (strlen(clienttag)!=4) { eventlog(eventlog_level_error,__FUNCTION__,"invalid client tag on line %u of file \"%s\"",line,filename); xfree((void *)vi->mpqfile); /* avoid warning */ xfree((void *)vi->eqn); /* avoid warning */ xfree(vi); continue; } if (!tag_check_client((vi->clienttag = tag_str_to_uint(clienttag)))) { eventlog(eventlog_level_error,__FUNCTION__,"got unknown clienttag\"%s\"",clienttag); xfree((void *)vi->mpqfile); /* avoid warning */ xfree((void *)vi->eqn); /* avoid warning */ xfree(vi); continue; } if (strcmp(exeinfo, "NULL") == 0) vi->parsed_exeinfo = NULL; else { if (!(vi->parsed_exeinfo = parse_exeinfo(exeinfo))) { eventlog(eventlog_level_error,__FUNCTION__,"encountered an error while parsing exeinfo"); xfree((void *)vi->mpqfile); /* avoid warning */ xfree((void *)vi->eqn); /* avoid warning */ xfree(vi); continue; } } vi->versionid = strtoul(versionid,NULL,0); if (verstr_to_vernum(gameversion,&vi->gameversion)<0) { eventlog(eventlog_level_error,__FUNCTION__,"malformed version on line %u of file \"%s\"",line,filename); xfree((void *)vi->parsed_exeinfo); /* avoid warning */ xfree((void *)vi->mpqfile); /* avoid warning */ xfree((void *)vi->eqn); /* avoid warning */ xfree(vi); continue; } vi->checksum = strtoul(checksum,NULL,0); if (versiontag) vi->versiontag = xstrdup(versiontag); else vi->versiontag = NULL; list_append_data(versioninfo_head,vi); } file_get_line(NULL); // clear file_get_line buffer if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close versioncheck file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno)); return 0; } extern int versioncheck_unload(void) { t_elem * curr; t_versioninfo * vi; if (versioninfo_head) { LIST_TRAVERSE(versioninfo_head,curr) { if (!(vi = elem_get_data(curr))) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"version list contains NULL item"); continue; } if (list_remove_elem(versioninfo_head,&curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); if (vi->parsed_exeinfo) { if (vi->parsed_exeinfo->exe) xfree((void *)vi->parsed_exeinfo->exe); xfree((void *)vi->parsed_exeinfo); /* avoid warning */ } xfree((void *)vi->mpqfile); /* avoid warning */ xfree((void *)vi->eqn); /* avoid warning */ if (vi->versiontag) xfree((void *)vi->versiontag); /* avoid warning */ xfree(vi); } if (list_destroy(versioninfo_head)<0) return -1; versioninfo_head = NULL; } return 0; } pvpgn-1.8.5/src/bnetd/sql_mysql.h0000644000175000017500000000171411151345317015725 0ustar aaronaaron/* * Copyright (C) 2002,2003 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SQL_MYSQL_PROTOS #define INCLUDED_SQL_MYSQL_PROTOS #define JUST_NEED_TYPES # include "sql_common.h" #undef JUST_NEED_TYPES extern t_sql_engine sql_mysql; #endif /* INCLUDED_SQL_MYSQL_PROTOS */ pvpgn-1.8.5/src/bnetd/attr.h0000644000175000017500000000377311151345317014662 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __ATTR_INCLUDED__ #define __ATTR_INCLUDED__ #include "common/elist.h" typedef struct attr_struct { const char *key; const char *val; int dirty; t_hlist link; } t_attr; #include "common/xalloc.h" static inline t_attr *attr_create(const char *key, const char *val) { t_attr *attr; attr = xmalloc(sizeof(t_attr)); attr->dirty = 0; hlist_init(&attr->link); attr->key = key ? xstrdup(key) : NULL; attr->val = val ? xstrdup(val) : NULL; return attr; } static inline int attr_destroy(t_attr *attr) { if (attr->key) xfree((void*)attr->key); if (attr->val) xfree((void*)attr->val); xfree((void*)attr); return 0; } static inline int attr_get_dirty(t_attr *attr) { return attr->dirty; } static inline void attr_clear_dirty(t_attr *attr) { attr->dirty = 0; } static inline const char *attr_get_key(t_attr *attr) { return attr->key; } static inline const char *attr_get_val(t_attr *attr) { return attr->val; } static inline void attr_set_val(t_attr *attr, const char *val) { if (attr->val) xfree((void*)attr->val); if (val) attr->val = xstrdup(val); else attr->val = NULL; } static inline void attr_set_dirty(t_attr *attr) { attr->dirty = 1; } #endif /* __ATTR_H_INCLUDED__ */ pvpgn-1.8.5/src/bnetd/storage_sql2.c0000644000175000017500000003035211151345317016301 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef WITH_SQL #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include "compat/strtoul.h" #include "compat/snprintf.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "common/eventlog.h" #include "prefs.h" #include "common/util.h" #define CLAN_INTERNAL_ACCESS #define TEAM_INTERNAL_ACCESS #include "team.h" #include "account.h" #include "connection.h" #include "clan.h" #undef TEAM_INTERNAL_ACCESS #undef CLAN_INTERNAL_ACCESS #include "common/tag.h" #include "common/xalloc.h" #include "common/flags.h" #include "sql_dbcreator.h" #define SQL_INTERNAL # include "sql_common.h" #undef SQL_INTERNAL #include "storage_sql2.h" #include "common/elist.h" #include "attr.h" #include "common/setup_after.h" static t_storage_info *sql2_create_account(char const *); static int sql2_read_attrs(t_storage_info *, t_read_attr_func, void *); static t_attr *sql2_read_attr(t_storage_info *, const char *); static int sql2_write_attrs(t_storage_info *, const t_hlist *); static t_storage_info * sql2_read_account(const char *,unsigned); static const char *sql2_escape_key(const char *); t_storage storage_sql2 = { sql_init, sql_close, sql_read_maxuserid, sql2_create_account, sql_get_defacct, sql_free_info, sql2_read_attrs, sql2_write_attrs, sql2_read_attr, sql_read_accounts, sql2_read_account, sql_cmp_info, sql2_escape_key, sql_load_clans, sql_write_clan, sql_remove_clan, sql_remove_clanmember, sql_load_teams, sql_write_team, sql_remove_team }; static char query[512]; #ifndef SQL_ON_DEMAND static const char *_db_add_tab(const char *tab, const char *key) { static char nkey[DB_MAX_ATTRKEY]; strncpy(nkey, tab, sizeof(nkey) - 1); nkey[strlen(nkey) + 1] = '\0'; nkey[strlen(nkey)] = '_'; strncpy(nkey + strlen(nkey), key, sizeof(nkey) - strlen(nkey)); return nkey; } #endif /* SQL_ON_DEMAND */ static int _db_get_tab(const char *key, char **ptab, char **pcol) { static char tab[DB_MAX_ATTRKEY]; static char col[DB_MAX_ATTRKEY]; char *p; strncpy(tab, key, DB_MAX_TAB - 1); tab[DB_MAX_TAB - 1] = 0; if (!(p = strchr(tab, '\\'))) return -1; *p = 0; strncpy(col, key + strlen(tab) + 1, DB_MAX_ATTRKEY - 1); col[DB_MAX_ATTRKEY - 1] = 0; /* return tab and col as 2 static buffers */ *ptab = tab; *pcol = col; return 0; } static t_storage_info *sql2_create_account(char const *username) { t_sql_res *result = NULL; t_sql_row *row; int uid = maxuserid + 1; t_storage_info *info; char *user; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return NULL; } user = xstrdup(username); strlower(user); snprintf(query, sizeof(query), "SELECT count(*) FROM %sBNET WHERE name = 'username' and value = '%s'", tab_prefix, user); if ((result = sql->query_res(query)) != NULL) { int num; row = sql->fetch_row(result); if (row == NULL || row[0] == NULL) { sql->free_result(result); eventlog(eventlog_level_error, __FUNCTION__, "got NULL count"); goto err_dup; } num = atol(row[0]); sql->free_result(result); if (num > 0) { eventlog(eventlog_level_error, __FUNCTION__, "got existant username"); goto err_dup; } } else { eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query); goto err_dup; } info = xmalloc(sizeof(t_sql_info)); *((unsigned int *) info) = uid; snprintf(query, sizeof(query), "DELETE FROM %sBNET WHERE " SQL_UID_FIELD " = '%u'", tab_prefix, uid); sql->query(query); snprintf(query, sizeof(query), "INSERT INTO %sBNET (" SQL_UID_FIELD ", name, value) VALUES('%u', 'username', '%s')", tab_prefix, uid, user); if (sql->query(query)) { eventlog(eventlog_level_error, __FUNCTION__, "user insert failed"); goto err_info; } snprintf(query, sizeof(query), "DELETE FROM %sprofile WHERE " SQL_UID_FIELD " = '%u'", tab_prefix, uid); sql->query(query); snprintf(query, sizeof(query), "DELETE FROM %sRecord WHERE " SQL_UID_FIELD " = '%u'", tab_prefix, uid); sql->query(query); snprintf(query, sizeof(query), "DELETE FROM %sfriend WHERE " SQL_UID_FIELD " = '%u'", tab_prefix, uid); sql->query(query); xfree(user); return info; err_info: xfree((void *) info); err_dup: xfree(user); return NULL; } static int sql2_read_attrs(t_storage_info * info, t_read_attr_func cb, void *data) { #ifndef SQL_ON_DEMAND t_sql_res *result = NULL; t_sql_row *row; char **tab; unsigned int uid; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } if (info == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL storage info"); return -1; } if (cb == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback"); return -1; } uid = *((unsigned int *) info); for (tab = sql_tables; *tab; tab++) { snprintf(query, sizeof(query), "SELECT (name, value) FROM %s%s WHERE " SQL_UID_FIELD " = '%u'", tab_prefix, *tab, uid); // eventlog(eventlog_level_trace, __FUNCTION__, "query: \"%s\"",query); result = sql->query_res(query); if (!result) continue; if (sql->num_fields != 2) { sql->free_result(result); continue; } for(row = sql->fetch_row(result); row; row = sql->fetch_row(result)) { if (cb(_db_add_tab(*tab, row[0]), row[1], data)) ERROR1("got error from callback on UID: %u", uid); } sql->free_result(result); } #endif /* SQL_ON_DEMAND */ return 0; } static t_attr *sql2_read_attr(t_storage_info * info, const char *key) { #ifdef SQL_ON_DEMAND t_sql_res *result = NULL; t_sql_row *row; char *tab, *col; unsigned int uid; t_attr *attr; char esckey[DB_MAX_ATTRKEY * 2 + 1]; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return NULL; } if (info == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL storage info"); return NULL; } if (key == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL key"); return NULL; } uid = *((unsigned int *) info); if (_db_get_tab(key, &tab, &col) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "error from db_get_tab"); return NULL; } sql->escape_string(esckey, col, strlen(col)); snprintf(query, sizeof(query), "SELECT value FROM %s%s WHERE " SQL_UID_FIELD " = '%u' and name= '%s'", tab_prefix, tab, uid, esckey); if ((result = sql->query_res(query)) == NULL) return NULL; if (sql->num_rows(result) != 1) { // eventlog(eventlog_level_debug, __FUNCTION__, "wrong numer of rows from query (%s)", query); sql->free_result(result); return NULL; } if (!(row = sql->fetch_row(result))) { eventlog(eventlog_level_error, __FUNCTION__, "could not fetch row"); sql->free_result(result); return NULL; } if (row[0] == NULL) { // eventlog(eventlog_level_debug, __FUNCTION__, "NULL value from query (%s)", query); sql->free_result(result); return NULL; } attr = attr_create(key, row[0]); sql->free_result(result); return (void *) attr; #else return NULL; #endif /* SQL_ON_DEMAND */ } /* write ONLY dirty attributes */ static int sql2_write_attrs(t_storage_info * info, const t_hlist *attrs) { char escval[DB_MAX_ATTRVAL * 2 + 1]; /* sql docs say the escape can take a maximum of double original size + 1 */ char safeval[DB_MAX_ATTRVAL]; char esckey[DB_MAX_ATTRKEY * 2 + 1]; char *tab, *col; t_attr *attr; t_hlist *curr; unsigned int uid; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return -1; } if (info == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL sql info"); return -1; } if (attrs == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL attributes list"); return -1; } uid = *((unsigned int *) info); hlist_for_each(curr, (t_hlist*)attrs) { attr = hlist_entry(curr, t_attr, link); if (!attr_get_dirty(attr)) continue; /* save ONLY dirty attributes */ if (attr_get_key(attr) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL key in attributes list"); continue; } if (attr_get_val(attr) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL value in attributes list"); continue; } if (_db_get_tab(attr_get_key(attr), &tab, &col) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "error from db_get_tab"); continue; } sql->escape_string(esckey, col, strlen(col)); strncpy(safeval, attr_get_val(attr), DB_MAX_ATTRVAL - 1); safeval[DB_MAX_ATTRVAL - 1] = 0; sql->escape_string(escval, safeval, strlen(safeval)); snprintf(query, sizeof(query), "UPDATE %s%s SET value = '%s' WHERE " SQL_UID_FIELD " = '%u' AND name = '%s'", tab_prefix, tab, escval, uid, esckey); // eventlog(eventlog_level_trace, "db_set", "update query: %s", query); if (sql->query(query) || !sql->affected_rows()) { snprintf(query, sizeof(query), "INSERT INTO %s%s (" SQL_UID_FIELD ", name, value) VALUES ('%u', '%s', '%s')", tab_prefix, tab, uid, esckey, escval); // eventlog(eventlog_level_trace, "db_set", "retry insert query: %s", query); if (sql->query(query) || !sql->affected_rows()) { eventlog(eventlog_level_error, __FUNCTION__, "could not INSERT attribute '%s'->'%s'", attr_get_key(attr), attr_get_val(attr)); continue; } } attr_clear_dirty(attr); } return 0; } static t_storage_info * sql2_read_account(const char *name, unsigned uid) { t_sql_res *result = NULL; t_sql_row *row; t_storage_info *info; if (!sql) { eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized"); return NULL; } /* SELECT uid from BNET WHERE uid=x sounds stupid, I agree but its a clean * way to check for account existence by an uid */ if (name) { char *user = xstrdup(name); strlower(user); snprintf(query, sizeof(query), "SELECT " SQL_UID_FIELD " FROM %sBNET WHERE name = 'username' AND value ='%s'", tab_prefix, user); xfree(user); } else snprintf(query, sizeof(query), "SELECT " SQL_UID_FIELD " FROM %sBNET WHERE " SQL_UID_FIELD "= '%u'", tab_prefix, uid); result = sql->query_res(query); if (!result) { eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query); return NULL; } if (sql->num_rows(result) < 1) { sql->free_result(result); return NULL; /* empty user list */ } row = sql->fetch_row(result); if (!row) { /* could not fetch row, this should not happen */ sql->free_result(result); return NULL; } if (row[0] == NULL) /* empty UID field */ eventlog(eventlog_level_error, __FUNCTION__, "got NULL uid from db"); else if ((unsigned int) atoi(row[0]) == sql_defacct); /* skip default account */ else { info = xmalloc(sizeof(t_sql_info)); *((unsigned int *) info) = atoi(row[0]); sql->free_result(result); return info; } sql->free_result(result); return NULL; } static const char *sql2_escape_key(const char *key) { return key; } #endif /* WITH_SQL */ pvpgn-1.8.5/src/bnetd/server.c0000644000175000017500000013232211151345317015202 0ustar aaronaaron/* * Copyright (C) 1998,1999 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define SERVER_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef WIN32 # include /* for kbhit() and getch() */ #endif #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/memset.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/difftime.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef DO_POSIXSIG # include # include "compat/signal.h" #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #ifdef HAVE_NETDB_H # include #endif #include "compat/inet_ntoa.h" #include "compat/psock.h" #include "common/packet.h" #include "connection.h" #include "common/hexdump.h" #include "common/eventlog.h" #include "message.h" #include "handle_bnet.h" #include "handle_bot.h" #include "handle_telnet.h" #include "handle_file.h" #include "handle_init.h" #include "handle_d2cs.h" #include "handle_irc.h" #include "handle_udp.h" #include "common/network.h" #include "prefs.h" #include "account.h" #include "common/tracker.h" #include "common/list.h" #include "adbanner.h" #include "timer.h" #include "common/addr.h" #include "common/util.h" #include "common/rlimit.h" #include "ipban.h" #include "helpfile.h" #include "autoupdate.h" #include "versioncheck.h" #include "realm.h" #include "channel.h" #include "game.h" #include "anongame.h" #include "server.h" #include "command_groups.h" #ifdef WIN32 # include "win32/service.h" #endif #include "ladder.h" #include "output.h" #include "alias_command.h" #include "anongame_infos.h" #include "news.h" #include "common/fdwatch.h" #include "clan.h" #include "common/trans.h" #include "common/xalloc.h" #include "tournament.h" #include #include "topic.h" #include "attrlayer.h" #include "cmdline.h" #include "common/setup_after.h" extern FILE * hexstrm; /* from main.c */ extern int g_ServiceStatus; #ifdef DO_POSIXSIG static void quit_sig_handle(int unused); static void restart_sig_handle(int unused); static void save_sig_handle(int unused); #ifdef HAVE_SETITIMER static void timer_sig_handle(int unused); #endif #endif time_t now; static time_t starttime; static time_t curr_exittime; static volatile time_t sigexittime=0; static volatile int do_restart=0; static volatile int do_save=0; static volatile int got_epipe=0; static char const * server_hostname=NULL; extern void server_quit_delay(int delay) { /* getting negative delay is ok too because it will force immediate * shutdown */ if (delay) sigexittime = time(NULL)+delay; else sigexittime = 0; } extern void server_quit_wraper(void) { if (sigexittime) sigexittime -= prefs_get_shutdown_decr(); else sigexittime = time(NULL)+(time_t)prefs_get_shutdown_delay(); } extern void server_restart_wraper(void){ do_restart = 1; } extern void server_save_wraper(void){ do_save = 1; } #ifdef DO_POSIXSIG static void quit_sig_handle(int unused) { server_quit_wraper(); } static void restart_sig_handle(int unused) { do_restart = 1; } static void save_sig_handle(int unused) { do_save = 1; } static void pipe_sig_handle(int unused) { got_epipe = 1; } #ifdef HAVE_SETITIMER static void timer_sig_handle(int unused) { time(&now); } #endif static void forced_quit_sig_handle(int unused) { server_quit_delay(-1); /* programs shutdown 1 second before now */ } #endif extern unsigned int server_get_uptime(void) { return (unsigned int)difftime(time(NULL),starttime); } extern unsigned int server_get_starttime(void) { return (unsigned int)starttime; } static char const * laddr_type_get_str(t_laddr_type laddr_type) { switch (laddr_type) { case laddr_type_bnet: return "bnet"; case laddr_type_w3route: return "w3route"; case laddr_type_irc: return "irc"; case laddr_type_wol: return "wol"; case laddr_type_telnet: return "telnet"; default: return "UNKNOWN"; } } static int handle_accept(void *data, t_fdwatch_type rw); static int handle_tcp(void *data, t_fdwatch_type rw); static int handle_udp(void *data, t_fdwatch_type rw); static int sd_accept(t_addr const * curr_laddr, t_laddr_info const * laddr_info, int ssocket, int usocket) { char tempa[32]; int csocket; struct sockaddr_in caddr; psock_t_socklen caddr_len; unsigned int raddr; unsigned short rport; if (!addr_get_addr_str(curr_laddr,tempa,sizeof(tempa))) strcpy(tempa,"x.x.x.x:x"); /* accept the connection */ memset(&caddr,0,sizeof(caddr)); /* not sure if this is needed... modern systems are ok anyway */ caddr_len = sizeof(caddr); if ((csocket = psock_accept(ssocket,(struct sockaddr *)&caddr,&caddr_len))<0) { /* BSD, POSIX error for aborted connections, SYSV often uses EAGAIN or EPROTO */ if ( #ifdef PSOCK_EWOULDBLOCK psock_errno()==PSOCK_EWOULDBLOCK || #endif #ifdef PSOCK_ECONNABORTED psock_errno()==PSOCK_ECONNABORTED || #endif #ifdef PSOCK_EPROTO psock_errno()==PSOCK_EPROTO || #endif 0) eventlog(eventlog_level_error,__FUNCTION__,"client aborted connection on %s (psock_accept: %s)",tempa,pstrerror(psock_errno())); else /* EAGAIN can mean out of resources _or_ connection aborted :( */ if ( #ifdef PSOCK_EINTR psock_errno()!=PSOCK_EINTR && #endif 1) eventlog(eventlog_level_error,__FUNCTION__,"could not accept new connection on %s (psock_accept: %s)",tempa,pstrerror(psock_errno())); return -1; } /* dont accept new connections while shutdowning */ if (curr_exittime) { psock_shutdown(csocket,PSOCK_SHUT_RDWR); psock_close(csocket); return 0; } if (ipbanlist_check(inet_ntoa(caddr.sin_addr))!=0) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] connection from banned address %s denied (closing connection)",csocket,inet_ntoa(caddr.sin_addr)); psock_close(csocket); return -1; } if ((prefs_get_max_conns_per_IP()!=0) && (connlist_count_connections(ntohl(caddr.sin_addr.s_addr)) > prefs_get_max_conns_per_IP())) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] too many connections from address %s (closing connection)",csocket,inet_ntoa(caddr.sin_addr)); psock_close(csocket); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"[%d] accepted connection from %s on %s",csocket,addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)),tempa); if (prefs_get_use_keepalive()) { int val=1; if (psock_setsockopt(csocket,PSOCK_SOL_SOCKET,PSOCK_SO_KEEPALIVE,&val,(psock_t_socklen)sizeof(val))<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set socket option SO_KEEPALIVE (psock_setsockopt: %s)",csocket,pstrerror(psock_errno())); /* not a fatal error */ } { struct sockaddr_in rsaddr; psock_t_socklen rlen; memset(&rsaddr,0,sizeof(rsaddr)); /* not sure if this is needed... modern systems are ok anyway */ rlen = sizeof(rsaddr); if (psock_getsockname(csocket,(struct sockaddr *)&rsaddr,&rlen)<0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to determine real local port (psock_getsockname: %s)",csocket,pstrerror(psock_errno())); /* not a fatal error */ raddr = addr_get_ip(curr_laddr); rport = addr_get_port(curr_laddr); } else { if (rsaddr.sin_family!=PSOCK_AF_INET) { eventlog(eventlog_level_error,__FUNCTION__,"local address returned with bad address family %d",(int)rsaddr.sin_family); /* not a fatal error */ raddr = addr_get_ip(curr_laddr); rport = addr_get_port(curr_laddr); } else { raddr = ntohl(rsaddr.sin_addr.s_addr); rport = ntohs(rsaddr.sin_port); } } } if (psock_ctl(csocket,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set TCP socket to non-blocking mode (closing connection) (psock_ctl: %s)",csocket,pstrerror(psock_errno())); psock_close(csocket); return -1; } { t_connection * c; if (!(c = conn_create(csocket,usocket,raddr,rport,addr_get_ip(curr_laddr),addr_get_port(curr_laddr),ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to create new connection (closing connection)",csocket); psock_close(csocket); return -1; } if (conn_add_fdwatch(c, handle_tcp) < 0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to add socket to fdwatch pool (max connections?)",csocket); conn_set_state(c,conn_state_destroy); return -1; } eventlog(eventlog_level_debug,__FUNCTION__,"[%d] client connected to a %s listening address",csocket,laddr_type_get_str(laddr_info->type)); switch (laddr_info->type) { case laddr_type_irc: conn_set_class(c,conn_class_irc); conn_set_state(c,conn_state_connected); break; case laddr_type_wol: conn_set_class(c,conn_class_wol); conn_set_state(c,conn_state_connected); break; case laddr_type_w3route: conn_set_class(c,conn_class_w3route); conn_set_state(c,conn_state_connected); break; case laddr_type_telnet: conn_set_class(c,conn_class_telnet); conn_set_state(c,conn_state_connected); break; case laddr_type_bnet: { /* add a timer to close stale connections */ int delay; t_timer_data data; data.p = NULL; delay = prefs_get_initkill_timer(); if (delay) timerlist_add_timer(c,time(NULL)+delay,conn_shutdown,data); } default: /* We have to wait for an initial "magic" byte on bnet connections to * tell us exactly what connection class we are dealing with. */ break; } } return 0; } static int sd_udpinput(t_addr * const curr_laddr, t_laddr_info const * laddr_info, int ssocket, int usocket) { int err; psock_t_socklen errlen; t_packet * upacket; err = 0; errlen = sizeof(err); if (psock_getsockopt(usocket,PSOCK_SOL_SOCKET,PSOCK_SO_ERROR,&err,&errlen)<0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to read socket error (psock_getsockopt: %s)",usocket,pstrerror(psock_errno())); return -1; } if (errlen && err) /* if it was an error, there is no packet to read */ { eventlog(eventlog_level_error,__FUNCTION__,"[%d] async UDP socket error notification (psock_getsockopt: %s)",usocket,pstrerror(err)); return -1; } if (!(upacket = packet_create(packet_class_udp))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input"); return -1; } { struct sockaddr_in fromaddr; psock_t_socklen fromlen; int len; fromlen = sizeof(fromaddr); if ((len = psock_recvfrom(usocket,packet_get_raw_data_build(upacket,0),MAX_PACKET_SIZE,0,(struct sockaddr *)&fromaddr,&fromlen))<0) { if ( #ifdef PSOCK_EINTR psock_errno()!=PSOCK_EINTR && #endif #ifdef PSOCK_EAGAIN psock_errno()!=PSOCK_EAGAIN && #endif #ifdef PSOCK_EWOULDBLOCK psock_errno()!=PSOCK_EWOULDBLOCK && #endif #ifdef PSOCK_ECONNRESET psock_errno()!=PSOCK_ECONNRESET && /* this is a win2k/winxp issue * their socket implementation returns this value * although it shouldn't */ #endif 1) eventlog(eventlog_level_error,__FUNCTION__,"could not recv UDP datagram (psock_recvfrom: %s)",pstrerror(psock_errno())); packet_del_ref(upacket); return -1; } if (fromaddr.sin_family!=PSOCK_AF_INET) { eventlog(eventlog_level_error,__FUNCTION__,"got UDP datagram with bad address family %d",(int)fromaddr.sin_family); packet_del_ref(upacket); return -1; } packet_set_size(upacket,len); if (hexstrm) { char tempa[32]; if (!addr_get_addr_str(curr_laddr,tempa,sizeof(tempa))) strcpy(tempa,"x.x.x.x:x"); fprintf(hexstrm,"%d: recv class=%s[0x%02x] type=%s[0x%04x] from=%s to=%s length=%u\n", usocket, packet_get_class_str(upacket),(unsigned int)packet_get_class(upacket), packet_get_type_str(upacket,packet_dir_from_client),packet_get_type(upacket), addr_num_to_addr_str(ntohl(fromaddr.sin_addr.s_addr),ntohs(fromaddr.sin_port)), tempa, packet_get_size(upacket)); hexdump(hexstrm,packet_get_raw_data(upacket,0),packet_get_size(upacket)); } handle_udp_packet(usocket,ntohl(fromaddr.sin_addr.s_addr),ntohs(fromaddr.sin_port),upacket); packet_del_ref(upacket); } return 0; } static int sd_tcpinput(t_connection * c) { unsigned int currsize; t_packet * packet; int csocket = conn_get_socket(c); currsize = conn_get_in_size(c); if (!conn_get_in_queue(c)) { switch (conn_get_class(c)) { case conn_class_init: if (!(packet = packet_create(packet_class_init))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate init packet for input"); return -1; } break; case conn_class_d2cs_bnetd: if (!(packet = packet_create(packet_class_d2cs_bnetd))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate d2cs_bnetd packet"); return -1; } break; case conn_class_bnet: if (!(packet = packet_create(packet_class_bnet))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate bnet packet for input"); return -1; } break; case conn_class_file: switch(conn_get_state(c)) { case conn_state_pending_raw: if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input"); return -1; } packet_set_size(packet, sizeof(t_client_file_req3)); break; default: if (!(packet = packet_create(packet_class_file))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate file packet for input"); return -1; } break; } break; case conn_class_bot: case conn_class_irc: case conn_class_wol: case conn_class_telnet: if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input"); return -1; } packet_set_size(packet,1); /* start by only reading one char */ break; case conn_class_w3route: if (!(packet = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate w3route packet for input"); return -1; } break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] connection has bad class (closing connection)",conn_get_socket(c)); /* marking connection as "destroyed", memory will be freed later */ conn_set_state(c, conn_state_destroy); return -2; } conn_put_in_queue(c,packet); currsize = 0; } packet = conn_get_in_queue(c); switch (net_recv_packet(csocket,packet,&currsize)) { case -1: eventlog(eventlog_level_debug,__FUNCTION__,"[%d] read returned -1 (closing connection)",conn_get_socket(c)); /* marking connection as "destroyed", memory will be freed later */ conn_set_state(c, conn_state_destroy); return -2; case 0: /* still working on it */ /* eventlog(eventlog_level_debug,__FUNCTION__,"[%d] still reading \"%s\" packet (%u of %u bytes so far)",conn_get_socket(c),packet_get_class_str(packet),conn_get_in_size(c),packet_get_size(packet)); */ conn_set_in_size(c,currsize); break; case 1: /* done reading */ switch (conn_get_class(c)) { case conn_class_bot: case conn_class_telnet: if (currsizeBNETD_MAX_OUTBURST || !conn_peek_outqueue(c)) return 0; totsize += currsize; break; } } /* not reached */ } void server_check_and_fix_hostname(char const * sname) { int ok = 1; char * tn = (char *)sname; char * sn = (char *)sname; if (!isalnum((int)*sn)) { eventlog(eventlog_level_error,__FUNCTION__,"hostname contains invalid first symbol (must be alphanumeric)"); *tn='a'; } tn++; sn++; for (;*sn!='\0';sn++) { if (isalnum((int)*sn) || *sn=='-' || *sn=='.') { *tn=*sn; tn++; } else ok = 0; } *tn='\0'; if (!ok) eventlog(eventlog_level_error,__FUNCTION__,"hostname contains invalid symbol(s) (must be alphanumeric, '-' or '.') - skipped those symbols"); } extern void server_set_hostname(void) { char temp[250]; char const * hn; #ifdef HAVE_GETHOSTBYNAME struct hostent * hp; #endif if (server_hostname) { xfree((void *)server_hostname); /* avoid warning */ server_hostname = NULL; } hn = prefs_get_hostname(); if ((!hn)||(hn[0]=='\0')) { if (gethostname(temp,sizeof(temp))<0) { #ifdef WIN32 sprintf(temp,"localhost"); #else eventlog(eventlog_level_error,__FUNCTION__,"could not get hostname: %s",pstrerror(errno)); return; #endif } #ifdef HAVE_GETHOSTBYNAME hp = gethostbyname(temp); if (!hp || !hp->h_name) { #endif server_hostname = xstrdup(temp); #ifdef HAVE_GETHOSTBYNAME } else { int i=0; if (strchr(hp->h_name,'.')) /* Default name is already a FQDN */ server_hostname = xstrdup(hp->h_name); /* ... if not we have to examine the aliases */ while (!server_hostname && hp->h_aliases && hp->h_aliases[i]) { if (strchr(hp->h_aliases[i],'.')) server_hostname = xstrdup(hp->h_aliases[i]); i++; } if (!server_hostname) /* Fall back to default name which might not be a FQDN */ server_hostname = xstrdup(hp->h_name); } #endif } else { server_hostname = xstrdup(hn); } server_check_and_fix_hostname(server_hostname); eventlog(eventlog_level_info,__FUNCTION__,"set hostname to \"%s\"",server_hostname); } extern char const * server_get_hostname(void) { if (!server_hostname) return "(null)"; /* avoid crashes */ else return server_hostname; } extern void server_clear_hostname(void) { if (server_hostname) { xfree((void *)server_hostname); /* avoid warning */ server_hostname = NULL; } } static int handle_accept(void *data, t_fdwatch_type rw) { t_laddr_info *laddr_info = addr_get_data((t_addr *)data).p; return sd_accept((t_addr *)data, laddr_info, laddr_info->ssocket, laddr_info->usocket); } static int handle_udp(void *data, t_fdwatch_type rw) { t_laddr_info *laddr_info = addr_get_data((t_addr *)data).p; return sd_udpinput((t_addr *)data, laddr_info, laddr_info->ssocket, laddr_info->usocket); } static int handle_tcp(void *data, t_fdwatch_type rw) { switch(rw) { case fdwatch_type_read: return sd_tcpinput((t_connection *)data); case fdwatch_type_write: return sd_tcpoutput((t_connection *)data); default: return -1; } } static int _setup_add_addrs(t_addrlist **pladdrs, const char *str, unsigned int defaddr, unsigned short defport, t_laddr_type type) { t_addr * curr_laddr; t_addr_data laddr_data; t_laddr_info * laddr_info; t_elem const * acurr; if (*pladdrs == NULL) { *pladdrs = addrlist_create(str, defaddr, defport); if (*pladdrs == NULL) return -1; } else if (addrlist_append(*pladdrs, str, defaddr, defport)) return -1; /* Mark all these laddrs for being classic Battle.net service */ LIST_TRAVERSE_CONST(*pladdrs,acurr) { curr_laddr = elem_get_data(acurr); if (addr_get_data(curr_laddr).p) continue; laddr_info = xmalloc(sizeof(t_laddr_info)); laddr_info->usocket = -1; laddr_info->ssocket = -1; laddr_info->type = type; laddr_data.p = laddr_info; if (addr_set_data(curr_laddr,laddr_data)<0) { eventlog(eventlog_level_error, __FUNCTION__,"could not set address data"); if (laddr_info->usocket!=-1) { psock_close(laddr_info->usocket); laddr_info->usocket = -1; } if (laddr_info->ssocket!=-1) { psock_close(laddr_info->ssocket); laddr_info->ssocket = -1; } return -1; } } return 0; } static int _set_reuseaddr(int sock) { int val = 1; return psock_setsockopt(sock,PSOCK_SOL_SOCKET,PSOCK_SO_REUSEADDR,&val,(psock_t_socklen)sizeof(int)); } static int _bind_socket(int sock, unsigned addr, short port) { struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.sin_family = PSOCK_AF_INET; saddr.sin_port = htons(port); saddr.sin_addr.s_addr = htonl(addr); return psock_bind(sock,(struct sockaddr *)&saddr,(psock_t_socklen)sizeof(saddr)); } static int _setup_listensock(t_addrlist *laddrs) { t_addr * curr_laddr; t_laddr_info * laddr_info; t_elem const * acurr; char tempa[32]; int fidx; LIST_TRAVERSE_CONST(laddrs,acurr) { curr_laddr = elem_get_data(acurr); if (!(laddr_info = addr_get_data(curr_laddr).p)) { eventlog(eventlog_level_error, __FUNCTION__, "NULL address info"); goto err; } if (!addr_get_addr_str(curr_laddr,tempa,sizeof(tempa))) strcpy(tempa,"x.x.x.x:x"); laddr_info->ssocket = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP); if (laddr_info->ssocket<0) { eventlog(eventlog_level_error, __FUNCTION__, "could not create a %s listening socket (psock_socket: %s)",laddr_type_get_str(laddr_info->type),pstrerror(psock_errno())); goto err; } if (_set_reuseaddr(laddr_info->ssocket)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set option SO_REUSEADDR on %s socket %d (psock_setsockopt: %s)",laddr_type_get_str(laddr_info->type),laddr_info->ssocket,pstrerror(psock_errno())); /* not a fatal error... */ if (_bind_socket(laddr_info->ssocket,addr_get_ip(curr_laddr),addr_get_port(curr_laddr))<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not bind %s socket to address %s TCP (psock_bind: %s)",laddr_type_get_str(laddr_info->type),tempa,pstrerror(psock_errno())); goto errsock; } /* tell socket to listen for connections */ if (psock_listen(laddr_info->ssocket,LISTEN_QUEUE)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set %s socket %d to listen (psock_listen: %s)",laddr_type_get_str(laddr_info->type),laddr_info->ssocket,pstrerror(psock_errno())); goto errsock; } if (psock_ctl(laddr_info->ssocket,PSOCK_NONBLOCK)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set %s TCP listen socket to non-blocking mode (psock_ctl: %s)",laddr_type_get_str(laddr_info->type),pstrerror(psock_errno())); /* index not stored persisently because we dont need to refer to it later */ fidx = fdwatch_add_fd(laddr_info->ssocket, fdwatch_type_read, handle_accept, curr_laddr); if (fidx < 0) { eventlog(eventlog_level_error, __FUNCTION__, "could not add listening socket %d to fdwatch pool (max sockets?)",laddr_info->ssocket); goto errsock; } eventlog(eventlog_level_info,__FUNCTION__,"listening for %s connections on %s TCP",laddr_type_get_str(laddr_info->type),tempa); if (laddr_info->type==laddr_type_bnet) { laddr_info->usocket = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_DGRAM,PSOCK_IPPROTO_UDP); if (laddr_info->usocket<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create UDP socket (psock_socket: %s)",pstrerror(psock_errno())); goto errfdw; } if (_set_reuseaddr(laddr_info->usocket)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set option SO_REUSEADDR on %s socket %d (psock_setsockopt: %s)",laddr_type_get_str(laddr_info->type),laddr_info->usocket,pstrerror(psock_errno())); /* not a fatal error... */ if (_bind_socket(laddr_info->usocket,addr_get_ip(curr_laddr),addr_get_port(curr_laddr))<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not bind %s socket to address %s UDP (psock_bind: %s)",laddr_type_get_str(laddr_info->type),tempa,pstrerror(psock_errno())); goto errusock; } if (psock_ctl(laddr_info->usocket,PSOCK_NONBLOCK)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set %s UDP socket to non-blocking mode (psock_ctl: %s)",laddr_type_get_str(laddr_info->type),pstrerror(psock_errno())); /* index ignored because we never need it after this */ if (fdwatch_add_fd(laddr_info->usocket, fdwatch_type_read, handle_udp, curr_laddr) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "could not add listening socket %d to fdwatch pool (max sockets?)",laddr_info->usocket); goto errusock; } } } return 0; errusock: psock_close(laddr_info->usocket); laddr_info->usocket = -1; errfdw: fdwatch_del_fd(fidx); errsock: psock_close(laddr_info->ssocket); laddr_info->ssocket = -1; err: return -1; } #ifdef DO_POSIXSIG static sigset_t block_set; static sigset_t save_set; static int _setup_posixsig(void) { if (sigemptyset(&save_set)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno)); return -1; } if (sigemptyset(&block_set)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno)); return -1; } if (sigaddset(&block_set,SIGINT)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno)); return -1; } if (sigaddset(&block_set,SIGHUP)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno)); return -1; } if (sigaddset(&block_set,SIGTERM)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno)); return -1; } if (sigaddset(&block_set,SIGUSR1)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno)); return -1; } if (sigaddset(&block_set,SIGUSR2)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno)); return -1; } if (sigaddset(&block_set,SIGALRM)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno)); return -1; } { struct sigaction quit_action; struct sigaction restart_action; struct sigaction save_action; struct sigaction pipe_action; #ifdef HAVE_SETITIMER struct sigaction timer_action; #endif struct sigaction forced_quit_action; quit_action.sa_handler = quit_sig_handle; if (sigemptyset(&quit_action.sa_mask)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno)); quit_action.sa_flags = SA_RESTART; restart_action.sa_handler = restart_sig_handle; if (sigemptyset(&restart_action.sa_mask)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno)); restart_action.sa_flags = SA_RESTART; save_action.sa_handler = save_sig_handle; if (sigemptyset(&save_action.sa_mask)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno)); save_action.sa_flags = SA_RESTART; pipe_action.sa_handler = pipe_sig_handle; if (sigemptyset(&pipe_action.sa_mask)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno)); pipe_action.sa_flags = SA_RESTART; #ifdef HAVE_SETITIMER timer_action.sa_handler = timer_sig_handle; if (sigemptyset(&timer_action.sa_mask)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno)); timer_action.sa_flags = SA_RESTART; #endif /* HAVE_SETITIMER */ forced_quit_action.sa_handler = forced_quit_sig_handle; if (sigemptyset(&forced_quit_action.sa_mask)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno)); forced_quit_action.sa_flags = SA_RESTART; if (sigaction(SIGINT,&quit_action,NULL)<0) /* control-c */ eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGINT signal handler (sigaction: %s)",pstrerror(errno)); if (sigaction(SIGHUP,&restart_action,NULL)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGHUP signal handler (sigaction: %s)",pstrerror(errno)); if (sigaction(SIGTERM,&quit_action,NULL)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGTERM signal handler (sigaction: %s)",pstrerror(errno)); if (sigaction(SIGUSR1,&save_action,NULL)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGUSR1 signal handler (sigaction: %s)",pstrerror(errno)); if (sigaction(SIGPIPE,&pipe_action,NULL)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGPIPE signal handler (sigaction: %s)",pstrerror(errno)); #ifdef HAVE_SETITIMER /* setup asynchronus timestamp update timer */ if (sigaction(SIGALRM,&timer_action,NULL)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGALRM signal handler (sigaction: %s)",pstrerror(errno)); { struct itimerval it; it.it_interval.tv_sec = BNETD_JIFFIES / 1000; it.it_interval.tv_usec = BNETD_JIFFIES % 1000; it.it_value.tv_sec = BNETD_JIFFIES / 1000; it.it_value.tv_usec = BNETD_JIFFIES % 1000; if (setitimer(ITIMER_REAL, &it, NULL)) { eventlog(eventlog_level_fatal, __FUNCTION__, "failed to set timers (setitimer(): %s)", pstrerror(errno)); return -1; } } #endif if (sigaction(SIGQUIT,&forced_quit_action,NULL)<0) /* immediate shutdown */ eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGQUIT signal handler (sigaction: %s)",pstrerror(errno)); } return 0; } #endif static time_t prev_exittime; static void _server_mainloop(t_addrlist *laddrs) { time_t next_savetime, next_flushtime, track_time; time_t war3_ladder_updatetime; time_t output_updatetime; unsigned int count; int savestep, flushstep; starttime = time(NULL); track_time = starttime - prefs_get_track(); next_savetime = starttime + prefs_get_user_sync_timer(); next_flushtime = starttime + prefs_get_user_flush_timer(); war3_ladder_updatetime = starttime - prefs_get_war3_ladder_update_secs(); output_updatetime = starttime - prefs_get_output_update_secs(); savestep = flushstep = 0; count = 0; for (;;) { #ifdef WIN32 # ifndef WIN32_GUI if (g_ServiceStatus<0 && kbhit() && getch()=='q') server_quit_wraper(); # endif if (g_ServiceStatus == 0) server_quit_wraper(); while (g_ServiceStatus == 2) Sleep(1000); #endif #ifdef DO_POSIXSIG if (sigprocmask(SIG_SETMASK,&save_set,NULL)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not unblock signals"); /* receive signals here */ if (sigprocmask(SIG_SETMASK,&block_set,NULL)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not block signals"); #endif if (got_epipe) { got_epipe = 0; eventlog(eventlog_level_info,__FUNCTION__,"handled SIGPIPE"); } #if !defined(DO_POSIXSIG) || !defined(HAVE_SETITIMER) /* if no DO_POSIXSIG or no HAVE_SETITIMER so we must read timestamp each loop */ time(&now); #endif curr_exittime = sigexittime; if (curr_exittime && (curr_exittime<=now || connlist_login_get_length()<1)) { eventlog(eventlog_level_info,__FUNCTION__,"the server is shutting down (%d connections left)",connlist_get_length()); clanlist_save(); /* no need for accountlist_save() when using "force" */ accountlist_save(FS_FORCE | FS_ALL); accountlist_flush(FS_FORCE | FS_ALL); break; } if (prev_exittime!=curr_exittime) { t_message * message; char const * tstr; if (curr_exittime!=0) { char text[29+256+2+32+24+1]; /* "The ... in " + time + " (" num + " connection ...)." + NUL */ tstr = seconds_to_timestr(curr_exittime-now); sprintf(text,"The server will shut down in %s (%d connections remaining).",tstr,connlist_get_length()); if ((message = message_create(message_type_error,NULL,NULL,text))) { message_send_all(message); message_destroy(message); } eventlog(eventlog_level_info,__FUNCTION__,"the server will shut down in %s (%d connections remaining)",tstr,connlist_get_length()); } else { if ((message = message_create(message_type_error,NULL,NULL,"Server shutdown has been canceled."))) { message_send_all(message); message_destroy(message); } eventlog(eventlog_level_info,__FUNCTION__,"server shutdown canceled"); } } prev_exittime = curr_exittime; if (next_savetime <=now) { if (!savestep) { /* do this stuff only first step of save */ clanlist_save(); gamelist_check_voidgame(); } savestep = accountlist_save(FS_NONE); if (!savestep) /* saving finished */ next_savetime += prefs_get_user_sync_timer(); } if (next_flushtime <=now) { if (!flushstep) { /* do this stuff only first step of save */ clanlist_save(); gamelist_check_voidgame(); } flushstep = accountlist_flush(FS_NONE); if (!flushstep) /* flushing finished */ next_flushtime += prefs_get_user_flush_timer(); } if (prefs_get_track() && track_time+(time_t)prefs_get_track()<=now) { track_time = now; tracker_send_report(laddrs); } if (prefs_get_war3_ladder_update_secs() && war3_ladder_updatetime+(time_t)prefs_get_war3_ladder_update_secs()<=now) { war3_ladder_updatetime = now; ladders_write_to_file(); } if (prefs_get_output_update_secs() && output_updatetime+(time_t)prefs_get_output_update_secs()<=now) { output_updatetime = now; output_write_to_file(); } if (do_save) { eventlog(eventlog_level_info,__FUNCTION__,"saving accounts due to signal"); clanlist_save(); savestep = accountlist_save(FS_NONE); if (!savestep) /* saving finished */ next_savetime += prefs_get_user_sync_timer(); do_save = 0; } if (do_restart) { eventlog(eventlog_level_info,__FUNCTION__,"reading configuration files"); if (cmdline_get_preffile()) { if (prefs_load(cmdline_get_preffile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not parse configuration file"); } else if (prefs_load(BNETD_DEFAULT_CONF_FILE)<0) eventlog(eventlog_level_error,__FUNCTION__,"using default configuration"); if (eventlog_open(prefs_get_logfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not use the file \"%s\" for the eventlog",prefs_get_logfile()); /* FIXME: load new network settings */ /* reload server name */ server_set_hostname(); attrlayer_load_default(); channellist_reload(); if (realmlist_reload(prefs_get_realmfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not reload realm list"); autoupdate_unload(); if (autoupdate_load(prefs_get_mpqfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load autoupdate list"); news_unload(); if (news_load(prefs_get_newsfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load news list"); versioncheck_unload(); if (versioncheck_load(prefs_get_versioncheck_file())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load versioncheck list"); if (ipbanlist_destroy()<0) eventlog(eventlog_level_error,__FUNCTION__,"could not unload old IP ban list"); ipbanlist_create(); if (ipbanlist_load(prefs_get_ipbanfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load new IP ban list"); helpfile_unload(); if (helpfile_init(prefs_get_helpfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load the helpfile"); if (adbannerlist_destroy()<0) eventlog(eventlog_level_error,__FUNCTION__,"could not unload old adbanner list"); if (adbannerlist_create(prefs_get_adfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load new adbanner list"); ladder_reload_conf(); if (prefs_get_track()) tracker_set_servers(prefs_get_trackserv_addrs()); if (command_groups_reload(prefs_get_command_groups_file())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load new command_groups list"); aliasfile_unload(); aliasfile_load(prefs_get_aliasfile()); if(trans_reload(prefs_get_transfile(),TRANS_BNETD)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not reload trans list"); tournament_reload(prefs_get_tournament_file()); anongame_infos_unload(); anongame_infos_load(prefs_get_anongame_infos_file()); topiclist_unload(); if (topiclist_load(prefs_get_topicfile())<0) eventlog(eventlog_level_error,__FUNCTION__,"could not load new topic list"); eventlog(eventlog_level_info,__FUNCTION__,"done reconfiguring"); do_restart = 0; } count += BNETD_POLL_INTERVAL; if (count>=1000) /* only check timers once a second */ { timerlist_check_timers(now); count = 0; } /* no need to populate the fdwatch structures as they are populated on the fly * by sd_accept, conn_push_outqueue, conn_pull_outqueue, conn_destory */ /* find which sockets need servicing */ switch (fdwatch(BNETD_POLL_INTERVAL)) { case -1: /* error */ if ( #ifdef PSOCK_EINTR psock_errno()!=PSOCK_EINTR && #endif 1) eventlog(eventlog_level_error,__FUNCTION__,"fdwatch() failed (errno: %s)",pstrerror(psock_errno())); case 0: /* timeout... no sockets need checking */ continue; } /* cycle through the ready sockets and handle them */ fdwatch_handle(); /* reap dead connections */ connlist_reap(); } } static void _shutdown_conns(void) { t_elem *ccurr; t_connection *c; LIST_TRAVERSE(connlist(),ccurr) { c = (t_connection *)elem_get_data(ccurr); conn_destroy(c,&ccurr,DESTROY_FROM_CONNLIST); } } static void _shutdown_addrs(t_addrlist *laddrs) { t_addr * curr_laddr; t_laddr_info * laddr_info; t_elem const * acurr; LIST_TRAVERSE_CONST(laddrs,acurr) { curr_laddr = elem_get_data(acurr); if ((laddr_info = addr_get_data(curr_laddr).p)) { if (laddr_info->usocket!=-1) psock_close(laddr_info->usocket); if (laddr_info->ssocket!=-1) psock_close(laddr_info->ssocket); xfree(laddr_info); } } addrlist_destroy(laddrs); } extern int server_process(void) { t_addrlist * laddrs; laddrs = NULL; /* Start with the Battle.net address list */ if (_setup_add_addrs(&laddrs, prefs_get_bnetdserv_addrs(),INADDR_ANY,BNETD_SERV_PORT,laddr_type_bnet)) { eventlog(eventlog_level_error,__FUNCTION__,"could not create %s server address list from \"%s\"",laddr_type_get_str(laddr_type_bnet),prefs_get_bnetdserv_addrs()); return -1; } /* Append list of addresses to listen for IRC connections */ if (_setup_add_addrs(&laddrs, prefs_get_irc_addrs(),INADDR_ANY,BNETD_IRC_PORT, laddr_type_irc)) { eventlog(eventlog_level_error,__FUNCTION__,"could not create %s server address list from \"%s\"",laddr_type_get_str(laddr_type_irc),prefs_get_irc_addrs()); _shutdown_addrs(laddrs); return -1; } /* Append list of addresses to listen for WOL IRC connections */ if (_setup_add_addrs(&laddrs, prefs_get_wol_addrs(),INADDR_ANY,BNETD_WOL_PORT, laddr_type_wol)) { eventlog(eventlog_level_error,__FUNCTION__,"could not create %s server address list from \"%s\"",laddr_type_get_str(laddr_type_wol),prefs_get_wol_addrs()); _shutdown_addrs(laddrs); return -1; } /* Append list of addresses to listen for W3ROUTE connections */ if (_setup_add_addrs(&laddrs,prefs_get_w3route_addr(),INADDR_ANY,BNETD_W3ROUTE_PORT, laddr_type_w3route)) { eventlog(eventlog_level_error,__FUNCTION__,"could not create %s server address list from \"%s\"",laddr_type_get_str(laddr_type_w3route),prefs_get_w3route_addr()); _shutdown_addrs(laddrs); return -1; } /* Append list of addresses to listen for telnet connections */ if (_setup_add_addrs(&laddrs,prefs_get_telnet_addrs(),INADDR_ANY,BNETD_TELNET_PORT,laddr_type_telnet)) { eventlog(eventlog_level_error,__FUNCTION__,"could not create %s server address list from \"%s\"",laddr_type_get_str(laddr_type_telnet),prefs_get_telnet_addrs()); _shutdown_addrs(laddrs); return -1; } if (_setup_listensock(laddrs)) { _shutdown_addrs(laddrs); return -1; } /* setup signal handlers */ prev_exittime = sigexittime; #ifdef DO_POSIXSIG _setup_posixsig(); #endif _server_mainloop(laddrs); /* cleanup for server shutdown */ _shutdown_conns(); _shutdown_addrs(laddrs); return 0; } pvpgn-1.8.5/src/bnetd/game_conv.c0000644000175000017500000012066611151345317015642 0ustar aaronaaron/* * Copyright (C) 1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999,2000 Rob Crittenden (rcrit@greyoak.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define GAME_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include "compat/strsep.h" #include "common/tag.h" #include "common/eventlog.h" #include "game.h" #include "common/bnet_protocol.h" #include "common/util.h" #include "common/bn_type.h" #include "common/xalloc.h" #include "game_conv.h" #include "common/setup_after.h" extern t_game_type bngreqtype_to_gtype(t_clienttag clienttag, unsigned short bngtype) { char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag"); return game_type_none; } if (clienttag==CLIENTTAG_WARCIIBNE_UINT) { switch (bngtype) { case CLIENT_GAMELISTREQ_ALL: return game_type_all; case CLIENT_GAMELISTREQ_TOPVBOT: return game_type_topvbot; case CLIENT_GAMELISTREQ_MELEE: return game_type_melee; case CLIENT_GAMELISTREQ_FFA: return game_type_ffa; case CLIENT_GAMELISTREQ_ONEONONE: return game_type_oneonone; case CLIENT_GAMELISTREQ_LADDER: return game_type_ladder; case CLIENT_GAMELISTREQ_IRONMAN: return game_type_ironman; case CLIENT_GAMELISTREQ_MAPSET: return game_type_mapset; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft bnet game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } else if (clienttag==CLIENTTAG_DIABLO2DV_UINT || clienttag==CLIENTTAG_DIABLO2XP_UINT) { switch (bngtype) { case CLIENT_GAMELISTREQ_ALL: return game_type_diablo2open; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Diablo II bnet game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } else if (clienttag==CLIENTTAG_DIABLORTL_UINT || clienttag==CLIENTTAG_DIABLOSHR_UINT) { switch (bngtype) { case CLIENT_GAMETYPE_DIABLO_0: case CLIENT_GAMETYPE_DIABLO_1: case CLIENT_GAMETYPE_DIABLO_2: case CLIENT_GAMETYPE_DIABLO_3: case CLIENT_GAMETYPE_DIABLO_4: case CLIENT_GAMETYPE_DIABLO_5: case CLIENT_GAMETYPE_DIABLO_6: case CLIENT_GAMETYPE_DIABLO_7: case CLIENT_GAMETYPE_DIABLO_8: case CLIENT_GAMETYPE_DIABLO_9: case CLIENT_GAMETYPE_DIABLO_a: case CLIENT_GAMETYPE_DIABLO_b: case CLIENT_GAMETYPE_DIABLO_c: case CLIENT_GAMETYPE_DIABLO_d: return game_type_diablo; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Diablo bnet game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } else if (clienttag==CLIENTTAG_STARCRAFT_UINT || clienttag==CLIENTTAG_BROODWARS_UINT || clienttag==CLIENTTAG_SHAREWARE_UINT) { switch (bngtype) { case CLIENT_GAMELISTREQ_ALL: return game_type_all; case CLIENT_GAMELISTREQ_MELEE: return game_type_melee; case CLIENT_GAMELISTREQ_FFA: return game_type_ffa; case CLIENT_GAMELISTREQ_ONEONONE: return game_type_oneonone; case CLIENT_GAMELISTREQ_CTF: return game_type_ctf; case CLIENT_GAMELISTREQ_GREED: return game_type_greed; case CLIENT_GAMELISTREQ_SLAUGHTER: return game_type_slaughter; case CLIENT_GAMELISTREQ_SDEATH: return game_type_sdeath; case CLIENT_GAMELISTREQ_LADDER: return game_type_ladder; case CLIENT_GAMELISTREQ_MAPSET: return game_type_mapset; case CLIENT_GAMELISTREQ_TEAMMELEE: return game_type_teammelee; case CLIENT_GAMELISTREQ_TEAMFFA: return game_type_teamffa; case CLIENT_GAMELISTREQ_TEAMCTF: return game_type_teamctf; case CLIENT_GAMELISTREQ_PGL: return game_type_pgl; case CLIENT_GAMELISTREQ_TOPVBOT: return game_type_topvbot; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } else if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT) { return game_type_all; } else { eventlog(eventlog_level_error,__FUNCTION__,"unknown game clienttag \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } extern t_game_type bngtype_to_gtype(t_clienttag clienttag, unsigned short bngtype) { char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag"); return game_type_none; } if (clienttag==CLIENTTAG_WARCIIBNE_UINT) { switch (bngtype) { case CLIENT_GAMELISTREQ_TOPVBOT: return game_type_topvbot; case CLIENT_GAMELISTREQ_MELEE: return game_type_melee; case CLIENT_GAMELISTREQ_FFA: return game_type_ffa; case CLIENT_GAMELISTREQ_ONEONONE: return game_type_oneonone; case CLIENT_GAMELISTREQ_LADDER: return game_type_ladder; case CLIENT_GAMELISTREQ_IRONMAN: return game_type_ironman; case CLIENT_GAMELISTREQ_MAPSET: return game_type_mapset; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft bnet game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } else if (clienttag==CLIENTTAG_DIABLO2DV_UINT || clienttag==CLIENTTAG_DIABLO2XP_UINT) { switch (bngtype) { case CLIENT_GAMETYPE_DIABLO2_OPEN_NORMAL: case CLIENT_GAMETYPE_DIABLO2_OPEN_NIGHTMARE: case CLIENT_GAMETYPE_DIABLO2_OPEN_HELL: return game_type_diablo2open; case CLIENT_GAMETYPE_DIABLO2_CLOSE: return game_type_diablo2closed; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Diablo II bnet game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } else if (clienttag==CLIENTTAG_DIABLORTL_UINT || clienttag==CLIENTTAG_DIABLOSHR_UINT) { switch (bngtype) { case CLIENT_GAMETYPE_DIABLO_0: case CLIENT_GAMETYPE_DIABLO_1: case CLIENT_GAMETYPE_DIABLO_2: case CLIENT_GAMETYPE_DIABLO_3: case CLIENT_GAMETYPE_DIABLO_4: case CLIENT_GAMETYPE_DIABLO_5: case CLIENT_GAMETYPE_DIABLO_6: case CLIENT_GAMETYPE_DIABLO_7: case CLIENT_GAMETYPE_DIABLO_8: case CLIENT_GAMETYPE_DIABLO_9: case CLIENT_GAMETYPE_DIABLO_a: case CLIENT_GAMETYPE_DIABLO_b: case CLIENT_GAMETYPE_DIABLO_c: return game_type_diablo; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Diablo bnet game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } else if (clienttag==CLIENTTAG_STARCRAFT_UINT || clienttag==CLIENTTAG_BROODWARS_UINT || clienttag==CLIENTTAG_SHAREWARE_UINT) { switch (bngtype) { case CLIENT_GAMELISTREQ_ALL: return game_type_all; case CLIENT_GAMELISTREQ_MELEE: return game_type_melee; case CLIENT_GAMELISTREQ_FFA: return game_type_ffa; case CLIENT_GAMELISTREQ_ONEONONE: return game_type_oneonone; case CLIENT_GAMELISTREQ_CTF: return game_type_ctf; case CLIENT_GAMELISTREQ_GREED: return game_type_greed; case CLIENT_GAMELISTREQ_SLAUGHTER: return game_type_slaughter; case CLIENT_GAMELISTREQ_SDEATH: return game_type_sdeath; case CLIENT_GAMELISTREQ_LADDER: return game_type_ladder; case CLIENT_GAMELISTREQ_MAPSET: return game_type_mapset; case CLIENT_GAMELISTREQ_TEAMMELEE: return game_type_teammelee; case CLIENT_GAMELISTREQ_TEAMFFA: return game_type_teamffa; case CLIENT_GAMELISTREQ_TEAMCTF: return game_type_teamctf; case CLIENT_GAMELISTREQ_PGL: return game_type_pgl; case CLIENT_GAMELISTREQ_TOPVBOT: return game_type_topvbot; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } else if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT) { return game_type_all; } else { eventlog(eventlog_level_error,__FUNCTION__,"unknown game clienttag \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),bngtype); return game_type_none; } } extern unsigned short gtype_to_bngtype(t_game_type gtype) { switch (gtype) { case game_type_all: return CLIENT_GAMELISTREQ_ALL; case game_type_melee: return CLIENT_GAMELISTREQ_MELEE; case game_type_ffa: return CLIENT_GAMELISTREQ_FFA; case game_type_oneonone: return CLIENT_GAMELISTREQ_ONEONONE; case game_type_ctf: return CLIENT_GAMELISTREQ_CTF; case game_type_greed: return CLIENT_GAMELISTREQ_GREED; case game_type_slaughter: return CLIENT_GAMELISTREQ_SLAUGHTER; case game_type_sdeath: return CLIENT_GAMELISTREQ_SDEATH; case game_type_ladder: return CLIENT_GAMELISTREQ_LADDER; case game_type_mapset: return CLIENT_GAMELISTREQ_MAPSET; case game_type_teammelee: return CLIENT_GAMELISTREQ_TEAMMELEE; case game_type_teamffa: return CLIENT_GAMELISTREQ_TEAMFFA; case game_type_teamctf: return CLIENT_GAMELISTREQ_TEAMCTF; case game_type_pgl: return CLIENT_GAMELISTREQ_PGL; case game_type_topvbot: return CLIENT_GAMELISTREQ_TOPVBOT; case game_type_diablo: return CLIENT_GAMELISTREQ_DIABLO; case game_type_diablo2open: return SERVER_GAMELISTREPLY_TYPE_DIABLO2_OPEN; case game_type_diablo2closed: eventlog(eventlog_level_error,__FUNCTION__,"don't know how to list Diablo II"); return 0; case game_type_anongame: return 0; case game_type_none: default: eventlog(eventlog_level_error,__FUNCTION__,"unknown game type %u",(unsigned int)gtype); return 0xffff; } } extern t_game_option bngoption_to_goption(t_clienttag clienttag, t_game_type gtype, unsigned short bngoption) { char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag"); return game_option_none; } if (clienttag==CLIENTTAG_WARCIIBNE_UINT) { switch (gtype) { case game_type_topvbot: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_TOPVBOT_1: return game_option_topvbot_1; case CLIENT_STARTGAME4_OPTION_TOPVBOT_2: return game_option_topvbot_2; case CLIENT_STARTGAME4_OPTION_TOPVBOT_3: return game_option_topvbot_3; case CLIENT_STARTGAME4_OPTION_TOPVBOT_4: return game_option_topvbot_4; case CLIENT_STARTGAME4_OPTION_TOPVBOT_5: return game_option_topvbot_5; case CLIENT_STARTGAME4_OPTION_TOPVBOT_6: return game_option_topvbot_6; case CLIENT_STARTGAME4_OPTION_TOPVBOT_7: return game_option_topvbot_7; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft II bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_melee: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_MELEE_NORMAL: return game_option_melee_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft II bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_ffa: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_FFA_NORMAL: return game_option_ffa_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft II bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_oneonone: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_ONEONONE_NORMAL: return game_option_oneonone_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft II bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_ladder: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_LADDER_COUNTASLOSS: return game_option_ladder_countasloss; case CLIENT_STARTGAME4_OPTION_LADDER_NOPENALTY: return game_option_ladder_nopenalty; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft II bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_ironman: switch (bngoption) { default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft II bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_mapset: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_MAPSET_NORMAL: return game_option_mapset_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft II bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Warcraft II game type \"%s\" %u",tag_uint_to_str(clienttag_str,clienttag),(unsigned int)gtype); return game_option_none; } } else if (clienttag==CLIENTTAG_DIABLO2DV_UINT || clienttag==CLIENTTAG_DIABLO2XP_UINT) { switch (gtype) { case game_type_diablo2open: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_NONE: /* FIXME: really? */ return game_option_none; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Diablo II bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_diablo2closed: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_NONE: /* FIXME: really? */ return game_option_none; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Diablo II bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Diablo II game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),(unsigned int)gtype); return game_option_none; } } else if (clienttag==CLIENTTAG_DIABLORTL_UINT || clienttag==CLIENTTAG_DIABLOSHR_UINT) { switch (gtype) { case game_type_diablo: switch (bngoption) { default: /* diablo doesn't use any options */ return game_option_none; } default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Diablo game type \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),(unsigned int)gtype); return game_option_none; } } else if (clienttag==CLIENTTAG_STARCRAFT_UINT || clienttag==CLIENTTAG_BROODWARS_UINT || clienttag==CLIENTTAG_SHAREWARE_UINT) { switch (gtype) { case game_type_melee: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_MELEE_NORMAL: return game_option_melee_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_ffa: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_FFA_NORMAL: return game_option_ffa_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_oneonone: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_ONEONONE_NORMAL: return game_option_oneonone_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_ctf: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_CTF_NORMAL: return game_option_ctf_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_greed: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_GREED_10000: return game_option_greed_10000; case CLIENT_STARTGAME4_OPTION_GREED_7500: return game_option_greed_7500; case CLIENT_STARTGAME4_OPTION_GREED_5000: return game_option_greed_5000; case CLIENT_STARTGAME4_OPTION_GREED_2500: return game_option_greed_2500; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_slaughter: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_SLAUGHTER_60: return game_option_slaughter_60; case CLIENT_STARTGAME4_OPTION_SLAUGHTER_45: return game_option_slaughter_45; case CLIENT_STARTGAME4_OPTION_SLAUGHTER_30: return game_option_slaughter_30; case CLIENT_STARTGAME4_OPTION_SLAUGHTER_15: return game_option_slaughter_15; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_sdeath: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_SDEATH_NORMAL: return game_option_sdeath_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_ladder: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_LADDER_COUNTASLOSS: return game_option_ladder_countasloss; case CLIENT_STARTGAME4_OPTION_LADDER_NOPENALTY: return game_option_ladder_nopenalty; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_mapset: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_MAPSET_NORMAL: return game_option_mapset_normal; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_teammelee: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_TEAMMELEE_4: return game_option_teammelee_4; case CLIENT_STARTGAME4_OPTION_TEAMMELEE_3: return game_option_teammelee_3; case CLIENT_STARTGAME4_OPTION_TEAMMELEE_2: return game_option_teammelee_2; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_teamffa: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_TEAMFFA_4: return game_option_teamffa_4; case CLIENT_STARTGAME4_OPTION_TEAMFFA_3: return game_option_teamffa_3; case CLIENT_STARTGAME4_OPTION_TEAMFFA_2: return game_option_teamffa_2; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_teamctf: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_TEAMCTF_4: return game_option_teamctf_4; case CLIENT_STARTGAME4_OPTION_TEAMCTF_3: return game_option_teamctf_3; case CLIENT_STARTGAME4_OPTION_TEAMCTF_2: return game_option_teamctf_2; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_pgl: switch (bngoption) { default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_topvbot: switch (bngoption) { case CLIENT_STARTGAME4_OPTION_TOPVBOT_1: return game_option_topvbot_1; case CLIENT_STARTGAME4_OPTION_TOPVBOT_2: return game_option_topvbot_2; case CLIENT_STARTGAME4_OPTION_TOPVBOT_3: return game_option_topvbot_3; case CLIENT_STARTGAME4_OPTION_TOPVBOT_4: return game_option_topvbot_4; case CLIENT_STARTGAME4_OPTION_TOPVBOT_5: return game_option_topvbot_5; case CLIENT_STARTGAME4_OPTION_TOPVBOT_6: return game_option_topvbot_6; case CLIENT_STARTGAME4_OPTION_TOPVBOT_7: return game_option_topvbot_7; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft bnet game option for \"%s\" game \"%s\" %hu",tag_uint_to_str(clienttag_str,clienttag),game_type_get_str(gtype),bngoption); return game_option_none; } case game_type_none: default: eventlog(eventlog_level_error,__FUNCTION__,"unknown Starcraft game type \"%s\" %u(%s)",tag_uint_to_str(clienttag_str,clienttag),(unsigned int)gtype,game_type_get_str(gtype)); return game_option_none; } } else if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT) { return game_option_none; } else { eventlog(eventlog_level_error,__FUNCTION__,"unknown game clienttag \"%s\" %u",tag_uint_to_str(clienttag_str,clienttag),(unsigned int)gtype); return game_option_none; } } extern t_game_result bngresult_to_gresult(unsigned int bngresult) { switch (bngresult) { case CLIENT_GAME_REPORT_RESULT_PLAYING: return game_result_playing; case CLIENT_GAME_REPORT_RESULT_WIN: return game_result_win; case CLIENT_GAME_REPORT_RESULT_LOSS: return game_result_loss; case CLIENT_GAME_REPORT_RESULT_DRAW: return game_result_draw; case CLIENT_GAME_REPORT_RESULT_DISCONNECT: return game_result_disconnect; case CLIENT_GAME_REPORT_RESULT_OBSERVER: return game_result_observer; default: eventlog(eventlog_level_error,__FUNCTION__,"unknown bnet game result %u",bngresult); return game_result_disconnect; /* bad packet? */ } } extern t_game_maptype bngmaptype_to_gmaptype(unsigned int bngmaptype) { switch (bngmaptype) { case CLIENT_MAPTYPE_SELFMADE: return game_maptype_selfmade; case CLIENT_MAPTYPE_BLIZZARD: return game_maptype_blizzard; case CLIENT_MAPTYPE_LADDER: return game_maptype_ladder; case CLIENT_MAPTYPE_PGL: return game_maptype_pgl; case CLIENT_MAPTYPE_KBK: return game_maptype_kbk; case CLIENT_MAPTYPE_CompUSA: return game_maptype_compusa; default: return game_maptype_none; } } extern t_game_tileset bngtileset_to_gtileset(unsigned int bngtileset) { switch (bngtileset) { case CLIENT_TILESET_BADLANDS: return game_tileset_badlands; case CLIENT_TILESET_SPACE: return game_tileset_space; case CLIENT_TILESET_INSTALLATION: return game_tileset_installation; case CLIENT_TILESET_ASHWORLD: return game_tileset_ashworld; case CLIENT_TILESET_JUNGLE: return game_tileset_jungle; case CLIENT_TILESET_DESERT: return game_tileset_desert; case CLIENT_TILESET_ICE: return game_tileset_ice; case CLIENT_TILESET_TWILIGHT: return game_tileset_twilight; default: return game_tileset_none; } } extern t_game_speed bngspeed_to_gspeed(unsigned int bngspeed) { switch (bngspeed) { case CLIENT_GAMESPEED_SLOWEST: return game_speed_slowest; case CLIENT_GAMESPEED_SLOWER: return game_speed_slower; case CLIENT_GAMESPEED_SLOW: return game_speed_slow; case CLIENT_GAMESPEED_NORMAL: return game_speed_normal; case CLIENT_GAMESPEED_FAST: return game_speed_fast; case CLIENT_GAMESPEED_FASTER: return game_speed_faster; case CLIENT_GAMESPEED_FASTEST: return game_speed_fastest; default: return game_speed_none; } } t_game_speed w3speed_to_gspeed(unsigned int w3speed) { switch (w3speed) { case 0: return game_speed_slow; case 1: return game_speed_normal; case 2: return game_speed_fast; default: return game_speed_none; } } extern t_game_difficulty bngdifficulty_to_gdifficulty(unsigned int bngdifficulty) { switch (bngdifficulty) { case CLIENT_DIFFICULTY_NORMAL: return game_difficulty_normal; case CLIENT_DIFFICULTY_NIGHTMARE: return game_difficulty_nightmare; case CLIENT_DIFFICULTY_HELL: return game_difficulty_hell; case CLIENT_DIFFICULTY_HARDCORE_NORMAL: return game_difficulty_hardcore_normal; case CLIENT_DIFFICULTY_HARDCORE_NIGHTMARE: return game_difficulty_hardcore_nightmare; case CLIENT_DIFFICULTY_HARDCORE_HELL: return game_difficulty_hardcore_hell; default: return game_difficulty_none; } } static const char * _w3_decrypt_mapinfo(const char *enc) { char *mapinfo; char *dec; unsigned pos; unsigned char bitmask; if (!(mapinfo = xstrdup(enc))) { eventlog(eventlog_level_error, __FUNCTION__, "not enough memory to setup temporary buffer"); return NULL; } dec = mapinfo; pos = 0; bitmask = 0; /* stupid gcc warning */ while(*enc) { if (pos % 8) { *dec = *enc; if (!(bitmask & 0x1)) (*dec)--; dec++; bitmask >>= 1; } else bitmask = *enc >> 1; enc++; pos++; } *dec = '\0'; return mapinfo; } extern int game_parse_info(t_game * game, char const * gameinfo) { t_clienttag clienttag; char * save; char * line1; char * line2; char * currtok; char const * unknown; char const * mapsize; char const * maxplayers; char const * speed; char const * maptype; char const * gametype; char const * option; char const * checksum; char const * tileset; char const * player; char const * mapname; unsigned int bngmapsize; unsigned int bngmaxplayers; unsigned int bngspeed; unsigned int bngmaptype; unsigned int bngtileset; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!gameinfo) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL gameinfo"); return -1; } /* BW 104: 9: recv class=bnet[0x01] type=CLIENT_STARTGAME4[0x1cff] length=74 0000: FF 1C 4A 00 00 00 00 00 00 00 00 00 09 00 01 00 ..J............. 0010: 00 00 00 00 01 00 00 00 4E 4F 50 45 4E 41 4C 54 ........NOPENALT 0020: 59 00 00 2C 34 34 2C 31 34 2C 2C 32 2C 39 2C 31 Y..,44,14,,2,9,1 0030: 2C 33 65 33 37 61 38 34 63 2C 33 2C 52 6F 73 73 ,3e37a84c,3,Ross 0040: 0D 41 73 68 72 69 67 6F 0D 00 .Ashrigo.. Diablo: 7: cli class=bnet[0x01] type=CLIENT_STARTGAME3[0x1aff] length=105 0000: FF 1A 69 00 01 00 00 00 00 00 00 00 00 00 00 00 ..i............. 0010: 0F 00 00 00 00 00 00 00 E0 17 00 00 61 73 64 66 ............asdf 0020: 61 73 64 66 61 73 64 66 61 73 64 66 32 00 61 73 asdfasdfasdf2.as 0030: 64 66 61 73 64 66 73 61 64 66 61 73 64 66 32 00 dfasdfsadfasdf2. 0040: 30 0D 7A 62 6E 7A 62 6E 7A 62 6E 0D 4C 54 52 44 0.zbnzbnzbn.LTRD 0050: 20 31 20 30 20 30 20 33 30 20 31 30 20 32 30 20 1 0 0 30 10 20 0060: 32 35 20 31 30 30 20 30 00 25 100 0. 10: recv class=bnet[0x01] type=CLIENT_STARTGAME3[0x1aff] length=72 0000: FF 1A 48 00 00 00 00 00 00 00 00 00 00 00 00 00 ..H............. 0010: 0F 00 00 00 00 00 00 00 E0 17 00 00 61 6E 73 00 ............ans. 0020: 00 30 0D 77 61 72 72 69 6F 72 0D 4C 54 52 44 20 .0.warrior.LTRD 0030: 31 20 30 20 30 20 33 30 20 31 30 20 32 30 20 32 1 0 0 30 10 20 2 0040: 35 20 31 30 30 20 30 00 5 100 0. Warcraft: 4: srv class=bnet[0x01] type=SERVER_GAMELISTREPLY[0x09ff] length=524 0000: FF 09 0C 02 05 00 00 00 02 00 01 00 09 04 00 00 ................ 0010: 02 00 17 E0 D0 C6 66 F0 00 00 00 00 00 00 00 00 ......f......... 0020: 04 00 00 00 74 00 00 00 48 65 79 77 6F 6F 64 73 ....t...Heywoods 0030: 20 47 4F 57 32 76 32 00 00 2C 2C 2C 36 2C 32 2C GOW2v2..,,,6,2, 0040: 32 2C 31 2C 31 39 37 33 64 35 66 32 2C 33 30 30 2,1,1973d5f2,300 0050: 30 2C 48 65 79 77 6F 6F 64 0D 47 61 72 64 65 6E 0,Heywood.Garden 0060: 20 6F 66 20 77 61 72 20 42 4E 45 2E 70 75 64 0D of war BNE.pud. 0070: 00 09 00 02 00 09 04 00 00 02 00 17 E0 CF 45 3E ..............E> 0080: 65 00 00 00 00 00 00 00 00 10 00 00 00 11 00 00 e............... 0090: 00 67 6F 77 20 6C 61 64 64 65 72 20 31 76 31 00 .gow ladder 1v1. 00A0: 00 2C 2C 2C 36 2C 32 2C 39 2C 32 2C 65 66 38 34 .,,,6,2,9,2,ef84 00B0: 33 61 35 33 2C 2C 77 63 73 63 6D 61 73 74 65 72 3a53,,wcscmaster 00C0: 0D 47 61 72 64 65 6E 20 6F 66 20 77 61 72 20 42 .Garden of war B 00D0: 4E 45 2E 70 75 64 0D 00 09 00 01 00 09 04 00 00 NE.pud.......... 00E0: 02 00 17 E0 98 CE 7C E2 00 00 00 00 00 00 00 00 ......|......... 00F0: 04 00 00 00 4D 00 00 00 4C 61 64 64 65 72 20 46 ....M...Ladder F 0100: 46 41 20 6F 6E 6C 79 00 00 2C 2C 2C 36 2C 32 2C FA only..,,,6,2, 0110: 39 2C 31 2C 61 65 32 66 61 61 62 37 2C 2C 6B 69 9,1,ae2faab7,,ki 0120: 6C 6F 67 72 61 6D 0D 50 6C 61 69 6E 73 20 6F 66 logram.Plains of 0130: 20 73 6E 6F 77 20 42 4E 45 2E 70 75 64 0D 00 0F snow BNE.pud... 0140: 00 04 00 09 04 00 00 02 00 17 E0 C6 0B 13 3C 00 ..............<. 0150: 00 00 00 00 00 00 00 04 00 00 00 BE 00 00 00 4C ...............L 0160: 61 64 64 65 72 20 31 20 6F 6E 20 31 00 00 2C 2C adder 1 on 1..,, 0170: 2C 36 2C 32 2C 66 2C 34 2C 66 63 63 35 38 65 34 ,6,2,f,4,fcc58e4 0180: 61 2C 37 32 30 30 2C 49 63 65 36 39 62 75 72 67 a,7200,Ice69burg 0190: 0D 46 6F 72 65 73 74 20 54 72 61 69 6C 20 42 4E .Forest Trail BN 01A0: 45 2E 70 75 64 0D 00 0F 00 04 00 09 04 00 00 02 E.pud........... 01B0: 00 04 15 D1 F4 B6 6A 00 00 00 00 00 00 00 00 04 ......j......... 01C0: 00 00 00 C8 03 00 00 52 6F 63 6B 20 49 74 21 21 .......Rock It!! 01D0: 20 32 76 32 2B 00 00 2C 2C 2C 38 2C 31 2C 66 2C 2v2+..,,,8,1,f, 01E0: 34 2C 62 30 36 38 63 62 34 62 2C 66 30 30 30 2C 4,b068cb4b,f000, 01F0: 6E 75 66 74 63 72 6F 77 0D 43 72 6F 73 73 68 61 nuftcrow.Crossha 0200: 69 72 20 42 4E 45 2E 70 75 64 0D 00 ir BNE.pud.. FIXME: Note the map size and max players fields are empty. Does WCII have different map sizes and starting positions? If so, are they reported here? Also note the map tileset is "3000". Maybe this isn't the tileset for WCII but instead the starting gold or something. FIXME: Also, what is the upper player limit on WCII... 8 like on Starcraft? */ if (!(clienttag = game_get_clienttag(game))) { eventlog(eventlog_level_error,__FUNCTION__,"NULL clienttag for game?"); return -1; } if (clienttag==CLIENTTAG_DIABLORTL_UINT || clienttag==CLIENTTAG_DIABLOSHR_UINT) { game_set_maxplayers(game,4); eventlog(eventlog_level_debug,__FUNCTION__,"no gameinfo for Diablo"); return 0; } else if (clienttag==CLIENTTAG_DIABLO2DV_UINT || clienttag==CLIENTTAG_DIABLO2XP_UINT) { if ((game->type == game_type_diablo2closed) && (!strlen(gameinfo))) { /* D2 closed games are handled by d2cs so we can have only have a generic startgame4 without any info :(, this fix also a memory leak for description allocation */ game_set_difficulty(game,game_difficulty_none); game_set_description(game, ""); } else { char difficulty[2]; unsigned int bngdifficulty; if (!strlen(gameinfo)) { eventlog(eventlog_level_info,__FUNCTION__, "got empty gameinfo (from D2 client)"); return -1; } difficulty[0] = gameinfo[0]; difficulty[1] = '\0'; if (str_to_uint(difficulty,&bngdifficulty)<0) { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing difficulty) \"%s\"",gameinfo); return -1; } game_set_difficulty(game,bngdifficulty); game_set_description(game,&gameinfo[1]); if ((game->type == game_type_diablo2closed)) { eventlog(eventlog_level_debug,__FUNCTION__,"D2 bug workarround needed (open games tagged as closed)"); game->type = game_type_diablo2open; } } return 0; } else if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT) { /* Warcraft 3 game info format -- by Soar 0x00 -- 1 byte (char, Empty slots) 0x01 -- 8 bytes (char[8], Count of games created) From offset 0x11 there is a bitmask byte before every 7 bytes, offset 0x09 to 0x10 also has bitmask 0. Bit 0 corresponds to byte 0, bit 1 to byte 1, and so on. Except offset 0x09, only Byte 1-7 contribute to the info data, bit 0 seems to be always 1; Decoding these bytes works as follows: If the corresponding bit is a '1' then the character is moved over directly. If the corresponding bit is a '0' then subtract 1 from the character. (We decode info data and remove the bitmask bytes from info data in following description) 0x09 -- 5 bytes (char[5], map options) 0x0e -- 1 bytes (0, seems to be a seperate sign) 0x0f -- 2 bytes (short, mapsize x) 0x11 -- 2 bytes (short, mapsize y) 0x13 -- 4 bytes (long, unknown, map checksum ?) 0x17 -- n bytes (string, mapname \0 terminated) 0x17+n -- m bytes (string, game creator \0 terminated, but we already set this to game before, :P) 0x17+n+m -- 2 bytes: \0 \0 (first \0 might be a reserved string for password, but blizzard didn't implement it, second \0 is the info string end sign) */ const char *pstr; if (!strlen(gameinfo)) { eventlog(eventlog_level_info,__FUNCTION__, "got empty gameinfo (from W3 client)"); return -1; } if (strlen(gameinfo) < 0xf + 2 + 1 + 2 + 4) { eventlog(eventlog_level_error, __FUNCTION__, "got too short W3 mapinfo"); return -1; } pstr = gameinfo + 9; pstr = _w3_decrypt_mapinfo(pstr); if (!pstr) return -1; /* after decryption we dont have the mask bytes anymore so offsets need * to be adjusted acordingly */ game_set_speed(game,w3speed_to_gspeed(bn_byte_get(*((bn_byte*)(pstr))))); game_set_mapsize_x(game, bn_short_get(*((bn_short*)(pstr + 5)))); game_set_mapsize_y(game, bn_short_get(*((bn_short*)(pstr + 7)))); game_set_mapname(game, pstr + 13); xfree((void*)pstr); return 0; } /* otherwise it's Starcraft, Brood War, or Warcraft II */ if (!(save = xstrdup(gameinfo))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for save"); return -1; } if (!(line1 = strtok(save,"\r"))) /* actual game info fields */ { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing line1) \"%s\"",gameinfo); xfree(save); return -1; } if (!(line2 = strtok(NULL,"\r"))) { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing player) \"%s\"",gameinfo); xfree(save); return -1; } /* is there room for another field after that? */ /* * This is the same as the normal strtok() function but it doesn't skip over * empty entries. The C-library strtok() will skip past entries like 12,,3 * and rather than you being able to get "12", "", "3" you get "12", "3". * Since some values returned by the client contain these empty entries we * need this. Unlike strtok() all state is recorded in the first argument. */ currtok = line1; if (!(unknown = strsep(&currtok,","))) /* skip past first field (always empty?) */ { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing unknown)"); xfree(save); return -1; } if (!(mapsize = strsep(&currtok,","))) { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing mapsize)"); xfree(save); return -1; } if (!(maxplayers = strsep(&currtok,","))) /* for later use (FIXME: what is upper field, max observers?) */ { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing maxplayers)"); xfree(save); return -1; } if (!(speed = strsep(&currtok,","))) { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing speed)"); xfree(save); return -1; } if (!(maptype = strsep(&currtok,","))) { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing maptype)"); xfree(save); return -1; } if (!(gametype = strsep(&currtok,","))) /* this is set from another field */ { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing gametype)"); xfree(save); return -1; } if (!(option = strsep(&currtok,","))) /* this is set from another field */ { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing option)"); xfree(save); return -1; } if (!(checksum = strsep(&currtok,","))) /* FIXME */ { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing checksum)"); xfree(save); return -1; } if (!(tileset = strsep(&currtok,","))) { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing tileset)"); xfree(save); return -1; } if (!(player = strsep(&currtok,","))) { eventlog(eventlog_level_error,__FUNCTION__,"bad gameinfo format (missing player)"); xfree(save); return -1; } mapname = line2; /* only one item on this line */ eventlog(eventlog_level_debug,__FUNCTION__,"got info \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"", mapsize, maxplayers, speed, maptype, gametype, option, checksum, tileset, player, mapname); /* The map size is determined by breaking the number into two pieces and * multiplying each piece by 32. * for example, 34 = (32*3) x (32*4) = 96 x 128 */ /* special handling for mapsize. empty is 256x256 */ if ((mapsize[0]=='\0') || (str_to_uint(mapsize,&bngmapsize)<0)) bngmapsize = 88; /* 256x256 */ game_set_mapsize_x(game,(bngmapsize/10)*32); game_set_mapsize_y(game,(bngmapsize%10)*32); /* special handling for maxplayers, empty is 8 */ if ((maxplayers[0]=='\0') || (str_to_uint(maxplayers,&bngmaxplayers)<0)) bngmaxplayers = 8; game_set_maxplayers(game,(bngmaxplayers%10)); /* special handling for gamespeed. empty is fast */ if ((speed[0]=='\0') || ( str_to_uint(speed,&bngspeed)<0)) bngspeed = CLIENT_GAMESPEED_FAST; game_set_speed(game,bngspeed_to_gspeed(bngspeed)); /* special handling for maptype. empty is self-made */ if ((maptype[0]=='\0') || (str_to_uint(maptype,&bngmaptype)<0)) bngmaptype = CLIENT_MAPTYPE_SELFMADE; game_set_maptype(game,bngmaptype_to_gmaptype(bngmaptype)); /* special handling for tileset. empty is badlands */ if ((tileset[0]=='\0') || (str_to_uint(tileset,&bngtileset)<0)) bngtileset = CLIENT_TILESET_BADLANDS; game_set_tileset(game,bngtileset_to_gtileset(bngtileset)); game_set_mapname(game,mapname); xfree(save); return 0; } pvpgn-1.8.5/src/bnetd/friends.c0000644000175000017500000001467011151345317015333 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strcasecmp.h" #include "common/eventlog.h" #include "common/list.h" #include "common/xalloc.h" #include "account.h" #include "prefs.h" #include "friends.h" #include "common/setup_after.h" extern t_account * friend_get_account(t_friend * fr) { if (fr == NULL) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL account"); return NULL; } return fr->friendacc; } extern int friend_set_account(t_friend * fr, t_account * acc) { if (fr == NULL) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL account"); return -1; } fr->friendacc=acc; return 0; } extern char friend_get_mutual(t_friend * fr) { if (fr == NULL) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL account"); return 0; } return fr->mutual; } extern int friend_set_mutual(t_friend * fr, char mutual) { if (fr == NULL) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL account"); return -1; } fr->mutual=mutual; return 0; } extern int friendlist_unload(t_list * flist) { t_elem * curr; t_friend * fr; if(flist==NULL) return -1; LIST_TRAVERSE(flist,curr) { if (!(fr = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } fr->mutual=-1; } return 0; } extern int friendlist_close(t_list * flist) { t_elem * curr; t_friend * fr; if(flist==NULL) return -1; LIST_TRAVERSE(flist,curr) { if (!(fr = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if (list_remove_elem(flist, &curr) < 0) eventlog(eventlog_level_error, __FUNCTION__, "could not remove elem from flist"); xfree((void *) fr); } list_destroy(flist); return 0; } extern int friendlist_purge(t_list * flist) { t_elem * curr; t_friend * fr; if(flist==NULL) return -1; LIST_TRAVERSE(flist,curr) { if (!(fr = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if (fr->mutual<0) { if(list_remove_elem(flist, &curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); } } return 0; } extern int friendlist_add_account(t_list * flist, t_account * acc, int mutual) { t_friend * fr; if(flist==NULL) return -1; fr = xmalloc(sizeof(t_friend)); fr->friendacc = acc; fr->mutual = mutual; list_append_data(flist, fr); return 0; } extern int friendlist_remove_friend(t_list * flist, t_friend * fr) { t_elem * elem; if(flist==NULL) return -1; if(fr!=NULL) { if(list_remove_data(flist, fr, &elem)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); return -1; } xfree((void *)fr); return 0; } return -1; } extern int friendlist_remove_account(t_list * flist, t_account * acc) { t_elem * elem; t_friend * fr; if(flist==NULL) return -1; fr=friendlist_find_account(flist, acc); if(fr!=NULL) { if(list_remove_data(flist, fr, &elem)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); return -1; } xfree((void *)fr); return 0; } return -1; } extern int friendlist_remove_username(t_list * flist, const char * accname) { t_elem * elem; t_friend * fr; if(flist==NULL) return -1; fr=friendlist_find_username(flist, accname); if(fr!=NULL) { if(list_remove_data(flist, fr, &elem)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); return -1; } xfree((void *)fr); return 0; } return -1; } extern t_friend * friendlist_find_account(t_list * flist, t_account * acc) { t_elem * curr; t_friend * fr; if(flist==NULL) return NULL; LIST_TRAVERSE(flist,curr) { if (!(fr = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if (fr->friendacc == acc) return fr; } return NULL; } extern t_friend * friendlist_find_username(t_list * flist, const char * accname) { t_elem * curr; t_friend * fr; if(flist==NULL) return NULL; LIST_TRAVERSE(flist,curr) { if (!(fr = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if (strcasecmp(account_get_name(fr->friendacc),accname)==0) return fr; } return NULL; } extern t_friend * friendlist_find_uid(t_list * flist, int uid) { t_elem * curr; t_friend * fr; if(flist==NULL) return NULL; LIST_TRAVERSE(flist,curr) { if (!(fr = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if (account_get_uid(fr->friendacc)==uid) return fr; } return NULL; } pvpgn-1.8.5/src/bnetd/game.h0000644000175000017500000002544111151345317014615 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_GAME_TYPES #define INCLUDED_GAME_TYPES #ifdef GAME_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # ifdef TIME_WITH_SYS_TIME # include # include # else # ifdef HAVE_SYS_TIME_H # include # else # include # endif # endif # include "account.h" # include "connection.h" # include "common/tag.h" # include "common/elist.h" #else # define JUST_NEED_TYPES # ifdef TIME_WITH_SYS_TIME # include # include # else # ifdef HAVE_SYS_TIME_H # include # else # include # endif # endif # include "account.h" # include "connection.h" # include "common/tag.h" # include "common/elist.h" # undef JUST_NEED_TYPES #endif #endif typedef enum { game_type_none, game_type_all, game_type_topvbot, game_type_melee, game_type_ffa, game_type_oneonone, game_type_ctf, game_type_greed, game_type_slaughter, game_type_sdeath, game_type_ladder, game_type_ironman, game_type_mapset, game_type_teammelee, game_type_teamffa, game_type_teamctf, game_type_pgl, game_type_diablo, game_type_diablo2open, game_type_diablo2closed, game_type_anongame } t_game_type; typedef enum { game_status_started, game_status_full, game_status_open, game_status_done, game_status_loaded } t_game_status; typedef enum { game_result_none, game_result_win, game_result_loss, game_result_draw, game_result_disconnect, game_result_observer, game_result_playing } t_game_result; typedef enum { game_option_none, game_option_melee_normal, game_option_ffa_normal, game_option_oneonone_normal, game_option_ctf_normal, game_option_greed_10000, game_option_greed_7500, game_option_greed_5000, game_option_greed_2500, game_option_slaughter_60, game_option_slaughter_45, game_option_slaughter_30, game_option_slaughter_15, game_option_sdeath_normal, game_option_ladder_countasloss, game_option_ladder_nopenalty, game_option_mapset_normal, game_option_teammelee_4, game_option_teammelee_3, game_option_teammelee_2, game_option_teamffa_4, game_option_teamffa_3, game_option_teamffa_2, game_option_teamctf_4, game_option_teamctf_3, game_option_teamctf_2, game_option_topvbot_7, game_option_topvbot_6, game_option_topvbot_5, game_option_topvbot_4, game_option_topvbot_3, game_option_topvbot_2, game_option_topvbot_1 } t_game_option; typedef enum { game_maptype_none, game_maptype_selfmade, game_maptype_blizzard, game_maptype_ladder, game_maptype_pgl, game_maptype_kbk, game_maptype_compusa } t_game_maptype; typedef enum { game_tileset_none, game_tileset_badlands, game_tileset_space, game_tileset_installation, game_tileset_ashworld, game_tileset_jungle, game_tileset_desert, game_tileset_ice, game_tileset_twilight } t_game_tileset; typedef enum { game_speed_none, game_speed_slowest, game_speed_slower, game_speed_slow, game_speed_normal, game_speed_fast, game_speed_faster, game_speed_fastest } t_game_speed; typedef enum { game_difficulty_none, game_difficulty_normal, game_difficulty_nightmare, game_difficulty_hell, game_difficulty_hardcore_normal, game_difficulty_hardcore_nightmare, game_difficulty_hardcore_hell } t_game_difficulty; typedef enum { game_flag_none, game_flag_private } t_game_flag; typedef struct game #ifdef GAME_INTERNAL_ACCESS { char const * name; char const * pass; char const * info; t_game_type type; unsigned int realm; char const * realmname; t_clienttag clienttag; /* type of client (STAR, SEXP, etc) */ unsigned int addr; /* host IP */ unsigned short port; /* host port */ int startver; unsigned long version; t_game_status status; unsigned int ref; /* current number of players */ unsigned int count; /* max number of players */ unsigned int id; char const * mapname; t_game_option option; t_game_maptype maptype; t_game_tileset tileset; t_game_speed speed; unsigned int mapsize_x; unsigned int mapsize_y; unsigned int maxplayers; t_connection * owner; t_connection * * connections; t_account * * players; t_game_result * results; t_game_result * * reported_results; char const * * report_heads; char const * * report_bodies; time_t create_time; time_t start_time; time_t lastaccess_time; int bad; /* if 1, then the results will be ignored */ t_game_difficulty difficulty; char const * description; t_game_flag flag; t_elist glist_link; } #endif t_game; typedef int (*t_glist_func)(t_game *, void *); #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_GAME_PROTOS #define INCLUDED_GAME_PROTOS #define MAX_GAME_EMPTY_TIME 300 #define STARTVER_UNKNOWN 0 #define STARTVER_GW1 1 #define STARTVER_GW3 3 #define STARTVER_GW4 4 #define STARTVER_REALM1 104 #define JUST_NEED_TYPES #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "account.h" #include "connection.h" #include "common/list.h" #include "common/tag.h" #undef JUST_NEED_TYPES extern char const * game_type_get_str(t_game_type type) ; extern char const * game_status_get_str(t_game_status status) ; extern char const * game_result_get_str(t_game_result result) ; extern char const * game_option_get_str(t_game_option option) ; extern char const * game_maptype_get_str(t_game_maptype maptype) ; extern char const * game_tileset_get_str(t_game_tileset tileset) ; extern char const * game_speed_get_str(t_game_speed speed) ; extern char const * game_difficulty_get_str(t_game_difficulty difficulty) ; extern t_game * game_create(char const * name, char const * pass, char const * info, t_game_type type, int startver, t_clienttag clienttag,unsigned long gameversion) ; extern unsigned int game_get_id(t_game const * game); extern char const * game_get_name(t_game const * game); extern t_game_type game_get_type(t_game const * game); extern t_game_maptype game_get_maptype(t_game const * game); extern int game_set_maptype(t_game * game, t_game_maptype maptype); extern t_game_tileset game_get_tileset(t_game const * game); extern int game_set_tileset(t_game * game, t_game_tileset tileset); extern t_game_speed game_get_speed(t_game const * game); extern int game_set_speed(t_game * game, t_game_speed speed); extern unsigned int game_get_mapsize_x(t_game const * game); extern int game_set_mapsize_x(t_game * game, unsigned int x); extern unsigned int game_get_mapsize_y(t_game const * game); extern int game_set_mapsize_y(t_game * game, unsigned int y); extern unsigned int game_get_maxplayers(t_game const * game); extern int game_set_maxplayers(t_game * game, unsigned int maxplayers); extern unsigned int game_get_difficulty(t_game const * game); extern int game_set_difficulty(t_game * game, unsigned int difficulty); extern char const * game_get_description(t_game const * game); extern int game_set_description(t_game * game, char const * description); extern char const * game_get_pass(t_game const * game); extern char const * game_get_info(t_game const * game); extern unsigned long game_get_version(t_game const * game); extern int game_get_startver(t_game const * game); extern unsigned int game_get_ref(t_game const * game); extern unsigned int game_get_count(t_game const * game); extern void game_set_status(t_game * game, t_game_status status); extern t_game_status game_get_status(t_game const * game); extern unsigned int game_get_addr(t_game const * game); extern unsigned short game_get_port(t_game const * game); extern unsigned int game_get_latency(t_game const * game); extern t_connection * game_get_player_conn(t_game const * game, unsigned int i); extern t_clienttag game_get_clienttag(t_game const * game); extern int game_add_player(t_game * game, char const * pass, int startver, t_connection * c); extern int game_del_player(t_game * game, t_connection * c); extern t_account * game_get_player(t_game * game, unsigned int i); extern int game_set_report(t_game * game, t_account * account, char const * head, char const * body); extern int game_set_reported_results(t_game * game, t_account * account, t_game_result * results); extern int game_set_self_report(t_game * game, t_account * account, t_game_result result); extern t_game_result * game_get_reported_results(t_game * game, t_account * account); extern char const * game_get_mapname(t_game const * game); extern int game_set_mapname(t_game * game, char const * mapname); extern t_connection * game_get_owner(t_game const * game); extern time_t game_get_create_time(t_game const * game); extern time_t game_get_start_time(t_game const * game); extern int game_set_option(t_game * game, t_game_option option); extern t_game_option game_get_option(t_game const * game); extern int gamelist_create(void); extern int gamelist_destroy(void); extern int gamelist_get_length(void); extern t_game * gamelist_find_game(char const * name, t_clienttag ctag, t_game_type type); extern t_game * gamelist_find_game_byid(unsigned int id); extern void gamelist_traverse(t_glist_func cb, void *data); extern int gamelist_total_games(void); extern int game_set_realm(t_game * game, unsigned int realm); extern unsigned int game_get_realm(t_game const * game); extern char const * game_get_realmname(t_game const * game); extern int game_set_realmname(t_game * game, char const * realmname); extern void gamelist_check_voidgame(void); extern void game_set_flag(t_game * game, t_game_flag flag); extern t_game_flag game_get_flag(t_game const * game); extern int game_get_count_by_clienttag(t_clienttag ct); extern int game_is_ladder(t_game *game); #endif #endif pvpgn-1.8.5/src/bnetd/watch.c0000644000175000017500000002207311151345317015003 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define WATCH_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strcasecmp.h" #include "common/field_sizes.h" #include "common/list.h" #include "account.h" #include "connection.h" #include "common/eventlog.h" #include "message.h" #include "watch.h" #include "friends.h" #include "common/tag.h" #include "common/xalloc.h" #include "prefs.h" #include "common/setup_after.h" static t_list * watchlist_head=NULL; /* who == NULL means anybody */ extern int watchlist_add_events(t_connection * owner, t_account * who, t_clienttag clienttag, t_watch_event events) { t_elem const * curr; t_watch_pair * pair; if (!owner) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL owner"); return -1; } LIST_TRAVERSE_CONST(watchlist_head,curr) { pair = elem_get_data(curr); if (!pair) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"watchlist contains NULL item"); return -1; } if (pair->owner==owner && pair->who==who && ((clienttag == pair->clienttag))) { pair->what |= events; return 0; } } pair = xmalloc(sizeof(t_watch_pair)); pair->owner = owner; pair->who = who; pair->what = events; pair->clienttag = clienttag; list_prepend_data(watchlist_head,pair); return 0; } /* who == NULL means anybody */ extern int watchlist_del_events(t_connection * owner, t_account * who, t_clienttag clienttag, t_watch_event events) { t_elem * curr; t_watch_pair * pair; if (!owner) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL owner"); return -1; } LIST_TRAVERSE(watchlist_head,curr) { pair = elem_get_data(curr); if (!pair) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"watchlist contains NULL item"); return -1; } if (pair->owner==owner && pair->who==who && ((!clienttag) || (clienttag == pair->clienttag))) { pair->what &= ~events; if (pair->what==0) { if (list_remove_elem(watchlist_head,&curr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove item"); pair->owner = NULL; } else xfree(pair); } return 0; } } return -1; /* not found */ } /* this differs from del_events because it doesn't return an error if nothing was found */ extern int watchlist_del_all_events(t_connection * owner) { t_elem * curr; t_watch_pair * pair; if (!owner) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL owner"); return -1; } LIST_TRAVERSE(watchlist_head,curr) { pair = elem_get_data(curr); if (!pair) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"watchlist contains NULL item"); return -1; } if (pair->owner==owner) { if (list_remove_elem(watchlist_head,&curr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove item"); pair->owner = NULL; } else { xfree(pair); } } } return 0; } /* this differs from del_events because it doesn't return an error if nothing was found */ extern int watchlist_del_by_account(t_account * who) { t_elem * curr; t_watch_pair * pair; if (!who) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } LIST_TRAVERSE(watchlist_head,curr) { pair = elem_get_data(curr); if (!pair) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"watchlist contains NULL item"); return -1; } if (pair->who==who) { if (list_remove_elem(watchlist_head,&curr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove item"); pair->owner = NULL; } else { xfree(pair); } } } return 0; } static int handle_event_whisper(t_account *account, char const *gamename, t_clienttag clienttag, t_watch_event event) { t_elem const * curr; t_watch_pair * pair; char msg[512]; int cnt = 0; char const *myusername; t_list * flist; t_connection * dest_c, * my_c; t_friend * fr; char const * game_title; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!(myusername = account_get_name(account))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account name"); return -1; } my_c = account_get_conn(account); game_title = clienttag_get_title(clienttag); /* mutual friends handling */ flist = account_get_friends(account); if(flist) { if (event == watch_event_joingame) { if (gamename) sprintf(msg,"Your friend %s has entered a %s game named \"%s\".",myusername,game_title,gamename); else sprintf(msg,"Your friend %s has entered a %s game",myusername,game_title); } if (event == watch_event_leavegame)sprintf(msg,"Your friend %s has left a %s game.",myusername,game_title); if (event == watch_event_login) sprintf(msg,"Your friend %s has entered %s.",myusername,prefs_get_servername()); if (event == watch_event_logout) sprintf(msg,"Your friend %s has left %s.",myusername,prefs_get_servername()); LIST_TRAVERSE(flist,curr) { if (!(fr = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } dest_c = connlist_find_connection_by_account(fr->friendacc); if (dest_c==NULL) /* If friend is offline, go on to next */ continue; else { cnt++; /* keep track of successful whispers */ if(friend_get_mutual(fr)) message_send_text(dest_c,message_type_whisper,NULL,msg); } } } if (cnt) eventlog(eventlog_level_info,__FUNCTION__,"notified %d friends about %s",cnt,myusername); /* watchlist handling */ if (event == watch_event_joingame) { if (gamename) sprintf(msg,"Watched user %s has entered a %s game named \"%s\".",myusername,game_title,gamename); else sprintf(msg,"Watched user %s has entered a %s game",myusername,game_title); } if (event == watch_event_leavegame)sprintf(msg,"Watched user %s has left a %s game.",myusername,game_title); if (event == watch_event_login) sprintf(msg,"Watched user %s has entered %s.",myusername,prefs_get_servername()); if (event == watch_event_logout) sprintf(msg,"Watched user %s has left %s",myusername,prefs_get_servername()); LIST_TRAVERSE_CONST(watchlist_head,curr) { pair = elem_get_data(curr); if (!pair) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"watchlist contains NULL item"); return -1; } if (pair->owner && (!pair->who || pair->who==account) && ((!pair->clienttag) || (clienttag == pair->clienttag)) && (pair->what&event)) { message_send_text(pair->owner,message_type_whisper,NULL,msg); } } return 0; } extern int watchlist_notify_event(t_account * who, char const * gamename, t_clienttag clienttag, t_watch_event event) { switch (event) { case watch_event_login: case watch_event_logout: case watch_event_joingame: case watch_event_leavegame: handle_event_whisper(who,gamename,clienttag,event); break; default: eventlog(eventlog_level_error,__FUNCTION__,"got unknown event %u",(unsigned int)event); return -1; } return 0; } extern int watchlist_create(void) { watchlist_head = list_create(); return 0; } extern int watchlist_destroy(void) { t_elem * curr; t_watch_pair * pair; if (watchlist_head) { LIST_TRAVERSE(watchlist_head,curr) { pair = elem_get_data(curr); if (!pair) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"watchlist contains NULL item"); continue; } if (list_remove_elem(watchlist_head,&curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); xfree(pair); } if (list_destroy(watchlist_head)<0) return -1; watchlist_head = NULL; } return 0; } pvpgn-1.8.5/src/bnetd/tick.c0000644000175000017500000000371111151345317014625 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/gettimeofday.h" #include "common/eventlog.h" #include "tick.h" #include "common/setup_after.h" /* * This routine returns the number of miliseconds that have passed since one second * before it is first called. This is used for timing fields in some packets. */ extern unsigned int get_ticks(void) { static int first=1; static long beginsec; struct timeval tv; if (gettimeofday(&tv,NULL)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not get time (gettimeofday: %s)",pstrerror(errno)); return 0; } if (first) { beginsec = tv.tv_sec-1; first = 0; } return (unsigned int)((tv.tv_sec-beginsec)*1000+tv.tv_usec/1000); } pvpgn-1.8.5/src/bnetd/ladder_calc.h0000644000175000017500000000271611151345317016121 0ustar aaronaaron/* * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_LADDER_CALC_TYPES #define INCLUDED_LADDER_CALC_TYPES typedef struct { double prob; unsigned int k; int adj; unsigned int oldrating; unsigned int oldrank; } t_ladder_info; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_LADDER_CALC_PROTOS #define INCLUDED_LADDER_CALC_PROTOS #define JUST_NEED_TYPES #include "ladder.h" #include "account.h" #include "game.h" #include "common/tag.h" #undef JUST_NEED_TYPES extern int ladder_calc_info(t_clienttag clienttag, t_ladder_id id, unsigned int count, t_account * * players, t_game_result * results, t_ladder_info * info); #endif #endif pvpgn-1.8.5/src/bnetd/sql_sqlite3.c0000644000175000017500000001360611151345317016142 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef WITH_SQL_SQLITE3 #include "common/setup_before.h" #ifdef HAVE_SQLITE3_H # include #endif #include #include "common/eventlog.h" #include "common/xalloc.h" #include "storage_sql.h" #include "sql_sqlite3.h" #include "common/setup_after.h" typedef struct { char** results; int rows; int columns; int crow; } t_sqlite3_res; static int sql_sqlite3_init(const char *, const char *, const char *, const char *, const char *, const char *); static int sql_sqlite3_close(void); static t_sql_res * sql_sqlite3_query_res(const char *); static int sql_sqlite3_query(const char *); static t_sql_row * sql_sqlite3_fetch_row(t_sql_res *); static void sql_sqlite3_free_result(t_sql_res *); static unsigned int sql_sqlite3_num_rows(t_sql_res *); static unsigned int sql_sqlite3_num_fields(t_sql_res *); static unsigned int sql_sqlite3_affected_rows(void); static t_sql_field * sql_sqlite3_fetch_fields(t_sql_res *); static int sql_sqlite3_free_fields(t_sql_field *); static void sql_sqlite3_escape_string(char *, const char *, int); t_sql_engine sql_sqlite3 = { '`', /* can't use single quotes or double quotes, ref: http://www.sqlite.org/lang_keywords.html */ sql_sqlite3_init, sql_sqlite3_close, sql_sqlite3_query_res, sql_sqlite3_query, sql_sqlite3_fetch_row, sql_sqlite3_free_result, sql_sqlite3_num_rows, sql_sqlite3_num_fields, sql_sqlite3_affected_rows, sql_sqlite3_fetch_fields, sql_sqlite3_free_fields, sql_sqlite3_escape_string }; static sqlite3 *db = NULL; static int sql_sqlite3_init(const char *host, const char *port, const char *socket, const char *name, const char *user, const char *pass) { /* SQLite3 has no host, port, socket, user or password and the database name is the path to the db file */ if (sqlite3_open(name, &db) != SQLITE_OK) { eventlog(eventlog_level_error, __FUNCTION__, "got error from sqlite3_open (%s)", sqlite3_errmsg(db)); sqlite3_close(db); return -1; } return 0; } static int sql_sqlite3_close(void) { if (db) { if (sqlite3_close(db) != SQLITE_OK) { eventlog(eventlog_level_error, __FUNCTION__, "got error from sqlite3_close (%s)", sqlite3_errmsg(db)); return -1; } db = NULL; } return 0; } static t_sql_res * sql_sqlite3_query_res(const char* query) { t_sqlite3_res *res; if (db == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "sqlite3 driver not initilized"); return NULL; } if (query == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL query"); return NULL; } res = xmalloc(sizeof(t_sqlite3_res)); if (sqlite3_get_table(db, query, &res->results, &res->rows, &res->columns, NULL) != SQLITE_OK) { /* eventlog(eventlog_level_debug, __FUNCTION__, "got error (%s) from query (%s)", sqlite3_errmsg(db), query); */ xfree((void*)res); return NULL; } res->crow = 0; return res; } static int sql_sqlite3_query(const char* query) { if (db == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "sqlite3 driver not initilized"); return -1; } if (query == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL query"); return -1; } return sqlite3_exec(db, query, NULL, NULL, NULL) == SQLITE_OK ? 0 : -1; } static t_sql_row * sql_sqlite3_fetch_row(t_sql_res *result) { t_sqlite3_res *res = (t_sqlite3_res*)result; if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return NULL; } return res->crow < res->rows ? (res->results + res->columns * (++res->crow)) : NULL; } static void sql_sqlite3_free_result(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return; } sqlite3_free_table(((t_sqlite3_res *)result)->results); xfree(result); } static unsigned int sql_sqlite3_num_rows(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return 0; } return ((t_sqlite3_res *)result)->rows; } static unsigned int sql_sqlite3_num_fields(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return 0; } return ((t_sqlite3_res *)result)->columns; } static unsigned int sql_sqlite3_affected_rows(void) { return sqlite3_changes(db); } static t_sql_field * sql_sqlite3_fetch_fields(t_sql_res *result) { if (result == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL result"); return NULL; } /* the first "row" is actually the field names */ return ((t_sqlite3_res*)result)->results; } static int sql_sqlite3_free_fields(t_sql_field *fields) { if (fields == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL fields"); return -1; } return 0; /* sqlite3_free_table() should free it properly */ } static void sql_sqlite3_escape_string(char *escape, const char *from, int len) { if (db == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "sqlite3 driver not initilized"); return; } sqlite3_snprintf(len * 2 + 1, escape, "%q", from); } #endif /* WITH_SQL_SQLITE3 */ pvpgn-1.8.5/src/bnetd/ladder.h0000644000175000017500000001502611151345317015135 0ustar aaronaaron/* * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_LADDER_TYPES #define INCLUDED_LADDER_TYPES #ifdef LADDER_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include "account.h" # include "ladder_binary.h" # include "common/tag.h" #else # define JUST_NEED_TYPES # include "account.h" # include "ladder_binary.h" # include "common/tag.h" # undef JUST_NEED_TYPES #endif #endif #define W3_XPCALC_MAXLEVEL 50 typedef enum { ladder_sort_highestrated, ladder_sort_mostwins, ladder_sort_mostgames } t_ladder_sort; typedef enum { ladder_time_active, ladder_time_current } t_ladder_time; typedef enum { ladder_id_none=0, ladder_id_normal=1, ladder_id_ironman=3, ladder_id_solo=5, ladder_id_team=6, ladder_id_ffa=7 } t_ladder_id; extern char * ladder_id_str[]; typedef enum { ladder_option_none=0, ladder_option_disconnectisloss=1 } t_ladder_option; typedef struct ladder_internal #ifdef LADDER_INTERNAL_ACCESS { int uid; int xp; int level; unsigned int teamcount; /* needed for AT ladder */ t_account *account; struct ladder_internal *prev; /* user with less XP */ struct ladder_internal *next; /* user with more XP */ } #endif t_ladder_internal; typedef struct ladder #ifdef LADDER_INTERNAL_ACCESS { t_ladder_internal *first; t_ladder_internal *last; int dirty; /* 0==no changes, 1==something changed */ t_binary_ladder_types type; t_clienttag clienttag; t_ladder_id ladder_id; } #endif t_ladder; #ifdef LADDER_INTERNAL_ACCESS typedef struct { int startxp, neededxp, lossfactor, mingames; } t_xplevel_entry; typedef struct { int higher_winxp, higher_lossxp, lower_winxp, lower_lossxp; } t_xpcalc_entry; #endif #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_LADDER_PROTOS #define INCLUDED_LADDER_PROTOS #define JUST_NEED_TYPES #include "account.h" #include "game.h" #include "ladder_calc.h" #include "ladder_binary.h" #include "common/tag.h" #undef JUST_NEED_TYPES extern int ladder_init_account(t_account * account, t_clienttag clienttag, t_ladder_id id); extern int ladder_check_map(char const * mapname, t_game_maptype maptype, t_clienttag clienttag); extern t_account * ladder_get_account_by_rank(unsigned int rank, t_ladder_sort lsort, t_ladder_time ltime, t_clienttag clienttag, t_ladder_id id); extern unsigned int ladder_get_rank_by_account(t_account * account, t_ladder_sort lsort, t_ladder_time ltime, t_clienttag clienttag, t_ladder_id id); extern int ladder_update(t_clienttag clienttag, t_ladder_id id, unsigned int count, t_account * * players, t_game_result * results, t_ladder_info * info, t_ladder_option opns); extern int ladderlist_make_all_active(void); extern int ladder_createxptable(const char *xplevelfile, const char *xpcalcfile); extern void ladder_destroyxptable(void); extern int ladder_war3_xpdiff(unsigned int winnerlevel, unsigned int looserlevel, int *, int *); extern int ladder_war3_updatelevel(unsigned int oldlevel, int xp); extern int ladder_war3_get_min_xp(unsigned int level); extern int war3_get_maxleveldiff(void); extern int war3_ladder_add(t_ladder *ladder, int uid, int xp, int level, t_account *account, unsigned int teamcount,t_clienttag clienttag); /* this function adds a user to the ladder and keeps the ladder sorted * returns 0 if everything is fine and -1 when error occured */ extern int war3_ladder_update(t_ladder *ladder, int uid, int xp, int level, t_account *account, unsigned int teamcount); /* this functions increases the xp of user with UID uid and corrects ranking * returns 0 if everything is fine * if user is not yet in ladder, he gets added automatically */ extern int ladder_get_rank(t_ladder *ladder, int uid, unsigned int teamcount, t_clienttag clienttag); /* this function returns the rank of a user with a given uid * returns 0 if no such user is found */ extern int ladder_update_all_accounts(void); /* write the correct ranking information to all user accounts * and cut down ladder size to given limit */ extern int ladders_write_to_file(void); /* outputs the ladders into files - for the guys that wanna make ladder pages */ extern void ladders_init(void); /* initialize the ladders */ extern void ladders_destroy(void); /* remove all ladder data from memory */ extern void ladders_load_accounts_to_ladderlists(void); /* enters all accounts from accountlist into the ladders */ extern void ladder_reload_conf(void); /* reloads relevant parameters from bnetd.conf (xml/std mode for ladder) */ extern t_account * ladder_get_account(t_ladder *ladder,int rank, unsigned int * teamcount, t_clienttag clienttag); /* returns the account that is on specified rank in specified ladder. also return teamcount for AT ladder * returns NULL if this rank is still vacant */ extern t_ladder * solo_ladder(t_clienttag clienttag); extern t_ladder * team_ladder(t_clienttag clienttag); extern t_ladder * ffa_ladder(t_clienttag clienttag); extern t_ladder * at_ladder(t_clienttag clienttag); extern t_ladder * ladder_ar(t_clienttag clienttag, t_ladder_id ladder_id); extern t_ladder * ladder_aw(t_clienttag clienttag, t_ladder_id ladder_id); extern t_ladder * ladder_ag(t_clienttag clienttag, t_ladder_id ladder_id); extern t_ladder * ladder_cr(t_clienttag clienttag, t_ladder_id ladder_id); extern t_ladder * ladder_cw(t_clienttag clienttag, t_ladder_id ladder_id); extern t_ladder * ladder_cg(t_clienttag clienttag, t_ladder_id ladder_id); /* for external clienttag specific reference of the ladders */ extern int ladder_get_from_ladder(t_binary_ladder_types type, int rank, int * results); extern int ladder_put_into_ladder(t_binary_ladder_types type, int * values); #endif #endif extern char * create_filename(const char * path, const char * filename, const char * ending); pvpgn-1.8.5/src/bnetd/account_wrap.c0000644000175000017500000020240211151345317016356 0ustar aaronaaron/* * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define CHARACTER_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "common/list.h" #include "common/eventlog.h" #include "common/util.h" #include "common/bnettime.h" #include "ladder.h" #include "account.h" #include "account_wrap.h" #include "character.h" #include "connection.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include "common/bnet_protocol.h" #include "common/tag.h" #include "command.h" #include "prefs.h" #include "friends.h" #include "clan.h" #include "anongame_infos.h" #include "team.h" #include "common/setup_after.h" static unsigned int char_icon_to_uint(char * icon); extern unsigned int account_get_numattr_real(t_account * account, char const * key, char const * fn, unsigned int ln) { char const * temp; unsigned int val; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account (from %s:%u)",fn,ln); return 0; } if (!key) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL key (from %s:%u)",fn,ln); return 0; } if (!(temp = account_get_strattr(account,key))) return 0; if (str_to_uint(temp,&val)<0) { eventlog(eventlog_level_error,__FUNCTION__,"not a numeric string \"%s\" for key \"%s\"",temp,key); return 0; } return val; } extern int account_set_numattr(t_account * account, char const * key, unsigned int val) { char temp[32]; /* should be more than enough room */ if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!key) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL key"); return -1; } sprintf(temp,"%u",val); return account_set_strattr(account,key,temp); } extern int account_get_boolattr_real(t_account * account, char const * key, char const * fn, unsigned int ln) { char const * temp; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account (from %s:%u)",fn,ln); return -1; } if (!key) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL key (from %s:%u)",fn,ln); return -1; } if (!(temp = account_get_strattr(account,key))) return -1; switch (str_get_bool(temp)) { case 1: return 1; case 0: return 0; default: eventlog(eventlog_level_error,__FUNCTION__,"bad boolean value \"%s\" for key \"%s\"",temp,key); return -1; } } extern int account_set_boolattr(t_account * account, char const * key, int val) { if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!key) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL key"); return -1; } return account_set_strattr(account,key,val?"true":"false"); } /****************************************************************/ extern char const * account_get_pass(t_account * account) { return account_get_strattr(account,"BNET\\acct\\passhash1"); } extern int account_set_pass(t_account * account, char const * passhash1) { return account_set_strattr(account,"BNET\\acct\\passhash1",passhash1); } /****************************************************************/ extern int account_get_auth_admin(t_account * account, char const * channelname) { char temp[256]; if (!channelname) return account_get_boolattr(account, "BNET\\auth\\admin"); sprintf(temp,"BNET\\auth\\admin\\%.100s",channelname); return account_get_boolattr(account, temp); } extern int account_set_auth_admin(t_account * account, char const * channelname, int val) { char temp[256]; if (!channelname) return account_set_boolattr(account, "BNET\\auth\\admin", val); sprintf(temp,"BNET\\auth\\admin\\%.100s",channelname); return account_set_boolattr(account, temp, val); } extern int account_get_auth_announce(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\announce"); } extern int account_get_auth_botlogin(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\botlogin"); } extern int account_get_auth_bnetlogin(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\normallogin"); } extern int account_get_auth_operator(t_account * account, char const * channelname) { char temp[256]; if (!channelname) return account_get_boolattr(account,"BNET\\auth\\operator"); sprintf(temp,"BNET\\auth\\operator\\%.100s",channelname); return account_get_boolattr(account,temp); } extern int account_set_auth_operator(t_account * account, char const * channelname, int val) { char temp[256]; if (!channelname) return account_set_boolattr(account, "BNET\\auth\\operator", val); sprintf(temp,"BNET\\auth\\operator\\%.100s",channelname); return account_set_boolattr(account, temp, val); } extern int account_get_auth_voice(t_account * account, char const * channelname) { char temp[256]; sprintf(temp,"BNET\\auth\\voice\\%.100s",channelname); return account_get_boolattr(account,temp); } extern int account_set_auth_voice(t_account * account, char const * channelname, int val) { char temp[256]; sprintf(temp,"BNET\\auth\\voice\\%.100s",channelname); return account_set_boolattr(account, temp, val); } extern int account_get_auth_changepass(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\changepass"); } extern int account_get_auth_changeprofile(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\changeprofile"); } extern int account_get_auth_createnormalgame(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\createnormalgame"); } extern int account_get_auth_joinnormalgame(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\joinnormalgame"); } extern int account_get_auth_createladdergame(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\createladdergame"); } extern int account_get_auth_joinladdergame(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\joinladdergame"); } extern int account_get_auth_lock(t_account * account) { return account_get_boolattr(account,"BNET\\auth\\lockk"); } extern int account_set_auth_lock(t_account * account, int val) { return account_set_boolattr(account,"BNET\\auth\\lockk",val); } /****************************************************************/ extern char const * account_get_sex(t_account * account) { char const * temp; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } if (!(temp = account_get_strattr(account,"profile\\sex"))) return ""; return temp; } extern char const * account_get_age(t_account * account) { char const * temp; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } if (!(temp = account_get_strattr(account,"profile\\age"))) return ""; return temp; } extern char const * account_get_loc(t_account * account) { char const * temp; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } if (!(temp = account_get_strattr(account,"profile\\location"))) return ""; return temp; } extern char const * account_get_desc(t_account * account) { char const * temp; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } if (!(temp = account_get_strattr(account,"profile\\description"))) return ""; return temp; } /****************************************************************/ extern unsigned int account_get_ll_time(t_account * account) { return account_get_numattr(account,"BNET\\acct\\lastlogin_time"); } extern int account_set_ll_time(t_account * account, unsigned int t) { return account_set_numattr(account,"BNET\\acct\\lastlogin_time",t); } extern t_clienttag account_get_ll_clienttag(t_account * account) { char const * clienttag; t_clienttag clienttag_uint; clienttag = account_get_strattr(account,"BNET\\acct\\lastlogin_clienttag"); clienttag_uint= tag_str_to_uint(clienttag); return clienttag_uint; } extern int account_set_ll_clienttag(t_account * account, t_clienttag clienttag) { char clienttag_str[5]; return account_set_strattr(account,"BNET\\acct\\lastlogin_clienttag",tag_uint_to_str(clienttag_str,clienttag)); } extern char const * account_get_ll_user(t_account * account) { return account_get_strattr(account,"BNET\\acct\\lastlogin_user"); } extern int account_set_ll_user(t_account * account, char const * user) { return account_set_strattr(account,"BNET\\acct\\lastlogin_user",user); } extern char const * account_get_ll_owner(t_account * account) { return account_get_strattr(account,"BNET\\acct\\lastlogin_owner"); } extern int account_set_ll_owner(t_account * account, char const * owner) { return account_set_strattr(account,"BNET\\acct\\lastlogin_owner",owner); } extern char const * account_get_ll_ip(t_account * account) { return account_get_strattr(account,"BNET\\acct\\lastlogin_ip"); } extern int account_set_ll_ip(t_account * account, char const * ip) { return account_set_strattr(account,"BNET\\acct\\lastlogin_ip",ip); } /****************************************************************/ extern unsigned int account_get_normal_wins(t_account * account, t_clienttag clienttag) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\0\\wins",tag_uint_to_str(clienttag_str,clienttag)); return account_get_numattr(account,key); } extern int account_inc_normal_wins(t_account * account, t_clienttag clienttag) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\0\\wins",tag_uint_to_str(clienttag_str,clienttag)); return account_set_numattr(account,key,account_get_normal_wins(account,clienttag)+1); } extern int account_set_normal_wins(t_account * account, t_clienttag clienttag, unsigned wins) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\0\\wins",tag_uint_to_str(clienttag_str,clienttag)); return account_set_numattr(account,key,wins); } extern unsigned int account_get_normal_losses(t_account * account, t_clienttag clienttag) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\0\\losses",tag_uint_to_str(clienttag_str,clienttag)); return account_get_numattr(account,key); } extern int account_inc_normal_losses(t_account * account, t_clienttag clienttag) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\0\\losses",tag_uint_to_str(clienttag_str,clienttag)); return account_set_numattr(account,key,account_get_normal_losses(account,clienttag)+1); } extern int account_set_normal_losses(t_account * account, t_clienttag clienttag,unsigned losses) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\0\\losses",tag_uint_to_str(clienttag_str,clienttag)); return account_set_numattr(account,key,losses); } extern unsigned int account_get_normal_draws(t_account * account, t_clienttag clienttag) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\0\\draws",tag_uint_to_str(clienttag_str,clienttag)); return account_get_numattr(account,key); } extern int account_inc_normal_draws(t_account * account, t_clienttag clienttag) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\0\\draws",tag_uint_to_str(clienttag_str,clienttag)); return account_set_numattr(account,key,account_get_normal_draws(account,clienttag)+1); } extern unsigned int account_get_normal_disconnects(t_account * account, t_clienttag clienttag) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\0\\disconnects",tag_uint_to_str(clienttag_str,clienttag)); return account_get_numattr(account,key); } extern int account_inc_normal_disconnects(t_account * account, t_clienttag clienttag) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\0\\disconnects",tag_uint_to_str(clienttag_str,clienttag)); return account_set_numattr(account,key,account_get_normal_disconnects(account,clienttag)+1); } extern int account_set_normal_disconnects(t_account * account, t_clienttag clienttag,unsigned discs) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\0\\disconnects",tag_uint_to_str(clienttag_str,clienttag)); return account_set_numattr(account,key,discs); } extern int account_set_normal_last_time(t_account * account, t_clienttag clienttag, t_bnettime t) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\0\\last game",tag_uint_to_str(clienttag_str,clienttag)); return account_set_strattr(account,key,bnettime_get_str(t)); } extern int account_set_normal_last_result(t_account * account, t_clienttag clienttag, char const * result) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\0\\last game result",tag_uint_to_str(clienttag_str,clienttag)); return account_set_strattr(account,key,result); } /****************************************************************/ extern unsigned int account_get_ladder_active_wins(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\active wins",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_numattr(account,key); } extern int account_set_ladder_active_wins(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int wins) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\active wins",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,wins); } extern unsigned int account_get_ladder_active_losses(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\active losses",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_numattr(account,key); } extern int account_set_ladder_active_losses(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int losses) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\active losses",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,losses); } extern unsigned int account_get_ladder_active_draws(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\active draws",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_numattr(account,key); } extern int account_set_ladder_active_draws(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int draws) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\active draws",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,draws); } extern unsigned int account_get_ladder_active_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\active disconnects",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_numattr(account,key); } extern int account_set_ladder_active_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int disconnects) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\active disconnects",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,disconnects); } extern unsigned int account_get_ladder_active_rating(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\active rating",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_numattr(account,key); } extern int account_set_ladder_active_rating(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int rating) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\active rating",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,rating); } extern int account_get_ladder_active_rank(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\active rank",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_numattr(account,key); } extern int account_set_ladder_active_rank(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int rank) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\active rank",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,rank); } extern char const * account_get_ladder_active_last_time(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return NULL; } sprintf(key,"Record\\%s\\%d\\active last game",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_strattr(account,key); } extern int account_set_ladder_active_last_time(t_account * account, t_clienttag clienttag, t_ladder_id id, t_bnettime t) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\active last game",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_strattr(account,key,bnettime_get_str(t)); } /****************************************************************/ extern unsigned int account_get_ladder_wins(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%s\\wins",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_get_numattr(account,key); } extern int account_inc_ladder_wins(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%s\\wins",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_set_numattr(account,key,account_get_ladder_wins(account,clienttag,id)+1); } extern int account_set_ladder_wins(t_account * account, t_clienttag clienttag, t_ladder_id id,unsigned wins) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%s\\wins",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_set_numattr(account,key,wins); } extern unsigned int account_get_ladder_losses(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%s\\losses",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_get_numattr(account,key); } extern int account_inc_ladder_losses(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%s\\losses",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_set_numattr(account,key,account_get_ladder_losses(account,clienttag,id)+1); } extern int account_set_ladder_losses(t_account * account, t_clienttag clienttag, t_ladder_id id,unsigned losses) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%s\\losses",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_set_numattr(account,key,losses); } extern unsigned int account_get_ladder_draws(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\draws",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_numattr(account,key); } extern int account_inc_ladder_draws(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\draws",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,account_get_ladder_draws(account,clienttag,id)+1); } extern unsigned int account_get_ladder_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\disconnects",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_numattr(account,key); } extern int account_inc_ladder_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\disconnects",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,account_get_ladder_disconnects(account,clienttag,id)+1); } extern int account_set_ladder_disconnects(t_account * account, t_clienttag clienttag, t_ladder_id id,unsigned discs) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\disconnects",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,discs); } extern unsigned int account_get_ladder_rating(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\rating",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_get_numattr(account,key); } extern int account_set_ladder_rating(t_account * account, t_clienttag clienttag, t_ladder_id id,unsigned rating) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%d\\rating",tag_uint_to_str(clienttag_str,clienttag),(int)id); return account_set_numattr(account,key,rating); } extern int account_adjust_ladder_rating(t_account * account, t_clienttag clienttag, t_ladder_id id, int delta) { char key[256]; char clienttag_str[5]; unsigned int oldrating; unsigned int newrating; int retval=0; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } sprintf(key,"Record\\%s\\%d\\rating",tag_uint_to_str(clienttag_str,clienttag),(int)id); /* don't allow rating to go below 1 */ oldrating = account_get_ladder_rating(account,clienttag,id); if (delta<0 && oldrating<=(unsigned int)-delta) newrating = 1; else newrating = oldrating+delta; if (account_set_numattr(account,key,newrating)<0) retval = -1; if (newrating>account_get_ladder_high_rating(account,clienttag,id)) { sprintf(key,"Record\\%s\\%d\\high rating",tag_uint_to_str(clienttag_str,clienttag),(int)id); if (account_set_numattr(account,key,newrating)<0) retval = -1; } return retval; } extern int account_get_ladder_rank(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return 0; } sprintf(key,"Record\\%s\\%s\\rank",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_get_numattr(account,key); } extern int account_set_ladder_rank(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int rank) { char key[256]; char clienttag_str[5]; unsigned int oldrank; int retval=0; if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } // if (rank==0) // eventlog(eventlog_level_warn,__FUNCTION__,"setting rank to zero?"); sprintf(key,"Record\\%s\\%s\\rank",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); if (account_set_numattr(account,key,rank)<0) retval = -1; oldrank = account_get_ladder_high_rank(account,clienttag,id); if (oldrank==0 || rankrealmname,ch->name); sprintf(key,"BNET\\CharacterList\\%s\\%s\\0",tag_uint_to_str(clienttag_str,clienttag),ch->realmname); old_list = account_get_strattr(account, key); if (old_list) { sprintf(chars_in_realm, "%s,%s", old_list, ch->name); } else { sprintf(chars_in_realm, "%s", ch->name); } eventlog(eventlog_level_debug,__FUNCTION__,"new character list for realm \"%s\" is \"%s\"", ch->realmname, chars_in_realm); account_set_strattr(account, key, chars_in_realm); sprintf(key,"BNET\\Characters\\%s\\%s\\%s\\0",tag_uint_to_str(clienttag_str,clienttag),ch->realmname,ch->name); str_to_hex(hex_buffer, ch->data, ch->datalen); account_set_strattr(account,key,hex_buffer); /* eventlog(eventlog_level_debug,__FUNCTION__,"key \"%s\"", key); eventlog(eventlog_level_debug,__FUNCTION__,"value \"%s\"", hex_buffer); */ return 0; } extern int account_set_friend( t_account * account, int friendnum, unsigned int frienduid ) { char key[256]; if ( frienduid == 0 || friendnum < 0 || friendnum >= prefs_get_max_friends()) { return -1; } sprintf(key, "friend\\%d\\uid", friendnum); return account_set_numattr( account, key, frienduid); } extern unsigned int account_get_friend( t_account * account, int friendnum) { char key[256]; int tmp; char const * name; t_account * acct; if (friendnum < 0 || friendnum >= prefs_get_max_friends()) { // bogus name (user himself) instead of NULL, otherwise clients might crash eventlog(eventlog_level_error, __FUNCTION__, "invalid friendnum %d (max: %d)", friendnum, prefs_get_max_friends()); return 0; } sprintf(key, "friend\\%d\\uid", friendnum); tmp = account_get_numattr(account, key); if(!tmp) { // ok, looks like we have a problem. Maybe friends still stored in old format? sprintf(key,"friend\\%d\\name",friendnum); name = account_get_strattr(account,key); if (name) { if ((acct = accountlist_find_account(name)) != NULL) { tmp = account_get_uid(acct); account_set_friend(account,friendnum,tmp); account_set_strattr(account,key,NULL); //remove old username-based friend now return tmp; } account_set_strattr(account,key,NULL); //remove old username-based friend now eventlog(eventlog_level_warn, __FUNCTION__, "unexistant friend name ('%s') in old storage format", name); return 0; } eventlog(eventlog_level_error, __FUNCTION__, "could not find friend (friendno: %d of '%s')", friendnum, account_get_name(account)); return 0; } return tmp; } static int account_set_friendcount( t_account * account, int count) { if (count < 0 || count > prefs_get_max_friends()) { return -1; } return account_set_numattr( account, "friend\\count", count); } extern int account_get_friendcount( t_account * account ) { return account_get_numattr( account, "friend\\count" ); } extern int account_add_friend( t_account * my_acc, t_account * facc) { unsigned my_uid; unsigned fuid; int nf; t_list *flist; if (my_acc == NULL || facc == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL account"); return -1; } my_uid = account_get_uid(my_acc); fuid = account_get_uid(facc); if (my_acc == facc) return -2; nf = account_get_friendcount(my_acc); if (nf >= prefs_get_max_friends()) return -3; flist = account_get_friends(my_acc); if (flist == NULL) return -1; if (friendlist_find_account(flist, facc) != NULL) return -4; account_set_friend(my_acc, nf, fuid); account_set_friendcount(my_acc, nf + 1); if (account_check_mutual(facc, my_uid) == 0) friendlist_add_account(flist, facc, 1); else friendlist_add_account(flist, facc, 0); return 0; } extern int account_remove_friend( t_account * account, int friendnum ) { unsigned i; int n = account_get_friendcount(account); if (account == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL account"); return -1; } if (friendnum < 0 || friendnum >= n) { eventlog(eventlog_level_error, __FUNCTION__, "got invalid friendnum (friendnum: %d max: %d)", friendnum, n); return -1; } for(i = friendnum ; i < n - 1; i++) account_set_friend(account, i, account_get_friend(account, i + 1)); account_set_friend(account, n-1, 0); /* FIXME: should delete the attribute */ account_set_friendcount(account, n-1); return 0; } extern int account_remove_friend2( t_account * account, const char * friend) { t_list *flist; t_friend *fr; unsigned i, uid; int n; if (account == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL account"); return -1; } if (friend == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL friend username"); return -1; } if ((flist = account_get_friends(account)) == NULL) return -1; if ((fr = friendlist_find_username(flist, friend)) == NULL) return -2; n = account_get_friendcount(account); uid = account_get_uid(friend_get_account(fr)); for (i = 0; i < n; i++) if (account_get_friend(account, i) == uid) { t_list * fflist; t_friend * ffr; t_account * facc; account_remove_friend(account, i); if((facc = friend_get_account(fr)) && (fflist = account_get_friends(facc)) && (ffr = friendlist_find_account(fflist, account))) friend_set_mutual(ffr, 0); friendlist_remove_friend(flist, fr); return i; } return -2; } // Some Extra Commands for REAL admins to promote other users to Admins // And Moderators of channels extern int account_set_admin( t_account * account ) { return account_set_strattr( account, "BNET\\auth\\admin", "true"); } extern int account_set_demoteadmin( t_account * account ) { return account_set_strattr( account, "BNET\\auth\\admin", "false" ); } extern unsigned int account_get_command_groups(t_account * account) { return account_get_numattr(account,"BNET\\auth\\command_groups"); } extern int account_set_command_groups(t_account * account, unsigned int groups) { return account_set_numattr(account,"BNET\\auth\\command_groups",groups); } // WAR3 Play Game & Profile Funcs extern char const * race_get_str(unsigned int race) { switch(race) { case W3_RACE_ORCS: return "orcs"; case W3_RACE_HUMANS: return "humans"; case W3_RACE_UNDEAD: case W3_ICON_UNDEAD: return "undead"; case W3_RACE_NIGHTELVES: return "nightelves"; case W3_RACE_RANDOM: case W3_ICON_RANDOM: return "random"; case W3_RACE_DEMONS: case W3_ICON_DEMONS: return "demons"; default: eventlog(eventlog_level_warn,__FUNCTION__,"unknown race: %x", race); return NULL; } } extern int account_inc_racewins( t_account * account, unsigned int intrace, t_clienttag clienttag) { char table[256]; char clienttag_str[5]; unsigned int wins; char const * race = race_get_str(intrace); if(!race) return -1; sprintf(table,"Record\\%s\\%s\\wins",tag_uint_to_str(clienttag_str,clienttag), race); wins = account_get_numattr(account,table); wins++; return account_set_numattr(account,table,wins); } extern int account_get_racewins( t_account * account, unsigned int intrace, t_clienttag clienttag) { char table[256]; char clienttag_str[5]; char const *race = race_get_str(intrace); if(!race) return 0; sprintf(table,"Record\\%s\\%s\\wins",tag_uint_to_str(clienttag_str,clienttag), race); return account_get_numattr(account,table); } extern int account_inc_racelosses( t_account * account, unsigned int intrace, t_clienttag clienttag) { char table[256]; char clienttag_str[5]; unsigned int losses; char const *race = race_get_str(intrace); if(!race) return -1; sprintf(table,"Record\\%s\\%s\\losses",tag_uint_to_str(clienttag_str,clienttag),race); losses=account_get_numattr(account,table); losses++; return account_set_numattr(account,table,losses); } extern int account_get_racelosses( t_account * account, unsigned int intrace, t_clienttag clienttag) { char table[256]; char clienttag_str[5]; char const *race = race_get_str(intrace); if(!race) return 0; sprintf(table,"Record\\%s\\%s\\losses",tag_uint_to_str(clienttag_str,clienttag),race); return account_get_numattr(account,table); } extern int account_update_xp(t_account * account, t_clienttag clienttag, t_game_result gameresult, unsigned int opponlevel, int * xp_diff,t_ladder_id id) { int xp; int mylevel; int xpdiff = 0, placeholder; xp = account_get_ladder_xp(account, clienttag,id); //get current xp if (xp < 0) { eventlog(eventlog_level_error, __FUNCTION__, "got negative XP"); return -1; } mylevel = account_get_ladder_level(account,clienttag,id); //get accounts level if (mylevel > W3_XPCALC_MAXLEVEL) { eventlog(eventlog_level_error, __FUNCTION__, "got invalid level: %d", mylevel); return -1; } if(mylevel<=0) //if level is 0 then set it to 1 mylevel=1; if (opponlevel < 1) opponlevel = 1; switch (gameresult) { case game_result_win: ladder_war3_xpdiff(mylevel, opponlevel, &xpdiff, &placeholder); break; case game_result_loss: ladder_war3_xpdiff(opponlevel, mylevel, &placeholder, &xpdiff); break; default: eventlog(eventlog_level_error, __FUNCTION__, "got invalid game result: %d", gameresult); return -1; } *xp_diff = xpdiff; xp += xpdiff; if (xp < 0) xp = 0; return account_set_ladder_xp(account,clienttag,id,xp); } extern int account_get_ladder_xp(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; sprintf(key,"Record\\%s\\%s\\xp",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_get_numattr(account,key); } extern int account_set_ladder_xp(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int xp) { char key[256]; char clienttag_str[5]; sprintf(key,"Record\\%s\\%s\\xp",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_set_numattr(account,key,xp); } extern int account_get_ladder_level(t_account * account, t_clienttag clienttag, t_ladder_id id) { char key[256]; char clienttag_str[5]; sprintf(key,"Record\\%s\\%s\\level",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_get_numattr(account,key); } extern int account_set_ladder_level(t_account * account, t_clienttag clienttag, t_ladder_id id, unsigned int level) { char key[256]; char clienttag_str[5]; sprintf(key,"Record\\%s\\%s\\level",tag_uint_to_str(clienttag_str,clienttag),ladder_id_str[(int)id]); return account_set_numattr(account,key,level); } extern int account_adjust_ladder_level(t_account * account, t_clienttag clienttag,t_ladder_id id) { int xp,mylevel; xp = account_get_ladder_xp(account, clienttag,id); if (xp < 0) xp = 0; mylevel = account_get_ladder_level(account,clienttag,id); if (mylevel < 1) mylevel = 1; if (mylevel > W3_XPCALC_MAXLEVEL) { eventlog(eventlog_level_error, __FUNCTION__, "got invalid level: %d", mylevel); return -1; } mylevel = ladder_war3_updatelevel(mylevel, xp); return account_set_ladder_level(account,clienttag,id,mylevel); } //Other funcs used in profiles and PG saving extern void account_get_raceicon(t_account * account, char * raceicon, unsigned int * raceiconnumber, unsigned int * wins, t_clienttag clienttag) //Based of wins for each race, Race with most wins, gets shown in chat channel { unsigned int humans; unsigned int orcs; unsigned int undead; unsigned int nightelf; unsigned int random; unsigned int i; random = account_get_racewins(account,W3_RACE_RANDOM,clienttag); humans = account_get_racewins(account,W3_RACE_HUMANS,clienttag); orcs = account_get_racewins(account,W3_RACE_ORCS,clienttag); undead = account_get_racewins(account,W3_RACE_UNDEAD,clienttag); nightelf = account_get_racewins(account,W3_RACE_NIGHTELVES,clienttag); if(orcs>=humans && orcs>=undead && orcs>=nightelf && orcs>=random) { *raceicon = 'O'; *wins = orcs; } else if(humans>=orcs && humans>=undead && humans>=nightelf && humans>=random) { *raceicon = 'H'; *wins = humans; } else if(nightelf>=humans && nightelf>=orcs && nightelf>=undead && nightelf>=random) { *raceicon = 'N'; *wins = nightelf; } else if(undead>=humans && undead>=orcs && undead>=nightelf && undead>=random) { *raceicon = 'U'; *wins = undead; } else { *raceicon = 'R'; *wins = random; } i = 1; while((signed)*wins >= anongame_infos_get_ICON_REQ(i,clienttag) && anongame_infos_get_ICON_REQ(i,clienttag) > 0) i++; *raceiconnumber = i ; } extern int account_get_profile_calcs(t_account * account, int xp, unsigned int Level) { int xp_min; int xp_max; unsigned int i; int t; unsigned int startlvl; if (Level==1) startlvl = 1; else startlvl = Level-1; for (i = startlvl; i < W3_XPCALC_MAXLEVEL; i++) { xp_min = ladder_war3_get_min_xp(i); xp_max = ladder_war3_get_min_xp(i+1); if ((xp >= xp_min) && (xp < xp_max)) { t = (int)((((double)xp - (double)xp_min) / ((double)xp_max - (double)xp_min)) * 128); if (i < Level) { return 128 + t; } else { return t; } } } return 0; } extern int account_set_saveladderstats(t_account * account,unsigned int gametype, t_game_result result, unsigned int opponlevel, t_clienttag clienttag) { unsigned int intrace; int xpdiff,uid,level; t_ladder_id id; t_ladder * ladder; if(!account) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL account"); return -1; } //added for better tracking down of problems with gameresults eventlog(eventlog_level_trace,__FUNCTION__,"parsing game result for player: %s result: %s",account_get_name(account),(result==game_result_win)?"WIN":"LOSS"); intrace = account_get_w3pgrace(account, clienttag); uid = account_get_uid(account); switch (gametype) { case ANONGAME_TYPE_1V1: //1v1 { id = ladder_id_solo; ladder = solo_ladder(clienttag); break; } case ANONGAME_TYPE_2V2: case ANONGAME_TYPE_3V3: case ANONGAME_TYPE_4V4: case ANONGAME_TYPE_5V5: case ANONGAME_TYPE_6V6: case ANONGAME_TYPE_2V2V2: case ANONGAME_TYPE_3V3V3: case ANONGAME_TYPE_4V4V4: case ANONGAME_TYPE_2V2V2V2: case ANONGAME_TYPE_3V3V3V3: { id = ladder_id_team; ladder = team_ladder(clienttag); break; } case ANONGAME_TYPE_SMALL_FFA: { id = ladder_id_ffa; ladder = ffa_ladder(clienttag); break; } default: eventlog(eventlog_level_error,__FUNCTION__,"Invalid Gametype? %u",gametype); return -1; } if(result == game_result_win) //win { account_inc_ladder_wins(account, clienttag,id); account_inc_racewins(account, intrace, clienttag); } if(result == game_result_loss) //loss { account_inc_ladder_losses(account, clienttag,id); account_inc_racelosses(account,intrace, clienttag); } account_update_xp(account,clienttag,result,opponlevel,&xpdiff,id); account_adjust_ladder_level(account,clienttag,id); level = account_get_ladder_level(account,clienttag,id); if (war3_ladder_update(ladder,uid,xpdiff,level,account,0)!=0) war3_ladder_add(ladder,uid,account_get_ladder_xp(account,clienttag,id),level,account,0,clienttag); return 0; } extern int account_set_w3pgrace( t_account * account, t_clienttag clienttag, unsigned int race) { char key[256]; char clienttag_str[5]; sprintf(key,"Record\\%s\\w3pgrace",tag_uint_to_str(clienttag_str,clienttag)); return account_set_numattr( account, key, race); } extern int account_get_w3pgrace( t_account * account, t_clienttag clienttag ) { char key[256]; char clienttag_str[5]; sprintf(key,"Record\\%s\\w3pgrace",tag_uint_to_str(clienttag_str,clienttag)); return account_get_numattr( account, key); } // Arranged Team Functions extern int account_set_currentatteam(t_account * account, unsigned int teamcount) { return account_set_numattr(account,"BNET\\current_at_team",teamcount); } extern int account_get_currentatteam(t_account * account) { return account_get_numattr(account,"BNET\\current_at_team"); } extern int account_get_highestladderlevel(t_account * account,t_clienttag clienttag) { t_elem * curr; t_team * team; unsigned int sololevel = account_get_ladder_level(account,clienttag,ladder_id_solo); unsigned int teamlevel = account_get_ladder_level(account,clienttag,ladder_id_team); unsigned int ffalevel = account_get_ladder_level(account,clienttag,ladder_id_ffa); unsigned int atlevel = 0; unsigned int t; if (account_get_teams(account)) { LIST_TRAVERSE(account_get_teams(account),curr) { if (!(team = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if ((team_get_clienttag(team)!=clienttag)) continue; if ((t = team_get_level(team)) > atlevel) atlevel = t; } } eventlog(eventlog_level_debug,__FUNCTION__,"Checking for highest level in Solo,Team,FFA,AT Ladder Stats"); eventlog(eventlog_level_debug,__FUNCTION__,"Solo Level: %d, Team Level %d, FFA Level %d, Highest AT Team Level: %d",sololevel,teamlevel,ffalevel,atlevel); if(sololevel >= teamlevel && sololevel >= atlevel && sololevel >= ffalevel) return sololevel; if(teamlevel >= sololevel && teamlevel >= atlevel && teamlevel >= ffalevel) return teamlevel; if(atlevel >= sololevel && atlevel >= teamlevel && atlevel >= ffalevel) return atlevel; return ffalevel; // we should never get here return -1; } //BlacKDicK 04/20/2003 extern int account_set_user_icon( t_account * account, t_clienttag clienttag,char const * usericon) { char key[256]; char clienttag_str[5]; sprintf(key,"Record\\%s\\userselected_icon",tag_uint_to_str(clienttag_str,clienttag)); if (usericon) return account_set_strattr(account,key,usericon); else return account_set_strattr(account,key,"NULL"); } extern char const * account_get_user_icon( t_account * account, t_clienttag clienttag ) { char key[256]; char const * retval; char clienttag_str[5]; sprintf(key,"Record\\%s\\userselected_icon",tag_uint_to_str(clienttag_str,clienttag)); retval = account_get_strattr(account,key); if ((retval) && ((strcmp(retval,"NULL")!=0))) return retval; else return NULL; } // Ramdom - Nothing, Grean Dragon Whelp, Azure Dragon (Blue Dragon), Red Dragon, Deathwing, Nothing // Humans - Peasant, Footman, Knight, Archmage, Medivh, Nothing // Orcs - Peon, Grunt, Tauren, Far Seer, Thrall, Nothing // Undead - Acolyle, Ghoul, Abomination, Lich, Tichondrius, Nothing // Night Elves - Wisp, Archer, Druid of the Claw, Priestess of the Moon, Furion Stormrage, Nothing // Demons - Nothing, ???(wich unit is nfgn), Infernal, Doom Guard, Pit Lord/Manaroth, Archimonde // ADDED TFT ICON BY DJP 07/16/2003 static char * profile_code[12][6] = { {NULL , "ngrd", "nadr", "nrdr", "nbwm", NULL }, {"hpea", "hfoo", "hkni", "Hamg", "nmed", NULL }, {"opeo", "ogru", "otau", "Ofar", "Othr", NULL }, {"uaco", "ugho", "uabo", "Ulic", "Utic", NULL }, {"ewsp", "earc", "edoc", "Emoo", "Efur", NULL }, {NULL , "nfng", "ninf", "nbal", "Nplh", "Uwar"}, /* not used by RoC */ {NULL , "nmyr", "nnsw", "nhyc", "Hvsh", "Eevm"}, {"hpea", "hrif", "hsor", "hspt", "Hblm", "Hjai"}, {"opeo", "ohun", "oshm", "ospw", "Oshd", "Orex"}, {"uaco", "ucry", "uban", "uobs", "Ucrl", "Usyl"}, {"ewsp", "esen", "edot", "edry", "Ekee", "Ewrd"}, {NULL , "nfgu", "ninf", "nbal", "Nplh", "Uwar"} }; extern unsigned int account_get_icon_profile(t_account * account, t_clienttag clienttag) { unsigned int humans = account_get_racewins(account,W3_RACE_HUMANS,clienttag); // 1; unsigned int orcs = account_get_racewins(account,W3_RACE_ORCS,clienttag); // 2; unsigned int nightelf = account_get_racewins(account,W3_RACE_NIGHTELVES,clienttag); // 4; unsigned int undead = account_get_racewins(account,W3_RACE_UNDEAD,clienttag); // 8; unsigned int random = account_get_racewins(account,W3_RACE_RANDOM,clienttag); // 32; unsigned int race; // 0 = Humans, 1 = Orcs, 2 = Night Elves, 3 = Undead, 4 = Ramdom unsigned int level = 0; // 0 = under 25, 1 = 25 to 249, 2 = 250 to 499, 3 = 500 to 1499, 4 = 1500 or more (wins) unsigned int wins; int number_ctag = 0; /* moved the check for orcs in the first place so people with 0 wins get peon */ if(orcs>=humans && orcs>=undead && orcs>=nightelf && orcs>=random) { wins = orcs; race = 2; } else if(humans>=orcs && humans>=undead && humans>=nightelf && humans>=random) { wins = humans; race = 1; } else if(nightelf>=humans && nightelf>=orcs && nightelf>=undead && nightelf>=random) { wins = nightelf; race = 4; } else if(undead>=humans && undead>=orcs && undead>=nightelf && undead>=random) { wins = undead; race = 3; } else { wins = random; race = 0; } while(wins >= anongame_infos_get_ICON_REQ(level+1,clienttag) && anongame_infos_get_ICON_REQ(level+1,clienttag) > 0) level++; if (clienttag == CLIENTTAG_WAR3XP_UINT) number_ctag = 6; eventlog(eventlog_level_info,__FUNCTION__,"race -> %u; level -> %u; wins -> %u; profileicon -> %s", race, level, wins, profile_code[race+number_ctag][level]); return char_icon_to_uint(profile_code[race+number_ctag][level]); } extern unsigned int account_icon_to_profile_icon(char const * icon,t_account * account, t_clienttag ctag) { char tmp_icon[4]; char * result; int number_ctag=0; if (icon==NULL) return account_get_icon_profile(account,ctag); if (sizeof(icon)>=4){ strncpy(tmp_icon,icon,4); tmp_icon[0]=tmp_icon[0]-48; if (ctag==CLIENTTAG_WAR3XP_UINT) { number_ctag = 6; } if (tmp_icon[0]>=1) { if (tmp_icon[1]=='R'){ result = profile_code[0+number_ctag][tmp_icon[0]-1]; }else if (tmp_icon[1]=='H'){ result = profile_code[1+number_ctag][tmp_icon[0]-1]; }else if (tmp_icon[1]=='O'){ result = profile_code[2+number_ctag][tmp_icon[0]-1]; }else if (tmp_icon[1]=='U'){ result = profile_code[3+number_ctag][tmp_icon[0]-1]; }else if (tmp_icon[1]=='N'){ result = profile_code[4+number_ctag][tmp_icon[0]-1]; }else if (tmp_icon[1]=='D'){ result = profile_code[5+number_ctag][tmp_icon[0]-1]; }else{ eventlog(eventlog_level_warn,__FUNCTION__,"got unrecognized race on [%s] icon ",icon); result = profile_code[2][0];} /* "opeo" */ }else{ eventlog(eventlog_level_warn,__FUNCTION__,"got race_level<1 on [%s] icon ",icon); result = NULL; } }else{ eventlog(eventlog_level_error,__FUNCTION__,"got invalid icon lenght [%s] icon ",icon); result = NULL; } //eventlog(eventlog_level_debug,__FUNCTION__,"from [%4.4s] icon returned [0x%X]",icon,char_icon_to_uint(result)); return char_icon_to_uint(result); } extern int account_is_operator_or_admin(t_account * account, char const * channel) { if ((account_get_auth_operator(account,channel)==1) || (account_get_auth_operator(account,NULL)==1) || (account_get_auth_admin(account,channel)==1) || (account_get_auth_admin(account,NULL)==1) ) return 1; else return 0; } static unsigned int char_icon_to_uint(char * icon) { unsigned int value; if (!icon) return 0; if (strlen(icon)!=4) return 0; value = ((unsigned int)icon[0])<<24; value |= ((unsigned int)icon[1])<<16; value |= ((unsigned int)icon[2])<< 8; value |= ((unsigned int)icon[3]) ; return value; } extern char const * account_get_email(t_account * account) { if(!account) { eventlog(eventlog_level_error,__FUNCTION__,"Unable to set account flag to TRUE"); return NULL; } return account_get_strattr(account,"BNET\\acct\\email"); } extern int account_set_email(t_account * account, char const * email) { if(!account) { eventlog(eventlog_level_error,__FUNCTION__,"Unable to set account flag to TRUE"); return -1; } return account_set_strattr(account,"BNET\\acct\\email", email); } /** * Westwood Online Extensions */ extern char const * account_get_wol_apgar(t_account * account) { return account_get_strattr(account,"WOL\\auth\\apgar"); } extern int account_set_wol_apgar(t_account * account, char const * apgar) { eventlog(eventlog_level_debug,__FUNCTION__,"[** WOL **] WOL\\auth\\apgar = %s",apgar); return account_set_strattr(account,"WOL\\auth\\apgar",apgar); } pvpgn-1.8.5/src/bnetd/anongame.h0000644000175000017500000000761611151345317015475 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_ANONGAME_TYPES #define INCLUDED_ANONGAME_TYPES #include "common/setup_before.h" #ifdef JUST_NEED_TYPES # include "account.h" # include "connection.h" # include "compat/uint.h" #else # define JUST_NEED_TYPES # include "account.h" # include "connection.h" # include "compat/uint.h" # undef JUST_NEED_TYPES #endif # include "anongame_gameresult.h" #include "common/setup_after.h" typedef struct { int currentplayers; int totalplayers; struct connection * player[ANONGAME_MAX_GAMECOUNT]; t_account * account[ANONGAME_MAX_GAMECOUNT]; int result[ANONGAME_MAX_GAMECOUNT]; t_anongame_gameresult * results[ANONGAME_MAX_GAMECOUNT]; } t_anongameinfo; typedef struct { t_anongameinfo * info; int count; t_uint32 id; t_uint32 tid; struct connection * tc[ANONGAME_MAX_GAMECOUNT/2]; t_uint32 race; t_uint32 handle; unsigned int addr; char loaded; char joined; t_uint8 playernum; t_uint32 map_prefs; t_uint8 type; t_uint8 gametype; int queue; } t_anongame; typedef struct { struct connection * c; t_uint32 map_prefs; char const * versiontag; } t_matchdata; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_ANONGAME_PROTOS #define INCLUDED_ANONGAME_PROTOS #define JUST_NEED_TYPES #include "common/packet.h" #include "connection.h" #undef JUST_NEED_TYPES extern int anongame_matchlists_create(void); extern int anongame_matchlists_destroy(void); extern int handle_anongame_search(t_connection * c, t_packet const * packet); extern int anongame_unqueue(t_connection * c, int queue); extern char anongame_arranged(int queue); extern int anongame_stats(t_connection * c); extern t_anongameinfo * anongameinfo_create(int totalplayers); extern void anongameinfo_destroy(t_anongameinfo * i); extern t_anongameinfo * anongame_get_info(t_anongame * a); extern int anongame_get_currentplayers(t_anongame *a); extern int anongame_get_totalplayers(t_anongame *a); extern t_connection * anongame_get_player(t_anongame * a, int plnum); extern int anongame_get_count(t_anongame *a); extern t_uint32 anongame_get_id(t_anongame * a); extern t_connection * anongame_get_tc(t_anongame *a, int tpnumber); extern t_uint32 anongame_get_race(t_anongame * a); extern t_uint32 anongame_get_handle(t_anongame * a); extern unsigned int anongame_get_addr(t_anongame * a); extern char anongame_get_loaded(t_anongame * a); extern char anongame_get_joined(t_anongame * a); extern t_uint8 anongame_get_playernum(t_anongame * a); extern t_uint8 anongame_get_queue(t_anongame *a); extern void anongame_set_result(t_anongame * a, int result); extern void anongame_set_gameresults(t_anongame * a, t_anongame_gameresult * results); extern void anongame_set_handle(t_anongame *a, t_uint32 h); extern void anongame_set_addr(t_anongame *a, unsigned int addr); extern void anongame_set_loaded(t_anongame * a, char loaded); extern void anongame_set_joined(t_anongame * a, char joined); extern int handle_w3route_packet(t_connection * c, t_packet const * const packet); extern int handle_anongame_join(t_connection * c); #endif #endif pvpgn-1.8.5/src/bnetd/topic.c0000644000175000017500000001246611151345317015020 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define TOPIC_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strrchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/pdir.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include "common/eventlog.h" #include "common/list.h" #include "common/field_sizes.h" #include "common/xalloc.h" #include "prefs.h" #include "topic.h" #include "common/setup_after.h" static t_list * topiclist_head=NULL; t_topic * get_topic(char const * channel_name) { t_elem * curr; t_topic * topic; if (topiclist_head) { LIST_TRAVERSE(topiclist_head,curr) { if (!(topic = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if (strcasecmp(channel_name,topic->channel_name)==0) return topic; } } return NULL; } char * channel_get_topic(char const * channel_name) { t_topic * topic; if (!(topic = get_topic(channel_name))) return NULL; else return topic->topic; } int topiclist_save(char const * topic_file) { t_elem * curr; t_topic * topic; FILE * fp; if (topiclist_head) { if ((fp = fopen(topic_file,"w"))==NULL) { eventlog(eventlog_level_error, __FUNCTION__,"can't open topic file"); return -1; } LIST_TRAVERSE(topiclist_head,curr) { if (!(topic = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if (topic->save == DO_SAVE_TOPIC) fprintf(fp,"\"%s\",\"%s\"\n",topic->channel_name,topic->topic); } fclose(fp); } return 0; } int topiclist_add_topic(char const * channel_name, char const * topic_text, int do_save) { t_topic * topic; topic = xmalloc(sizeof(t_topic)); topic->channel_name = xstrdup(channel_name); topic->topic = xstrdup(topic_text); list_prepend_data(topiclist_head,topic); topic->save = do_save; return 0; } int channel_set_topic(char const * channel_name, char const * topic_text, int do_save) { t_topic * topic; if (!(channel_name)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel_name"); return -1; } if (!(topic_text)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL topic"); return -1; } if ((topic = get_topic(channel_name))) { xfree((void *)topic->topic); topic->topic = xstrdup(topic_text); } else { topiclist_add_topic(channel_name, topic_text,do_save); } if (do_save == DO_SAVE_TOPIC) { if (topiclist_save(prefs_get_topicfile())<0) { eventlog(eventlog_level_error,__FUNCTION__,"error saving topic list"); return -1; } } return 0; } int topiclist_load(char const * topicfile) { FILE * fp; char channel_name[CHANNEL_NAME_LEN]; char topic[MAX_TOPIC_LEN]; // make sure to unload previous topiclist before loading again if (topiclist_head) topiclist_unload(); if ((fp = fopen(topicfile,"r"))==NULL) { eventlog(eventlog_level_error, __FUNCTION__,"can't open topic file"); return -1; } topiclist_head = list_create(); eventlog(eventlog_level_trace,__FUNCTION__,"start reading topic file"); while (fscanf(fp,"\"%[^\"]\",\"%[^\"]\"\n",channel_name,topic)==2) { topiclist_add_topic(channel_name,topic,DO_SAVE_TOPIC); eventlog(eventlog_level_trace,__FUNCTION__,"channel: %s topic: \"%s\"",channel_name,topic); } eventlog(eventlog_level_trace,__FUNCTION__,"finished reading topic file"); fclose(fp); return 0; } int topiclist_unload(void) { t_elem * curr; t_topic * topic; if (topiclist_head) { LIST_TRAVERSE(topiclist_head,curr) { if (!(topic = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if (topic->channel_name) xfree((void *)topic->channel_name); if (topic->topic) xfree((void *)topic->topic); xfree((void *)topic); list_remove_elem(topiclist_head,&curr); } if (list_destroy(topiclist_head)<0) return -1; topiclist_head = NULL; } return 0; } pvpgn-1.8.5/src/bnetd/alias_command.c0000644000175000017500000003267311151345317016473 0ustar aaronaaron/* * Copyright (C) 2000 Onlyer (onlyer@263.net) * Copyright (C) 2002 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define ALIAS_COMMAND_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strcasecmp.h" #include #include #include "compat/strerror.h" #include "common/field_sizes.h" #include "common/util.h" #include "common/eventlog.h" #include "common/list.h" #include "common/xalloc.h" #include "message.h" #include "connection.h" #include "alias_command.h" #include "common/setup_after.h" static t_list * aliaslist_head=NULL; #define MAX_ALIAS_LEN 32 static int list_aliases(t_connection * c); static char * replace_args(char const * in, unsigned int * offsets, int numargs, char const * text); static int do_alias(t_connection * c, char const * cmd, char const * args); static int list_aliases(t_connection * c) { t_elem const * elem1; t_elem const * elem2; t_alias const * alias; t_output * output; char temp[MAX_MESSAGE_LEN]; message_send_text(c,message_type_info,c,"Alias list:"); LIST_TRAVERSE_CONST(aliaslist_head,elem1) { if (!(alias = elem_get_data(elem1))) continue; sprintf(temp,"@%.128s",alias->alias); message_send_text(c,message_type_info,c,temp); LIST_TRAVERSE_CONST(alias->output,elem2) { if (!(output = elem_get_data(elem2))) continue; /* * FIXME: need a more user-friendly way to express this... maybe * add a help line to the file format? */ if (output->min==-1) sprintf(temp,"[*]%.128s",output->line); else if (output->max==-1) sprintf(temp,"[%d+]%.128s",output->min,output->line); else if (output->min == output->max) sprintf(temp,"[%d]%.128s",output->min,output->line); else sprintf(temp,"[%d-%d]%.128s",output->min,output->max,output->line); message_send_text(c,message_type_info,c,temp); } } return 0; } static char * replace_args(char const * in, unsigned int * offsets, int numargs, char const * text) { char * out; unsigned int inpos; unsigned int outpos; unsigned int off1; unsigned int off2; unsigned int size; off1 = off2 = 0; out = xstrdup(in); size = strlen(out); for (inpos=outpos=0; inpos=numargs) arg2 = numargs-1; if (arg1>arg2) { while (in[inpos]!='\0' && in[inpos]!='}') inpos++; continue; } off1 = offsets[arg1]; if (arg2+1==numargs) off2 = strlen(text); else off2 = offsets[arg2+1]-1; while (in[inpos]!='\0' && in[inpos]!='}') inpos++; } else if (isdigit((int)in[inpos])) { int arg; if (in[inpos]=='0') arg = 0; else if (in[inpos]=='1') arg = 1; else if (in[inpos]=='2') arg = 2; else if (in[inpos]=='3') arg = 3; else if (in[inpos]=='4') arg = 4; else if (in[inpos]=='5') arg = 5; else if (in[inpos]=='6') arg = 6; else if (in[inpos]=='7') arg = 7; else if (in[inpos]=='8') arg = 8; else arg = 9; if (arg>=numargs) continue; for (off1=off2=offsets[arg]; text[off2]!='\0' && text[off2]!=' ' && text[off2]!='\t'; off2++); } { char * newout; newout = xmalloc(size+(off2-off1)+1); /* curr + new + nul */ size = size+(off2-off1)+1; memmove(newout,out,outpos); xfree(out); out = newout; while (off1alias,cmd)==NULL) continue; LIST_TRAVERSE_CONST(alias->output,elem2) { if (!(output = elem_get_data(elem2))) continue; if (!output->line) continue; if ((output->min==-1) || ((output->min<=numargs) && (output->max==-1)) || ((output->min<=numargs) && (output->max>=numargs))) //TODO: initialize offsets { char * msgtmp; char * tmp2; char * cmd = "%C"; match = 1; if ((msgtmp = replace_args(output->line,offsets,numargs+1,text))) { if (msgtmp[0]!='\0') { if ((msgtmp[0]=='/')&&(msgtmp[1]!='/')) // to make sure we don't get endless aliasing loop { tmp2 = xmalloc(strlen(msgtmp)+3); sprintf(tmp2,"%s%s",cmd,msgtmp); xfree((void *)msgtmp); msgtmp=tmp2; } if (strlen(msgtmp)>MAX_MESSAGE_LEN) { msgtmp[MAX_MESSAGE_LEN]='\0'; eventlog(eventlog_level_info,__FUNCTION__,"message line after alias expansion was too long, truncating it"); } message_send_formatted(c,msgtmp); } xfree((void *)msgtmp); /* avoid warning */ } else eventlog(eventlog_level_error,__FUNCTION__,"could not perform argument replacement"); } } } xfree(offsets); return match; } extern int aliasfile_load(char const * filename) { FILE * afp; char * buff; char * temp; unsigned int line; unsigned int pos; int inalias; t_alias * alias = NULL; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(afp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to open alias file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return -1; } aliaslist_head = list_create(); inalias = 0; for (line=1; (buff = file_get_line(afp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if (!(temp = strrchr(buff,'"'))) /* FIXME: assumes comments don't contain " */ temp = buff; if ((temp = strrchr(temp,'#'))) { unsigned int len; unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } switch (inalias) { case 0: if (buff[pos]!='@') /* not start of alias */ { eventlog(eventlog_level_error,__FUNCTION__,"expected start of alias stanza on line %u of alias file \"%s\" but found \"%s\"",line,filename,&buff[pos]); break; } inalias = 1; break; case 1: { if (buff[pos]=='\0') break; inalias = 2; alias = xmalloc(sizeof(t_alias)); alias->output=0; alias->alias=xstrdup(&buff[pos]); } break; case 2: { char * dummy; char * out = NULL; int min, max; t_output * output; min = max = 0; if (buff[pos]!='[') { eventlog(eventlog_level_error,__FUNCTION__,"expected output entry on line %u of alias file \"%s\" but found \"%s\"",line,filename,&buff[pos]); break; } if ((dummy=strchr(&buff[pos],']'))) { if (dummy[1]!='\0') out = xstrdup(&dummy[1]); } if (buff[pos+1]=='*') { min = max = -1; } else if (buff[pos+1]=='+') { min = 1; max = -1; } else if (sscanf(&buff[pos],"[%u",&min)==1) { if (*(dummy-1)=='+') max = -1; else max = min; } else { eventlog(eventlog_level_error,__FUNCTION__,"error parsing min/max value for alias output"); } if (out!=NULL) { output = xmalloc(sizeof(t_output)); output->min=min; output->max=max; output->line = out; alias->output = list_create(); list_append_data(alias->output,output); inalias = 3; } } break; case 3: { if (buff[pos]=='@') { inalias = 1; if (alias!=NULL) list_append_data(aliaslist_head,alias); alias=NULL; break; } else if (buff[pos]=='[') { char * dummy; char * out = NULL; int min, max; t_output * output; min = max = 0; if ((dummy=strchr(&buff[pos],']'))) { if (dummy[1]!='\0') out = xstrdup(&dummy[1]); } if (buff[pos+1]=='*') { min = max = -1; } else if (buff[pos+1]=='+') { min = 1; max = -1; } else if (sscanf(&buff[pos],"[%u",&min)==1) { if (*(dummy-1)=='+') max = -1; else max = min; } else { eventlog(eventlog_level_error,__FUNCTION__,"error parsing min/max value for alias output"); } if (out!=NULL) { output = xmalloc(sizeof(t_output)); output->min=min; output->max=max; output->line = out; list_append_data(alias->output,output); } } else eventlog(eventlog_level_error,__FUNCTION__,"expected output entry or next alias stanza on line %u of file \"%s\"i but found \"%s\"",line,filename,&buff[pos]); break; } } } if (alias!=NULL) list_append_data(aliaslist_head,alias); file_get_line(NULL); // clear file_get_line buffer fclose(afp); eventlog(eventlog_level_info,__FUNCTION__,"done loading aliases"); return 0; } extern int aliasfile_unload(void) { t_elem * elem1; t_elem * elem2; t_alias const * alias; t_output * output; if (aliaslist_head) { LIST_TRAVERSE(aliaslist_head,elem1) { if (!(alias = elem_get_data(elem1))) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"alias list contains NULL item"); continue; } if (list_remove_elem(aliaslist_head,&elem1)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove alias"); continue; } if (alias->output) { LIST_TRAVERSE(alias->output,elem2) { if (!(output = elem_get_data(elem2))) { eventlog(eventlog_level_error,__FUNCTION__,"output list contains NULL item"); continue; } if (list_remove_elem(alias->output,&elem2)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove output"); continue; } xfree((void *)output->line); /* avoid warning */ xfree((void *)output); } list_destroy(alias->output); } if (alias->alias) xfree((void *)alias->alias); xfree((void *)alias); } if (list_destroy(aliaslist_head)<0) return -1; aliaslist_head = NULL; } return 0; } extern int handle_alias_command(t_connection * c, char const * text) { unsigned int i,j; char cmd[MAX_COMMAND_LEN]; for (i=j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get command */ if (j #endif #define MAX_TEAMSIZE 4 typedef struct team #ifdef TEAM_INTERNAL_ACCESS { unsigned char size; int wins; int losses; int xp; int level; int rank; unsigned int teamid; unsigned int teammembers[MAX_TEAMSIZE]; t_account * members[MAX_TEAMSIZE]; t_clienttag clienttag; time_t lastgame; } #endif t_team; #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_TEAM_PROTOS #define INCLUDED_TEAM_PROTOS extern int teamlist_load(void); extern int teamlist_unload(void); extern int teams_destroy(t_list *); extern t_team* create_team(t_account **accounts,t_clienttag clienttag); extern void dispose_team(t_team * team); extern t_team* teamlist_find_team_by_accounts(t_account **accounts,t_clienttag clienttag); extern t_team* teamlist_find_team_by_uids(unsigned int * uids, t_clienttag clienttag); extern t_team* teamlist_find_team_by_teamid(unsigned int teamid); extern t_team* _list_find_team_by_accounts(t_account **accounts,t_clienttag clienttag,t_list * list); extern t_team* _list_find_team_by_uids(unsigned int * uids,t_clienttag clienttag, t_list * list); extern t_team* _list_find_team_by_teamid(unsigned int teamid, t_list * list); extern unsigned int team_get_teamid(t_team * team); extern t_account * team_get_member(t_team * team,int count); extern unsigned int team_get_memberuid(t_team * team,int count); extern t_clienttag team_get_clienttag(t_team * team); extern unsigned char team_get_size(t_team * team); extern int team_get_wins(t_team * team); extern int team_get_losses(t_team * team); extern int team_get_xp(t_team * team); extern int team_get_level(t_team * team); extern int team_get_rank(t_team * team); extern time_t team_get_lastgame(t_team * team); extern int team_inc_wins(t_team * team); extern int team_inc_losses(t_team * team); extern int team_set_saveladderstats(t_team * team, unsigned int gametype, int result, unsigned int opponlevel,t_clienttag clienttag); #endif #endif pvpgn-1.8.5/src/bnetd/anongame_gameresult.c0000644000175000017500000001461011151345317017710 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strrchr.h" #include #include "compat/strerror.h" #include "common/list.h" #include "common/eventlog.h" #include "common/util.h" #include "common/packet.h" #include "common/tag.h" #include "common/bn_type.h" #include "common/packet.h" #ifdef HAVE_ASSERT_H # include #endif #include "common/xalloc.h" #define ANONGAME_GAMERESULT_INTERNAL_ACCESS #include "anongame_gameresult.h" #include "common/setup_after.h" extern int gameresult_destroy(t_anongame_gameresult * gameresult) { if (!(gameresult)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL gameresult"); return -1; } if ((gameresult->players)) xfree((void *)gameresult->players); if ((gameresult->heroes)) xfree((void *)gameresult->heroes); xfree((void *)gameresult); return 0; } extern t_anongame_gameresult * anongame_gameresult_parse(t_packet const * const packet) { t_anongame_gameresult * gameresult; t_client_w3route_gameresult_player * player; t_client_w3route_gameresult_part2 * part2; t_client_w3route_gameresult_hero * hero; t_client_w3route_gameresult_part3 * part3; int counter, heroes_count; int expectedsize; //still without hero infos unsigned int offset = 0; int result_count = bn_byte_get(packet->u.client_w3route_gameresult.number_of_results); expectedsize = sizeof(t_client_w3route_gameresult) + sizeof(t_client_w3route_gameresult_player) * result_count + sizeof(t_client_w3route_gameresult_part2) + sizeof(t_client_w3route_gameresult_part3); if (packet_get_size(packet) < expectedsize) { eventlog(eventlog_level_error,__FUNCTION__,"gameresult packet is smaller than expected"); return NULL; } gameresult = xmalloc(sizeof(t_anongame_gameresult)); gameresult->players = xmalloc(sizeof(t_anongame_player)*result_count); gameresult->number_of_results = result_count; offset+= sizeof(t_client_w3route_gameresult); for (counter=0; counterplayers[counter].number = bn_byte_get(player->number); gameresult->players[counter].result = bn_int_get(player->result); gameresult->players[counter].race = bn_int_get(player->race); offset+= sizeof(t_client_w3route_gameresult_player); } part2 = (t_client_w3route_gameresult_part2 *)packet_get_raw_data_const(packet,offset); gameresult->unit_score = bn_int_get(part2->unit_score); gameresult->heroes_score = bn_int_get(part2->heroes_score); gameresult->resource_score = bn_int_get(part2->resource_score); gameresult->units_produced = bn_int_get(part2->units_produced); gameresult->units_killed = bn_int_get(part2->units_killed); gameresult->buildings_produced = bn_int_get(part2->buildings_produced); gameresult->buildings_razed = bn_int_get(part2->buildings_razed); gameresult->largest_army = bn_int_get(part2->largest_army); heroes_count = bn_int_get(part2->heroes_used_count); gameresult->heroes_used_count = heroes_count; offset+= sizeof(t_client_w3route_gameresult_part2); if ((heroes_count)) { gameresult->heroes = xmalloc(sizeof(t_anongame_hero)*heroes_count); if (packet_get_size(packet) < expectedsize + sizeof(t_client_w3route_gameresult_hero)*heroes_count) { eventlog(eventlog_level_error,__FUNCTION__,"gameresult packet is smaller than expected"); return NULL; } for (counter=0; counter < heroes_count; counter++) { hero = (t_client_w3route_gameresult_hero *)packet_get_raw_data_const(packet,offset); gameresult->heroes[counter].level = bn_int_get(hero->level); gameresult->heroes[counter].race_and_name = bn_int_get(hero->race_and_name); gameresult->heroes[counter].hero_xp = bn_int_get(hero->hero_xp); offset+= sizeof(t_client_w3route_gameresult_hero); } } else gameresult->heroes = NULL; part3 = (t_client_w3route_gameresult_part3 *)packet_get_raw_data_const(packet,offset); gameresult->heroes_killed = bn_int_get(part3->heroes_killed); gameresult->items_obtained = bn_int_get(part3->items_obtained); gameresult->mercenaries_hired = bn_int_get(part3->mercenaries_hired); gameresult->total_hero_xp = bn_int_get(part3->total_hero_xp); gameresult->gold_mined = bn_int_get(part3->gold_mined); gameresult->lumber_harvested = bn_int_get(part3->lumber_harvested); gameresult->resources_traded_given = bn_int_get(part3->resources_traded_given); gameresult->resources_traded_taken = bn_int_get(part3->resources_traded_taken); gameresult->tech_percentage = bn_int_get(part3->tech_percentage); gameresult->gold_lost_to_upkeep = bn_int_get(part3->gold_lost_to_upkeep); return gameresult; } extern char gameresult_get_number_of_results(t_anongame_gameresult * gameresult) { assert(gameresult); return gameresult->number_of_results; } extern int gameresult_get_player_result(t_anongame_gameresult * gameresult, int player) { if (!(gameresult)) return -1; if (player >= gameresult->number_of_results) { eventlog(eventlog_level_error,__FUNCTION__,"request for invalid player number"); return -1; } return gameresult->players[player].result; } extern int gameresult_get_player_number(t_anongame_gameresult * gameresult, int player) { if (!(gameresult)) return -1; if (player >= gameresult->number_of_results) { eventlog(eventlog_level_error,__FUNCTION__,"request for invalid player number"); return -1; } return gameresult->players[player].number; } pvpgn-1.8.5/src/bnetd/mail.c0000644000175000017500000005175611151345317014631 0ustar aaronaaron/* * Copyright (C) 2001 Dizzy * Copyright (C) 2004 Donny Redmond (dredmond@linuxmail.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define MAIL_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strcasecmp.h" #include #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #include "compat/statmacros.h" #include "compat/mkdir.h" #include "compat/pdir.h" #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #include "message.h" #include "connection.h" #include "common/util.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "account.h" #include "prefs.h" #include "mail.h" #include "common/setup_after.h" static int identify_mail_function(const char *); static void mail_usage(t_connection*); static void mail_func_send(t_connection*,const char *); static void mail_func_read(t_connection*,const char *); static void mail_func_delete(t_connection*,const char *); static int get_mail_quota(t_account *); /* Mail API */ /* for now this functions are only for internal use */ static t_mailbox * mailbox_open(t_account *, t_mbox_mode mode); static int mailbox_count(t_mailbox *); static int mailbox_deliver(t_mailbox *, const char *, const char *); static t_mail * mailbox_read(t_mailbox *, unsigned int); static void mailbox_unread(t_mail*); static struct maillist_struct * mailbox_get_list(t_mailbox *); static void mailbox_unget_list(struct maillist_struct *); static int mailbox_delete(t_mailbox *, unsigned int); static int mailbox_delete_all(t_mailbox *); static void mailbox_close(t_mailbox *); static char * clean_str(char *); static t_mailbox * mailbox_open(t_account * user, t_mbox_mode mode) { t_mailbox * rez; char * path; char const * maildir; rez=xmalloc(sizeof(t_mailbox)); maildir=prefs_get_maildir(); if (mode & mbox_mode_write) p_mkdir(maildir,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); path=xmalloc(strlen(maildir)+1+8+1); if (maildir[0]!='\0' && maildir[strlen(maildir)-1]=='/') sprintf(path,"%s%06u",maildir,account_get_uid(user)); else sprintf(path,"%s/%06u",maildir,account_get_uid(user)); if (mode & mbox_mode_write) p_mkdir(path,S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH); if ((rez->maildir=p_opendir(path))==NULL) { if (mode & mbox_mode_write) eventlog(eventlog_level_error,__FUNCTION__,"error opening maildir"); xfree(path); xfree(rez); return NULL; } rez->uid=account_get_uid(user); rez->path=path; return rez; } static int mailbox_count(t_mailbox *mailbox) { char const * dentry; int count=0; /* consider NULL mailbox as empty mailbox */ if (mailbox==NULL) return 0; if (mailbox->maildir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL maildir"); return -1; } p_rewinddir(mailbox->maildir); while ((dentry=p_readdir(mailbox->maildir))!=NULL) if (dentry[0]!='.') count++; return count; } static int mailbox_deliver(t_mailbox * mailbox, const char * sender, const char * message) { FILE * fd; char * filename; if (mailbox==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL mailbox"); return -1; } if (mailbox->maildir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL maildir"); return -1; } if (mailbox->path==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL path"); return -1; } filename=xmalloc(strlen(mailbox->path)+1+15+1); sprintf(filename,"%s/%015lu",mailbox->path,(unsigned long)time(NULL)); if ((fd=fopen(filename,"wb"))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL file descriptor. check permissions"); xfree(filename); return -1; } fprintf(fd,"%s\n",sender); /* write the sender on the first line of message */ fprintf(fd,"%s\n",message); /* then write the actual message */ fclose(fd); xfree(filename); return 0; } static t_mail * mailbox_read(t_mailbox * mailbox, unsigned int idx) { char const * dentry; unsigned int i; t_mail * rez; FILE * fd; char * filename; if (mailbox==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL mailbox"); return NULL; } if (mailbox->maildir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL maildir"); return NULL; } rez=xmalloc(sizeof(t_mail)); p_rewinddir(mailbox->maildir); dentry = NULL; /* if idx < 1 we should not crash :) */ for(i=0;imaildir))!=NULL;i++) if (dentry[0]=='.') i--; if (dentry==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"index out of range"); xfree(rez); return NULL; } rez->timestamp=atoi(dentry); filename=xmalloc(strlen(dentry)+1+strlen(mailbox->path)+1); sprintf(filename,"%s/%s",mailbox->path,dentry); if ((fd=fopen(filename,"rb"))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"error while opening message"); xfree(rez); xfree(filename); return NULL; } xfree(filename); rez->sender=xmalloc(256); fgets(rez->sender,256,fd); /* maybe 256 isnt the right value to bound a line but right now its all i have :) */ clean_str(rez->sender); rez->message=xmalloc(256); fgets(rez->message,256,fd); clean_str(rez->message); fclose(fd); rez->timestamp=atoi(dentry); return rez; } static void mailbox_unread(t_mail * mail) { if (mail==NULL) eventlog(eventlog_level_error,__FUNCTION__,"got NULL mail"); else { if (mail->sender==NULL) eventlog(eventlog_level_error,__FUNCTION__,"got NULL sender"); else xfree(mail->sender); if (mail->message==NULL) eventlog(eventlog_level_error,__FUNCTION__,"got NULL message"); else xfree(mail->message); xfree(mail); } } static struct maillist_struct * mailbox_get_list(t_mailbox *mailbox) { char const * dentry; FILE * fd; struct maillist_struct *rez=NULL, *p=NULL,*q; char *sender,*filename; if (mailbox==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL mailbox"); return NULL; } if (mailbox->maildir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL maildir"); return NULL; } filename=xmalloc(strlen(mailbox->path)+1+15+1); p_rewinddir(mailbox->maildir); for(;(dentry=p_readdir(mailbox->maildir))!=NULL;) if (dentry[0]!='.') { q=xmalloc(sizeof(struct maillist_struct)); sprintf(filename,"%s/%s",mailbox->path,dentry); if ((fd=fopen(filename,"rb"))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"error while opening message file"); xfree(filename); xfree(q); return rez; } sender=xmalloc(256); fgets(sender,256,fd); clean_str(sender); fclose(fd); q->sender=sender; q->timestamp=atoi(dentry); q->next=NULL; if (p==NULL) rez=q; else p->next=q; p=q; } xfree(filename); return rez; } static void mailbox_unget_list(struct maillist_struct * maill) { struct maillist_struct *p, *q; for(p=maill;p!=NULL;p=q) { if (p->sender!=NULL) xfree(p->sender); q=p->next; xfree(p); } } static int mailbox_delete(t_mailbox * mailbox, unsigned int idx) { char * filename; char const * dentry; unsigned int i; int rez; if (mailbox==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL mailbox"); return -1; } if (mailbox->maildir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL maildir"); return -1; } p_rewinddir(mailbox->maildir); dentry = NULL; /* if idx < 1 we should not crash :) */ for(i=0;imaildir))!=NULL;i++) if (dentry[0]=='.') i--; if (dentry==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"index out of range"); return -1; } filename=xmalloc(strlen(dentry)+1+strlen(mailbox->path)+1); sprintf(filename,"%s/%s",mailbox->path,dentry); rez=remove(filename); if (rez<0) { eventlog(eventlog_level_info,__FUNCTION__,"could not remove file \"%s\" (remove: %s)",filename,pstrerror(errno)); } xfree(filename); return rez; } static int mailbox_delete_all(t_mailbox * mailbox) { char * filename; char const * dentry; int count; if (mailbox==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL mailbox"); return -1; } if (mailbox->maildir==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL maildir"); return -1; } filename=xmalloc(strlen(mailbox->path)+1+15+1); p_rewinddir(mailbox->maildir); count = 0; while ((dentry=p_readdir(mailbox->maildir))!=NULL) if (dentry[0]!='.') { sprintf(filename,"%s/%s",mailbox->path,dentry); if (!remove(filename)) count++; } xfree(filename); return count; } static void mailbox_close(t_mailbox *mailbox) { if (mailbox==NULL) return; if (mailbox->maildir!=NULL) { p_closedir(mailbox->maildir); } else { eventlog(eventlog_level_error,__FUNCTION__,"got NULL maildir"); } if (mailbox->path) xfree(mailbox->path); xfree(mailbox); } static char * clean_str(char * str) { char *p; for(p=str;*p!='\0';p++) if (*p=='\n' || *p=='\r') { *p='\0'; break; } return str; } extern int handle_mail_command(t_connection * c, char const * text) { unsigned int i,j; char comm[MAX_FUNC_LEN]; if (!prefs_get_mail_support()) { message_send_text(c,message_type_error,c,"This server has NO mail support."); return -1; } for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip /mail command */ for (; text[i]==' '; i++); /* skip any spaces after it */ for (j=0; text[i]!=' ' && text[i]!='\0' && jMAX_MAIL_QUOTA) quota=MAX_MAIL_QUOTA; } return quota; } static void mail_func_send(t_connection * c, const char * str) { int i; char *dest; char const *p,*myname; t_account * recv; t_mailbox * mailbox; if (c==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (str==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command string"); return; } for(i=0;str[i]==' ';i++); /* skip any spaces */ if (str[i]=='\0') { /* the %mail send command has no receiver */ message_send_text(c,message_type_error,c,"You must specify the receiver"); message_send_text(c,message_type_error,c,"Syntax: /mail send "); return; } p=str+i; /* set ip at the start of receiver string */ for(i=1;p[i]!=' ' && p[i]!='\0';i++); /* skip the receiver string */ if (p[i]=='\0') { /* it seems user forgot to write any message */ message_send_text(c,message_type_error,c,"Your message is empty!"); message_send_text(c,message_type_error,c,"Syntax: /mail send "); return; } dest=xmalloc(i+1); memmove(dest,p,i); dest[i]='\0'; /* copy receiver in his separate string */ if ((recv=accountlist_find_account(dest))==NULL) { /* is dest a valid account on this server ? */ message_send_text(c,message_type_error,c,"Receiver UNKNOWN!"); xfree(dest); return; } xfree(dest); /* free dest here, the sooner the better */ if ((mailbox=mailbox_open(recv, mbox_mode_write))==NULL) { message_send_text(c,message_type_error,c,"There was an error completing your request!"); return; } if (get_mail_quota(recv)<=mailbox_count(mailbox)) { /* check quota */ message_send_text(c,message_type_error,c,"Receiver has reached his mail quota. Your message will NOT be sent."); mailbox_close(mailbox); return; } myname=conn_get_username(c); /* who am i ? */ if (mailbox_deliver(mailbox,myname,p+i+1)<0) message_send_text(c,message_type_error,c,"There was an error completing your request!"); else message_send_text(c,message_type_info,c,"Your mail has been sent successfully."); mailbox_close(mailbox); } static void mail_func_read(t_connection * c, const char * str) { t_account * user; t_mailbox * mailbox; const char *p; char tmp[256]; int i; if (c==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (str==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command string"); return; } for(i=0;str[i]==' ';i++); p=str+i; if ((user=conn_get_account(c))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return; } mailbox=mailbox_open(user, mbox_mode_read); if (*p=='\0') { /* user wants to see the mail summary */ struct maillist_struct *maill, *mp; unsigned int idx; if (!mailbox_count(mailbox)) { message_send_text(c,message_type_info,c,"You have no mail."); mailbox_close(mailbox); return; } if ((maill=mailbox_get_list(mailbox))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL maillist"); mailbox_close(mailbox); return; } sprintf(tmp,"You have %d messages. Your mail qouta is set to %d.",mailbox_count(mailbox),get_mail_quota(user)); message_send_text(c,message_type_info,c,tmp); message_send_text(c,message_type_info,c,"ID Sender Date"); message_send_text(c,message_type_info,c,"-------------------------------------"); for(mp=maill,idx=1;mp!=NULL;mp=mp->next,idx++) { sprintf(tmp,"%02u %-14s %s",idx,mp->sender,ctime(&mp->timestamp)); clean_str(tmp); /* ctime() appends an newline that we get cleaned */ message_send_text(c,message_type_info,c,tmp); } message_send_text(c,message_type_info,c,"Use /mail read to read the content of any message"); mailbox_unget_list(maill); } else { /* user wants to read a message */ int idx; t_mail * mail; for(i=0;p[i]>='0' && p[i]<='9' && p[i]!='\0';i++); if (p[i]!='\0' && p[i]!=' ') { message_send_text(c,message_type_error,c,"Invalid index. Please use /mail read where is a number."); mailbox_close(mailbox); return; } idx=atoi(p); if (idx<1 || idx>mailbox_count(mailbox)) { message_send_text(c,message_type_error,c,"That index is out of range."); mailbox_close(mailbox); return; } if ((mail=mailbox_read(mailbox,idx))==NULL) { message_send_text(c,message_type_error,c,"There was an error completing your request."); mailbox_close(mailbox); return; } sprintf(tmp,"Message #%d from %s on %s:",idx,mail->sender,clean_str(ctime(&mail->timestamp))); message_send_text(c,message_type_info,c,tmp); message_send_text(c,message_type_info,c,mail->message); mailbox_unread(mail); } mailbox_close(mailbox); } static void mail_func_delete(t_connection * c, const char * str) { t_account * user; t_mailbox * mailbox; const char * p; char tmp[256]; /* that should be enough */ int i; if (c==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (str==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command string"); return; } for(i=0;str[i]==' ';i++); p=str+i; if (*p=='\0') { message_send_text(c,message_type_error,c,"Please specify which message to delete. Use the following syntax: /mail delete {|all} ."); return; } if ((user=conn_get_account(c))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return; } if ((mailbox=mailbox_open(user, mbox_mode_write))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL mailbox"); return; } if (strcmp(p,"all")==0) { int rez; if ((rez=mailbox_delete_all(mailbox))<0) { message_send_text(c,message_type_error,c,"There was an error completing your request."); mailbox_close(mailbox); return; } sprintf(tmp,"Successfuly deleted %d messages.",rez); message_send_text(c,message_type_info,c,tmp); } else { int idx; for(i=0;p[i]>='0' && p[i]<='9' && p[i]!='\0';i++); if (p[i]!='\0' && p[i]!=' ') { message_send_text(c,message_type_error,c,"Invalid index. Please use /mail delete {|all} where is a number."); mailbox_close(mailbox); return; } idx=atoi(p); if (idx<1 || idx>mailbox_count(mailbox)) { message_send_text(c,message_type_error,c,"That index is out of range."); mailbox_close(mailbox); return; } if (mailbox_delete(mailbox,idx)<0) { message_send_text(c,message_type_error,c,"There was an error completing your request."); mailbox_close(mailbox); return; } sprintf(tmp,"Succesfully deleted message #%02d.",idx); message_send_text(c,message_type_info,c,tmp); } mailbox_close(mailbox); } static void mail_usage(t_connection * c) { message_send_text(c,message_type_info,c,"to print this information:"); message_send_text(c,message_type_info,c," /mail help"); message_send_text(c,message_type_info,c,"to print an index of you messages:"); message_send_text(c,message_type_info,c," /mail [read]"); message_send_text(c,message_type_info,c,"to send a message:"); message_send_text(c,message_type_info,c," /mail send "); message_send_text(c,message_type_info,c,"to read a message:"); message_send_text(c,message_type_info,c," /mail read "); message_send_text(c,message_type_info,c,"to delete a message:"); message_send_text(c,message_type_info,c," /mail delete {|all}"); message_send_text(c,message_type_info,c,"Commands may be abbreviated as follows:"); message_send_text(c,message_type_info,c," help: h"); message_send_text(c,message_type_info,c," read: r"); message_send_text(c,message_type_info,c," send: s"); message_send_text(c,message_type_info,c," delete: del"); } extern char const * check_mail(t_connection const * c) { t_account * user; t_mailbox * mailbox; static char tmp[64]; int count; if (!(c)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return ""; } if (!(user=conn_get_account(c))) return ""; mailbox=mailbox_open(user, mbox_mode_read); count = mailbox_count(mailbox); mailbox_close(mailbox); if (count == 0) { return "You have no mail."; } else { sprintf(tmp,"You have %d message(s) in your mailbox.",count); return tmp; } } pvpgn-1.8.5/src/bnetd/anongame_gameresult.h0000644000175000017500000000430511151345317017715 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_ANONGAME_GAMERESULT_TYPES #define INCLUDED_ANONGAME_GAMERESULT_TYPES #ifdef ANONGAME_GAMERESULT_INTERNAL_ACCESS typedef struct { char number; int result; int race; } t_anongame_player; typedef struct { int level; int race_and_name; int hero_xp; } t_anongame_hero; #endif typedef struct anongame_gameresult_struct #ifdef ANONGAME_GAMERESULT_INTERNAL_ACCESS { char number_of_results; t_anongame_player *players; int unit_score; int heroes_score; int resource_score; int units_produced; int units_killed; int buildings_produced; int buildings_razed; int largest_army; int heroes_used_count; t_anongame_hero *heroes; int heroes_killed; int items_obtained; int mercenaries_hired; int total_hero_xp; int gold_mined; int lumber_harvested; int resources_traded_given; int resources_traded_taken; int tech_percentage; int gold_lost_to_upkeep; } #endif t_anongame_gameresult; #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_ANONGAME_GAMERESULT_PROTOS #define INCLUDED_ANONGAME_GAMERESULT_PROTOS extern t_anongame_gameresult * anongame_gameresult_parse(t_packet const * const packet); extern int gameresult_destroy(t_anongame_gameresult * gameresult); extern char gameresult_get_number_of_results(t_anongame_gameresult * gameresult); extern int gameresult_get_player_result(t_anongame_gameresult * gameresult, int player); extern int gameresult_get_player_number(t_anongame_gameresult * gameresult, int player); #endif #endif pvpgn-1.8.5/src/bnetd/team.c0000644000175000017500000002717311151345317014631 0ustar aaronaaron/* * (C) 2004 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define TEAM_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include "compat/pdir.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include "common/eventlog.h" #include "common/packet.h" #include "common/tag.h" #include "common/util.h" #include "common/xalloc.h" #include "common/list.h" #include "storage.h" #include "team.h" #include "account.h" #include "account_wrap.h" #include "ladder.h" #ifdef HAVE_ASSERT_H # include #endif #include "server.h" #include "common/setup_after.h" static t_list *teamlist_head = NULL; int max_teamid = 0; int teamlist_add_team(t_team * team); /* callback function for storage use */ static int _cb_load_teams(void *team) { if (teamlist_add_team(team) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "failed to add team to teamlist"); return -1; } if (((t_team *) team)->teamid > max_teamid) max_teamid = ((t_team *) team)->teamid; return 0; } int teamlist_add_team(t_team * team) { int i; if (!(team)) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL team"); return -1; } for (i=0; isize; i++) { if (!(team->members[i] = accountlist_find_account_by_uid(team->teammembers[i]))) { eventlog(eventlog_level_error,__FUNCTION__,"at least one non-existant member (id %d) in team %u - discarding team",team->teammembers[i],team->teamid); //FIXME: delete team file now??? return team->teamid; //we return teamid even though we have an error, we don't want unintentional overwriting } } for (i=0; isize; i++) account_add_team(team->members[i],team); if (!(team->teamid)) team->teamid = ++max_teamid; list_append_data(teamlist_head, team); return team->teamid; } int teamlist_load(void) { // make sure to unload previous teamlist before loading again if (teamlist_head) teamlist_unload(); teamlist_head = list_create(); storage->load_teams(_cb_load_teams); return 0; } int teamlist_unload(void) { t_elem *curr; t_team *team; if ((teamlist_head)) { LIST_TRAVERSE(teamlist_head, curr) { if (!(team = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } xfree((void *) team); list_remove_elem(teamlist_head, &curr); } if (list_destroy(teamlist_head) < 0) return -1; teamlist_head = NULL; } return 0; } int teams_destroy(t_list * teams) { t_elem *curr; t_team *team; if ((teams)) { LIST_TRAVERSE(teams,curr) { if (!(team = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } list_remove_elem(teams, &curr); } if (list_destroy(teams) < 0) return -1; } teams = NULL; return 0; } t_team* create_team(t_account **accounts, t_clienttag clienttag) { t_team * team; int i; unsigned char size; team = xmalloc(sizeof(t_team)); memset(team,0,sizeof(t_team)); size = 0; for (i=0; imembers[i] = accounts[i]; if ((accounts[i])) { team->teammembers[i] = account_get_uid(accounts[i]); size++; } } team->size = size; team->clienttag = clienttag; _cb_load_teams(team); storage->write_team(team); return team; } void dispose_team(t_team * team) { if ((team)) xfree((void *)team); team = NULL; } t_team * teamlist_find_team_by_accounts(t_account **accounts,t_clienttag clienttag) { return _list_find_team_by_accounts(accounts, clienttag, teamlist_head); } t_team * _list_find_team_by_accounts(t_account **accounts, t_clienttag clienttag, t_list * teamlist) { t_elem *curr; t_team *cteam; int i,j,found; unsigned char size; assert(accounts); found = 0; if ((teamlist)) { LIST_TRAVERSE(teamlist,curr) { if (!(cteam = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } size = 0; for (i=0; imembers[j])) { found = 1; break; } } if (!(found)) break; } if ((found) && (clienttag==cteam->clienttag) && (size==cteam->size)) return cteam; } } return NULL; } t_team * teamlist_find_team_by_uids(unsigned int * uids, t_clienttag clienttag) { return _list_find_team_by_uids(uids, clienttag, teamlist_head); } t_team * _list_find_team_by_uids(unsigned int * uids, t_clienttag clienttag, t_list * teamlist) { t_elem *curr; t_team *cteam; int i,j,found; unsigned char size; assert(uids); found = 0; if ((teamlist)) { LIST_TRAVERSE(teamlist,curr) { if (!(cteam = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } size = 0; for (i=0; iteammembers[j])) { found = 1; break; } } if (!(found)) break; } if ((found) && (clienttag==cteam->clienttag) && (size==cteam->size)) return cteam; } } return NULL; } t_team * teamlist_find_team_by_teamid(unsigned int teamid) { return _list_find_team_by_teamid(teamid,teamlist_head); } t_team* _list_find_team_by_teamid(unsigned int teamid, t_list * teamlist) { t_elem * curr; t_team * cteam; assert(teamid); if ((teamlist)) { LIST_TRAVERSE(teamlist,curr) { if (!(cteam = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } if ((cteam->teamid == teamid)) return cteam; } } return NULL; } unsigned int team_get_teamid(t_team * team) { assert(team); return team->teamid; } t_account * team_get_member(t_team * team,int count) { assert(team); assert(count>=0); assert(countmembers[count]; } unsigned int team_get_memberuid(t_team * team,int count) { assert(team); assert(count>=0); assert(countteammembers[count]; } t_clienttag team_get_clienttag(t_team * team) { assert(team); return team->clienttag; } unsigned char team_get_size(t_team * team) { assert(team); return team->size; } int team_get_wins(t_team * team) { assert(team); return team->wins; } int team_get_losses(t_team * team) { assert(team); return team->losses; } int team_get_xp(t_team * team) { assert(team); return team->xp; } int team_get_level(t_team * team) { assert(team); return team->level; } int team_get_rank(t_team * team) { assert(team); return team->rank; } time_t team_get_lastgame(t_team * team) { assert(team); return team->lastgame; } int team_inc_wins(t_team * team) { assert(team); team->wins++; return 0; } int team_inc_losses(t_team * team) { assert(team); team->losses++; return 0; } int team_update_lastgame(t_team * team) { assert(team); team->lastgame = now; return 0; } extern int team_update_xp(t_team * team, int gameresult, unsigned int opponlevel, int * xp_diff) { int xp; int mylevel; int xpdiff = 0, placeholder; xp = team->xp; //get current xp if (xp < 0) { eventlog(eventlog_level_error, __FUNCTION__, "got negative XP"); return -1; } mylevel = team->level; //get teams level if (mylevel > W3_XPCALC_MAXLEVEL) { eventlog(eventlog_level_error, __FUNCTION__, "got invalid level: %d", mylevel); return -1; } if(mylevel<=0) //if level is 0 then set it to 1 mylevel=1; if (opponlevel < 1) opponlevel = 1; switch (gameresult) { case W3_GAMERESULT_WIN: ladder_war3_xpdiff(mylevel, opponlevel, &xpdiff, &placeholder); break; case W3_GAMERESULT_LOSS: ladder_war3_xpdiff(opponlevel, mylevel, &placeholder, &xpdiff); break; default: eventlog(eventlog_level_error, __FUNCTION__, "got invalid game result: %d", gameresult); return -1; } *xp_diff = xpdiff; xp += xpdiff; if (xp < 0) xp = 0; team->xp = xp; return 0; } int team_update_level(t_team * team) { int xp, mylevel; xp = team->xp; if (xp < 0) xp = 0; mylevel = team->level; if (mylevel < 1) mylevel = 1; if (mylevel > W3_XPCALC_MAXLEVEL) { eventlog(eventlog_level_error, "account_set_sololevel", "got invalid level: %d", mylevel); return -1; } mylevel = ladder_war3_updatelevel(mylevel, xp); team->level = mylevel; return 0; } int team_set_saveladderstats(t_team * team, unsigned int gametype, int result, unsigned int opponlevel,t_clienttag clienttag) { unsigned int intrace; int xpdiff,level; int i; t_account * account; if(!team) { eventlog(eventlog_level_error,__FUNCTION__, "got NULL team"); return -1; } //added for better tracking down of problems with gameresults eventlog(eventlog_level_trace,__FUNCTION__,"parsing game result for team: %u result: %s",team_get_teamid(team),(result==W3_GAMERESULT_WIN)?"WIN":"LOSS"); if(result == W3_GAMERESULT_WIN) { team_inc_wins(team); } if(result == W3_GAMERESULT_LOSS) { team_inc_losses(team); } team_update_xp(team, result, opponlevel,&xpdiff); team_update_level(team); team_update_lastgame(team); level = team_get_level(team); /* if (war3_ladder_update(at_ladder(clienttag),uid,xpdiff,level,account,0)!=0) war3_ladder_add(at_ladder(clienttag),uid,account_get_atteamxp(account,current_teamnum,clienttag),level,account,0,clienttag); */ storage->write_team(team); // now set currentatteam to 0 so we only get one report for each team for (i=0; imembers[i])) { intrace = account_get_w3pgrace(account,clienttag); if(result == W3_GAMERESULT_WIN) { account_inc_racewins(account,intrace,clienttag); } if(result == W3_GAMERESULT_LOSS) { account_inc_racelosses(account,intrace,clienttag); } account_set_currentatteam(account,0); } } return 0; } pvpgn-1.8.5/src/bnetd/handle_file.c0000644000175000017500000000754011151345317016131 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999,2000 Rob Crittenden (rcrit@greyoak.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #include "common/packet.h" #include "common/file_protocol.h" #include "common/eventlog.h" #include "connection.h" #include "common/queue.h" #include "file.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "handle_file.h" /* ADDED BY UNDYING SOULZZ 4/3/02 */ #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/psock.h" #include "common/setup_after.h" extern int handle_file_packet(t_connection * c, t_packet const * const packet) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c)); return -1; } /* REMOVED BY UNDYING SOULZZ 4/3/02 */ /* if (packet_get_class(packet)!=packet_class_file) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet)); return -1; } */ switch (conn_get_state(c)) { case conn_state_connected: switch (packet_get_type(packet)) { case CLIENT_FILE_REQ: { char const * rawname; if (!(rawname = packet_get_str_const(packet,sizeof(t_client_file_req),MAX_FILENAME_STR))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad FILE_REQ (missing or too long filename)",conn_get_socket(c)); return -1; } file_send(c,rawname, bn_int_get(packet->u.client_file_req.adid), bn_int_get(packet->u.client_file_req.extensiontag), bn_int_get(packet->u.client_file_req.startoffset), 1); } break; case CLIENT_FILE_REQ2: { t_packet * rpacket = NULL; if((rpacket = packet_create(packet_class_raw))) { packet_set_size(rpacket,sizeof(t_server_file_unknown1)); bn_int_set( &rpacket->u.server_file_unknown1.unknown, 0xdeadbeef ); conn_push_outqueue(c, rpacket ); packet_del_ref( rpacket ); } conn_set_state(c, conn_state_pending_raw); break; } default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown file packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet)); break; } break; case conn_state_pending_raw: switch (packet_get_type(packet)) { case CLIENT_FILE_REQ3: { char rawname[MAX_FILENAME_STR]; psock_recv( conn_get_socket(c), rawname, MAX_FILENAME_STR, 0 ); file_send(c, rawname, 0, 0, 0, 1); } break; default: eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown file packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet)); break; } break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown file connection state %d",conn_get_socket(c),(int)conn_get_state(c)); } return 0; } pvpgn-1.8.5/src/bnetd/account.h0000644000175000017500000001037711151345317015342 0ustar aaronaaron/* * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_ACCOUNT_TYPES #define INCLUDED_ACCOUNT_TYPES #ifndef JUST_NEED_TYPES #define JUST_NEED_TYPES #include "common/list.h" #include "common/elist.h" #include "clan.h" #include "team.h" #include "attrgroup.h" #undef JUST_NEED_TYPES #else #include "common/list.h" #include "common/elist.h" #include "clan.h" #include "team.h" #include "attrgroup.h" #endif #define ACCOUNT_FLAG_NONE 0 #define ACCOUNT_FLAG_FLOADED 1 /* friends list loaded */ struct connection; typedef struct account_struct #ifdef ACCOUNT_INTERNAL_ACCESS { t_attrgroup * attrgroup; char * name; /* profiling proved 99% of getstrattr its from get_name */ unsigned int namehash; /* cached from attrs */ unsigned int uid; /* cached from attrs */ unsigned int flags; struct connection * conn; t_clanmember * clanmember; t_list * friends; t_list * teams; } #endif t_account; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_ACCOUNT_PROTOS #define INCLUDED_ACCOUNT_PROTOS #define JUST_NEED_TYPES #include "common/hashtable.h" #include "connection.h" #undef JUST_NEED_TYPES extern unsigned int maxuserid; extern int accountlist_reload(void); extern int account_check_name(char const * name); extern unsigned int account_get_uid(t_account const * account); extern int account_match(t_account * account, char const * username); extern int account_save(t_account *account, unsigned flags); extern char const * account_get_strattr_real(t_account * account, char const * key, char const * fn, unsigned int ln); #define account_get_strattr(A,K) account_get_strattr_real(A,K,__FILE__,__LINE__) extern int account_set_strattr(t_account * account, char const * key, char const * val); extern int accountlist_create(void); extern int accountlist_destroy(void); extern t_hashtable * accountlist(void); extern t_hashtable * accountlist_uid(void); extern int accountlist_load_all(int flag); extern unsigned int accountlist_get_length(void); extern int accountlist_save(unsigned flags); extern int accountlist_flush(unsigned flags); extern t_account * accountlist_find_account(char const * username); extern t_account * accountlist_find_account_by_uid(unsigned int uid); extern int accountlist_allow_add(void); extern t_account * accountlist_create_account(const char *username, const char *passhash1); extern void accounts_get_attr(char const *); /* names and passwords */ extern char const * account_get_name_real(t_account * account, char const * fn, unsigned int ln); # define account_get_name(A) account_get_name_real(A,__FILE__,__LINE__) extern int account_check_mutual( t_account * account, int myuserid); extern t_list * account_get_friends(t_account * account); extern int account_set_clanmember(t_account * account, t_clanmember * clanmember); extern t_clanmember * account_get_clanmember(t_account * account); extern t_clanmember * account_get_clanmember_forced(t_account * account); extern t_clan * account_get_clan(t_account * account); extern t_clan * account_get_creating_clan(t_account * account); extern int account_set_conn(t_account * account, t_connection * conn); extern t_connection * account_get_conn(t_account * account); extern void account_add_team(t_account * account, t_team * team); extern t_team * account_find_team_by_accounts(t_account * account, t_account **accounts, t_clienttag clienttag); extern t_team * account_find_team_by_teamid(t_account * account, unsigned int teamid); extern t_list * account_get_teams(t_account * account); #endif #endif pvpgn-1.8.5/src/bnetd/attrgroup.h0000644000175000017500000000447711151345317015741 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __ATTRGROUP_H_INCLUDED__ #define __ATTRGROUP_H_INCLUDED__ #ifdef HAVE_TIME_H # include #endif #include "common/elist.h" #ifndef JUST_NEED_TYPES #define JUST_NEED_TYPES #include "storage.h" #undef JUST_NEED_TYPES #else #include "storage.h" #endif #define ATTRGROUP_FLAG_NONE 0 #define ATTRGROUP_FLAG_LOADED 1 #define ATTRGROUP_FLAG_ACCESSED 2 #define ATTRGROUP_FLAG_DIRTY 4 /* attrgroup represents a group of attributes which are read/saved/flush together * ex: each account stores it's data into a attrgroup */ typedef struct attrgroup_struct #ifdef ATTRGROUP_INTERNAL_ACCESS { t_hlist list; t_storage_info *storage; int flags; time_t lastaccess; time_t dirtytime; t_elist loadedlist; t_elist dirtylist; } #endif t_attrgroup; typedef int (*t_attr_cb)(t_attrgroup *, void *); extern t_attrgroup *attrgroup_create_storage(t_storage_info *storage); extern t_attrgroup *attrgroup_create_newuser(const char *name); extern t_attrgroup *attrgroup_create_nameuid(const char *name, unsigned uid); extern int attrgroup_destroy(t_attrgroup *attrgroup); extern int attrgroup_load(t_attrgroup *attrgroup); extern int attrgroup_unload(t_attrgroup *attrgroup); extern int attrgroup_read_accounts(int flag, t_attr_cb cb, void *data); extern const char *attrgroup_get_attr(t_attrgroup *attrgroup, const char *key); extern int attrgroup_set_attr(t_attrgroup *attrgroup, const char *key, const char *val); extern int attrgroup_save(t_attrgroup *attrgroup, int flags); extern int attrgroup_flush(t_attrgroup *attrgroup, int flags); #endif /* __ATTRGROUP_H_INCLUDED__ */ pvpgn-1.8.5/src/bnetd/storage_sql2.h0000644000175000017500000000202411151345317016301 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* the types defined in there are general for both SQL layouts */ #include "storage.h" #ifndef JUST_NEED_TYPES #ifndef INCLUDED_STORAGE_SQL2_PROTOS #define INCLUDED_STORAGE_SQL2_PROTOS extern t_storage storage_sql2; #endif /* INCLUDED_STORAGE_SQL2_PROTOS */ #endif /* JUST_NEED_TYPES */ pvpgn-1.8.5/src/bnetd/autoupdate.h0000644000175000017500000000273111151345317016054 0ustar aaronaaron/* * Copyright (C) 2000 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 2002 Gianluigi Tiesi (sherpya@netfarm.it) * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_AUTOUPDATE_TYPES #define INCLUDED_AUTOUPDATE_TYPES #include "common/tag.h" #ifdef AUTOUPDATE_INTERNAL_ACCESS typedef struct { t_tag archtag; t_tag clienttag; char const * versiontag; char const * mpqfile; } t_autoupdate; #endif #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_AUTOUPDATE_PROTOS #define INCLUDED_AUTOUPDATE_PROTOS extern int autoupdate_load(char const * filename); extern int autoupdate_unload(void); extern char * autoupdate_check(t_tag archtag, t_tag clienttag, t_tag gamelang, char const * versiontag); #endif #endif pvpgn-1.8.5/src/bnetd/server.h0000644000175000017500000000415611151345317015212 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SERVER_TYPES #define INCLUDED_SERVER_TYPES #ifdef SERVER_INTERNAL_ACCESS typedef enum { laddr_type_bnet, /* classic battle.net service (usually on port 6112) */ laddr_type_w3route, /* warcraft 3 playgame routing (def. port 6200) */ laddr_type_irc, /* Internet Relay Chat service (port is varying; mostly on port 6667 or 7000) */ laddr_type_wol, /* Westwood Online (IRC) Chat Services (port is 4005) */ laddr_type_telnet /* telnet service (usually on port 23) */ } t_laddr_type; /* listen address structure */ typedef struct { int ssocket; /* TCP listen socket */ int usocket; /* UDP socket */ t_laddr_type type; } t_laddr_info; #endif #ifdef HAVE_TIME_H # include #endif extern time_t now; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_SERVER_PROTOS #define INCLUDED_SERVER_PROTOS extern unsigned int server_get_uptime(void); extern unsigned int server_get_starttime(void); extern void server_quit_delay(int delay); extern void server_set_hostname(void); extern char const * server_get_hostname(void); extern void server_clear_hostname(void); extern int server_process(void); extern void server_quit_wraper(void); extern void server_restart_wraper(void); extern void server_save_wraper(void); #endif #endif pvpgn-1.8.5/src/bnetd/ladder.c0000644000175000017500000022702611151345317015135 0ustar aaronaaron/* * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999,2000 D.Moreaux (vapula@linuxbe.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define LADDER_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include #include "common/field_sizes.h" #include "account.h" #include "account_wrap.h" #include "common/eventlog.h" #include "common/util.h" #include "game.h" #include "common/tag.h" #include "common/list.h" #include "common/bnettime.h" #include "prefs.h" #include "common/hashtable.h" #include "ladder_calc.h" #include "ladder.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include "ladder_binary.h" #include "storage.h" #include "account.h" #include "common/bnet_protocol.h" #include "common/xalloc.h" #include "common/setup_after.h" #define MaxRankKeptInLadder 1000 /* for War3 XP computations */ static t_xpcalc_entry * xpcalc; static t_xplevel_entry * xplevels; int w3_xpcalc_maxleveldiff; const char * WAR3_solo_file = "WAR3_solo"; const char * W3XP_solo_file = "W3XP_solo"; const char * WAR3_team_file = "WAR3_team"; const char * W3XP_team_file = "W3XP_team"; const char * WAR3_ffa_file = "WAR3_ffa"; const char * W3XP_ffa_file = "W3XP_ffa"; const char * WAR3_at_file = "WAR3_atteam"; const char * W3XP_at_file = "W3XP_atteam"; const char * STAR_ar_file = "STAR_active_rating"; const char * STAR_cr_file = "STAR_current_rating"; const char * SEXP_ar_file = "SEXP_active_rating"; const char * SEXP_cr_file = "SEXP_current_rating"; const char * W2BN_ar_file = "W2BN_active_rating"; const char * W2BN_cr_file = "W2BN_current_rating"; const char * W2BN_ari_file = "W2BN_active_rating_iron"; const char * W2BN_cri_file = "W2BN_current_rating_iron"; const char * std_end = ".dat"; const char * xml_end = ".xml"; char * ladder_id_str[] = {"0","1","","3","","solo","team","ffa"}; char * WAR3_solo_filename, * WAR3_team_filename, * WAR3_ffa_filename, * WAR3_at_filename; char * W3XP_solo_filename, * W3XP_team_filename, * W3XP_ffa_filename, * W3XP_at_filename; char * STAR_ar_filename, * STAR_cr_filename, * SEXP_ar_filename, * SEXP_cr_filename; char * W2BN_ar_filename, * W2BN_cr_filename, * W2BN_ari_filename, * W2BN_cri_filename; t_ladder WAR3_solo_ladder, WAR3_team_ladder, WAR3_ffa_ladder, WAR3_at_ladder; t_ladder W3XP_solo_ladder, W3XP_team_ladder, W3XP_ffa_ladder, W3XP_at_ladder; t_ladder STAR_active_rating, STAR_active_wins, STAR_active_games, STAR_current_rating, STAR_current_wins, STAR_current_games; t_ladder SEXP_active_rating, SEXP_active_wins, SEXP_active_games, SEXP_current_rating, SEXP_current_wins, SEXP_current_games; t_ladder W2BN_active_rating, W2BN_active_wins, W2BN_active_games, W2BN_active_rating_ironman, W2BN_active_wins_ironman, W2BN_active_games_ironman; t_ladder W2BN_current_rating, W2BN_current_wins, W2BN_current_games, W2BN_current_rating_ironman, W2BN_current_wins_ironman, W2BN_current_games_ironman; t_ladder_internal * last_internal = NULL; t_ladder * last_ladder = NULL; int last_rank = 0; /* * Make the current ladder statistics the active ones. */ extern int ladder_make_active(t_ladder *current, t_ladder *active,int set_attributes); extern int ladderlist_make_all_active(void) { ladder_make_active(ladder_cr(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), ladder_ar(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),1); ladder_make_active(ladder_cw(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), ladder_aw(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),0); ladder_make_active(ladder_cg(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), ladder_ag(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),0); ladder_make_active(ladder_cr(CLIENTTAG_BROODWARS_UINT,ladder_id_normal), ladder_ar(CLIENTTAG_BROODWARS_UINT,ladder_id_normal),1); ladder_make_active(ladder_cw(CLIENTTAG_BROODWARS_UINT,ladder_id_normal), ladder_aw(CLIENTTAG_BROODWARS_UINT,ladder_id_normal),0); ladder_make_active(ladder_cg(CLIENTTAG_BROODWARS_UINT,ladder_id_normal), ladder_ag(CLIENTTAG_BROODWARS_UINT,ladder_id_normal),0); ladder_make_active(ladder_cr(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), ladder_ar(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),1); ladder_make_active(ladder_cw(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), ladder_aw(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),0); ladder_make_active(ladder_cg(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), ladder_ag(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),0); ladder_make_active(ladder_cr(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),ladder_ar(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),1); ladder_make_active(ladder_cw(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),ladder_aw(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),0); ladder_make_active(ladder_cg(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),ladder_ag(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),0); ladder_update_all_accounts(); return 0; } /* * Prepare an account for first ladder play if necessary. */ extern int ladder_init_account(t_account * account, t_clienttag clienttag, t_ladder_id id) { int uid; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } if (account_get_ladder_rating(account,clienttag,id)==0) { if (account_get_ladder_wins(account,clienttag,id)+ account_get_ladder_losses(account,clienttag,id)>0) /* no ladder games so far... */ { eventlog(eventlog_level_warn,__FUNCTION__,"account for \"%s\" (%s) has %u wins and %u losses but has zero rating",account_get_name(account),clienttag_uint_to_str(clienttag),account_get_ladder_wins(account,clienttag,id),account_get_ladder_losses(account,clienttag,id)); return -1; } account_adjust_ladder_rating(account,clienttag,id,prefs_get_ladder_init_rating()); uid = account_get_uid(account); war3_ladder_add(ladder_cr(clienttag,id),uid,0,account_get_ladder_rating(account,clienttag,id),account,0,clienttag); war3_ladder_add(ladder_cw(clienttag,id),uid,0,0,account,0,clienttag); war3_ladder_add(ladder_cg(clienttag,id),uid,0,0,account,0,clienttag); eventlog(eventlog_level_info,__FUNCTION__,"initialized account for \"%s\" for \"%s\" ladder",account_get_name(account),clienttag_uint_to_str(clienttag)); } return 0; } /* * Update player ratings, rankings, etc due to game results. */ extern int ladder_update(t_clienttag clienttag, t_ladder_id id, unsigned int count, t_account * * players, t_game_result * results, t_ladder_info * info, t_ladder_option opns) { unsigned int curr; unsigned int winners=0; unsigned int losers=0; unsigned int draws=0; int uid; if (count<1 || count>8) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid player count %u",count); return -1; } if (!players) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL players"); return -1; } if (!results) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL results"); return -1; } if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag"); return -1; } if (!info) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL info"); return -1; } for (curr=0; curr0) { if (draws!=count) { eventlog(eventlog_level_error,__FUNCTION__,"some, but not all players had a draw count=%u (winners=%u losers=%u draws=%u)",count,winners,losers,draws); return -1; } return -1; /* no change in case of draw */ } if ((losers<1) || (winners<1) || (winners>1 && (winners!=losers))) { eventlog(eventlog_level_info,__FUNCTION__,"missing winner or loser for count=%u (winners=%u losers=%u draws=%u) - discarding result",count,winners,losers,draws); return -1; } if (ladder_calc_info(clienttag,id,count,players,results,info)<0) { eventlog(eventlog_level_error,__FUNCTION__,"unable to calculate info from game results"); return -1; } for (curr=0; currclienttag; } t_binary_ladder_types w3_ladder_to_binary_ladder_types(t_ladder * ladder) { return ladder->type; } t_ladder * binary_ladder_types_to_w3_ladder(t_binary_ladder_types type) { t_ladder * ladder; switch (type) { case WAR3_SOLO: ladder = &WAR3_solo_ladder; break; case WAR3_TEAM: ladder = &WAR3_team_ladder; break; case WAR3_FFA: ladder = &WAR3_ffa_ladder; break; case WAR3_AT: ladder = &WAR3_at_ladder; break; case W3XP_SOLO: ladder = &W3XP_solo_ladder; break; case W3XP_TEAM: ladder = &W3XP_team_ladder; break; case W3XP_FFA: ladder = &W3XP_ffa_ladder; break; case W3XP_AT: ladder = &W3XP_at_ladder; break; case STAR_AR : ladder = &STAR_active_rating; break; case STAR_AW : ladder = &STAR_active_wins; break; case STAR_AG : ladder = &STAR_active_games; break; case STAR_CR : ladder = &STAR_current_rating; break; case STAR_CW : ladder = &STAR_current_wins; break; case STAR_CG : ladder = &STAR_current_games; break; case SEXP_AR : ladder = &SEXP_active_rating; break; case SEXP_AW : ladder = &SEXP_active_wins; break; case SEXP_AG : ladder = &SEXP_active_games; break; case SEXP_CR : ladder = &SEXP_current_rating; break; case SEXP_CW : ladder = &SEXP_current_wins; break; case SEXP_CG : ladder = &SEXP_current_games; break; case W2BN_AR : ladder = &W2BN_active_rating; break; case W2BN_AW : ladder = &W2BN_active_wins; break; case W2BN_AG : ladder = &W2BN_active_games; break; case W2BN_CR : ladder = &W2BN_current_rating; break; case W2BN_CW : ladder = &W2BN_current_wins; break; case W2BN_CG : ladder = &W2BN_current_games; break; case W2BN_ARI : ladder = &W2BN_active_rating_ironman; break; case W2BN_AWI : ladder = &W2BN_active_wins_ironman; break; case W2BN_AGI : ladder = &W2BN_active_games_ironman; break; case W2BN_CRI : ladder = &W2BN_current_rating_ironman; break; case W2BN_CWI : ladder = &W2BN_current_wins_ironman; break; case W2BN_CGI : ladder = &W2BN_current_games_ironman; break; default: eventlog(eventlog_level_error,__FUNCTION__,"got invalid ladder type %d",type); return NULL; } return ladder; } void ladder_init(t_ladder *ladder,t_binary_ladder_types type, t_clienttag clienttag, t_ladder_id ladder_id) { ladder->first = NULL; ladder->last = NULL; ladder->dirty = 1; ladder->type = type; ladder->clienttag = clienttag; ladder->ladder_id = ladder_id; } void ladder_destroy(t_ladder *ladder) { t_ladder_internal *pointer; while (ladder->first!=NULL) { pointer = ladder->first; ladder->first = pointer->prev; xfree((void *)pointer); } } extern int war3_ladder_add(t_ladder *ladder, int uid, int xp, int level, t_account *account, unsigned int teamcount,t_clienttag clienttag) { t_ladder_internal *ladder_entry; ladder_entry = xmalloc(sizeof(t_ladder_internal)); ladder_entry->uid = uid; ladder_entry->xp = xp; ladder_entry->level = level; ladder_entry->account = account; ladder_entry->teamcount = teamcount; ladder_entry->prev = NULL; ladder_entry->next = NULL; if (ladder->first == NULL) { // ladder empty, so just insert element ladder->first = ladder_entry; ladder->last = ladder_entry; } else { // already elements in list // determine if first or last user in ladder has XP // closest to current, cause should be the shorter way to insert // new user if ((ladder->first->xp - xp) >= (xp - ladder->last->xp)) // we should enter from last to first { t_ladder_internal *search; search = ladder->last; while ((search != NULL) && (search->level < level)) { search = search->next; } while ((search != NULL) && (search->level == level) && (search->xp < xp)) { search = search->next; } if (teamcount!=0) // this only happens for atteams { t_ladder_internal *teamsearch; t_ladder_internal *teamfound; teamsearch = search; teamfound = NULL; while ((teamsearch != NULL) && (teamsearch->xp == xp) && (teamsearch->level == level)) { if (in_same_team(account,teamsearch->account,teamcount,teamsearch->teamcount,clienttag)) { teamfound = teamsearch; break; } teamsearch = teamsearch->next; } if (teamfound!=NULL) search = teamfound; } if (search == NULL) { ladder->first->next = ladder_entry; ladder_entry->prev = ladder->first; ladder->first = ladder_entry; } else { ladder_entry->next = search; ladder_entry->prev = search->prev; if (search == ladder->last) // enter at end of list { search->prev = ladder_entry; ladder->last = ladder_entry; } else { search->prev->next = ladder_entry; search->prev = ladder_entry; } } } else // start from first and the search towards last { t_ladder_internal *search; search = ladder->first; while ((search != NULL) && (search->level > level)) { search = search->prev; } while ((search != NULL) && (search->level == level) && (search->xp > xp)) { search = search->prev; } if (teamcount!=0) // this only happens for atteams { t_ladder_internal *teamsearch; t_ladder_internal *teamfound; teamsearch = search; teamfound = NULL; while ((teamsearch != NULL) && (teamsearch->xp == xp)) { if (in_same_team(account,teamsearch->account,teamcount,teamsearch->teamcount,clienttag)) { teamfound = teamsearch; break; } teamsearch = teamsearch->prev; } if (teamfound!=NULL) search = teamfound; } if (search == NULL) { ladder->last->prev = ladder_entry; ladder_entry->next = ladder->last; ladder->last = ladder_entry; } else { ladder_entry->prev = search; ladder_entry->next = search->next; if (search == ladder->first) // enter at beginning of list { search->next = ladder_entry; ladder->first = ladder_entry; } else { search->next->prev = ladder_entry; search->next = ladder_entry; } } } } ladder->dirty = 1; return 0; } extern int war3_ladder_update(t_ladder *ladder, int uid, int xp, int level, t_account *account, unsigned int teamcount) { t_ladder_internal *search, *newpos; search = ladder->first; while (search && ((search->uid != uid) || (search->teamcount!=teamcount))) { search = search->prev; } if (search != NULL) { search->xp += xp; search->level = level; ladder->dirty = 1; // make sure, we don't get negative XP if (search->xp < 0) search->xp = 0; if (xp>0) // XP gained.... maybe getting better ranking { newpos = search->next; while ((newpos != NULL) && (newpos->level < level)) { newpos = newpos->next; } while ((newpos != NULL) && (newpos->level == level) && (newpos->xp < search->xp)) { newpos = newpos->next; } if (newpos != search->next) // so we really have to change ranking now { // first close gap, where we've been... search->next->prev = search->prev; if (search->prev != NULL) search->prev->next = search->next; else ladder->last = search->next; // and then move to new position search->next = newpos; if (newpos == NULL) { search->prev = ladder->first; ladder->first->next = search; ladder->first = search; } else { search->prev = newpos->prev; newpos->prev->next = search; newpos->prev = search; } } } if (xp<0) // XP lost.... maybe ranking gets worse { newpos = search->prev; while ((newpos != NULL) && (newpos->level > level)) { newpos = newpos->prev; } while ((newpos != NULL) && (newpos->level == level) && (newpos->xp > search->xp)) { newpos = newpos->prev; } if (newpos != search->prev) // so we really have to change ranking now { // first close gap, where we've been... search->prev->next = search->next; if (search->next != NULL) search->next->prev = search->prev; else ladder->first = search->prev; // and then move to new position search->prev = newpos; if (newpos == NULL) { search->next = ladder->last; ladder->last->prev = search; ladder->last = search; } else { search->next = newpos->next; newpos->next->prev = search; newpos->next = search; } } } return 0; } else return -1; } extern int ladder_get_rank(t_ladder *ladder, int uid, unsigned int teamcount, t_clienttag clienttag) { int ranking = 1; t_ladder_internal *search; search = ladder->first; while ((search!=NULL) && ((search->uid != uid) || (search->teamcount!=teamcount))) { search = search->prev; ranking++; if (ladder==at_ladder(clienttag)) { // if in the same team as previous account if ((search) && (search->next) && in_same_team(search->account,search->next->account,teamcount,search->next->teamcount,clienttag)) ranking--; } } if (search != NULL) { return ranking; } else { return 0; } } t_ladder_internal * ladder_get_rank_internal(t_ladder * ladder,int rank, t_clienttag clienttag) { int ranking; t_ladder_internal *search; // this should be a huge speedup when getting many subsequent entries from ladder // like used in saving of binary ladders if ((last_ladder == ladder) && (last_rank < rank) && (last_internal != NULL)) { ranking = last_rank; search = last_internal; } else { ranking = 1; search = ladder->first; } while ((search!=NULL) && (rankingprev; ranking++; if (ladder == at_ladder(clienttag)) { if ((search) && (search->next) && in_same_team(search->account,search->next->account,search->teamcount,search->next->teamcount,clienttag)) ranking--; } } last_ladder = ladder; last_internal = search; last_rank = rank; return search; } extern t_account * ladder_get_account(t_ladder *ladder, int rank, unsigned int * teamcount,t_clienttag clienttag) { t_ladder_internal *search; if (!(ladder)) { // eventlog(eventlog_level_error,__FUNCTION__,"got request for non-existant ladder"); return NULL; } search = ladder_get_rank_internal(ladder,rank,clienttag); if (search) { *teamcount = search->teamcount; return search->account; } else { *teamcount = 0; return NULL; } } typedef int (* t_set_fct)(t_account *account,t_clienttag cltag, t_ladder_id ldr_id,unsigned int rank); typedef int (* t_get_fct)(t_account *account,t_clienttag cltag, t_ladder_id ldr_id); extern int ladder_update_accounts(t_ladder *ladder, t_set_fct set_fct, t_get_fct get_fct1) { t_ladder_internal *pointer, *tmp_pointer; t_account *account; t_clienttag clienttag; int rank = 1; int update = 0; char clienttag_str[5]; if (ladder->dirty == 1) { if ((set_fct!=NULL) && (get_fct1!=NULL)) { clienttag = ladder_get_clienttag(ladder); pointer = ladder->first; while (pointer!=NULL) { account = pointer->account; if (rank <= MaxRankKeptInLadder) { if (ladder->ladder_id == ladder_id_none) //war3/w3xp AT ladder { // do nothing now } else //other ladders... { if ((*get_fct1)(account,clienttag,ladder->ladder_id)!=rank) { (*set_fct)(account,clienttag,ladder->ladder_id,rank); update++; } } pointer=pointer->prev; rank++; } else { // leave while loop break; } } while (pointer!=NULL) { // all accounts following now are out of the ladder range we keep track of.... // so set rank to 0 and remove account from ladder if (ladder->ladder_id == ladder_id_none) //war3/w3xp AT ladder { if ((*get_fct1)(account,pointer->teamcount,clienttag)!=0) (*set_fct)(account,pointer->teamcount,clienttag,0); } else { if ((*get_fct1)(account,clienttag,ladder->ladder_id)!=0) (*set_fct)(account,clienttag,ladder->ladder_id,0); } // remove account from ladder if (pointer->next!=NULL) pointer->next->prev = pointer->prev; if (pointer->prev!=NULL) pointer->prev->next = pointer->next; if (ladder->last == pointer) ladder->last = pointer->next; if (ladder->first == pointer) ladder->first = pointer->prev; tmp_pointer = pointer->prev; xfree((void *)pointer); pointer = tmp_pointer; } } binary_ladder_save(w3_ladder_to_binary_ladder_types(ladder),4,&ladder_get_from_ladder); if (update != 0) eventlog(eventlog_level_info,__FUNCTION__,"updated %u accounts for clienttag %s",update,tag_uint_to_str(clienttag_str,ladder->clienttag)); } ladder->dirty = 0; return 0; } extern int ladder_update_all_accounts(void) { eventlog(eventlog_level_info,__FUNCTION__,"updating ranking for all accounts"); ladder_update_accounts(&WAR3_solo_ladder, &account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&WAR3_team_ladder, &account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&WAR3_ffa_ladder, &account_set_ladder_rank, &account_get_ladder_rank); //ladder_update_accounts(&WAR3_at_ladder, &account_set_atteamrank, &account_get_atteamrank); ladder_update_accounts(&W3XP_solo_ladder, &account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&W3XP_team_ladder, &account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&W3XP_ffa_ladder, &account_set_ladder_rank, &account_get_ladder_rank); //ladder_update_accounts(&W3XP_at_ladder, &account_set_atteamrank, &account_get_atteamrank); ladder_update_accounts(&STAR_current_rating,&account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&STAR_current_wins, NULL, NULL); ladder_update_accounts(&STAR_current_games, NULL, NULL); ladder_update_accounts(&SEXP_current_rating,&account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&SEXP_current_wins, NULL, NULL); ladder_update_accounts(&SEXP_current_games, NULL, NULL); ladder_update_accounts(&STAR_active_rating, &account_set_ladder_active_rank, &account_get_ladder_active_rank); ladder_update_accounts(&STAR_active_wins, NULL, NULL); ladder_update_accounts(&STAR_active_games, NULL, NULL); ladder_update_accounts(&SEXP_active_rating, &account_set_ladder_active_rank, &account_get_ladder_active_rank); ladder_update_accounts(&SEXP_active_wins, NULL, NULL); ladder_update_accounts(&SEXP_active_games, NULL, NULL); ladder_update_accounts(&W2BN_current_rating,&account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&W2BN_current_wins, NULL, NULL); ladder_update_accounts(&W2BN_current_games, NULL, NULL); ladder_update_accounts(&W2BN_active_rating, &account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&W2BN_active_wins, NULL, NULL); ladder_update_accounts(&W2BN_active_games, NULL, NULL); ladder_update_accounts(&W2BN_current_rating_ironman, &account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&W2BN_current_wins_ironman, NULL, NULL); ladder_update_accounts(&W2BN_current_games_ironman, NULL, NULL); ladder_update_accounts(&W2BN_active_rating_ironman, &account_set_ladder_rank, &account_get_ladder_rank); ladder_update_accounts(&W2BN_active_wins_ironman, NULL, NULL); ladder_update_accounts(&W2BN_active_games_ironman, NULL, NULL); eventlog(eventlog_level_info,__FUNCTION__,"finished updating ranking for all accounts"); return 0; } t_binary_ladder_load_result binary_load(t_binary_ladder_types type) { t_binary_ladder_load_result result; t_ladder * ladder; result = binary_ladder_load(type,4,&ladder_put_into_ladder); if (result == illegal_checksum) { t_clienttag clienttag; t_ladder_id ladder_id; ladder = binary_ladder_types_to_w3_ladder(type); clienttag = ladder_get_clienttag(ladder); ladder_id = ladder->ladder_id; ladder_destroy(ladder); ladder_init(ladder,type,clienttag,ladder_id); } return result; } extern void ladders_load_accounts_to_ladderlists(void) { t_entry * curr; t_account * account; int xp; t_binary_ladder_load_result war3_solo_res, war3_team_res, war3_ffa_res, war3_at_res; t_binary_ladder_load_result w3xp_solo_res, w3xp_team_res, w3xp_ffa_res, w3xp_at_res; t_binary_ladder_load_result star_ar_res, star_aw_res, star_ag_res, star_cr_res, star_cw_res, star_cg_res; t_binary_ladder_load_result sexp_ar_res, sexp_aw_res, sexp_ag_res, sexp_cr_res, sexp_cw_res, sexp_cg_res; t_binary_ladder_load_result w2bn_cr_res, w2bn_cw_res, w2bn_cg_res, w2bn_cri_res, w2bn_cwi_res, w2bn_cgi_res; t_binary_ladder_load_result w2bn_ar_res, w2bn_aw_res, w2bn_ag_res, w2bn_ari_res, w2bn_awi_res, w2bn_agi_res; war3_solo_res = binary_load(WAR3_SOLO); war3_team_res = binary_load(WAR3_TEAM); war3_ffa_res = binary_load(WAR3_FFA); war3_at_res = load_success; // binary_load(WAR3_AT); w3xp_solo_res = binary_load(W3XP_SOLO); w3xp_team_res = binary_load(W3XP_TEAM); w3xp_ffa_res = binary_load(W3XP_FFA); w3xp_at_res = load_success; // binary_load(W3XP_AT); star_ar_res = binary_load(STAR_AR); star_aw_res = binary_load(STAR_AW); star_ag_res = binary_load(STAR_AG); star_cr_res = binary_load(STAR_CR); star_cw_res = binary_load(STAR_CW); star_cg_res = binary_load(STAR_CG); sexp_ar_res = binary_load(SEXP_AR); sexp_aw_res = binary_load(SEXP_AW); sexp_ag_res = binary_load(SEXP_AG); sexp_cr_res = binary_load(SEXP_CR); sexp_cw_res = binary_load(SEXP_CW); sexp_cg_res = binary_load(SEXP_CG); w2bn_cr_res = binary_load(W2BN_CR); w2bn_cw_res = binary_load(W2BN_CW); w2bn_cg_res = binary_load(W2BN_CG); w2bn_cri_res = binary_load(W2BN_CRI); w2bn_cwi_res = binary_load(W2BN_CWI); w2bn_cgi_res = binary_load(W2BN_CGI); w2bn_ar_res = binary_load(W2BN_AR); w2bn_aw_res = binary_load(W2BN_AW); w2bn_ag_res = binary_load(W2BN_AG); w2bn_ari_res = binary_load(W2BN_ARI); w2bn_awi_res = binary_load(W2BN_AWI); w2bn_agi_res = binary_load(W2BN_AGI); if ((war3_solo_res + war3_team_res + war3_ffa_res + war3_at_res + w3xp_solo_res + w3xp_team_res + w3xp_ffa_res + w3xp_at_res + star_ar_res + star_aw_res + star_ag_res + star_cr_res + star_cw_res + star_cg_res + sexp_ar_res + sexp_aw_res + sexp_ag_res + sexp_cr_res + sexp_cw_res + sexp_cg_res + w2bn_cr_res + w2bn_cw_res + w2bn_cg_res + w2bn_cri_res + w2bn_cwi_res + w2bn_cgi_res + w2bn_ar_res + w2bn_aw_res + w2bn_ag_res + w2bn_ari_res + w2bn_awi_res + w2bn_agi_res ) == load_success) { eventlog(eventlog_level_trace,__FUNCTION__,"everything went smooth... taking shortcut"); return; } eventlog(eventlog_level_warn, __FUNCTION__, "binary ladders missing or incomplete, going to load all accounts to rebuild them"); if (accountlist_load_all(ST_FORCE)) { eventlog(eventlog_level_error, __FUNCTION__, "error loading all accounts"); return; } HASHTABLE_TRAVERSE(accountlist(),curr) { if ((account=((t_account *)entry_get_data(curr)))) { int rating, wins; int uid = account_get_uid(account); if ((war3_solo_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_solo)))) { war3_ladder_add(&WAR3_solo_ladder, uid, xp, account_get_ladder_level(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_solo), account,0,CLIENTTAG_WARCRAFT3_UINT); } if ((war3_team_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_team)))) { war3_ladder_add(&WAR3_team_ladder, uid, xp, account_get_ladder_level(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_team), account,0,CLIENTTAG_WARCRAFT3_UINT); } if ((war3_ffa_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_ffa)))) { war3_ladder_add(&WAR3_ffa_ladder, uid, xp, account_get_ladder_level(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_ffa), account,0,CLIENTTAG_WARCRAFT3_UINT); } // user is part of a team /* if ((war3_at_res!=load_success) && ((teamcount = account_get_atteamcount(account,CLIENTTAG_WARCRAFT3_UINT)))) { int counter; for (counter=1; counter<=teamcount; counter++) { if ((xp = account_get_atteamxp(account,counter,CLIENTTAG_WARCRAFT3_UINT)) && account_get_atteammembers(account,counter,CLIENTTAG_WARCRAFT3_UINT)) { war3_ladder_add(&WAR3_at_ladder, uid, xp, account_get_atteamlevel(account,counter,CLIENTTAG_WARCRAFT3_UINT), account, counter,CLIENTTAG_WARCRAFT3_UINT); } } } */ if ((w3xp_solo_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WAR3XP_UINT,ladder_id_solo)))) { war3_ladder_add(&W3XP_solo_ladder, uid, xp, account_get_ladder_level(account,CLIENTTAG_WAR3XP_UINT,ladder_id_solo), account,0,CLIENTTAG_WAR3XP_UINT); } if ((w3xp_team_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WAR3XP_UINT,ladder_id_team)))) { war3_ladder_add(&W3XP_team_ladder, uid, xp, account_get_ladder_level(account,CLIENTTAG_WAR3XP_UINT,ladder_id_team), account,0,CLIENTTAG_WAR3XP_UINT); } if ((w3xp_ffa_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WAR3XP_UINT,ladder_id_ffa)))) { war3_ladder_add(&W3XP_ffa_ladder, uid, xp, account_get_ladder_level(account,CLIENTTAG_WAR3XP_UINT,ladder_id_ffa), account,0, CLIENTTAG_WAR3XP_UINT); } // user is part of a team /* if ((w3xp_at_res!=load_success) && ((teamcount = account_get_atteamcount(account,CLIENTTAG_WAR3XP_UINT)))) { int counter; for (counter=1; counter<=teamcount; counter++) { if ((xp = account_get_atteamxp(account,counter,CLIENTTAG_WAR3XP_UINT)) && account_get_atteammembers(account,counter,CLIENTTAG_WAR3XP_UINT)) { war3_ladder_add(&W3XP_at_ladder, uid, xp, account_get_atteamlevel(account,counter,CLIENTTAG_WAR3XP_UINT), account, counter,CLIENTTAG_WAR3XP_UINT); } } } */ if ((rating = account_get_ladder_rating(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal))>0) { wins = account_get_ladder_wins(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); if (star_cr_res!=load_success) { war3_ladder_add(&STAR_current_rating, uid,wins,rating,account,0,CLIENTTAG_STARCRAFT_UINT); } if (star_cw_res!=load_success) { war3_ladder_add(&STAR_current_wins, uid,rating,wins,account,0,CLIENTTAG_STARCRAFT_UINT); } if (star_cg_res!=load_success) { int games = wins + account_get_ladder_losses(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal)+ account_get_ladder_disconnects(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); war3_ladder_add(&STAR_current_games, uid,rating,games,account,0,CLIENTTAG_STARCRAFT_UINT); } } if ((rating = account_get_ladder_active_rating(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal))>0) { wins = account_get_ladder_active_wins(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); if (star_ar_res!=load_success) { war3_ladder_add(&STAR_active_rating, uid,wins,rating,account,0,CLIENTTAG_STARCRAFT_UINT); } if (star_aw_res!=load_success) { war3_ladder_add(&STAR_active_wins, uid,rating,wins,account,0,CLIENTTAG_STARCRAFT_UINT); } if (star_ag_res!=load_success) { int games = wins + account_get_ladder_active_losses(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal)+ account_get_ladder_active_disconnects(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); war3_ladder_add(&STAR_active_games, uid,rating,games,account,0,CLIENTTAG_STARCRAFT_UINT); } } if ((rating = account_get_ladder_rating(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal))>0) { wins = account_get_ladder_wins(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal); if (sexp_cr_res!=load_success) { war3_ladder_add(&SEXP_current_rating, uid,wins,rating,account,0,CLIENTTAG_BROODWARS_UINT); } if (sexp_cw_res!=load_success) { war3_ladder_add(&SEXP_current_wins, uid,rating,wins,account,0,CLIENTTAG_BROODWARS_UINT); } if (sexp_cg_res!=load_success) { int games = wins + account_get_ladder_losses(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal)+ account_get_ladder_disconnects(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal); war3_ladder_add(&SEXP_current_games, uid,rating,games,account,0,CLIENTTAG_BROODWARS_UINT); } } if ((rating = account_get_ladder_active_rating(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal))>0) { wins = account_get_ladder_active_wins(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal); if (sexp_ar_res!=load_success) { war3_ladder_add(&SEXP_active_rating, uid,wins,rating,account,0,CLIENTTAG_BROODWARS_UINT); } if (sexp_aw_res!=load_success) { war3_ladder_add(&SEXP_active_wins, uid,rating,wins,account,0,CLIENTTAG_BROODWARS_UINT); } if (sexp_ag_res!=load_success) { int games = wins + account_get_ladder_active_losses(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal)+ account_get_ladder_active_disconnects(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal); war3_ladder_add(&SEXP_active_games, uid,rating,games,account,0,CLIENTTAG_BROODWARS_UINT); } } if ((rating = account_get_ladder_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal))>0) { wins = account_get_ladder_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); if (w2bn_cr_res!=load_success) { war3_ladder_add(&W2BN_current_rating, uid,wins,rating,account,0,CLIENTTAG_WARCIIBNE_UINT); } if (w2bn_cw_res!=load_success) { war3_ladder_add(&W2BN_current_wins, uid,rating,wins,account,0,CLIENTTAG_WARCIIBNE_UINT); } if (w2bn_cg_res!=load_success) { int games = wins + account_get_ladder_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal)+ account_get_ladder_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); war3_ladder_add(&W2BN_current_games, uid,rating,games,account,0,CLIENTTAG_WARCIIBNE_UINT); } } if ((rating = account_get_ladder_active_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal))>0) { wins = account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); if (w2bn_ar_res!=load_success) { war3_ladder_add(&W2BN_active_rating, uid,wins,rating,account,0,CLIENTTAG_WARCIIBNE_UINT); } if (w2bn_aw_res!=load_success) { war3_ladder_add(&W2BN_active_wins, uid,rating,wins,account,0,CLIENTTAG_WARCIIBNE_UINT); } if (w2bn_ag_res!=load_success) { int games = wins + account_get_ladder_active_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal)+ account_get_ladder_active_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); war3_ladder_add(&W2BN_active_games, uid,rating,games,account,0,CLIENTTAG_WARCIIBNE_UINT); } } if ((rating = account_get_ladder_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman))>0) { wins = account_get_ladder_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); if (w2bn_cri_res!=load_success) { war3_ladder_add(&W2BN_current_rating_ironman, uid,wins,rating,account,0,CLIENTTAG_WARCIIBNE_UINT); } if (w2bn_cwi_res!=load_success) { war3_ladder_add(&W2BN_current_wins_ironman, uid,rating,wins,account,0,CLIENTTAG_WARCIIBNE_UINT); } if (w2bn_cgi_res!=load_success) { int games = wins + account_get_ladder_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)+ account_get_ladder_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); war3_ladder_add(&W2BN_current_games_ironman, uid,rating,games,account,0,CLIENTTAG_WARCIIBNE_UINT); } } if ((rating = account_get_ladder_active_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman))>0) { wins = account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); if (w2bn_ari_res!=load_success) { war3_ladder_add(&W2BN_active_rating_ironman, uid,wins,rating,account,0,CLIENTTAG_WARCIIBNE_UINT); } if (w2bn_awi_res!=load_success) { war3_ladder_add(&W2BN_active_wins_ironman, uid,rating,wins,account,0,CLIENTTAG_WARCIIBNE_UINT); } if (w2bn_agi_res!=load_success) { int games = account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)+ account_get_ladder_active_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)+ account_get_ladder_active_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); war3_ladder_add(&W2BN_active_games_ironman, uid,rating, games,account,0,CLIENTTAG_WARCIIBNE_UINT); } } } } } int standard_writer(FILE * fp, t_ladder * ladder, t_clienttag clienttag) { t_ladder_internal * pointer; unsigned int rank=0; pointer = ladder->first; while (pointer != NULL) { rank++; if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT) { if (ladder==at_ladder(clienttag)) { // if in the same team as previous account if ((pointer) && (pointer->next) && in_same_team(pointer->account,pointer->next->account,pointer->teamcount,pointer->next->teamcount,clienttag)) { rank--; } // other team... so write all team members names, xp and rank to file else { //fprintf(fp,"%s,%u,%u\n",account_get_atteammembers(pointer->account,pointer->teamcount,clienttag),pointer->xp,rank); } } else // write username, xp and rank to file fprintf(fp,"%s,%u,%u\n",account_get_name(pointer->account),pointer->xp,rank); } else if (clienttag==CLIENTTAG_STARCRAFT_UINT || clienttag==CLIENTTAG_BROODWARS_UINT || clienttag==CLIENTTAG_WARCIIBNE_UINT) { fprintf(fp,"%u %s %u (%u / %u / %u)\n",rank, account_get_name(pointer->account),pointer->level, account_get_ladder_wins(pointer->account,ladder->clienttag,ladder->ladder_id), account_get_ladder_losses(pointer->account,ladder->clienttag,ladder->ladder_id), account_get_ladder_disconnects(pointer->account,ladder->clienttag,ladder->ladder_id)); } pointer=pointer->prev; } return 0; } int XML_writer(FILE * fp, t_ladder * ladder, t_clienttag clienttag) /* XML Ladder files * added by jfro * 1/2/2003 */ { t_ladder_internal * pointer; unsigned int rank=0; unsigned int level; unsigned int wins; unsigned int losses; unsigned int discs; unsigned int orc_wins,human_wins,undead_wins,nightelf_wins,random_wins; unsigned int orc_losses,human_losses,undead_losses,nightelf_losses,random_losses; fprintf(fp,"\n\n"); pointer = ladder->first; while (pointer != NULL) { rank++; if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT) { if (ladder==at_ladder(clienttag)) { // if in the same team as previous account if ((pointer) && (pointer->next) && in_same_team(pointer->account,pointer->next->account,pointer->teamcount,pointer->next->teamcount,clienttag)) rank--; else { /* other team... so write all team members names, xp and rank to file fprintf(fp,"\t\n"); if (account_get_atteammembers(pointer->account,pointer->teamcount,clienttag)==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid team, skipping"); pointer=pointer->prev; continue; } members = xstrdup(account_get_atteammembers(pointer->account,pointer->teamcount,clienttag)); for ( member = strtok(members," "); member; member = strtok(NULL," ")) fprintf(fp,"\t\t%s\n",member); xfree(members); fprintf(fp,"\t\t%u\n\t\t%u\n\t\n",pointer->xp,rank); */ } } else { if (ladder==solo_ladder(clienttag)) { level = account_get_ladder_level(pointer->account,clienttag,ladder_id_solo); wins = account_get_ladder_wins(pointer->account,clienttag,ladder_id_solo); losses = account_get_ladder_losses(pointer->account,clienttag,ladder_id_solo); } else if (ladder==team_ladder(clienttag)) { level = account_get_ladder_level(pointer->account,clienttag,ladder_id_team); wins = account_get_ladder_wins(pointer->account,clienttag,ladder_id_team); losses = account_get_ladder_losses(pointer->account,clienttag,ladder_id_team); } else if (ladder==ffa_ladder(clienttag)) { level = account_get_ladder_level(pointer->account,clienttag,ladder_id_ffa); wins = account_get_ladder_wins(pointer->account,clienttag,ladder_id_ffa); losses = account_get_ladder_losses(pointer->account,clienttag,ladder_id_ffa); } else { level = 0; wins = 0; losses = 0; } orc_wins = account_get_racewins(pointer->account,W3_RACE_ORCS,clienttag); orc_losses = account_get_racelosses(pointer->account,W3_RACE_ORCS,clienttag); undead_wins = account_get_racewins(pointer->account,W3_RACE_UNDEAD,clienttag); undead_losses = account_get_racelosses(pointer->account,W3_RACE_UNDEAD,clienttag); human_wins = account_get_racewins(pointer->account,W3_RACE_HUMANS,clienttag); human_losses = account_get_racelosses(pointer->account,W3_RACE_HUMANS,clienttag); nightelf_wins = account_get_racewins(pointer->account,W3_RACE_NIGHTELVES,clienttag); nightelf_losses = account_get_racelosses(pointer->account,W3_RACE_NIGHTELVES,clienttag); random_wins = account_get_racewins(pointer->account,W3_RACE_RANDOM,clienttag); random_losses = account_get_racelosses(pointer->account,W3_RACE_RANDOM,clienttag); // write username, xp and rank to file and everyhing else needed for nice ladder pages fprintf(fp,"\t\n\t\t%s\n\t\t%u\n\t\t%u\n", account_get_name(pointer->account),level,pointer->xp); fprintf(fp,"\t\t%u\n\t\t%u\n\t\t%u\n", wins,losses,rank); fprintf(fp,"\t\t\n\t\t\t\n\t\t\t\t%u\n\t\t\t\t%u\n\t\t\t\n", orc_wins,orc_losses); fprintf(fp,"\t\t\t\n\t\t\t\t%u\n\t\t\t\t%u\n\t\t\t\n", human_wins,human_losses); fprintf(fp,"\t\t\t\n\t\t\t\t%u\n\t\t\t\t%u\n\t\t\t\n", nightelf_wins,nightelf_losses); fprintf(fp,"\t\t\t\n\t\t\t\t%u\n\t\t\t\t%u\n\t\t\t\n", undead_wins,undead_losses); fprintf(fp,"\t\t\t\n\t\t\t\t%u\n\t\t\t\t%u\n\t\t\t\n\t\t\n\t\n", random_wins,random_losses); } } // end: if clienttag WAR3 or WAR3XP else if (clienttag==CLIENTTAG_STARCRAFT_UINT || clienttag==CLIENTTAG_BROODWARS_UINT || clienttag==CLIENTTAG_WARCIIBNE_UINT) { wins = account_get_ladder_wins(pointer->account,ladder->clienttag,ladder->ladder_id); losses = account_get_ladder_losses(pointer->account,ladder->clienttag,ladder->ladder_id); discs = account_get_ladder_disconnects(pointer->account,ladder->clienttag,ladder->ladder_id); fprintf(fp,"\t\n\t\t%u\n\t\t%s\n\t\t%u\n", rank, account_get_name(pointer->account),pointer->level); fprintf(fp,"\t\t%u\n\t\t%u\n\t\t%u\n\t\n", wins,losses,discs); } pointer=pointer->prev; } fprintf(fp,"\n"); return 0; } extern int ladder_write_to_file(char const * filename, t_ladder * ladder, t_clienttag clienttag) { FILE * fp; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(fp = fopen(filename,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for writing (fopen: %s)",filename,pstrerror(errno)); return -1; } if (prefs_get_XML_output_ladder()) XML_writer(fp,ladder,clienttag); else standard_writer(fp,ladder,clienttag); fclose(fp); return 0; } extern int ladders_write_to_file() { ladder_write_to_file(WAR3_solo_filename, &WAR3_solo_ladder,CLIENTTAG_WARCRAFT3_UINT); ladder_write_to_file(WAR3_team_filename, &WAR3_team_ladder,CLIENTTAG_WARCRAFT3_UINT); ladder_write_to_file(WAR3_ffa_filename, &WAR3_ffa_ladder, CLIENTTAG_WARCRAFT3_UINT); ladder_write_to_file(WAR3_at_filename, &WAR3_at_ladder, CLIENTTAG_WARCRAFT3_UINT); ladder_write_to_file(W3XP_solo_filename, &W3XP_solo_ladder, CLIENTTAG_WAR3XP_UINT); ladder_write_to_file(W3XP_team_filename, &W3XP_team_ladder, CLIENTTAG_WAR3XP_UINT); ladder_write_to_file(W3XP_ffa_filename, &W3XP_ffa_ladder, CLIENTTAG_WAR3XP_UINT); ladder_write_to_file(W3XP_at_filename, &W3XP_at_ladder, CLIENTTAG_WAR3XP_UINT); ladder_write_to_file(STAR_ar_filename, &STAR_active_rating, CLIENTTAG_STARCRAFT_UINT); ladder_write_to_file(STAR_cr_filename, &STAR_current_rating,CLIENTTAG_STARCRAFT_UINT); ladder_write_to_file(SEXP_ar_filename, &SEXP_active_rating, CLIENTTAG_BROODWARS_UINT); ladder_write_to_file(SEXP_cr_filename, &SEXP_current_rating,CLIENTTAG_BROODWARS_UINT); ladder_write_to_file(W2BN_ar_filename, &W2BN_active_rating, CLIENTTAG_WARCIIBNE_UINT); ladder_write_to_file(W2BN_cr_filename, &W2BN_current_rating,CLIENTTAG_WARCIIBNE_UINT); ladder_write_to_file(W2BN_ari_filename, &W2BN_active_rating_ironman, CLIENTTAG_WARCIIBNE_UINT); ladder_write_to_file(W2BN_cri_filename, &W2BN_current_rating_ironman,CLIENTTAG_WARCIIBNE_UINT); return 0; } extern char * create_filename(const char * path, const char * filename, const char * ending) { char * result; result = xmalloc(strlen(path)+1+strlen(filename)+strlen(ending)+1); sprintf(result,"%s/%s%s",path,filename,ending); return result; } static void dispose_filename(char * filename) { if (filename) xfree(filename); } void create_filenames(void) { // In the ladderdir are binary ladder files, the human readable ladderlist output // is better in other place, in the outputdir [KWS] if (prefs_get_XML_output_ladder()) { WAR3_solo_filename = create_filename(prefs_get_outputdir(),WAR3_solo_file,xml_end); WAR3_team_filename = create_filename(prefs_get_outputdir(),WAR3_team_file,xml_end); WAR3_ffa_filename = create_filename(prefs_get_outputdir(),WAR3_ffa_file,xml_end); WAR3_at_filename = create_filename(prefs_get_outputdir(),WAR3_at_file,xml_end); W3XP_solo_filename = create_filename(prefs_get_outputdir(),W3XP_solo_file,xml_end); W3XP_team_filename = create_filename(prefs_get_outputdir(),W3XP_team_file,xml_end); W3XP_ffa_filename = create_filename(prefs_get_outputdir(),W3XP_ffa_file,xml_end); W3XP_at_filename = create_filename(prefs_get_outputdir(),W3XP_at_file,xml_end); STAR_ar_filename = create_filename(prefs_get_outputdir(),STAR_ar_file,xml_end); STAR_cr_filename = create_filename(prefs_get_outputdir(),STAR_cr_file,xml_end); SEXP_ar_filename = create_filename(prefs_get_outputdir(),SEXP_ar_file,xml_end); SEXP_cr_filename = create_filename(prefs_get_outputdir(),SEXP_cr_file,xml_end); W2BN_ar_filename = create_filename(prefs_get_outputdir(),W2BN_ar_file,xml_end); W2BN_cr_filename = create_filename(prefs_get_outputdir(),W2BN_cr_file,xml_end); W2BN_ari_filename = create_filename(prefs_get_outputdir(),W2BN_ari_file,xml_end); W2BN_cri_filename = create_filename(prefs_get_outputdir(),W2BN_cri_file,xml_end); } else { WAR3_solo_filename = create_filename(prefs_get_outputdir(),WAR3_solo_file,std_end); WAR3_team_filename = create_filename(prefs_get_outputdir(),WAR3_team_file,std_end); WAR3_ffa_filename = create_filename(prefs_get_outputdir(),WAR3_ffa_file,std_end); WAR3_at_filename = create_filename(prefs_get_outputdir(),WAR3_at_file,std_end); W3XP_solo_filename = create_filename(prefs_get_outputdir(),W3XP_solo_file,std_end); W3XP_team_filename = create_filename(prefs_get_outputdir(),W3XP_team_file,std_end); W3XP_ffa_filename = create_filename(prefs_get_outputdir(),W3XP_ffa_file,std_end); W3XP_at_filename = create_filename(prefs_get_outputdir(),W3XP_at_file,std_end); STAR_ar_filename = create_filename(prefs_get_outputdir(),STAR_ar_file,std_end); STAR_cr_filename = create_filename(prefs_get_outputdir(),STAR_cr_file,std_end); SEXP_ar_filename = create_filename(prefs_get_outputdir(),SEXP_ar_file,std_end); SEXP_cr_filename = create_filename(prefs_get_outputdir(),SEXP_cr_file,std_end); W2BN_ar_filename = create_filename(prefs_get_outputdir(),W2BN_ar_file,std_end); W2BN_cr_filename = create_filename(prefs_get_outputdir(),W2BN_cr_file,std_end); W2BN_ari_filename = create_filename(prefs_get_outputdir(),W2BN_ari_file,std_end); W2BN_cri_filename = create_filename(prefs_get_outputdir(),W2BN_cri_file,std_end); } } extern void ladders_init(void) { eventlog(eventlog_level_info,__FUNCTION__,"initializing war3 ladders"); ladder_init(&WAR3_solo_ladder, WAR3_SOLO, CLIENTTAG_WARCRAFT3_UINT,ladder_id_solo); ladder_init(&WAR3_team_ladder, WAR3_TEAM, CLIENTTAG_WARCRAFT3_UINT,ladder_id_team); ladder_init(&WAR3_ffa_ladder, WAR3_FFA, CLIENTTAG_WARCRAFT3_UINT,ladder_id_ffa); ladder_init(&WAR3_at_ladder, WAR3_AT, CLIENTTAG_WARCRAFT3_UINT,ladder_id_none); ladder_init(&W3XP_solo_ladder, W3XP_SOLO, CLIENTTAG_WAR3XP_UINT,ladder_id_solo); ladder_init(&W3XP_team_ladder, W3XP_TEAM, CLIENTTAG_WAR3XP_UINT,ladder_id_team); ladder_init(&W3XP_ffa_ladder, W3XP_FFA, CLIENTTAG_WAR3XP_UINT,ladder_id_ffa); ladder_init(&W3XP_at_ladder, W3XP_AT, CLIENTTAG_WAR3XP_UINT,ladder_id_none); ladder_init(&STAR_active_rating, STAR_AR, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); ladder_init(&STAR_active_wins, STAR_AW, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); ladder_init(&STAR_active_games, STAR_AG, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); ladder_init(&STAR_current_rating, STAR_CR, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); ladder_init(&STAR_current_wins, STAR_CW, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); ladder_init(&STAR_current_games, STAR_CG, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal); ladder_init(&SEXP_active_rating, SEXP_AR, CLIENTTAG_BROODWARS_UINT,ladder_id_normal); ladder_init(&SEXP_active_wins, SEXP_AW, CLIENTTAG_BROODWARS_UINT,ladder_id_normal); ladder_init(&SEXP_active_games, SEXP_AG, CLIENTTAG_BROODWARS_UINT,ladder_id_normal); ladder_init(&SEXP_current_rating, SEXP_CR, CLIENTTAG_BROODWARS_UINT,ladder_id_normal); ladder_init(&SEXP_current_wins, SEXP_CW, CLIENTTAG_BROODWARS_UINT,ladder_id_normal); ladder_init(&SEXP_current_games, SEXP_CG, CLIENTTAG_BROODWARS_UINT,ladder_id_normal); ladder_init(&W2BN_current_rating, W2BN_CR, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); ladder_init(&W2BN_current_wins, W2BN_CW, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); ladder_init(&W2BN_current_games, W2BN_CG, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); ladder_init(&W2BN_current_rating_ironman, W2BN_CRI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); ladder_init(&W2BN_current_wins_ironman, W2BN_CWI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); ladder_init(&W2BN_current_games_ironman, W2BN_CGI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); ladder_init(&W2BN_active_rating, W2BN_AR, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); ladder_init(&W2BN_active_wins, W2BN_AW, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); ladder_init(&W2BN_active_games, W2BN_AG, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal); ladder_init(&W2BN_active_rating_ironman, W2BN_ARI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); ladder_init(&W2BN_active_wins_ironman, W2BN_AWI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); ladder_init(&W2BN_active_games_ironman, W2BN_AGI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman); create_filenames(); } void dispose_filenames(void) { dispose_filename(WAR3_solo_filename); dispose_filename(WAR3_team_filename); dispose_filename(WAR3_ffa_filename); dispose_filename(WAR3_at_filename); dispose_filename(W3XP_solo_filename); dispose_filename(W3XP_team_filename); dispose_filename(W3XP_ffa_filename); dispose_filename(W3XP_at_filename); dispose_filename(STAR_ar_filename); dispose_filename(STAR_cr_filename); dispose_filename(SEXP_ar_filename); dispose_filename(SEXP_cr_filename); dispose_filename(W2BN_ar_filename); dispose_filename(W2BN_cr_filename); dispose_filename(W2BN_ari_filename); dispose_filename(W2BN_cri_filename); } extern void ladders_destroy(void) { eventlog(eventlog_level_info,__FUNCTION__,"destroying war3 ladders"); ladder_destroy(&WAR3_solo_ladder); ladder_destroy(&WAR3_team_ladder); ladder_destroy(&WAR3_ffa_ladder); ladder_destroy(&WAR3_at_ladder); ladder_destroy(&W3XP_solo_ladder); ladder_destroy(&W3XP_team_ladder); ladder_destroy(&W3XP_ffa_ladder); ladder_destroy(&W3XP_at_ladder); ladder_destroy(&STAR_active_rating); ladder_destroy(&STAR_active_wins); ladder_destroy(&STAR_active_games); ladder_destroy(&STAR_current_rating); ladder_destroy(&STAR_current_wins); ladder_destroy(&STAR_current_games); ladder_destroy(&SEXP_active_rating); ladder_destroy(&SEXP_active_wins); ladder_destroy(&SEXP_active_games); ladder_destroy(&SEXP_current_rating); ladder_destroy(&SEXP_current_wins); ladder_destroy(&SEXP_current_games); ladder_destroy(&W2BN_current_rating); ladder_destroy(&W2BN_current_wins); ladder_destroy(&W2BN_current_games); ladder_destroy(&W2BN_current_rating_ironman); ladder_destroy(&W2BN_current_wins_ironman); ladder_destroy(&W2BN_current_games_ironman); ladder_destroy(&W2BN_active_rating); ladder_destroy(&W2BN_active_wins); ladder_destroy(&W2BN_active_games); ladder_destroy(&W2BN_active_rating_ironman); ladder_destroy(&W2BN_active_wins_ironman); ladder_destroy(&W2BN_active_games_ironman); dispose_filenames(); } extern void ladder_reload_conf(void) { dispose_filenames(); create_filenames(); } int ladder_get_from_ladder(t_binary_ladder_types type, int rank,int * results) { t_ladder * ladder; t_ladder_internal * internal; if (!(results)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL results"); return -1; } if (!(ladder = binary_ladder_types_to_w3_ladder(type))) return -1; if (!(internal = ladder_get_rank_internal(ladder,rank,ladder_get_clienttag(ladder)))) { return -1; } results[0] = internal->uid; results[1] = internal->xp; results[2] = internal->level; results[3] = internal->teamcount; return 0; } int ladder_put_into_ladder(t_binary_ladder_types type, int * values) { t_ladder * ladder; t_account * acct; if (!(values)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL values"); return -1; } if (!(ladder = binary_ladder_types_to_w3_ladder(type))) return -1; if ((acct = accountlist_find_account_by_uid(values[0]))) war3_ladder_add(ladder,values[0],values[1],values[2],acct,values[3],ladder_get_clienttag(ladder)); else eventlog(eventlog_level_error,__FUNCTION__,"no account with this UID - skip"); return 0; } extern int ladder_make_active(t_ladder *current, t_ladder *active,int set_attributes) { t_ladder_id id; t_clienttag clienttag; t_binary_ladder_types type; t_ladder_internal * internal; t_account * account; char const * timestr; t_bnettime bt; int rank = 1; id = active->ladder_id; clienttag = active->clienttag; type = active->type; //FIXME: take care of ppl that might have drop'ed from ladder !!! ladder_destroy(active); ladder_init(active,type,clienttag,id); while ((internal = ladder_get_rank_internal(current,rank,clienttag))) { account = internal->account; war3_ladder_add(active,internal->uid,internal->xp,internal->level,account,0,clienttag); if (set_attributes) { account_set_ladder_active_wins(account,clienttag,id,account_get_ladder_wins(account,clienttag,id)); account_set_ladder_active_losses(account,clienttag,id,account_get_ladder_losses(account,clienttag,id)); account_set_ladder_active_draws(account,clienttag,id,account_get_ladder_draws(account,clienttag,id)); account_set_ladder_active_disconnects(account,clienttag,id,account_get_ladder_disconnects(account,clienttag,id)); account_set_ladder_active_rating(account,clienttag,id,account_get_ladder_rating(account,clienttag,id)); account_set_ladder_active_rank(account,clienttag,id,account_get_ladder_rank(account,clienttag,id)); if (!(timestr = account_get_ladder_last_time(account,clienttag,id))) timestr = BNETD_LADDER_DEFAULT_TIME; bnettime_set_str(&bt,timestr); account_set_ladder_active_last_time(account,clienttag,id,bt); } rank++; } //now traverse the current ladder and put everything into the active one.... return 0; } extern int ladder_createxptable(const char *xplevelfile, const char *xpcalcfile) { FILE *fd1, *fd2; char buffer[256]; char *p; t_xpcalc_entry * newxpcalc; int len,i ,j; int level, startxp, neededxp, mingames; float lossfactor; int minlevel, leveldiff, higher_xpgained, higher_xplost, lower_xpgained, lower_xplost = 10; if (xplevelfile == NULL || xpcalcfile == NULL) { eventlog(eventlog_level_error, "ladder_createxptable", "got NULL filename(s)"); return -1; } /* first lets open files */ if ((fd1 = fopen(xplevelfile, "rt")) == NULL) { eventlog(eventlog_level_error, "ladder_createxptable", "could not open XP level file : \"%s\"", xplevelfile); return -1; } if ((fd2 = fopen(xpcalcfile, "rt")) == NULL) { eventlog(eventlog_level_error, "ladder_createxptable", "could not open XP calc file : \"%s\"", xpcalcfile); fclose(fd1); return -1; } /* then lets allocate mem for all the arrays */ xpcalc = xmalloc(sizeof(t_xpcalc_entry) * W3_XPCALC_MAXLEVEL); //presume the maximal leveldiff is level number w3_xpcalc_maxleveldiff = -1; memset(xpcalc, 0, sizeof(t_xpcalc_entry) * W3_XPCALC_MAXLEVEL); xplevels = xmalloc(sizeof(t_xplevel_entry) * W3_XPCALC_MAXLEVEL); memset(xplevels, 0, sizeof(t_xplevel_entry) * W3_XPCALC_MAXLEVEL); /* finally, lets read from the files */ while(fgets(buffer, 256, fd1)) { len = strlen(buffer); if (len < 2) continue; if (buffer[len - 1] == '\n') buffer[len - 1] = '\0'; /* support comments */ for(p=buffer; *p && *p != '#'; p++); if (*p == '#') *p = '\0'; if (sscanf(buffer, "%d %d %d %f %d", &level, &startxp, &neededxp, &lossfactor, &mingames) != 5) continue; if (level < 1 || level > W3_XPCALC_MAXLEVEL) { /* invalid level */ eventlog(eventlog_level_error, "ladder_createxptable", "read INVALID player level : %d", level); continue; } level--; /* the index in a C array starts from 0 */ xplevels[level].startxp = startxp; xplevels[level].neededxp = neededxp; xplevels[level].lossfactor = lossfactor * 100; /* we store the loss factor as % */ xplevels[level].mingames = mingames; eventlog(eventlog_level_trace, "ladder_createxptable", "inserting level XP info (level: %d, startxp: %d neededxp: %d lossfactor: %d mingames: %d)", level+1, xplevels[level].startxp, xplevels[level].neededxp, xplevels[level].lossfactor, xplevels[level].mingames); } fclose(fd1); while(fgets(buffer, 256, fd2)) { len = strlen(buffer); if (len < 2) continue; if (buffer[len - 1] == '\n') buffer[len - 1] = '\0'; /* support comments */ for(p=buffer; *p && *p != '#'; p++); if (*p == '#') *p = '\0'; if (sscanf(buffer, " %d %d %d %d %d %d ", &minlevel, &leveldiff, &higher_xpgained, &higher_xplost, &lower_xpgained, &lower_xplost) != 6) continue; eventlog(eventlog_level_trace, "ladder_createxptable", "parsed xpcalc leveldiff : %d", leveldiff); if (leveldiff <0) { eventlog(eventlog_level_error, "ladder_createxptable", "got invalid level diff : %d", leveldiff); continue; } if (leveldiff> (w3_xpcalc_maxleveldiff+1)) { eventlog(eventlog_level_error, __FUNCTION__,"expected entry for leveldiff=%u but found %u",w3_xpcalc_maxleveldiff+1,leveldiff); continue; } w3_xpcalc_maxleveldiff = leveldiff; xpcalc[leveldiff].higher_winxp = higher_xpgained; xpcalc[leveldiff].higher_lossxp = higher_xplost; xpcalc[leveldiff].lower_winxp = lower_xpgained; xpcalc[leveldiff].lower_lossxp = lower_xplost; } fclose(fd2); newxpcalc = xrealloc(xpcalc, sizeof(t_xpcalc_entry) * (w3_xpcalc_maxleveldiff+1)); xpcalc=newxpcalc; /* OK, now we need to test couse if the user forgot to put some values * lots of profiles could get screwed up */ if (w3_xpcalc_maxleveldiff<0) { eventlog(eventlog_level_error,__FUNCTION__,"found no valid entries for WAR3 xp calculation"); ladder_destroyxptable(); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"set war3 xpcalc maxleveldiff to %u",w3_xpcalc_maxleveldiff); for(j=0;j<=w3_xpcalc_maxleveldiff;j++) if (xpcalc[j].higher_winxp == 0 || xpcalc[j].higher_lossxp == 0 || xpcalc[j].lower_winxp == 0 || xpcalc[j].lower_lossxp == 0) { eventlog(eventlog_level_error, "ladder_createxptable", "i found 0 for a win/loss XP, please check your config file"); ladder_destroyxptable(); return -1; } for (i=0; i 0 && xplevels[i].neededxp == 0) || xplevels[i].lossfactor == 0 || xplevels[i].neededxp > xplevels[i].startxp || (i > 0 && (xplevels[i].startxp <= xplevels[i-1].startxp || xplevels[i].neededxp < xplevels[i-1].neededxp))) { eventlog(eventlog_level_error, "ladder_createxptable", "i found 0 for a level XP, please check your config file (level: %d neededxp: %d lossfactor: %d)", i+1, xplevels[i].neededxp , xplevels[i].lossfactor); ladder_destroyxptable(); return -1; } return 0; } extern void ladder_destroyxptable() { if (xpcalc != NULL) xfree(xpcalc); if (xplevels != NULL) xfree(xplevels); } extern int war3_get_maxleveldiff() { return w3_xpcalc_maxleveldiff; } extern int ladder_war3_xpdiff(unsigned int winnerlevel, unsigned int looserlevel, int *winxpdiff, int *loosxpdiff) { int diff, absdiff; diff = winnerlevel - looserlevel; absdiff = (diff < 0)?(-diff):diff; if (absdiff > w3_xpcalc_maxleveldiff) { eventlog(eventlog_level_error, "ladder_war3_xpdiff", "got invalid level difference : %d", absdiff); return -1; } if (winnerlevel > W3_XPCALC_MAXLEVEL || looserlevel > W3_XPCALC_MAXLEVEL || winnerlevel <1 || looserlevel<1) { eventlog(eventlog_level_error, "ladder_war3_xpdiff", "got invalid account levels (win: %d loss: %d)",winnerlevel, looserlevel); return -1; } if (winxpdiff == NULL || loosxpdiff == NULL) { eventlog(eventlog_level_error, "ladder_war3_xpdiff", "got NULL winxpdiff, loosxpdiff"); return -1; } /* we return the xp difference for the winner and the looser * we compute that from the xp charts also applying the loss factor for * lower level profiles * FIXME: ?! loss factor doesnt keep the sum of xp won/lost constant * DON'T CARE, cause current win/loss values aren't symetrical any more */ if (diff >= 0) { *winxpdiff = xpcalc[absdiff].higher_winxp; *loosxpdiff = - (xpcalc[absdiff].lower_lossxp * xplevels[looserlevel - 1].lossfactor) / 100; } else { *winxpdiff = xpcalc[absdiff].lower_winxp; *loosxpdiff = - (xpcalc[absdiff].higher_lossxp * xplevels[looserlevel - 1].lossfactor) / 100; } return 0; } extern int ladder_war3_updatelevel(unsigned int oldlevel, int xp) { int i, mylevel; if (oldlevel < 1 || oldlevel > W3_XPCALC_MAXLEVEL) { eventlog(eventlog_level_error, "ladder_war3_updatelevel", "got invalid level: %d", oldlevel); return oldlevel; } if (xp <= 0) return 1; mylevel = oldlevel; for(i=mylevel ; i < W3_XPCALC_MAXLEVEL; i++) if (xplevels[i].startxp > xp) { mylevel = i; break;} for(i=mylevel - 1; i >0 ; i--) if (xplevels[i-1].startxp < xp) { mylevel = i+1; break; } return mylevel; } extern int ladder_war3_get_min_xp(unsigned int Level) { if (Level < 1 || Level > W3_XPCALC_MAXLEVEL) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid Level %d",Level); return -1; } return xplevels[Level-1].startxp; } pvpgn-1.8.5/src/bnetd/sql_dbcreator.h0000644000175000017500000000327211151345317016526 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SQL_DBCREATOR_TYPES #define INCLUDED_SQL_DBCRETAOR_TYPES #include "common/list.h" typedef struct sqlcommand #ifdef SQL_DBCREATOR_INTERNAL_ACCESS { char * sql_command; char * mode; char * extra_cmd; } #endif t_sqlcommand; typedef struct column #ifdef SQL_DBCREATOR_INTERNAL_ACCESS { char * name; char * value; char * mode; char * extra_cmd; } #endif t_column; typedef struct table #ifdef SQL_DBCREATOR_INTERNAL_ACCESS { char * name; t_list * columns; t_list * sql_commands; } #endif t_table; typedef struct db_layout #ifdef SQL_DBCREATOR_INTERNAL_ACCESS { t_list * tables; } #endif t_db_layout; #endif /* INCLUDED_SQL_DBCREATOR_TYPES */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_SQL_DBCREATOR_PROTOS #define INCLUDED_SQL_DBCRETAOR_PROTOS #ifndef SQL_INTERNAL #define SQL_INTERNAL 1 #endif # include "sql_common.h" #undef SQL_INTERNAL int sql_dbcreator(t_sql_engine * sql); #endif /* INCLUDED_SQL_DBCREATOR_PROTOS */ #endif /* JUST_NEED_TYPES */ pvpgn-1.8.5/src/bnetd/sql_odbc.c0000644000175000017500000002453111151345317015464 0ustar aaronaaron/* * Copyright (C) 2005 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef WITH_SQL_ODBC #include "common/setup_before.h" #ifdef WIN32 # include #endif #include #include #include #include "common/eventlog.h" #include "common/xalloc.h" #include "storage_sql.h" #include "sql_odbc.h" #include "common/setup_after.h" /* t_sql_engine Interface methods. */ static int sql_odbc_init(const char *, const char *, const char *, const char *, const char *, const char *); static int sql_odbc_close(void); static t_sql_res * sql_odbc_query_res(const char *); static int sql_odbc_query(const char *); static t_sql_row * sql_odbc_fetch_row(t_sql_res *); static void sql_odbc_free_result(t_sql_res *); static unsigned int sql_odbc_num_rows(t_sql_res *); static unsigned int sql_odbc_affected_rows(void); static unsigned int sql_odbc_num_fields(t_sql_res *); static t_sql_field * sql_odbc_fetch_fields(t_sql_res *); static int sql_odbc_free_fields(t_sql_field *); static void sql_odbc_escape_string(char *, const char *, int); t_sql_engine sql_odbc = { ' ', /* I'm not sure but I dont think ODBC "translates" the SQL queries but instead just forwards them to the engine, * thus if the engine is mysql it will need "`" but if somethign else it will need "'" so just put space here */ sql_odbc_init, sql_odbc_close, sql_odbc_query_res, sql_odbc_query, sql_odbc_fetch_row, sql_odbc_free_result, sql_odbc_num_rows, sql_odbc_num_fields, sql_odbc_affected_rows, sql_odbc_fetch_fields, sql_odbc_free_fields, sql_odbc_escape_string }; struct t_odbc_rowSet_{ t_sql_row *row; struct t_odbc_rowSet_ *next; }; typedef struct t_odbc_rowSet_ t_odbc_rowSet; typedef struct{ HSTMT stmt; t_odbc_rowSet *curRow; t_odbc_rowSet *rowSet; unsigned int rowCount; } t_odbc_res; static t_sql_row *odbc_alloc_row(t_odbc_res *result, SQLINTEGER *sizes); static t_odbc_rowSet *odbc_alloc_rowSet(); static int odbc_Result(SQLRETURN retCode); static void odbc_Error(SQLSMALLINT type, void *obj, t_eventlog_level level, const char *function); static int odbc_Fail(); static HENV env = SQL_NULL_HENV; static HDBC con = SQL_NULL_HDBC; static SQLINTEGER ROWCOUNT = 0; /************************************************ t_sql_engine Interface methods. ************************************************/ static int sql_odbc_init(const char *host, const char *port, const char *socket, const char *name, const char *user, const char *pass) { /* Create environment. */ if(odbc_Result(SQLAllocEnv(&env)) && odbc_Result(SQLAllocConnect(env, &con))) { eventlog(eventlog_level_debug, __FUNCTION__, "Created ODBC environment."); } else { eventlog(eventlog_level_error, __FUNCTION__, "Unable to allocate ODBC environment."); return odbc_Fail(); } if(odbc_Result(SQLConnect(con, (SQLCHAR*)name, SQL_NTS, (SQLCHAR*)user, SQL_NTS, (SQLCHAR*)pass, SQL_NTS))) { eventlog(eventlog_level_debug, __FUNCTION__, "Connected to ODBC datasource \"%s\".", name); } else { eventlog(eventlog_level_error, __FUNCTION__, "Unable to connect to ODBC datasource \"%s\".", name); odbc_Error(SQL_HANDLE_DBC, con, eventlog_level_error, __FUNCTION__); return odbc_Fail(); } return 0; } static int sql_odbc_close(void) { if(con) { SQLDisconnect(con); SQLFreeHandle(SQL_HANDLE_DBC, con); con = NULL; } if(env) { SQLFreeHandle(SQL_HANDLE_ENV, env); env = NULL; } eventlog(eventlog_level_debug, __FUNCTION__, "ODBC connection closed."); return 0; } static t_sql_res* sql_odbc_query_res(const char *query) { t_odbc_res *res = NULL; HSTMT stmt = SQL_NULL_HSTMT; SQLRETURN result = 0; t_odbc_rowSet *rowSet = NULL; ROWCOUNT = 0; /* Validate query. */ if(query == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "Got a NULL query!"); return NULL; } // eventlog(eventlog_level_trace, __FUNCTION__, "%s", query); /* Run query and check for success. */ SQLAllocStmt(con, &stmt); result = SQLExecDirect(stmt, (SQLCHAR*)query, SQL_NTS); if(!odbc_Result(result)) { // odbc_Error(SQL_HANDLE_STMT, stmt, eventlog_level_debug, __FUNCTION__); SQLFreeHandle(SQL_HANDLE_STMT, stmt); return NULL; } /* Create a result. */ res = xmalloc(sizeof *res); res->stmt = stmt; rowSet = odbc_alloc_rowSet(); res->rowSet = rowSet; res->curRow = rowSet; res->rowCount = 0; /* Store rows. */ do { SQLINTEGER *sizes = NULL; t_sql_row *row = odbc_alloc_row(res, sizes); if(!row) { sql_odbc_free_result(res); return NULL; } result = SQLFetch(stmt); if(odbc_Result(result)) { rowSet->row = row; rowSet->next = odbc_alloc_rowSet(); rowSet = rowSet->next; res->rowCount++; } else { sql_odbc_free_fields(row); } if(sizes) xfree(sizes); } while(odbc_Result(result)); ROWCOUNT = res->rowCount; if(result == SQL_NO_DATA_FOUND) { return res; } else if(!odbc_Result(result)) { eventlog(eventlog_level_error, __FUNCTION__, "Unable to fetch row - ODBC error %i.", result); odbc_Error(SQL_HANDLE_STMT, stmt, eventlog_level_error, __FUNCTION__); sql_odbc_free_result(res); return NULL; } return res; } static int sql_odbc_query(const char *query) { int result; HSTMT stmt = SQL_NULL_HSTMT; /* Validate query. */ if(query == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "Got a NULL query!"); return -1; } // eventlog(eventlog_level_trace, __FUNCTION__, "%s", query); SQLAllocStmt(con, &stmt); result = odbc_Result(SQLExecDirect(stmt, (SQLCHAR*)query, SQL_NTS)); if(result) { SQLRowCount(stmt, &ROWCOUNT); } else { // odbc_Error(SQL_HANDLE_STMT, stmt, eventlog_level_trace, __FUNCTION__); } SQLFreeHandle(SQL_HANDLE_STMT, stmt); result = result == -1 ? 0 : -1; return result; } static t_sql_row* sql_odbc_fetch_row(t_sql_res *result) { t_odbc_res *res; t_sql_row *row; if(!result) { eventlog(eventlog_level_error, __FUNCTION__, "Got NULL result."); return NULL; } res = (t_odbc_res*)result; row = res->curRow->row; if(row) { res->curRow = res->curRow->next; } return row; } static void sql_odbc_free_result(t_sql_res *result) { if(result) { t_odbc_res *res = (t_odbc_res*)result; if(res->stmt) { SQLFreeHandle(SQL_HANDLE_STMT, res->stmt); res->stmt = NULL; } if(res->rowSet) { t_odbc_rowSet *rowSet = res->rowSet; while(rowSet) { t_odbc_rowSet *temp = (rowSet->next); sql_odbc_free_fields(rowSet->row); xfree(rowSet); rowSet = temp; } } xfree(result); } } static unsigned int sql_odbc_num_rows(t_sql_res *result) { if(!result) { eventlog(eventlog_level_error, __FUNCTION__, "Got NULL result."); return 0; } return ((t_odbc_res*)result)->rowCount; } static unsigned int sql_odbc_num_fields(t_sql_res *result) { SQLSMALLINT numCols = 0; if(!result) { eventlog(eventlog_level_error, __FUNCTION__, "Got NULL result."); } else { SQLNumResultCols(((t_odbc_res*)result)->stmt, &numCols); } return numCols; } static unsigned int sql_odbc_affected_rows(void) { return ROWCOUNT; } static t_sql_field* sql_odbc_fetch_fields(t_sql_res *result) { int i; t_odbc_res *res; int fieldCount; t_sql_field *fields; if(!result) { eventlog(eventlog_level_error, __FUNCTION__, "Got NULL result."); return NULL; } res = (t_odbc_res*)result; fieldCount = sql_odbc_num_fields(result); fields = xcalloc(sizeof *fields, fieldCount+1); if(!fields) { return NULL; } fields[fieldCount] = NULL; for(i=0; istmt, i+1, SQL_DESC_NAME, NULL, 0, &fNameSz, NULL); fName = xmalloc(fNameSz); if(!fName) { return NULL; } SQLColAttribute(res->stmt, i+1, SQL_DESC_NAME, fName, fNameSz, &fNameSz, NULL); tmp = fName; for ( ; *tmp; ++tmp) *tmp = toupper(*tmp); fields[i] = fName; } return fields; } static int sql_odbc_free_fields(t_sql_field *fields) { if(fields) { int i=0; while(fields[i]) { xfree(fields[i]); i++; } xfree(fields); } return 0; } static void sql_odbc_escape_string(char *escape, const char *from, int len) { int i; for (i=0; istmt; t_sql_row *row; fieldCount = sql_odbc_num_fields(result); /* Create a new row. */ row = xcalloc(sizeof *row, fieldCount+1); if(!row) { return NULL; } row[fieldCount] = NULL; sizes = xcalloc(sizeof *sizes, fieldCount); for(i=0; irow = NULL; rowSet->next = NULL; return rowSet; } static void odbc_Error(SQLSMALLINT type, void *obj, t_eventlog_level level, const char *function) { SQLCHAR mState[6] = "\0"; long native = 0; SQLSMALLINT mTextLen; short i = 0; while(SQLGetDiagRec(type, obj, ++i, NULL, NULL, NULL, 0, &mTextLen) != SQL_NO_DATA) { SQLCHAR *mText = xcalloc(sizeof *mText, ++mTextLen); SQLGetDiagRec(type, obj, i, mState, &native, mText, mTextLen, NULL); eventlog(level, function, "ODBC Error: State %s, Native %i: %s", mState, native, mText); xfree(mText); } } static int odbc_Result(SQLRETURN retCode) { int result = 0; if(retCode == SQL_SUCCESS || retCode == SQL_SUCCESS_WITH_INFO) { result = -1; } return result; } static int odbc_Fail() { sql_odbc_close(); return -1; } #endif pvpgn-1.8.5/src/bnetd/account.c0000644000175000017500000006123311151345317015332 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * Copyright (C) 2002,2003,2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define ACCOUNT_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strchr.h" #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include #ifdef HAVE_LIMITS_H # include #endif #include "compat/char_bit.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include "compat/strerror.h" #ifdef HAVE_SYS_TYPES_H # include #endif #include "compat/pdir.h" #include "common/list.h" #include "common/elist.h" #include "common/eventlog.h" #include "prefs.h" #include "common/util.h" #include "common/field_sizes.h" #include "common/bnethash.h" #include "common/introtate.h" #include "account.h" #include "account_wrap.h" #include "common/hashtable.h" #include "connection.h" #include "watch.h" #include "friends.h" #include "team.h" #include "common/tag.h" #include "ladder.h" #include "clan.h" #include "server.h" #include "attrgroup.h" #include "attrlayer.h" #include "storage.h" #include "common/flags.h" #include "common/xalloc.h" #ifdef HAVE_ASSERT_H # include #endif #include "common/setup_after.h" static t_hashtable * accountlist_head=NULL; static t_hashtable * accountlist_uid_head=NULL; unsigned int maxuserid=0; /* This is to force the creation of all accounts when we initially load the accountlist. */ static int force_account_add=0; static unsigned int account_hash(char const * username); static t_account * account_load(t_attrgroup *); static int account_load_friends(t_account * account); static int account_unload_friends(t_account * account); static void account_destroy(t_account * account); static t_account * accountlist_add_account(t_account * account); static unsigned int account_hash(char const *username) { register unsigned int h; register unsigned int len = strlen(username); for (h = 5381; len > 0; --len, ++username) { h += h << 5; if (isupper((int) *username) == 0) h ^= *username; else h ^= tolower((int) *username); } return h; } static t_account * account_create(char const * username, char const * passhash1) { t_account * account; if (username && !passhash1) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL passhash1"); return NULL; } if (username && account_check_name(username)) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid chars in username"); return NULL; } account = xmalloc(sizeof(t_account)); account->name = NULL; account->clanmember = NULL; account->attrgroup = NULL; account->friends = NULL; account->teams = NULL; account->conn = NULL; FLAG_ZERO(&account->flags); account->namehash = 0; /* hash it later before inserting */ account->uid = 0; /* hash it later before inserting */ if (username) { /* actually making a new account */ /* first check if such a username already owns an account. * we search in the memory hash mainly for non-indexed storage types. * indexed storage types check themselves if the username exists already * in the storage (see storage_sql.c) */ if (accountlist_find_account(username)) { eventlog(eventlog_level_debug,__FUNCTION__,"user \"%s\" already has an account",username); goto err; } account->attrgroup = attrgroup_create_newuser(username); if(!account->attrgroup) { eventlog(eventlog_level_error,__FUNCTION__,"failed to add user"); goto err; } account->name = xstrdup(username); if (account_set_strattr(account,"BNET\\acct\\username",username)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set username"); goto err; } if (account_set_numattr(account,"BNET\\acct\\userid",maxuserid+1)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set userid"); goto err; } if (account_set_strattr(account,"BNET\\acct\\passhash1",passhash1)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set passhash1"); goto err; } if (account_set_numattr(account,"BNET\\acct\\ctime",(unsigned int)now)) { eventlog(eventlog_level_error,__FUNCTION__,"could not set ctime"); goto err; } } return account; err: account_destroy(account); return NULL; } static void account_destroy(t_account * account) { assert(account); friendlist_close(account->friends); teams_destroy(account->teams); if (account->attrgroup) attrgroup_destroy(account->attrgroup); if (account->name) xfree(account->name); xfree(account); } extern unsigned int account_get_uid(t_account const * account) { if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return 0; } return account->uid; } extern int account_match(t_account * account, char const * username) { unsigned int userid=0; unsigned int namehash; char const * tname; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!username) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL username"); return -1; } if (username[0]=='#') if (str_to_uint(&username[1],&userid)<0) userid = 0; if (userid) { if (account->uid==userid) return 1; } else { namehash = account_hash(username); if (account->namehash==namehash && (tname = account_get_name(account))) { if (strcasecmp(tname,username)==0) return 1; } } return 0; } extern int account_save(t_account * account, unsigned flags) { assert(account); return attrgroup_save(account->attrgroup, flags); } extern int account_flush(t_account * account, unsigned flags) { int res; assert(account); res = attrgroup_flush(account->attrgroup, flags); if (res<0) return res; account_unload_friends(account); return res; } extern char const * account_get_strattr_real(t_account * account, char const * key, char const * fn, unsigned int ln) { if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account (from %s:%u)",fn,ln); return NULL; } if (!key) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL key (from %s:%u)",fn,ln); return NULL; } return attrgroup_get_attr(account->attrgroup, key); } extern int account_set_strattr(t_account * account, char const * key, char const * val) { if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!key) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL key"); return -1; } return attrgroup_set_attr(account->attrgroup, key, val); } static t_account * account_load(t_attrgroup *attrgroup) { t_account * account; assert(attrgroup); if (!(account = account_create(NULL,NULL))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create account"); return NULL; } account->attrgroup = attrgroup; return account; } static t_account * account_load_new(char const * name, unsigned uid) { t_account *account; t_attrgroup *attrgroup; if (name && account_check_name(name)) return NULL; force_account_add = 1; /* disable the protection */ attrgroup = attrgroup_create_nameuid(name, uid); if (!attrgroup) { force_account_add = 0; return NULL; } if (!(account = account_load(attrgroup))) { eventlog(eventlog_level_error, __FUNCTION__,"could not load account"); attrgroup_destroy(attrgroup); force_account_add = 0; return NULL; } if (!accountlist_add_account(account)) { eventlog(eventlog_level_error, __FUNCTION__,"could not add account to list"); account_destroy(account); force_account_add = 0; return NULL; } force_account_add = 0; return account; } static int _cb_read_accounts(t_attrgroup *attrgroup, void *data) { unsigned int *count = (unsigned int *)data; t_account *account; if (!(account = account_load(attrgroup))) { eventlog(eventlog_level_error, __FUNCTION__,"could not load account"); attrgroup_destroy(attrgroup); return -1; } if (!accountlist_add_account(account)) { eventlog(eventlog_level_error, __FUNCTION__,"could not add account to list"); account_destroy(account); return -1; } /* might as well free up the memory since we probably won't need it */ account_flush(account,FS_FORCE); /* force unload */ (*count)++; return 0; } extern int accountlist_load_all(int flag) { unsigned int count; int starttime = time(NULL); static int loaded = 0; /* all accounts already loaded ? */ int res; if (loaded) return 0; count = 0; res = 0; force_account_add = 1; /* disable the protection */ switch(attrgroup_read_accounts(flag, _cb_read_accounts, &count)) { case -1: eventlog(eventlog_level_error, __FUNCTION__,"got error reading users"); res = -1; break; case 0: loaded = 1; eventlog(eventlog_level_info, __FUNCTION__, "loaded %u user accounts in %ld seconds",count,time(NULL) - starttime); break; default: break; } force_account_add = 0; /* enable the protection */ return res; } extern int accountlist_create(void) { eventlog(eventlog_level_info, __FUNCTION__, "started creating accountlist"); if (!(accountlist_head = hashtable_create(prefs_get_hashtable_size()))) { eventlog(eventlog_level_error, __FUNCTION__, "could not create accountlist_head"); return -1; } if (!(accountlist_uid_head = hashtable_create(prefs_get_hashtable_size()))) { eventlog(eventlog_level_error, __FUNCTION__, "could not create accountlist_uid_head"); return -1; } /* load accounts without force, indexed storage types wont be loading */ accountlist_load_all(ST_NONE); maxuserid = storage->read_maxuserid(); return 0; } extern int accountlist_destroy(void) { t_entry * curr; t_account * account; HASHTABLE_TRAVERSE(accountlist_head,curr) { if (!(account = entry_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL account in list"); else { if (account_flush(account, FS_FORCE)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not save account"); account_destroy(account); } hashtable_remove_entry(accountlist_head,curr); } HASHTABLE_TRAVERSE(accountlist_uid_head,curr) { hashtable_remove_entry(accountlist_head,curr); } if (hashtable_destroy(accountlist_head)<0) return -1; accountlist_head = NULL; if (hashtable_destroy(accountlist_uid_head)<0) return -1; accountlist_uid_head = NULL; return 0; } extern t_hashtable * accountlist(void) { return accountlist_head; } extern t_hashtable * accountlist_uid(void) { return accountlist_uid_head; } extern unsigned int accountlist_get_length(void) { return hashtable_get_length(accountlist_head); } extern int accountlist_save(unsigned flags) { return attrlayer_save(flags); } extern int accountlist_flush(unsigned flags) { return attrlayer_flush(flags); } extern t_account * accountlist_find_account(char const * username) { unsigned int userid=0; t_entry * curr; t_account * account; if (!username) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL username"); return NULL; } if (username[0]=='#') { if (str_to_uint(&username[1],&userid)<0) userid = 0; } else if (!(prefs_get_savebyname())) if (str_to_uint(username,&userid)<0) userid = 0; /* all accounts in list must be hashed already, no need to check */ if (userid) { account=accountlist_find_account_by_uid(userid); if (account) return account; } if ((!(userid)) || (userid && ((username[0]=='#') || (isdigit((int)username[0]))))) { unsigned int namehash; char const * tname; namehash = account_hash(username); HASHTABLE_TRAVERSE_MATCHING(accountlist_head,curr,namehash) { account = entry_get_data(curr); if ((tname = account_get_name(account))) { if (strcasecmp(tname,username)==0) { hashtable_entry_release(curr); return account; } } } } return account_load_new(username,0); } extern t_account * accountlist_find_account_by_uid(unsigned int uid) { t_entry * curr; t_account * account; if (uid) { HASHTABLE_TRAVERSE_MATCHING(accountlist_uid_head,curr,uid) { account = entry_get_data(curr); if (account->uid==uid) { hashtable_entry_release(curr); return account; } } } return account_load_new(NULL,uid); } extern int accountlist_allow_add(void) { if (force_account_add) return 1; /* the permission was forced */ if (prefs_get_max_accounts()==0) return 1; /* allow infinite accounts */ if (prefs_get_max_accounts()<=hashtable_get_length(accountlist_head)) return 0; /* maximum account limit reached */ return 1; /* otherwise let them proceed */ } static t_account * accountlist_add_account(t_account * account) { unsigned int uid; char const * username; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } username = account_get_name(account); uid = account_get_numattr(account,"BNET\\acct\\userid"); if (!username || strlen(username)<1) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account (empty username)"); return NULL; } if (uid<1) { ERROR2("got bad account (bad uid: %u) for \"%s\", fix it!", uid, username); return NULL; } /* check whether the account limit was reached */ if (!accountlist_allow_add()) { eventlog(eventlog_level_warn,__FUNCTION__,"account limit reached (current is %u, storing %u)",prefs_get_max_accounts(),hashtable_get_length(accountlist_head)); return NULL; } /* delayed hash, do it before inserting account into the list */ account->namehash = account_hash(username); account->uid = uid; /* FIXME: this check actually (with the new attr system) happens too late * we already have created the attrgroup here which is "dirty" and refusing * an account here will trigger attrgroup_destroy which will "sync" the * bad data to the storage! The codes should make sure we don't fail here */ /* mini version of accountlist_find_account(username) || accountlist_find_account(uid) */ { t_entry * curr; t_account * curraccount; char const * tname; if(uid <= maxuserid) HASHTABLE_TRAVERSE_MATCHING(accountlist_uid_head,curr,uid) { curraccount = entry_get_data(curr); if (curraccount->uid==uid) { eventlog(eventlog_level_debug,__FUNCTION__,"BUG: user \"%s\":"UID_FORMAT" already has an account (\"%s\":"UID_FORMAT")",username,uid,account_get_name(curraccount),curraccount->uid); hashtable_entry_release(curr); return NULL; } } HASHTABLE_TRAVERSE_MATCHING(accountlist_head,curr,account->namehash) { curraccount = entry_get_data(curr); if ((tname = account_get_name(curraccount))) { if (strcasecmp(tname,username)==0) { eventlog(eventlog_level_debug,__FUNCTION__,"BUG: user \"%s\":"UID_FORMAT" already has an account (\"%s\":"UID_FORMAT")",username,uid,tname,curraccount->uid); hashtable_entry_release(curr); return NULL; } } } } if (hashtable_insert_data(accountlist_head,account,account->namehash)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not add account to list"); return NULL; } if (hashtable_insert_data(accountlist_uid_head,account,uid)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not add account to list"); return NULL; } /* hashtable_stats(accountlist_head); */ if (uid>maxuserid) maxuserid = uid; return account; } extern t_account * accountlist_create_account(const char *username, const char *passhash1) { t_account *res; assert(username != NULL); assert(passhash1 != NULL); res = account_create(username,passhash1); if (!res) return NULL; /* eventlog reported ealier */ if (!accountlist_add_account(res)) { account_destroy(res); return NULL; /* eventlog reported earlier */ } account_save(res,FS_FORCE); /* sync new account to storage */ return res; } extern int account_check_name(char const * name) { unsigned int i; char ch; if (!name) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL name"); return -1; } for (i=0; i=USER_NAME_MAX) return -1; return 0; } extern char const * account_get_name_real(t_account * account, char const * fn, unsigned int ln) { char const * temp; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account (from %s:%u)",fn,ln); return NULL; /* FIXME: places assume this can't fail */ } if (account->name) /* we have a cached username so return it */ return account->name; /* we dont have a cached username so lets get it from attributes */ if (!(temp = account_get_strattr(account,"BNET\\acct\\username"))) eventlog(eventlog_level_error,__FUNCTION__,"account has no username"); else account->name = xstrdup(temp); return account->name; } extern int account_check_mutual( t_account * account, int myuserid) { if (account == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL account"); return -1; } if(!myuserid) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL userid"); return -1; } if(account->friends!=NULL) { t_friend * fr; if((fr=friendlist_find_uid(account->friends, myuserid))!=NULL) { friend_set_mutual(fr, 1); return 0; } } else { int i; int n = account_get_friendcount(account); int friend; for(i=0; iflags,ACCOUNT_FLAG_FLOADED)) if(account_load_friends(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not load friend list"); return NULL; } return account->friends; } static int account_load_friends(t_account * account) { int i; int n; int friend; t_account * acc; t_friend * fr; int newlist=0; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if(FLAG_ISSET(account->flags,ACCOUNT_FLAG_FLOADED)) return 0; if(account->friends==NULL) { account->friends=list_create(); newlist=1; } n = account_get_friendcount(account); for(i=0; ifriends, friend))==NULL) { if((acc = accountlist_find_account_by_uid(friend))==NULL) { if(account_remove_friend(account, i) == 0) { i--; n--; } continue; } if(account_check_mutual(acc, account_get_uid(account))==0) friendlist_add_account(account->friends, acc, 1); else friendlist_add_account(account->friends, acc, 0); } else { if((acc=friend_get_account(fr))==NULL) { account_remove_friend(account, i); continue; } if(account_check_mutual(acc, account_get_uid(account))==0) friend_set_mutual(fr, 1); else friend_set_mutual(fr, 0); } } if(!newlist) friendlist_purge(account->friends); FLAG_SET(&account->flags,ACCOUNT_FLAG_FLOADED); return 0; } static int account_unload_friends(t_account * account) { if(friendlist_unload(account->friends)<0) return -1; FLAG_CLEAR(&account->flags,ACCOUNT_FLAG_FLOADED); return 0; } extern int account_set_clanmember(t_account * account, t_clanmember * clanmember) { if(account==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } account->clanmember = clanmember; return 0; } extern t_clanmember * account_get_clanmember(t_account * account) { t_clanmember * member; if(account==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } if ((member = account->clanmember)&&(clanmember_get_clan(member))&&(clan_get_created(clanmember_get_clan(member)) > 0)) return member; else return NULL; } extern t_clanmember * account_get_clanmember_forced(t_account * account) { if(account==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } return account->clanmember; } extern t_clan * account_get_clan(t_account * account) { if(account==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } if(account->clanmember && (clanmember_get_clan(account->clanmember) != NULL) && (clan_get_created(clanmember_get_clan(account->clanmember)) > 0)) return clanmember_get_clan(account->clanmember); else return NULL; } extern t_clan * account_get_creating_clan(t_account * account) { if(account==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } if(account->clanmember && (clanmember_get_clan(account->clanmember) != NULL) && (clan_get_created(clanmember_get_clan(account->clanmember)) <= 0)) return clanmember_get_clan(account->clanmember); else return NULL; } int account_set_conn(t_account * account, t_connection * conn) { if (!(account)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } account->conn = conn; return 0; } t_connection * account_get_conn(t_account * account) { if (!(account)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return NULL; } return account->conn; } void account_add_team(t_account * account,t_team * team) { assert(account); assert(team); if (!(account->teams)) account->teams = list_create(); list_append_data(account->teams,team); } t_team * account_find_team_by_accounts(t_account * account, t_account **accounts, t_clienttag clienttag) { if ((account->teams)) return _list_find_team_by_accounts(accounts,clienttag,account->teams); else return NULL; } t_team * account_find_team_by_teamid(t_account * account, unsigned int teamid) { if ((account->teams)) return _list_find_team_by_teamid(teamid,account->teams); else return NULL; } t_list * account_get_teams(t_account * account) { assert(account); return account->teams; } pvpgn-1.8.5/src/bnetd/irc.h0000644000175000017500000000417211151345317014457 0ustar aaronaaron/* * Copyright (C) 2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_IRC_PROTOS #define INCLUDED_IRC_PROTOS #define JUST_NEED_TYPES #include "connection.h" #undef JUST_NEED_TYPES extern int irc_send_cmd(t_connection * conn, char const * command, char const * params); extern int irc_send_cmd2(t_connection * conn, char const * prefix, char const * command, char const * postfix, char const * comment); extern int irc_send(t_connection * conn, int code, char const * params); extern int irc_send_ping(t_connection * conn); extern int irc_send_pong(t_connection * conn, char const * params); extern int irc_authenticate(t_connection * conn, char const * passhash); extern int irc_welcome(t_connection * conn); extern char const * irc_convert_channel(t_channel const * channel); extern char const * irc_convert_ircname(char const * pircname); extern char ** irc_get_listelems(char * list); extern int irc_unget_listelems(char ** elems); extern char ** irc_get_paramelems(char * list); extern int irc_unget_paramelems(char ** elems); extern int irc_message_postformat(t_packet * packet, t_connection const * dest); extern int irc_message_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags); extern int irc_send_rpl_namreply(t_connection * c, t_channel const * channel); extern int irc_who(t_connection * c, char const * name); #endif #endif pvpgn-1.8.5/src/bnetd/handle_anongame.h0000644000175000017500000000172611151345317017004 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_HANDLE_ANONGAME_TYPES #define INCLUDED_HANDLE_ANONGAME_TYPES #endif #ifndef INCLUDED_HANDLE_ANONGAME_PROTOS #define INCLUDED_HANDLE_ANONGAME_PROTOS extern int handle_anongame_packet(t_connection * c, t_packet const * const packet); #endif pvpgn-1.8.5/src/bnetd/cmdline.h0000644000175000017500000000215211151345317015311 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __CMDLINE_H_PROTOS__ #define __CMDLINE_H_PROTOS__ extern int cmdline_load(int argc, char * * argv); extern void cmdline_unload(void); /* options exported by cmdline */ #ifdef DO_DAEMONIZE extern int cmdline_get_foreground(void); #endif extern const char* cmdline_get_preffile(void); extern const char* cmdline_get_hexfile(void); #endif /* __CMDLINE_H_PROTOS__ */ pvpgn-1.8.5/src/bnetd/news.c0000644000175000017500000001521011151345317014644 0ustar aaronaaron/* * Copyright (C) 2000 Alexey Belyaev (spider@omskart.ru) * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define NEWS_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/strtoul.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_ERRNO_H # include #endif #ifdef HAVE_TIME_H # include #endif #ifdef HAVE_ASSERT_H # include #endif #include "compat/strchr.h" #include "compat/strdup.h" #include "compat/strerror.h" #include "common/eventlog.h" #include "common/elist.h" #include "common/util.h" #include "common/proginfo.h" #include "common/xalloc.h" #include "news.h" #include "common/setup_after.h" static t_elist news_head; static int _news_parsetime(char *buff, struct tm *date, unsigned line) { char *p; date->tm_hour= 6; date->tm_min = 6; // need to set non-zero values or else date is displayed wrong date->tm_sec = 6; date->tm_isdst=-1; if (!(p = strchr(buff,'/'))) return -1; *p = '\0'; date->tm_mon = atoi(buff) - 1; if ((date->tm_mon<0) || (date->tm_mon>11)) { eventlog(eventlog_level_error,__FUNCTION__,"found invalid month (%i) in news date. (format: {MM/DD/YYYY}) on line %u",date->tm_mon,line); } buff = p + 1; if (!(p = strchr(buff,'/'))) return -1; *p = '\0'; date->tm_mday = atoi(buff); if ((date->tm_mday<1) || (date->tm_mday>31)) { eventlog(eventlog_level_error,__FUNCTION__,"found invalid month day (%i) in news date. (format: {MM/DD/YYYY}) on line %u",date->tm_mday,line); return -1; } buff = p + 1; if (!(p = strchr(buff,'}'))) return -1; *p = '\0'; date->tm_year=atoi(buff)-1900; if (date->tm_year>137) //limited due to 32bit t_time { eventlog(eventlog_level_error,__FUNCTION__,"found invalid year (%i) (>2037) in news date. on line %u",date->tm_year+1900,line); return -1; } return 0; } static void _news_insert_index(t_news_index *ni, const char *buff, unsigned len, int date_set) { t_elist *curr; t_news_index *cni; elist_for_each(curr,&news_head) { cni = elist_entry(curr,t_news_index,list); if (cni->date <= ni->date) break; } if (curr != &news_head && cni->date == ni->date) { if (date_set == 1) eventlog(eventlog_level_warn,__FUNCTION__,"found another news item for same date, trying to join both"); if ((lstr_get_len(&cni->body) + len +2) > 1023) eventlog(eventlog_level_error,__FUNCTION__,"failed in joining news, cause news too long - skipping"); else { lstr_set_str(&cni->body,xrealloc(lstr_get_str(&cni->body),lstr_get_len(&cni->body) + len + 1 + 1)); strcpy(lstr_get_str(&cni->body) + lstr_get_len(&cni->body), buff); *(lstr_get_str(&cni->body) + lstr_get_len(&cni->body) + len) = '\n'; *(lstr_get_str(&cni->body) + lstr_get_len(&cni->body) + len + 1) = '\0'; lstr_set_len(&cni->body,lstr_get_len(&cni->body) + len + 1); } xfree((void *)ni); } else { /* adding new index entry */ lstr_set_str(&ni->body,xmalloc(len + 2)); strcpy(lstr_get_str(&ni->body),buff); strcat(lstr_get_str(&ni->body),"\n"); lstr_set_len(&ni->body,len + 1); elist_add_tail(curr,&ni->list); } } static void _news_insert_default(void) { const char * deftext = "No news today"; t_news_index *ni; ni = (t_news_index*)xmalloc(sizeof(t_news_index)); ni->date = time(NULL); _news_insert_index(ni, deftext, strlen(deftext), 1); } extern int news_load(const char *filename) { FILE * fp; unsigned int line; unsigned int len; char buff[256]; struct tm date; char date_set; t_news_index *ni; elist_init(&news_head); date_set = 0; if (!filename) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL fullname"); return -1; } if ((fp = fopen(filename,"rt"))==NULL) { eventlog(eventlog_level_warn, __FUNCTION__,"can't open news file"); _news_insert_default(); return 0; } for (line=1; fgets(buff,sizeof(buff),fp); line++) { len = strlen(buff); while(len && (buff[len - 1] == '\n' || buff[len - 1] == '\r')) len--; if (!len) continue; /* empty line */ buff[len] = '\0'; if (buff[0]=='{') { if (_news_parsetime(buff + 1,&date, line)) { eventlog(eventlog_level_error,__FUNCTION__,"error parsing news date on line %u",line); return -1; } date_set = 1; } else { ni = (t_news_index*)xmalloc(sizeof(t_news_index)); if (date_set) ni->date = mktime(&date); else { ni->date = time(NULL); eventlog(eventlog_level_warn,__FUNCTION__,"(first) news entry seems to be missing a timestamp, please check your news file on line %u",line); } _news_insert_index(ni,buff,len,date_set); date_set = 2; } } fclose(fp); if (elist_empty(&news_head)) { eventlog(eventlog_level_warn,__FUNCTION__,"no news configured"); _news_insert_default(); } return 0; } /* Free up all of the elements in the linked list */ extern int news_unload(void) { t_elist * curr, *save; t_news_index * ni; elist_for_each_safe(curr,&news_head,save) { ni = elist_entry(curr,t_news_index,list); elist_del(&ni->list); xfree((void *)lstr_get_str(&ni->body)); xfree((void *)ni); } elist_init(&news_head); return 0; } extern unsigned int news_get_lastnews(void) { if (elist_empty(&news_head)) return 0; return ((elist_entry(news_head.next,t_news_index,list))->date); } extern unsigned int news_get_firstnews(void) { if (elist_empty(&news_head)) return 0; return ((elist_entry(news_head.prev,t_news_index,list))->date); } extern void news_traverse(t_news_cb cb, void *data) { t_elist *curr; t_news_index *cni; assert(cb); elist_for_each(curr,&news_head) { cni = elist_entry(curr,t_news_index,list); if (cb(cni->date,&cni->body,data)) break; } } pvpgn-1.8.5/src/bnetd/storage.h0000644000175000017500000000462011151345317015344 0ustar aaronaaron/* * Copyright (C) 2002,2003 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_STORAGE_TYPES #define INCLUDED_STORAGE_TYPES #include "common/elist.h" #include "attr.h" /* flags to tell if calling codes really want all accounts loading */ #define ST_NONE 0 #define ST_FORCE 1 #define t_storage_info void typedef int (*t_read_attr_func)(const char *, const char *, void *); typedef int (*t_read_accounts_func)(t_storage_info *, void*); typedef int (*t_load_clans_func)(void*); typedef int (*t_load_teams_func)(void*); typedef struct { int (*init)(const char *); int (*close)(void); unsigned (*read_maxuserid)(void); t_storage_info * (*create_account)(char const * ); t_storage_info * (*get_defacct)(void); int (*free_info)(t_storage_info *); int (*read_attrs)(t_storage_info *, t_read_attr_func, void *); int (*write_attrs)(t_storage_info *, const t_hlist *); t_attr * (*read_attr)(t_storage_info *, const char *); int (*read_accounts)(int,t_read_accounts_func, void *); t_storage_info * (*read_account)(const char *,unsigned); int (*cmp_info)(t_storage_info *, t_storage_info *); const char * (*escape_key)(const char *); int (*load_clans)(t_load_clans_func); int (*write_clan)(void *); int (*remove_clan)(int); int (*remove_clanmember)(int); int (*load_teams)(t_load_teams_func); int (*write_team)(void *); int (*remove_team)(unsigned int); } t_storage; #endif /* INCLUDED_STORAGE_TYPES */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_STORAGE_PROTOS #define INCLUDED_STORAGE_PROTOS extern t_storage *storage; extern int storage_init(const char *); extern void storage_close(void); #endif /* INCLUDED_STORAGE_PROTOS */ #endif /* JUST_NEED_TYPES */ pvpgn-1.8.5/src/bnetd/alias_command.h0000644000175000017500000000313211151345317016464 0ustar aaronaaron/* * Copyright (C) 2000 Onlyer (onlyer@263.net) * Copyright (C) 2002 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_ALIAS_COMMAND_TYPES #define INCLUDED_ALIAS_COMMAND_TYPES #ifdef ALIAS_COMMAND_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include "common/list.h" #else # define JUST_NEED_TYPES # include "common/list.h" # undef JUST_NEED_TYPES #endif typedef struct { char const * line; int min; int max; } t_output; typedef struct { char const * alias; t_list * output; /* of t_output * */ } t_alias; #endif #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_ALIAS_COMMAND_PROTOS #define INCLUDED_ALIAS_COMMAND_PROTOS #define JUST_NEED_TYPES #include "connection.h" #undef JUST_NEED_TYPES extern int aliasfile_load(char const * filename); extern int aliasfile_unload(void); extern int handle_alias_command(t_connection * c, char const * text); #endif #endif pvpgn-1.8.5/src/bnetd/handle_irc.c0000644000175000017500000017633511151345317016000 0ustar aaronaaron/* * Copyright (C) 2001 Marco Ziech (mmz@gmx.net) * Copyright (C) 2005 Bryan Biedenkapp (gatekeep@gmail.com) * Copyright (C) 2006,2007,2008 Pelish (pelish@gmail.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define CONNECTION_INTERNAL_ACCESS #include "common/setup_before.h" #include "common/util.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "compat/strdup.h" #include "compat/strcasecmp.h" #include #include "compat/strerror.h" #include "common/irc_protocol.h" #include "common/packet.h" #include "common/eventlog.h" #include "connection.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/addr.h" #include "common/version.h" #include "common/queue.h" #include "common/list.h" #include "common/bnethash.h" #include "common/bnethashconv.h" #include "message.h" #include "account.h" #include "account_wrap.h" #include "channel.h" #include "irc.h" #include "prefs.h" #include "tick.h" #include "timer.h" #include "server.h" #include "command.h" #include "handle_irc.h" #include "topic.h" #include "command_groups.h" #include "common/tag.h" #include "common/xalloc.h" #include "ctype.h" #include "common/setup_after.h" typedef int (* t_irc_command)(t_connection * conn, int numparams, char ** params, char * text); typedef struct { const char * irc_command_string; t_irc_command irc_command_handler; } t_irc_command_table_row; static int _handle_nick_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_user_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_ping_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_pong_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_pass_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_privmsg_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_notice_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_quit_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_who_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_list_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_topic_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_join_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_names_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_mode_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_userhost_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_ison_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_whois_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_part_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_cvers_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_verchk_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_lobcount_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_whereto_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_apgar_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_serial_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_squadinfo_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_setopt_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_setcodepage_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_setlocale_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_getcodepage_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_getlocale_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_joingame_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_gameopt_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_finduserex_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_page_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_startg_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_kick_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_listsearch_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_rungsearch_command(t_connection * conn, int numparams, char ** params, char * text); static int _handle_highscore_command(t_connection * conn, int numparams, char ** params, char * text); /* state "connected" handlers */ static const t_irc_command_table_row irc_con_command_table[] = { { "NICK" , _handle_nick_command }, { "USER" , _handle_user_command }, { "PING" , _handle_ping_command }, { "PONG" , _handle_pong_command }, { "PASS" , _handle_pass_command }, { "PRIVMSG" , _handle_privmsg_command }, { "NOTICE" , _handle_notice_command }, { "QUIT" , _handle_quit_command }, { "CVERS" , _handle_cvers_command }, { "VERCHK" , _handle_verchk_command }, { "LOBCOUNT" , _handle_lobcount_command }, { "WHERETO" , _handle_whereto_command }, { "APGAR" , _handle_apgar_command }, { "SERIAL" , _handle_serial_command }, /* Ladder server commands */ { "LISTSEARCH" , _handle_listsearch_command }, { "RUNGSEARCH" , _handle_rungsearch_command }, { "HIGHSCORE" , _handle_highscore_command }, { NULL , NULL } }; /* state "logged in" handlers */ static const t_irc_command_table_row irc_log_command_table[] = { { "WHO" , _handle_who_command }, { "LIST" , _handle_list_command }, { "TOPIC" , _handle_topic_command }, { "JOIN" , _handle_join_command }, { "NAMES" , _handle_names_command }, { "MODE" , _handle_mode_command }, { "USERHOST" , _handle_userhost_command }, { "ISON" , _handle_ison_command }, { "WHOIS" , _handle_whois_command }, { "PART" , _handle_part_command }, { "SQUADINFO" , _handle_squadinfo_command }, { "SETOPT" , _handle_setopt_command }, { "SETCODEPAGE" , _handle_setcodepage_command }, { "SETLOCALE" , _handle_setlocale_command }, { "GETCODEPAGE" , _handle_getcodepage_command }, { "GETLOCALE" , _handle_getlocale_command }, { "JOINGAME" , _handle_joingame_command }, { "GAMEOPT" , _handle_gameopt_command }, { "FINDUSEREX" , _handle_finduserex_command }, { "PAGE" , _handle_page_command }, { "STARTG" , _handle_startg_command }, { "KICK" , _handle_kick_command }, { NULL , NULL } }; static int handle_irc_con_command(t_connection * conn, char const * command, int numparams, char ** params, char * text) { t_irc_command_table_row const *p; for (p = irc_con_command_table; p->irc_command_string != NULL; p++) { if (strcasecmp(command, p->irc_command_string)==0) { if (p->irc_command_handler != NULL) return ((p->irc_command_handler)(conn,numparams,params,text)); } } return -1; } static int handle_irc_log_command(t_connection * conn, char const * command, int numparams, char ** params, char * text) { t_irc_command_table_row const *p; for (p = irc_log_command_table; p->irc_command_string != NULL; p++) { if (strcasecmp(command, p->irc_command_string)==0) { if (p->irc_command_handler != NULL) return ((p->irc_command_handler)(conn,numparams,params,text)); } } return -1; } static int handle_irc_line(t_connection * conn, char const * ircline) { /* [:prefix] [[param1] [param2] ... [paramN]] [:] */ char * line; /* copy of ircline */ char * prefix = NULL; /* optional; mostly NULL */ char * command; /* mandatory */ char ** params = NULL; /* optional (array of params) */ char * text = NULL; /* optional */ char * bnet_command = NULL; /* amadeo: used for battle.net.commands */ int unrecognized_before = 0; int linelen; /* amadeo: counter for stringlenghts */ int numparams = 0; char * tempparams; int i; char paramtemp[MAX_IRC_MESSAGE_LEN*2]; int first = 1; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!ircline) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ircline"); return -1; } if (ircline[0] == '\0') { eventlog(eventlog_level_error,__FUNCTION__,"got empty ircline"); return -1; } //amadeo: code was sent by some unknown fellow of pvpgn, prevents buffer-overflow for // too long irc-lines if (strlen(ircline)>254) { char * tmp = (char *)ircline; eventlog(eventlog_level_warn,__FUNCTION__,"line to long, truncation..."); tmp[254]='\0'; } line = xstrdup(ircline); /* split the message */ if (line[0] == ':') { /* The prefix is optional and is rarely provided */ prefix = line; if (!(command = strchr(line,' '))) { eventlog(eventlog_level_warn,__FUNCTION__,"got malformed line (missing command)"); xfree(line); return -1; } *command++ = '\0'; } else { /* In most cases command is the first thing on the line */ command = line; } tempparams = strchr(command,' '); if (tempparams) { *tempparams++ = '\0'; if (tempparams[0]==':') { text = tempparams+1; /* theres just text, no params. skip the colon */ } else { for (i=0;tempparams[i]!='\0';i++) { if ((tempparams[i]==' ')&&(tempparams[i+1]==':')) { text = tempparams+i; *text++ = '\0'; text++; /* skip the colon */ break; /* text found, stop search */ } } params = irc_get_paramelems(tempparams); } } if (params) { /* count parameters */ for (numparams=0;params[numparams];numparams++); } memset(paramtemp,0,sizeof(paramtemp)); for (i=0;((numparams>0)&&(params[i]));i++) { if (!first) strcat(paramtemp," "); strcat(paramtemp,"\""); strcat(paramtemp,params[i]); strcat(paramtemp,"\""); first = 0; } eventlog(eventlog_level_debug,__FUNCTION__,"[%d] got \"%s\" \"%s\" [%s] \"%s\"",conn_get_socket(conn),((prefix)?(prefix):("")),command,paramtemp,((text)?(text):(""))); if (conn_get_state(conn)==conn_state_connected) { t_timer_data temp; conn_set_state(conn,conn_state_bot_username); temp.n = prefs_get_irc_latency(); conn_test_latency(conn,time(NULL),temp); } if (handle_irc_con_command(conn, command, numparams, params, text)!=-1) {} else if (conn_get_state(conn)!=conn_state_loggedin) { char temp[MAX_IRC_MESSAGE_LEN+1]; if ((38+strlen(command)+16+1)class != conn_class_irc)"); return -1; } /* eventlog(eventlog_level_debug,__FUNCTION__,"got \"%s\"",packet_get_raw_data_const(packet,0)); */ memset(ircline,0,sizeof(ircline)); data = conn_get_ircline(conn); /* fetch current status */ if (data) strcpy(ircline,data); ircpos = strlen(ircline); data = packet_get_raw_data_const(packet,0); for (i=0; i < packet_get_size(packet); i++) { if ((data[i] == '\r')||(data[i] == '\0')) { /* kindly ignore \r and NUL ... */ } else if (data[i] == '\n') { /* end of line */ handle_irc_line(conn,ircline); memset(ircline,0,sizeof(ircline)); ircpos = 0; } else { if (ircpos < MAX_IRC_MESSAGE_LEN-1) ircline[ircpos++] = data[i]; else { ircpos++; /* for the statistic :) */ eventlog(eventlog_level_warn,__FUNCTION__,"[%d] client exceeded maximum allowed message length by %d characters",conn_get_socket(conn),ircpos-MAX_IRC_MESSAGE_LEN); if ((ircpos-MAX_IRC_MESSAGE_LEN)>100) { /* automatic flood protection */ eventlog(eventlog_level_error,__FUNCTION__,"[%d] excess flood",conn_get_socket(conn)); return -1; } } } } conn_set_ircline(conn,ircline); /* write back current status */ return 0; } static int _handle_nick_command(t_connection * conn, int numparams, char ** params, char * text) { /* FIXME: more strict param checking */ if ((conn_get_loggeduser(conn))&& (conn_get_state(conn)!=conn_state_bot_password && conn_get_state(conn)!=conn_state_bot_username)) { irc_send(conn,ERR_RESTRICTED,":You can't change your nick after login"); } else { if ((params)&&(params[0])) { if (conn_get_loggeduser(conn)) irc_send_cmd2(conn,conn_get_loggeduser(conn),"NICK","",params[0]); conn_set_loggeduser(conn,params[0]); } else if (text) { if (conn_get_loggeduser(conn)) irc_send_cmd2(conn,conn_get_loggeduser(conn),"NICK","",text); conn_set_loggeduser(conn,text); } else irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to NICK"); if ((conn_get_user(conn))&&(conn_get_loggeduser(conn))) irc_welcome(conn); /* only send the welcome if we have USER and NICK */ } return 0; } static int _handle_user_command(t_connection * conn, int numparams, char ** params, char * text) { /* RFC 2812 says: */ /* :*/ /* ircII and X-Chat say: */ /* mz SHODAN localhost :Marco Ziech */ /* BitchX says: */ /* mz +iws mz :Marco Ziech */ /* Don't bother with, params 1 and 2 anymore they don't contain what they should. */ char * user = NULL; char * realname = NULL; t_account * a; if ((numparams>=3)&&(params[0])&&(text)) { user = params[0]; realname = text; if (conn_get_wol(conn) == 1) { user = (char *)conn_get_loggeduser(conn); realname = (char *)conn_get_loggeduser(conn); if (conn_get_user(conn)) { irc_send(conn,ERR_ALREADYREGISTRED,":You are already registred"); } else { eventlog(eventlog_level_debug,__FUNCTION__,"[%d][** WOL **] got USER: user=\"%s\"",conn_get_socket(conn),user); a = accountlist_find_account(user); if (!a) { if((conn_get_wol(conn) == 1)) { t_account * tempacct; t_hash pass_hash; char * pass = xstrdup(conn_wol_get_apgar(conn)); /* FIXME: Do not use bnet passhash when we have wol passhash */ int j; for (j=0; j=1) { val = strtoul(params[0],NULL,10); sname = params[0]; } else if (text) { val = strtoul(text,NULL,10); sname = text; } else { val = 0; sname = 0; } if (conn_get_ircping(conn) != val) { if ((!(sname)) || (strcmp(sname,server_get_hostname())!=0)) { /* Actually the servername should not be always accepted but we aren't that pedantic :) */ eventlog(eventlog_level_warn,__FUNCTION__,"[%d] got bad PONG (%u!=%u && %s!=%s)",conn_get_socket(conn),val,conn_get_ircping(conn),sname,server_get_hostname()); return -1; } } conn_set_latency(conn,get_ticks()-conn_get_ircping(conn)); eventlog(eventlog_level_debug,__FUNCTION__,"[%d] latency is now %d (%u-%u)",conn_get_socket(conn),get_ticks()-conn_get_ircping(conn),get_ticks(),conn_get_ircping(conn)); conn_set_ircping(conn,0); } return 0; } static int _handle_pass_command(t_connection * conn, int numparams, char ** params, char * text) { if ((!conn_get_ircpass(conn))&&(conn_get_state(conn)==conn_state_bot_username)) { t_hash h; if (numparams>=1) { bnet_hash(&h,strlen(params[0]),params[0]); conn_set_ircpass(conn,hash_get_str(h)); } else irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to PASS"); } else { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] client tried to set password twice with PASS",conn_get_socket(conn)); } return 0; } static int _handle_privmsg_command(t_connection * conn, int numparams, char ** params, char * text) { if ((numparams>=1)&&(text)) { int i; char ** e; e = irc_get_listelems(params[0]); /* FIXME: support wildcards! */ /* start amadeo: code was sent by some unkown fellow of pvpgn (maybe u wanna give us your name for any credits), it adds nick-registration, i changed some things here and there... */ for (i=0;((e)&&(e[i]));i++) { if (strcasecmp(e[i],"NICKSERV")==0) { char * pass; char * p; pass = strchr(text,' '); if (pass) *pass++ = '\0'; if (strcasecmp(text,"identify")==0) { switch (conn_get_state(conn)) { case conn_state_bot_password: { if (pass) { t_hash h; for (p = pass; *p; p++) if (isupper((int)*p)) *p = tolower(*p); bnet_hash(&h,strlen(pass),pass); irc_authenticate(conn,hash_get_str(h)); } else { irc_send_cmd(conn,"NOTICE",":Syntax: IDENTIFY (max 16 characters)"); } break; } case conn_state_loggedin: { irc_send_cmd(conn,"NOTICE",":You don't need to IDENTIFY"); break; } default: ; eventlog(eventlog_level_trace,__FUNCTION__,"got /msg in unexpected connection state (%s)",conn_state_get_str(conn_get_state(conn))); } } else if (strcasecmp(text,"register")==0) { unsigned int j; t_hash passhash; t_account * temp; char msgtemp[MAX_MESSAGE_LEN]; char * username=(char *)conn_get_loggeduser(conn); if (account_check_name(username)<0) { message_send_text(conn,message_type_error,conn,"Account name contains invalid symbol!"); break; } if (!pass || pass[0]=='\0' || (strlen(pass)>16) ) { message_send_text(conn,message_type_error,conn,":Syntax: REGISTER (max 16 characters)"); break; } for (j=0; j=9)&&(strncmp(text,"\001ACTION ",8)==0)&&(text[strlen(text)-1]=='\001')) { /* at least "\001ACTION \001" */ /* it's a CTCP ACTION message */ text = text + 8; text[strlen(text)-1] = '\0'; channel_message_send(channel,message_type_emote,conn,text); } else { if ((conn_get_wol(conn)==1) && (text[0] == '/')) { /* "/" commands (like "/help..." */ handle_command(conn, text); } else { channel_message_log(channel, conn, 1, text); channel_message_send(channel,message_type_talk,conn,text); } } } else { irc_send(conn,ERR_NOSUCHCHANNEL,":No such channel"); } } else { /* whisper */ t_connection * user; if ((user = connlist_find_connection_by_accountname(e[i]))) { message_send_text(user,message_type_whisper,conn,text); } else { irc_send(conn,ERR_NOSUCHNICK,":No such user"); } } } } if (e) irc_unget_listelems(e); } else irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to PRIVMSG"); return 0; } static int _handle_notice_command(t_connection * conn, int numparams, char ** params, char * text) { if ((numparams>=1)&&(text)) { int i; char ** e; e = irc_get_listelems(params[0]); /* FIXME: support wildcards! */ for (i=0;((e)&&(e[i]));i++) { if (conn_get_state(conn)==conn_state_loggedin) { t_connection * user; if ((user = connlist_find_connection_by_accountname(e[i]))) { message_send_text(user,message_type_notice,conn,text); } else { irc_send(conn,ERR_NOSUCHNICK,":No such user"); } } } if (e) irc_unget_listelems(e); } else irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to PRIVMSG"); return 0; } static int _handle_who_command(t_connection * conn, int numparams, char ** params, char * text) { if (numparams>=1) { int i; char ** e; e = irc_get_listelems(params[0]); for (i=0; ((e)&&(e[i]));i++) { irc_who(conn,e[i]); } irc_send(conn,RPL_ENDOFWHO,":End of WHO list"); /* RFC2812 only requires this to be sent if a list of names was given. Undernet seems to always send it, so do we :) */ if (e) irc_unget_listelems(e); } else irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to WHO"); return 0; } static int _handle_list_command(t_connection * conn, int numparams, char ** params, char * text) { char temp[MAX_IRC_MESSAGE_LEN]; irc_send(conn,RPL_LISTSTART,"Channel :Users Name"); /* backward compatibility */ if((conn_get_wol(conn) == 1)) { t_elem const * curr; if((params) && (strcmp(params[0], "0") == 0)) { /* HACK: Currently, this is the best way to set the game type... */ conn_wol_set_game_type(conn,atoi(params[1])); eventlog(eventlog_level_debug,__FUNCTION__,"[** WOL **] LIST [Channel]"); LIST_TRAVERSE_CONST(channellist(),curr) { t_channel const * channel = elem_get_data(curr); char const * tempname; tempname = irc_convert_channel(channel); if(strstr(tempname,"Lob") != NULL) { eventlog(eventlog_level_debug,__FUNCTION__,"[** WOL **] LIST [Channel: \"Lob\"] (%s)",tempname); if (strlen(tempname)+1+20+1+1=1) { int i; char ** e; e = irc_get_listelems(params[0]); /* FIXME: support wildcards! */ for (i=0;((e)&&(e[i]));i++) { t_channel const * channel; char const * verytemp; /* another good example for creative naming conventions :) */ char const * tempname; char * topic; verytemp = irc_convert_ircname(e[i]); if (!verytemp) continue; /* something is wrong with the name ... */ channel = channellist_find_channel_by_name(verytemp,NULL,NULL); if (!channel) continue; /* channel doesn't exist */ topic = channel_get_topic(channel_get_name(channel)); tempname = irc_convert_channel(channel); if (topic) { if (strlen(tempname)+1+20+1+1+strlen(topic)=1) { char ** e; e = irc_get_listelems(params[0]); if ((e)&&(e[0])) { char temp[MAX_IRC_MESSAGE_LEN]; char const * ircname = irc_convert_ircname(e[0]); char * old_channel_name = NULL; t_channel * old_channel = conn_get_channel(conn); t_channel * channel; t_account * acc = conn_get_account(conn); if (old_channel) old_channel_name = xstrdup(irc_convert_channel(old_channel)); if ((ircname) && (channel = channellist_find_channel_by_name(ircname,NULL,NULL))) { if (channel_check_banning(channel,conn)) { snprintf(temp, sizeof(temp), "%s :You are banned from that channel.",e[0]); irc_send(conn,ERR_BANNEDFROMCHAN, temp); if (e) irc_unget_listelems(e); return 0; } if ((account_get_auth_admin(acc,NULL)!=1) && (account_get_auth_admin(acc,ircname)!=1) && (account_get_auth_operator(acc,NULL)!=1) && (account_get_auth_operator(acc,ircname)!=1) && (channel_get_max(channel) != -1) && (channel_get_curr(channel)>=channel_get_max(channel))) { snprintf(temp, sizeof(temp), "%s :The channel is currently full.",e[0]); irc_send(conn,ERR_CHANNELISFULL, temp); if (e) irc_unget_listelems(e); return 0; } } if ((!(ircname)) || (conn_set_channel(conn,ircname)<0)) { irc_send(conn,ERR_NOSUCHCHANNEL,":JOIN failed"); /* FIXME: be more precise; what is the real error code for that? */ } else { char temp[MAX_IRC_MESSAGE_LEN]; channel = conn_get_channel(conn); if ((conn_get_wol(conn) == 1)) { channel_set_userflags(conn); message_send_text(conn,message_type_join,conn,NULL); /* we have to send the JOIN acknowledgement */ ircname=irc_convert_channel(channel); irc_send_rpl_namreply(conn,channel); if ((strlen(ircname)+1+strlen(":End of NAMES list")+1)=1) { char ** e; char const * ircname; char const * verytemp; char temp[MAX_IRC_MESSAGE_LEN]; int i; e = irc_get_listelems(params[0]); for (i=0;((e)&&(e[i]));i++) { verytemp = irc_convert_ircname(e[i]); if (!verytemp) continue; /* something is wrong with the name ... */ channel = channellist_find_channel_by_name(verytemp,NULL,NULL); if (!channel) continue; /* channel doesn't exist */ irc_send_rpl_namreply(conn,channel); ircname=irc_convert_channel(channel); if ((strlen(ircname)+1+strlen(":End of NAMES list")+1)=1) { int i; temp[0]='\0'; for (i=0; (i=1) { int i; char ** e; t_connection * c; t_channel * chan; temp[0]='\0'; temp2[0]='\0'; e = irc_get_listelems(params[0]); for (i=0; ((e)&&(e[i]));i++) { if ((c = connlist_find_connection_by_accountname(e[i]))) { if (prefs_get_hide_addr() && !(account_get_command_groups(conn_get_account(conn)) & command_get_group("/admin-addr"))) sprintf(temp,"%s %s hidden * :%s",e[i],clienttag_uint_to_str(conn_get_clienttag(c)),"PvPGN user"); else sprintf(temp,"%s %s %s * :%s",e[i],clienttag_uint_to_str(conn_get_clienttag(c)),addr_num_to_ip_str(conn_get_addr(c)),"PvPGN user"); irc_send(conn,RPL_WHOISUSER,temp); if ((chan=conn_get_channel(conn))) { char flg; unsigned int flags; flags = conn_get_flags(c); if (flags & MF_BLIZZARD) flg='@'; else if ((flags & MF_BNET) || (flags & MF_GAVEL)) flg='%'; else if (flags & MF_VOICE) flg='+'; else flg = ' '; sprintf(temp2,"%s :%c%s",e[i],flg,irc_convert_channel(chan)); irc_send(conn,RPL_WHOISCHANNELS,temp2); } } else irc_send(conn,ERR_NOSUCHNICK,":No such nick/channel"); } irc_send(conn,RPL_ENDOFWHOIS,":End of /WHOIS list"); if (e) irc_unget_listelems(e); } else irc_send(conn,ERR_NEEDMOREPARAMS,":Too few arguments to WHOIS"); return 0; } static int _handle_part_command(t_connection * conn, int numparams, char ** params, char * text) { if ((conn_get_wol(conn) == 1) && (conn_wol_get_ingame(conn) == 1)) conn_wol_set_ingame(conn,0); conn_set_channel(conn, NULL); message_send_text(conn,message_type_part,conn,NULL); return 0; } /** * Westwood Online Extensions */ static int _handle_cvers_command(t_connection * conn, int numparams, char ** params, char * text) { // Ignore command return 0; } static int _handle_verchk_command(t_connection * conn, int numparams, char ** params, char * text) { char temp[MAX_IRC_MESSAGE_LEN]; if (numparams == 2) { snprintf(temp, sizeof(temp), ":none none none 1 %s NONREQ", params[0]); eventlog(eventlog_level_debug,__FUNCTION__,"[** WOL **] VERCHK %s",temp); irc_send(conn,RPL_VERCHK_NONREQ,temp); } else irc_send(conn,ERR_NEEDMOREPARAMS,"VERCHK :Not enough parameters"); return 0; } static int _handle_lobcount_command(t_connection * conn, int numparams, char ** params, char * text) { // Ignore command but, return 1 irc_send(conn,RPL_LOBCOUNT,"1"); return 0; } static int _handle_whereto_command(t_connection * conn, int numparams, char ** params, char * text) { // Ignore command, but output proper server information... char temp[MAX_IRC_MESSAGE_LEN]; // Casted to avoid warnings const char * ircip; const char * ircname = prefs_get_servername(); const char * irctimezone = prefs_get_wol_timezone(); const char * irclong = prefs_get_wol_longitude(); const char * irclat = prefs_get_wol_latitude(); { /* trans support */ unsigned short port = conn_get_real_local_port(conn); unsigned int addr = conn_get_real_local_addr(conn); trans_net(conn_get_addr(conn), &addr, &port); ircip = addr_num_to_ip_str(addr); } sprintf(temp,":%s %d '0:%s' %s %s %s",ircip,BNETD_WOL_PORT,ircname,irctimezone,irclong,irclat); irc_send(conn,RPL_IRCSERV,temp); sprintf(temp,":%s %d 'Live chat server' %s %s %s",ircip,BNETD_IRC_PORT,irctimezone,irclong,irclat); irc_send(conn,RPL_IRCSERV,temp); sprintf(temp,":%s %d 'Gameres server' %s %s %s",ircip,BNETD_WOL_PORT,irctimezone,irclong,irclat); irc_send(conn,RPL_GAMERESSERV,temp); sprintf(temp,":%s %d 'Ladder server' %s %s %s",ircip,BNETD_WOL_PORT,irctimezone,irclong,irclat); irc_send(conn,RPL_LADDERSERV,temp); irc_send(conn,RPL_ENDSERVLIST,""); return 0; } static int _handle_apgar_command(t_connection * conn, int numparams, char ** params, char * text) { char * apgar = NULL; if((numparams>=1)&¶ms[0]) { apgar = params[0]; conn_wol_set_apgar(conn,apgar); } else irc_send(conn,ERR_NEEDMOREPARAMS,"APGAR :Not enough parameters"); return 0; } static int _handle_serial_command(t_connection * conn, int numparams, char ** params, char * text) { // Ignore command return 0; } static int _handle_squadinfo_command(t_connection * conn, int numparams, char ** params, char * text) { if ((numparams>=1)&&(params[0])) irc_send(conn,ERR_IDNOEXIST,":ID does not exist"); else irc_send(conn,ERR_NEEDMOREPARAMS,"SQUADINFO :Not enough parameters"); return 0; } static int _handle_setopt_command(t_connection * conn, int numparams, char ** params, char * text) { // Ignore this command return 0; } static int _handle_setcodepage_command(t_connection * conn, int numparams, char ** params, char * text) { char * codepage = NULL; if((numparams>=1)&¶ms[0]) { codepage = params[0]; conn_wol_set_codepage(conn,atoi(codepage)); irc_send(conn,RPL_SET_CODEPAGE,codepage); } else irc_send(conn,ERR_NEEDMOREPARAMS,"SETCODEPAGE :Not enough parameters"); return 0; } static int _handle_setlocale_command(t_connection * conn, int numparams, char ** params, char * text) { char * locale = NULL; if((numparams>=1)&&(params[0])) { locale = params[0]; conn_wol_set_locale(conn,atoi(locale)); irc_send(conn,RPL_SET_LOCALE,locale); } else irc_send(conn,ERR_NEEDMOREPARAMS,"SETLOCALE :Not enough parameters"); return 0; } static int _handle_getcodepage_command(t_connection * conn, int numparams, char ** params, char * text) { char temp[MAX_IRC_MESSAGE_LEN]; char _temp[MAX_IRC_MESSAGE_LEN]; memset(temp,0,sizeof(temp)); memset(_temp,0,sizeof(_temp)); if((numparams>=1)) { int i; for (i=0; i=1)) { int i; for (i=0; i=8)) { char ** e; eventlog(eventlog_level_debug,__FUNCTION__,"[** WOL **] JOINGAME: * Create * (%s, %s)", params[0],params[1]); sprintf(_temp,"%s %s %s %s 0 %u %s :%s",params[1],params[2],params[3],params[4],conn_get_addr(conn),params[6],params[0]); eventlog(eventlog_level_debug,__FUNCTION__,"[** WOL **] JOINGAME [Game Options] (%s)",_temp); e = irc_get_listelems(params[0]); if ((e)&&(e[0])) { char const * ircname = irc_convert_ircname(e[0]); char * old_channel_name = NULL; t_channel * old_channel = conn_get_channel(conn); if (old_channel) old_channel_name = xstrdup(irc_convert_channel(old_channel)); if ((!(ircname)) || (conn_set_channel(conn,ircname)<0)) { irc_send(conn,ERR_NOSUCHCHANNEL,":JOINGAME failed"); /* FIXME: be more precise; what is the real error code for that? */ } else { t_channel * channel; channel = conn_get_channel(conn); if (channel!=old_channel) { char temp[MAX_IRC_MESSAGE_LEN]; char * topic; channel_set_userflags(conn); channel_wol_set_game_options(channel,_temp); channel_wol_set_game_owner(channel,conn_get_chatname(conn)); channel_wol_set_game_ownerip(channel,conn_get_addr(conn)); channel_wol_set_game_type(channel,conn_wol_get_game_type(conn)); channel_set_max(channel,atoi(params[2])); channel_wol_set_game_tournament(channel,atoi(params[6])); message_send_text(conn,message_wol_joingame,conn,_temp); /* we have to send the JOINGAME acknowledgement */ ircname=irc_convert_channel(channel); if ((topic = channel_get_topic(channel_get_name(channel)))) { if ((strlen(ircname)+1+1+strlen(topic)+1)=1)&&(text)) { int i; char ** e; e = irc_get_listelems(params[0]); /* FIXME: support wildcards! */ eventlog(eventlog_level_debug,__FUNCTION__,"[** WOL **] GAMEOPT: (%s :%s)",params[0],text); conn_wol_set_game_options(conn,text); for (i=0;((e)&&(e[i]));i++) { if (e[i][0]=='#') { /* game owner change */ t_channel * channel; if ((channel = channellist_find_channel_by_name(irc_convert_ircname(params[0]),NULL,NULL))) { sprintf(temp,":%s",text); channel_message_send(channel,message_wol_gameopt_owner,conn,temp); } else { irc_send(conn,ERR_NOSUCHCHANNEL,":No such channel"); } } else { /* user change */ t_connection * user; if ((user = connlist_find_connection_by_accountname(e[i]))) { sprintf(temp,":%s",text); message_send_text(user,message_wol_gameopt_join,conn,temp); } else { irc_send(conn,ERR_NOSUCHNICK,":No such user"); } } } } else irc_send(conn,ERR_NEEDMOREPARAMS,"GAMEOPT :Not enough parameters"); return 0; } static int _handle_finduserex_command(t_connection * conn, int numparams, char ** params, char * text) { char _temp[MAX_IRC_MESSAGE_LEN]; char const * ircname = NULL; memset(_temp,0,sizeof(_temp)); if ((numparams>=1)) { t_connection * user; if((user = connlist_find_connection_by_accountname(params[0]))) { ircname = irc_convert_channel(conn_get_channel(user)); } sprintf(_temp,"0 :%s,0",ircname); irc_send(conn,RPL_FIND_USER_EX,_temp); } else irc_send(conn,ERR_NEEDMOREPARAMS,"FINDUSEREX :Not enough parameters"); return 0; } static int _handle_page_command(t_connection * conn, int numparams, char ** params, char * text) { char _temp[MAX_IRC_MESSAGE_LEN]; memset(_temp,0,sizeof(_temp)); if ((numparams>=1)&&(text)) { t_connection * user; sprintf(_temp,":%s",text); if((user = connlist_find_connection_by_accountname(params[0]))) { message_send_text(user,message_wol_page,conn,_temp); } } else irc_send(conn,ERR_NEEDMOREPARAMS,"PAGE :Not enough parameters"); return 0; } static int _handle_startg_command(t_connection * conn, int numparams, char ** params, char * text) { char temp[MAX_IRC_MESSAGE_LEN]; char _temp_a[MAX_IRC_MESSAGE_LEN]; t_channel * channel; time_t now; /** * Heres the output expected (this can have up-to 8 entries (ie 8 players): * (we are assuming for this example that user1 is the game owner) * * user1!WWOL@hostname STARTG u :user1 xxx.xxx.xxx.xxx user2 xxx.xxx.xxx.xxx :gameNumber t_Time */ if((numparams>=1)) { int i; char ** e; memset(temp,0,sizeof(temp)); memset(_temp_a,0,sizeof(_temp_a)); e = irc_get_listelems(params[1]); /* FIXME: support wildcards! */ strcat(temp,":"); for (i=0;((e)&&(e[i]));i++) { t_connection * user; const char * addr = NULL; if((user = connlist_find_connection_by_accountname(e[i]))) { addr = addr_num_to_ip_str(conn_get_addr(user)); } sprintf(_temp_a,"%s %s ",e[i],addr); strcat(temp,_temp_a); } strcat(temp,":"); strcat(temp,"1337"); /* yes, ha ha funny, i just don't generate game numbers yet */ strcat(temp," "); now = time(NULL); sprintf(_temp_a,"%lu",now); strcat(temp,_temp_a);; eventlog(eventlog_level_debug,__FUNCTION__,"[** WOL **] STARTG: (%s)",temp); if ((channel = channellist_find_channel_by_name(irc_convert_ircname(params[0]),NULL,NULL))) { channel_message_send(channel,message_wol_start_game,conn,temp); } else { irc_send(conn,ERR_NOSUCHCHANNEL,":No such channel"); } } else irc_send(conn,ERR_NEEDMOREPARAMS,"STARTG :Not enough parameters"); return 0; } static int _handle_kick_command(t_connection * conn, int numparams, char ** params, char * text) { char temp[MAX_IRC_MESSAGE_LEN]; char ** e; /** * Heres the imput expected * KICK [channel] [kicked_user],[kicked_user2] * * Heres the output expected * :user!WWOL@hostname KICK [channel] [kicked_user] :[text] * * WOL in [text] sends Admin name */ if ((numparams != 2) || !(params[1])) { irc_send(conn,ERR_NEEDMOREPARAMS,"KICK :Not enough parameters"); return 0; } e = irc_get_listelems(params[1]); /* Make standart PvPGN KICK from RFC2812 KICK */ if (text) snprintf(temp, sizeof(temp), "/kick %s %s", e[0], text); else snprintf(temp, sizeof(temp), "/kick %s", e[0]); handle_command(conn, temp); if (e) irc_unget_listelems(e); return 0; } /** * LADDER Server commands: * * Client standartly initialise connection, sends command and after that * standing for server response. When all data are sended, server close * connection which is an infromation to client that transfer is done. * At the moment we only closing connection. */ static int _handle_listsearch_command(t_connection * conn, int numparams, char ** params, char * text) { // FIXME: Not implemetned yet conn_set_state(conn, conn_state_destroy); return 0; } static int _handle_rungsearch_command(t_connection * conn, int numparams, char ** params, char * text) { // FIXME: Not implemetned yet conn_set_state(conn, conn_state_destroy); return 0; } static int _handle_highscore_command(t_connection * conn, int numparams, char ** params, char * text) { // FIXME: Not implemetned yet conn_set_state(conn, conn_state_destroy); return 0; } pvpgn-1.8.5/src/bnetd/topic.h0000644000175000017500000000305511151345317015017 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_TOPIC_TYPES #define INCLUDED_TOPIC_TYPES #ifdef TOPIC_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include # include "common/list.h" #else # define JUST_NEED_TYPES # include # include "common/list.h" # undef JUST_NEED_TYPES #endif #endif typedef struct topic #ifdef TOPIC_INTERNAL_ACCESS { char * channel_name; char * topic; int save; } #endif t_topic; #define DO_SAVE_TOPIC 1 #define NO_SAVE_TOPIC 0 #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_TOPIC_PROTOS #define INCLUDED_TOPIC_PROTOS #define JUST_NEED_TYPES #include "common/list.h" #undef JUST_NEED_TYPES int topiclist_load(char const * topicfile); int topiclist_unload(void); int channel_set_topic(char const * channel_name, char const * topic_text, int do_save); char * channel_get_topic(char const * channel_name); #endif #endif pvpgn-1.8.5/src/bnetd/sql_sqlite3.h0000644000175000017500000000171511151345317016145 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SQL_SQLITE3_PROTOS #define INCLUDED_SQL_SQLITE3_PROTOS #define JUST_NEED_TYPES # include "sql_common.h" #undef JUST_NEED_TYPES extern t_sql_engine sql_sqlite3; #endif /* INCLUDED_SQL_MYSQL_PROTOS */ pvpgn-1.8.5/src/bnetd/command.c0000644000175000017500000047743711151345317015335 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999 Gediminas (gediminas_lt@mailexcite.com) * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * Copyright (C) 2000 Dizzy * Copyright (C) 2000 Onlyer (onlyer@263.net) * Copyright (C) 2003,2004 Aaron * Copyright (C) 2004 Donny Redmond (dredmond@linuxmail.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/strtoul.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include "compat/strcasecmp.h" #include "compat/snprintf.h" #include #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES # include #endif #include "compat/strftime.h" #include "message.h" #include "common/tag.h" #include "connection.h" #include "channel.h" #include "game.h" #include "common/util.h" #include "common/version.h" #include "team.h" #include "account.h" #include "account_wrap.h" #include "server.h" #include "prefs.h" #include "common/eventlog.h" #include "ladder.h" #include "timer.h" #include "common/bnettime.h" #include "common/addr.h" #include "common/packet.h" #include "helpfile.h" #include "mail.h" #include "common/bnethash.h" #include "runprog.h" #include "common/list.h" #include "common/proginfo.h" #include "alias_command.h" #include "realm.h" #include "ipban.h" #include "command_groups.h" #include "common/queue.h" #include "common/bn_type.h" #include "common/xalloc.h" #include "command.h" #include "news.h" #include "common/trans.h" #include "common/lstr.h" // aaron #include "topic.h" #include "friends.h" #include "clan.h" #include "common/setup_after.h" static char const * bnclass_get_str(unsigned int class); static void do_whisper(t_connection * user_c, char const * dest, char const * text); static void do_whois(t_connection * c, char const * dest); static void user_timer_cb(t_connection * c, time_t now, t_timer_data str); char msgtemp[MAX_MESSAGE_LEN]; char msgtemp2[MAX_MESSAGE_LEN]; static char const * bnclass_get_str(unsigned int class) { switch (class) { case PLAYERINFO_DRTL_CLASS_WARRIOR: return "warrior"; case PLAYERINFO_DRTL_CLASS_ROGUE: return "rogue"; case PLAYERINFO_DRTL_CLASS_SORCERER: return "sorcerer"; default: return "unknown"; } } static void do_whisper(t_connection * user_c, char const * dest, char const * text) { t_connection * dest_c; char const * tname; if (!(dest_c = connlist_find_connection_by_name(dest,conn_get_realm(user_c)))) { message_send_text(user_c,message_type_error,user_c,"That user is not logged on."); return; } if (conn_get_dndstr(dest_c)) { snprintf(msgtemp, sizeof(msgtemp), "%.64s is unavailable (%.128s)",conn_get_username(dest_c),conn_get_dndstr(dest_c)); message_send_text(user_c,message_type_info,user_c,msgtemp); return; } message_send_text(user_c,message_type_whisperack,dest_c,text); if (conn_get_awaystr(dest_c)) { snprintf(msgtemp, sizeof(msgtemp), "%.64s is away (%.128s)",conn_get_username(dest_c),conn_get_awaystr(dest_c)); message_send_text(user_c,message_type_info,user_c,msgtemp); } message_send_text(dest_c,message_type_whisper,user_c,text); if ((tname = conn_get_username(user_c))) { char username[1+USER_NAME_MAX]; /* '*' + username (including NUL) */ if (strlen(tname)command_string != NULL; p++) { if (strstart(text, p->command_string)==0) { if (!(command_get_group(p->command_string))) { message_send_text(c,message_type_error,c,"This command has been deactivated"); return 0; } if (!((command_get_group(p->command_string) & account_get_command_groups(conn_get_account(c))))) { message_send_text(c,message_type_error,c,"This command is reserved for admins."); return 0; } if (p->command_handler != NULL) return ((p->command_handler)(c,text)); } } if (prefs_get_extra_commands()==0) { message_send_text(c,message_type_error,c,"Unknown command."); eventlog(eventlog_level_debug,__FUNCTION__,"got unknown standard command \"%s\"",text); return 0; } for (p = extended_command_table; p->command_string != NULL; p++) { if (strstart(text, p->command_string)==0) { if (!(command_get_group(p->command_string))) { message_send_text(c,message_type_error,c,"This command has been deactivated"); return 0; } if (!((command_get_group(p->command_string) & account_get_command_groups(conn_get_account(c))))) { message_send_text(c,message_type_error,c,"This command is reserved for admins."); return 0; } if (p->command_handler != NULL) return ((p->command_handler)(c,text)); } } if (strlen(text)>=2 && strncmp(text,"//",2)==0) { handle_alias_command(c,text); return 0; } message_send_text(c,message_type_error,c,"Unknown command."); eventlog(eventlog_level_debug,__FUNCTION__,"got unknown command \"%s\"",text); return 0; } // +++++++++++++++++++++++++++++++++ command implementations +++++++++++++++++++++++++++++++++++++++ static int _handle_clan_command(t_connection * c, char const * text) { t_account * acc; t_clanmember * member; t_clan * clan; text = skip_command(text); if ( text[0] == '\0' ) { message_send_text(c,message_type_info,c,"usage:"); message_send_text(c,message_type_info,c,"/clan public /clan pub"); message_send_text(c,message_type_info,c,"Opens the clan channel up to the public so that anyone may enter."); message_send_text(c,message_type_info,c,"/clan private /clan priv"); message_send_text(c,message_type_info,c,"Closes the clan channel such that only members of the clan may enter."); message_send_text(c,message_type_info,c,"/clan motd MESSAGE"); message_send_text(c,message_type_info,c,"Update the clan message of the day to MESSAGE."); return 0; } if((acc = conn_get_account(c)) && (member = account_get_clanmember(acc)) && (clan = clanmember_get_clan(member))) { if(clanmember_get_status(member)>=CLAN_SHAMAN) { if (strstart(text,"public")==0 || strstart(text,"pub")==0) { if(clan_get_channel_type(clan)!=0) { clan_set_channel_type(clan,0); message_send_text(c,message_type_info,c,"Clan channel is opened up!"); } else message_send_text(c,message_type_error,c,"Clan channel has already been opened up!"); } else if (strstart(text,"private")==0 || strstart(text,"priv")==0) { if(clan_get_channel_type(clan)!=1) { clan_set_channel_type(clan,1); message_send_text(c,message_type_info,c,"Clan channel is closed!"); } else message_send_text(c,message_type_error,c,"Clan channel has already been closed!"); } else if (strstart(text,"motd")==0) { const char * msg=skip_command(text); if(msg[0]=='\0') { message_send_text(c,message_type_info,c,"usage:"); message_send_text(c,message_type_info,c,"/clan motd MESSAGE"); message_send_text(c,message_type_info,c,"Update the clan message of the day to MESSAGE."); } else { clan_set_motd(clan, msg); message_send_text(c,message_type_info,c,"Clan message of day is updated!"); } } } else message_send_text(c,message_type_error,c,"You are not the chieftain or shaman of clan!"); } else message_send_text(c,message_type_error,c,"You are not in a clan!"); return 0; } static int command_set_flags(t_connection * c) { return channel_set_userflags(c); } static int _handle_admin_command(t_connection * c, char const * text) { char const * username; char command; t_account * acc; t_connection * dst_c; int changed=0; text = skip_command(text); if ((text[0]=='\0') || ((text[0] != '+') && (text[0] != '-'))) { message_send_text(c,message_type_info,c,"usage: /admin +username to promote user to Server Admin."); message_send_text(c,message_type_info,c," /admin -username to demote user from Server Admin."); return -1; } command = text[0]; username = &text[1]; if(!*username) { message_send_text(c,message_type_info,c,"You need to supply a username."); return -1; } if(!(acc = accountlist_find_account(username))) { snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username); message_send_text(c, message_type_info, c, msgtemp); return -1; } dst_c = account_get_conn(acc); if (command == '+') { if (account_get_auth_admin(acc,NULL) == 1) { snprintf(msgtemp, sizeof(msgtemp), "%.64s is already a Server Admin",username); } else { account_set_auth_admin(acc,NULL,1); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a Server Admin",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Server Admin",conn_get_loggeduser(c)); changed = 1; } } else { if (account_get_auth_admin(acc,NULL) != 1) snprintf(msgtemp, sizeof(msgtemp), "%.64s is no Server Admin, so you can't demote him",username); else { account_set_auth_admin(acc,NULL,0); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a Server Admin",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a Server Admin",conn_get_loggeduser(c)); changed = 1; } } if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); message_send_text(c, message_type_info, c, msgtemp); command_set_flags(dst_c); return 0; } static int _handle_operator_command(t_connection * c, char const * text) { char const * username; char command; t_account * acc; t_connection * dst_c; int changed = 0; text = skip_command(text); if ((text[0]=='\0') || ((text[0] != '+') && (text[0] != '-'))) { message_send_text(c,message_type_info,c,"usage: /operator +username to promote user to Server Operator."); message_send_text(c,message_type_info,c," /operator -username to demote user from Server Operator."); return -1; } command = text[0]; username = &text[1]; if(!*username) { message_send_text(c,message_type_info,c,"You need to supply a username."); return -1; } if(!(acc = accountlist_find_account(username))) { snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username); message_send_text(c, message_type_info, c, msgtemp); return -1; } dst_c = account_get_conn(acc); if (command == '+') { if (account_get_auth_operator(acc,NULL) == 1) snprintf(msgtemp, sizeof(msgtemp), "%.64s is already a Server Operator",username); else { account_set_auth_operator(acc,NULL,1); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a Server Operator",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Server Operator",conn_get_loggeduser(c)); changed = 1; } } else { if (account_get_auth_operator(acc,NULL) != 1) snprintf(msgtemp, sizeof(msgtemp), "%.64s is no Server Operator, so you can't demote him",username); else { account_set_auth_operator(acc,NULL,0); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a Server Operator",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Server Operator",conn_get_loggeduser(c)); changed = 1; } } if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); message_send_text(c, message_type_info, c, msgtemp); command_set_flags(dst_c); return 0; } static int _handle_aop_command(t_connection * c, char const * text) { char const * username; char const * channel; t_account * acc; t_connection * dst_c; int changed = 0; if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return -1; } if (account_get_auth_admin(conn_get_account(c),NULL)!=1 && account_get_auth_admin(conn_get_account(c),channel)!=1) { message_send_text(c,message_type_error,c,"You must be at least a Channel Admin to use this command."); return -1; } text = skip_command(text); if (!(username = &text[0])) { message_send_text(c, message_type_info, c, "You need to supply a username."); return -1; } if(!(acc = accountlist_find_account(username))) { snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username); message_send_text(c, message_type_info, c, msgtemp); return -1; } dst_c = account_get_conn(acc); if (account_get_auth_admin(acc,channel) == 1) snprintf(msgtemp, sizeof(msgtemp), "%.64s is already a Channel Admin",username); else { account_set_auth_admin(acc,channel,1); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a Channel Admin",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Channel Admin for channel \"%.128s\"",conn_get_loggeduser(c),channel); changed = 1; } if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); message_send_text(c, message_type_info, c, msgtemp); command_set_flags(dst_c); return 0; } static int _handle_vop_command(t_connection * c, char const * text) { char const * username; char const * channel; t_account * acc; t_connection * dst_c; int changed = 0; if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return -1; } if (account_get_auth_admin(conn_get_account(c),NULL)!=1 && account_get_auth_admin(conn_get_account(c),channel)!=1) { message_send_text(c,message_type_error,c,"You must be at least a Channel Admin to use this command."); return -1; } text = skip_command(text); if (!(username = &text[0])) { message_send_text(c, message_type_info, c, "You need to supply a username."); return -1; } if(!(acc = accountlist_find_account(username))) { snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username); message_send_text(c, message_type_info, c, msgtemp); return -1; } dst_c = account_get_conn(acc); if (account_get_auth_voice(acc,channel) == 1) snprintf(msgtemp, sizeof(msgtemp), "%.64s is already on VOP list",username); else { account_set_auth_voice(acc,channel,1); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been added to the VOP list",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has added you to the VOP list of channel \"%.128s\"",conn_get_loggeduser(c),channel); changed = 1; } if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); message_send_text(c, message_type_info, c, msgtemp); command_set_flags(dst_c); return 0; } static int _handle_voice_command(t_connection * c, char const * text) { char const * username; char const * channel; t_account * acc; t_connection * dst_c; int changed = 0; if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return -1; } if (!(account_is_operator_or_admin(conn_get_account(c),channel_get_name(conn_get_channel(c))))) { message_send_text(c,message_type_error,c,"You must be at least a Channel Operator to use this command."); return -1; } text = skip_command(text); if (!(username = &text[0])) { message_send_text(c, message_type_info, c, "You need to supply a username."); return -1; } if(!(acc = accountlist_find_account(username))) { snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username); message_send_text(c, message_type_info, c, msgtemp); return -1; } dst_c = account_get_conn(acc); if (account_get_auth_voice(acc,channel)==1) snprintf(msgtemp, sizeof(msgtemp), "%s is already on VOP list, no need to Voice him", username); else { if ((!dst_c) || conn_get_channel(c)!=conn_get_channel(dst_c)) { snprintf(msgtemp, sizeof(msgtemp), "%.64s must be on the same channel to voice him",username); } else { if (channel_conn_has_tmpVOICE(conn_get_channel(c),dst_c)) snprintf(msgtemp, sizeof(msgtemp), "%.64s has already Voice in this channel",username); else { if (account_is_operator_or_admin(acc,channel)) snprintf(msgtemp, sizeof(msgtemp), "%.64s allready is operator or admin, no need to voice him",username); else { conn_set_tmpVOICE_channel(dst_c,channel); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been granted Voice in this channel",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has granted you Voice in this channel",conn_get_loggeduser(c)); changed = 1; } } } } if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); message_send_text(c, message_type_info, c, msgtemp); command_set_flags(dst_c); return 0; } static int _handle_devoice_command(t_connection * c, char const * text) { char const * username; char const * channel; t_account * acc; t_connection * dst_c; int done = 0; int changed = 0; if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return -1; } if (!(account_is_operator_or_admin(conn_get_account(c),channel_get_name(conn_get_channel(c))))) { message_send_text(c,message_type_error,c,"You must be at least a Channel Operator to use this command."); return -1; } text = skip_command(text); if (!(username = &text[0])) { message_send_text(c, message_type_info, c, "You need to supply a username."); return -1; } if(!(acc = accountlist_find_account(username))) { snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username); message_send_text(c, message_type_info, c, msgtemp); return -1; } dst_c = account_get_conn(acc); if (account_get_auth_voice(acc,channel)==1) { if ((account_get_auth_admin(conn_get_account(c),channel)==1) || (account_get_auth_admin(conn_get_account(c),NULL)==1)) { account_set_auth_voice(acc,channel,0); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been removed from VOP list.",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has removed you from VOP list of channel \"%.128s\"",conn_get_loggeduser(c),channel); changed = 1; } else { snprintf(msgtemp, sizeof(msgtemp), "You must be at least Channel Admin to remove %.64s from the VOP list",username); } done = 1; } if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); message_send_text(c, message_type_info, c, msgtemp); changed = 0; if ((dst_c) && channel_conn_has_tmpVOICE(conn_get_channel(c),dst_c)==1) { conn_set_tmpVOICE_channel(dst_c,NULL); snprintf(msgtemp, sizeof(msgtemp), "Voice has been taken from %.64s in this channel",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has taken your Voice in channel \"%.128s\"",conn_get_loggeduser(c),channel); changed = 1; done = 1; } if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); message_send_text(c, message_type_info, c, msgtemp); if (!done) { snprintf(msgtemp, sizeof(msgtemp), "%.64s has no Voice in this channel, so it can't be taken away",username); message_send_text(c, message_type_info, c, msgtemp); } command_set_flags(dst_c); return 0; } static int _handle_op_command(t_connection * c, char const * text) { char const * username; char const * channel; t_account * acc; int OP_lvl; t_connection * dst_c; int changed = 0; if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return -1; } acc = conn_get_account(c); OP_lvl = 0; if (account_is_operator_or_admin(acc,channel)) OP_lvl = 1; else if (channel_conn_is_tmpOP(conn_get_channel(c),c)) OP_lvl = 2; if (OP_lvl==0) { message_send_text(c,message_type_error,c,"You must be at least a Channel Operator or tempOP to use this command."); return -1; } text = skip_command(text); if (!(username = &text[0])) { message_send_text(c, message_type_info, c, "You need to supply a username."); return -1; } if(!(acc = accountlist_find_account(username))) { snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username); message_send_text(c, message_type_info, c, msgtemp); return -1; } dst_c = account_get_conn(acc); if (OP_lvl==1) // user is full op so he may fully op others { if (account_get_auth_operator(acc,channel) == 1) snprintf(msgtemp, sizeof(msgtemp), "%.64s is allready a Channel Operator",username); else { account_set_auth_operator(acc,channel,1); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a Channel Operator",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Channel Operator in channel \"%.128s\"",conn_get_loggeduser(c),channel); changed = 1; } } else { // user is only tempOP so he may only tempOP others if ((!(dst_c)) || (conn_get_channel(c) != conn_get_channel(dst_c))) snprintf(msgtemp, sizeof(msgtemp), "%.64s must be on the same channel to tempOP him",username); else { if (account_is_operator_or_admin(acc,channel)) snprintf(msgtemp, sizeof(msgtemp), "%.64s allready is operator or admin, no need to tempOP him",username); else { conn_set_tmpOP_channel(dst_c,channel); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a tempOP",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a tempOP in this channel",conn_get_loggeduser(c)); changed = 1; } } } if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); message_send_text(c, message_type_info, c, msgtemp); command_set_flags(dst_c); return 0; } static int _handle_tmpop_command(t_connection * c, char const * text) { char const * username; char const * channel; t_account * acc; t_connection * dst_c; int changed = 0; if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return -1; } if (!(account_is_operator_or_admin(conn_get_account(c),channel_get_name(conn_get_channel(c))) || channel_conn_is_tmpOP(conn_get_channel(c),c))) { message_send_text(c,message_type_error,c,"You must be at least a Channel Operator or tmpOP to use this command."); return -1; } text = skip_command(text); if (!(username = &text[0])) { message_send_text(c, message_type_info, c, "You need to supply a username."); return -1; } if(!(acc = accountlist_find_account(username))) { snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username); message_send_text(c, message_type_info, c, msgtemp); return -1; } dst_c = account_get_conn(acc); if (channel_conn_is_tmpOP(conn_get_channel(c),dst_c)) snprintf(msgtemp, sizeof(msgtemp), "%.64s has already tmpOP in this channel",username); else { if ((!(dst_c)) || (conn_get_channel(c) != conn_get_channel(dst_c))) snprintf(msgtemp, sizeof(msgtemp), "%.64s must be on the same channel to tempOP him",username); else { if (account_is_operator_or_admin(acc,channel)) snprintf(msgtemp, sizeof(msgtemp), "%.64s allready is operator or admin, no need to tempOP him",username); else { conn_set_tmpOP_channel(dst_c,channel); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to tmpOP in this channel",username); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a tempOP in this channel",conn_get_loggeduser(c)); changed = 1; } } } if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); message_send_text(c, message_type_info, c, msgtemp); command_set_flags(dst_c); return 0; } static int _handle_deop_command(t_connection * c, char const * text) { char const * username; char const * channel; t_account * acc; int OP_lvl; t_connection * dst_c; int done = 0; if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return -1; } acc = conn_get_account(c); OP_lvl = 0; if (account_is_operator_or_admin(acc,channel)) OP_lvl = 1; else if (channel_conn_is_tmpOP(conn_get_channel(c),account_get_conn(acc))) OP_lvl = 2; if (OP_lvl==0) { message_send_text(c,message_type_error,c,"You must be at least a Channel Operator or tempOP to use this command."); return -1; } text = skip_command(text); if (!(username = &text[0])) { message_send_text(c, message_type_info, c, "You need to supply a username."); return -1; } if(!(acc = accountlist_find_account(username))) { snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username); message_send_text(c, message_type_info, c, msgtemp); return -1; } dst_c = account_get_conn(acc); if (OP_lvl==1) // user is real OP and allowed to deOP { if (account_get_auth_admin(acc,channel) == 1 || account_get_auth_operator(acc,channel) == 1) { if (account_get_auth_admin(acc,channel) == 1) { if (account_get_auth_admin(conn_get_account(c),channel)!=1 && account_get_auth_admin(conn_get_account(c),NULL)!=1) message_send_text(c,message_type_info,c,"You must be at least a Channel Admin to demote another Channel Admin"); else { account_set_auth_admin(acc,channel,0); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a Channel Admin.", username); message_send_text(c, message_type_info, c, msgtemp); if (dst_c) { snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a Channel Admin of channel \"%.128s\"",conn_get_loggeduser(c),channel); message_send_text(dst_c, message_type_info, c, msgtemp2); } } } if (account_get_auth_operator(acc,channel) == 1) { account_set_auth_operator(acc,channel,0); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a Channel Operator",username); message_send_text(c, message_type_info, c, msgtemp); if (dst_c) { snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a Channel Operator of channel \"%.128s\"",conn_get_loggeduser(c),channel); message_send_text(dst_c, message_type_info, c, msgtemp2); } } done = 1; } if ((dst_c) && channel_conn_is_tmpOP(conn_get_channel(c),dst_c)) { conn_set_tmpOP_channel(dst_c,NULL); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a tempOP of this channel",username); message_send_text(c, message_type_info, c, msgtemp); if (dst_c) { snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a tmpOP of channel \"%.128s\"",conn_get_loggeduser(c),channel); message_send_text(dst_c, message_type_info, c, msgtemp2); } done = 1; } if (!done) { snprintf(msgtemp, sizeof(msgtemp), "%.64s is no Channel Admin or Channel Operator or tempOP, so you can't demote him.",username); message_send_text(c, message_type_info, c, msgtemp); } } else //user is just a tempOP and may only deOP other tempOPs { if (dst_c && channel_conn_is_tmpOP(conn_get_channel(c),dst_c)) { conn_set_tmpOP_channel(account_get_conn(acc),NULL); snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a tempOP of this channel",username); message_send_text(c, message_type_info, c, msgtemp); snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a tempOP of channel \"%.128s\"",conn_get_loggeduser(c),channel); if (dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2); } else { snprintf(msgtemp, sizeof(msgtemp), "%.64s is no tempOP in this channel, so you can't demote him",username); message_send_text(c, message_type_info, c, msgtemp); } } command_set_flags(connlist_find_connection_by_accountname(username)); return 0; } static int _handle_friends_command(t_connection * c, char const * text) { int i; t_account *my_acc = conn_get_account(c); text = skip_command(text);; if(text[0]=='\0' || strstart(text,"help")==0 || strstart(text, "h")==0) { message_send_text(c,message_type_info,c,"Friends List (Used in Arranged Teams and finding online friends.)"); message_send_text(c,message_type_info,c,"Type: /f add (adds a friend to your list)"); message_send_text(c,message_type_info,c,"Type: /f del (removes a friend from your list)"); message_send_text(c,message_type_info,c,"Type: /f promote (promote a friend in your list)"); message_send_text(c,message_type_info,c,"Type: /f demote (demote a friend in your list)"); message_send_text(c,message_type_info,c,"Type: /f list (shows your full friends list)"); message_send_text(c,message_type_info,c,"Type: /f msg (whispers a message to all your friends at once)"); return 0; } if (strstart(text,"add")==0 || strstart(text,"a")==0) { char msgtemp[MAX_MESSAGE_LEN]; t_packet * rpacket; t_connection * dest_c; t_account * friend_acc; t_server_friendslistreply_status status; t_game * game; t_channel * channel; char stat; t_list * flist; t_friend * fr; text = skip_command(text); if (text[0] == '\0') { message_send_text(c,message_type_info,c,"usage: /f add "); return 0; } if (!(friend_acc = accountlist_find_account(text))) { message_send_text(c,message_type_info,c,"That user does not exist."); return 0; } switch(account_add_friend(my_acc, friend_acc)) { case -1: message_send_text(c,message_type_error,c,"Server error."); return 0; case -2: message_send_text(c,message_type_info,c,"You can't add yourself to your friends list."); return 0; case -3: snprintf(msgtemp, sizeof(msgtemp), "You can only have a maximum of %d friends.", prefs_get_max_friends()); message_send_text(c,message_type_info,c,msgtemp); return 0; case -4: snprintf(msgtemp, sizeof(msgtemp), "%.64s is already on your friends list!", text); message_send_text(c,message_type_info,c,msgtemp); return 0; } snprintf(msgtemp, sizeof(msgtemp), "Added %.64s to your friends list.", text); message_send_text(c,message_type_info,c,msgtemp); dest_c = connlist_find_connection_by_account(friend_acc); if(dest_c!=NULL) { snprintf(msgtemp, sizeof(msgtemp), "%.64s added you to his/her friends list.",conn_get_username(c)); message_send_text(dest_c,message_type_info,dest_c,msgtemp); } if ((conn_get_class(c)!=conn_class_bnet) || (!(rpacket = packet_create(packet_class_bnet)))) return 0; packet_set_size(rpacket,sizeof(t_server_friendadd_ack)); packet_set_type(rpacket,SERVER_FRIENDADD_ACK); packet_append_string(rpacket, account_get_name(friend_acc)); game = NULL; channel = NULL; if(!(dest_c)) { bn_byte_set(&status.location,FRIENDSTATUS_OFFLINE); bn_byte_set(&status.status,0); bn_int_set(&status.clienttag,0); } else { bn_int_set(&status.clienttag, conn_get_clienttag(dest_c)); stat = 0; flist = account_get_friends(my_acc); fr = friendlist_find_account(flist,friend_acc); if ((friend_get_mutual(fr))) stat |= FRIEND_TYPE_MUTUAL; if ((conn_get_dndstr(dest_c))) stat |= FRIEND_TYPE_DND; if ((conn_get_awaystr(dest_c))) stat |= FRIEND_TYPE_AWAY; bn_byte_set(&status.status,stat); if((game = conn_get_game(dest_c))) { if (game_get_flag(game) != game_flag_private) bn_byte_set(&status.location,FRIENDSTATUS_PUBLIC_GAME); else bn_byte_set(&status.location,FRIENDSTATUS_PRIVATE_GAME); } else if((channel = conn_get_channel(dest_c))) { bn_byte_set(&status.location,FRIENDSTATUS_CHAT); } else { bn_byte_set(&status.location,FRIENDSTATUS_ONLINE); } } packet_append_data(rpacket, &status, sizeof(status)); if (game) packet_append_string(rpacket,game_get_name(game)); else if (channel) packet_append_string(rpacket,channel_get_name(channel)); else packet_append_string(rpacket,""); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); return 0; } if (strstart(text,"msg")==0 || strstart(text,"w")==0 || strstart(text,"whisper")==0 || strstart(text,"m")==0) { char const *msg; int cnt = 0; t_connection * dest_c; t_elem * curr; t_friend * fr; t_list * flist; msg = skip_command(text); /* if the message test is empty then ignore command */ if (msg[0]=='\0') { message_send_text(c,message_type_info,c,"Did not message any friends. Type some text next time."); return 0; } flist=account_get_friends(my_acc); if(flist==NULL) return -1; LIST_TRAVERSE(flist,curr) { if (!(fr = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } if(friend_get_mutual(fr)) { dest_c = connlist_find_connection_by_account(friend_get_account(fr)); if (!dest_c) continue; message_send_text(dest_c,message_type_whisper,c,msg); cnt++; } } if(cnt) message_send_text(c,message_type_friendwhisperack,c,msg); else message_send_text(c,message_type_info,c,"All your friends are offline."); return 0; } if (strstart(text,"r")==0 || strstart(text,"remove")==0 || strstart(text,"del")==0 || strstart(text,"delete")==0) { int num; char msgtemp[MAX_MESSAGE_LEN]; t_packet * rpacket; text = skip_command(text); if (text[0]=='\0') { message_send_text(c,message_type_info,c,"usage: /f remove "); return 0; } switch((num = account_remove_friend2(my_acc, text))) { case -1: return -1; case -2: snprintf(msgtemp, sizeof(msgtemp), "%.64s was not found on your friends list.", text); message_send_text(c,message_type_info,c,msgtemp); return 0; default: snprintf(msgtemp, sizeof(msgtemp), "Removed %.64s from your friends list.", text); message_send_text(c,message_type_info,c,msgtemp); if ((conn_get_class(c)!=conn_class_bnet) || (!(rpacket = packet_create(packet_class_bnet)))) return 0; packet_set_size(rpacket,sizeof(t_server_frienddel_ack)); packet_set_type(rpacket,SERVER_FRIENDDEL_ACK); bn_byte_set(&rpacket->u.server_frienddel_ack.friendnum, num); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); return 0; } } if (strstart(text,"p")==0 || strstart(text,"promote")==0) { int num; int n; char msgtemp[MAX_MESSAGE_LEN]; char const * dest_name; t_packet * rpacket; t_list * flist; t_friend * fr; t_account * dest_acc; unsigned int dest_uid; text = skip_command(text); if (text[0]=='\0') { message_send_text(c,message_type_info,c,"usage: /f promote "); return 0; } num = account_get_friendcount(my_acc); flist = account_get_friends(my_acc); for(n = 1; nu.server_friendmove_ack.pos1, n-1); bn_byte_set(&rpacket->u.server_friendmove_ack.pos2, n); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); return 0; } return 0; } if (strstart(text,"d")==0 || strstart(text,"demote")==0) { int num; int n; char msgtemp[MAX_MESSAGE_LEN]; char const * dest_name; t_packet * rpacket; t_list * flist; t_friend * fr; t_account * dest_acc; unsigned int dest_uid; text = skip_command(text); if (text[0]=='\0') { message_send_text(c,message_type_info,c,"usage: /f demote "); return 0; } num = account_get_friendcount(my_acc); flist = account_get_friends(my_acc); for(n = 0; nu.server_friendmove_ack.pos1, n); bn_byte_set(&rpacket->u.server_friendmove_ack.pos2, n+1); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); return 0; } return 0; } if (strstart(text,"list")==0 || strstart(text,"l")==0) { char const * friend; char status[128]; char software[64]; char msgtemp[MAX_MESSAGE_LEN]; t_connection * dest_c; t_account * friend_acc; t_game const * game; t_channel const * channel; t_friend * fr; t_list * flist; int num; unsigned int uid; message_send_text(c,message_type_info,c,"Your PvPGN - Friends List"); message_send_text(c,message_type_info,c,"=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); num = account_get_friendcount(my_acc); flist=account_get_friends(my_acc); if(flist!=NULL) { for (i=0;i "); return 0; } do_whisper(c,dest,&text[i]); return 0; } static int _handle_status_command(t_connection * c, char const *text) { char ctag[5]; unsigned int i,j; t_clienttag clienttag; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get clienttag */ if (j"); return 0; } if (!(channel = channellist_find_channel_by_name(&text[i],conn_get_country(c),realm_get_name(conn_get_realm(c))))) { message_send_text(c,message_type_error,c,"That channel does not exist."); message_send_text(c,message_type_error,c,"(If you are trying to search for a user, use the /whois command.)"); return 0; } if (channel_check_banning(channel,c)==1) { message_send_text(c,message_type_error,c,"You are banned from that channel."); return 0; } snprintf(msgtemp, sizeof(msgtemp), "Users in channel %.64s:",&text[i]); i = strlen(msgtemp); for (conn=channel_get_first(channel); conn; conn=channel_get_next()) { if (i+strlen((tname = conn_get_username(conn)))+2>sizeof(msgtemp)) /* " ", name, '\0' */ { message_send_text(c,message_type_info,c,msgtemp); i = 0; } sprintf(&msgtemp[i]," %s",tname); i += strlen(&msgtemp[i]); } if (i>0) message_send_text(c,message_type_info,c,msgtemp); return 0; } static int _handle_whois_command(t_connection * c, char const * text) { unsigned int i; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='\0') { message_send_text(c,message_type_info,c,"usage: /whois "); return 0; } do_whois(c,&text[i]); return 0; } static int _handle_whoami_command(t_connection * c, char const *text) { char const * tname; if (!(tname = conn_get_username(c))) { message_send_text(c,message_type_error,c,"Unable to obtain your account name."); return 0; } do_whois(c,tname); return 0; } static int _handle_announce_command(t_connection * c, char const *text) { unsigned int i; t_message * message; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='\0') { message_send_text(c,message_type_info,c,"usage: /announce "); return 0; } snprintf(msgtemp, sizeof(msgtemp), "Announcement from %.64s: %.128s",conn_get_username(c),&text[i]); if (!(message = message_create(message_type_broadcast,c,NULL,msgtemp))) message_send_text(c,message_type_info,c,"Could not broadcast message."); else { if (message_send_all(message)<0) message_send_text(c,message_type_info,c,"Could not broadcast message."); message_destroy(message); } return 0; } static int _handle_beep_command(t_connection * c, char const *text) { message_send_text(c,message_type_info,c,"Audible notification on."); /* FIXME: actually do something */ return 0; /* FIXME: these only affect CHAT clients... I think they prevent ^G from being sent */ } static int _handle_nobeep_command(t_connection * c, char const *text) { message_send_text(c,message_type_info,c,"Audible notification off."); /* FIXME: actually do something */ return 0; } static int _handle_version_command(t_connection * c, char const *text) { message_send_text(c,message_type_info,c,PVPGN_SOFTWARE" "PVPGN_VERSION); return 0; } static int _handle_copyright_command(t_connection * c, char const *text) { static char const * const info[] = { " Copyright (C) 2002 See source for details", " ", " PvPGN is free software; you can redistribute it and/or", " modify it under the terms of the GNU General Public License", " as published by the Free Software Foundation; either version 2", " of the License, or (at your option) any later version.", " ", " This program is distributed in the hope that it will be useful,", " but WITHOUT ANY WARRANTY; without even the implied warranty of", " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the", " GNU General Public License for more details.", " ", " You should have received a copy of the GNU General Public License", " along with this program; if not, write to the Free Software", " Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.", NULL }; unsigned int i; for (i=0; info[i]; i++) message_send_text(c,message_type_info,c,info[i]); return 0; } static int _handle_uptime_command(t_connection * c, char const *text) { snprintf(msgtemp, sizeof(msgtemp), "Uptime: %.128s",seconds_to_timestr(server_get_uptime())); message_send_text(c,message_type_info,c,msgtemp); return 0; } static int _handle_stats_command(t_connection * c, char const *text) { char dest[USER_NAME_MAX]; unsigned int i,j; t_account * account; char const * clienttag=NULL; t_clienttag clienttag_uint; char clienttag_str[5]; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */ if (j0) snprintf(msgtemp, sizeof(msgtemp), "Ladder games: %u-%u-%u (rating %d)", account_get_ladder_wins(account,clienttag_uint,ladder_id_normal), account_get_ladder_losses(account,clienttag_uint,ladder_id_normal), account_get_ladder_disconnects(account,clienttag_uint,ladder_id_normal), account_get_ladder_rating(account,clienttag_uint,ladder_id_normal)); else strcpy(msgtemp,"Ladder games: 0-0-0"); message_send_text(c,message_type_info,c,msgtemp); if (account_get_ladder_rating(account,clienttag_uint,ladder_id_ironman)>0) snprintf(msgtemp, sizeof(msgtemp), "IronMan games: %u-%u-%u (rating %d)", account_get_ladder_wins(account,clienttag_uint,ladder_id_ironman), account_get_ladder_losses(account,clienttag_uint,ladder_id_ironman), account_get_ladder_disconnects(account,clienttag_uint,ladder_id_ironman), account_get_ladder_rating(account,clienttag_uint,ladder_id_ironman)); else strcpy(msgtemp,"IronMan games: 0-0-0"); message_send_text(c,message_type_info,c,msgtemp); return 0; case CLIENTTAG_WARCRAFT3_UINT: case CLIENTTAG_WAR3XP_UINT: snprintf(msgtemp, sizeof(msgtemp), "%.64s's Ladder Record's:",account_get_name(account)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Users Solo Level: %u, Experience: %u", account_get_ladder_level(account,clienttag_uint,ladder_id_solo), account_get_ladder_xp(account,clienttag_uint,ladder_id_solo)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "SOLO Ladder Record: %u-%u-0", account_get_ladder_wins(account,clienttag_uint,ladder_id_solo), account_get_ladder_losses(account,clienttag_uint,ladder_id_solo)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "SOLO Rank: %u", account_get_ladder_rank(account,clienttag_uint,ladder_id_solo)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Users Team Level: %u, Experience: %u", account_get_ladder_level(account,clienttag_uint,ladder_id_team), account_get_ladder_xp(account,clienttag_uint,ladder_id_team)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "TEAM Ladder Record: %u-%u-0", account_get_ladder_wins(account,clienttag_uint,ladder_id_team), account_get_ladder_losses(account,clienttag_uint,ladder_id_team)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "TEAM Rank: %u", account_get_ladder_rank(account,clienttag_uint,ladder_id_team)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Users FFA Level: %u, Experience: %u", account_get_ladder_level(account,clienttag_uint,ladder_id_ffa), account_get_ladder_xp(account,clienttag_uint,ladder_id_ffa)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "FFA Ladder Record: %u-%u-0", account_get_ladder_wins(account,clienttag_uint,ladder_id_ffa), account_get_ladder_losses(account,clienttag_uint,ladder_id_ffa)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "FFA Rank: %u", account_get_ladder_rank(account,clienttag_uint,ladder_id_ffa)); message_send_text(c,message_type_info,c,msgtemp); if (account_get_teams(account)) { t_elem * curr; t_list * list; t_team * team; int teamcount = 0; list = account_get_teams(account); LIST_TRAVERSE(list,curr) { if (!(team = elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } if (team_get_clienttag(team) != clienttag_uint) continue; teamcount++; snprintf(msgtemp, sizeof(msgtemp), "Users AT Team No. %u",teamcount); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Users AT TEAM Level: %u, Experience: %u", team_get_level(team),team_get_xp(team)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "AT TEAM Ladder Record: %u-%u-0", team_get_wins(team),team_get_losses(team)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "AT TEAM Rank: %u", team_get_rank(team)); message_send_text(c,message_type_info,c,msgtemp); } } return 0; default: snprintf(msgtemp, sizeof(msgtemp), "%.64s's record:",account_get_name(account)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Normal games: %u-%u-%u", account_get_normal_wins(account,clienttag_uint), account_get_normal_losses(account,clienttag_uint), account_get_normal_disconnects(account,clienttag_uint)); message_send_text(c,message_type_info,c,msgtemp); if (account_get_ladder_rating(account,clienttag_uint,ladder_id_normal)>0) snprintf(msgtemp, sizeof(msgtemp), "Ladder games: %u-%u-%u (rating %d)", account_get_ladder_wins(account,clienttag_uint,ladder_id_normal), account_get_ladder_losses(account,clienttag_uint,ladder_id_normal), account_get_ladder_disconnects(account,clienttag_uint,ladder_id_normal), account_get_ladder_rating(account,clienttag_uint,ladder_id_normal)); else strcpy(msgtemp,"Ladder games: 0-0-0"); message_send_text(c,message_type_info,c,msgtemp); return 0; } } static int _handle_time_command(t_connection * c, char const *text) { t_bnettime btsystem; t_bnettime btlocal; time_t now; struct tm * tmnow; btsystem = bnettime(); /* Battle.net time: Wed Jun 23 15:15:29 */ btlocal = bnettime_add_tzbias(btsystem,local_tzbias()); now = bnettime_to_time(btlocal); if (!(tmnow = gmtime(&now))) strcpy(msgtemp,"PvPGN Server Time: ?"); else strftime(msgtemp,sizeof(msgtemp),"PvPGN Server Time: %a %b %d %H:%M:%S",tmnow); message_send_text(c,message_type_info,c,msgtemp); if (conn_get_class(c)==conn_class_bnet) { btlocal = bnettime_add_tzbias(btsystem,conn_get_tzbias(c)); now = bnettime_to_time(btlocal); if (!(tmnow = gmtime(&now))) strcpy(msgtemp,"Your local time: ?"); else strftime(msgtemp,sizeof(msgtemp),"Your local time: %a %b %d %H:%M:%S",tmnow); message_send_text(c,message_type_info,c,msgtemp); } return 0; } static int _handle_channel_command(t_connection * c, char const *text) { t_channel * channel; text = skip_command(text); if (conn_get_wol(c)) { message_send_text(c,message_type_error,c,"Sorry, this command is currently disabled for WOL clients."); return 0; } if (text[0]=='\0') { message_send_text(c,message_type_info,c,"usage /channel "); return 0; } if(strcasecmp(text,"Arranged Teams")==0) { // if(account_get_auth_admin(conn_get_account(c))>0) // { // message_send_text(c,message_type_error,c,"Please do not talk in channel Arranged Teams"); // message_send_text(c,message_type_error,c,"This channel is dedicated for the preparation of"); // message_send_text(c,message_type_error,c,"Arranged Team Games."); // } // else // { message_send_text(c,message_type_error,c,"Channel Arranged Teams is a RESTRICTED Channel!"); return 0; // } } if (!(strlen(text) < CHANNEL_NAME_LEN)) { snprintf(msgtemp, sizeof(msgtemp), "max channel name length exceeded (max %d symbols)", CHANNEL_NAME_LEN - 1); message_send_text(c,message_type_error,c,msgtemp); return 0; } if ((channel = conn_get_channel(c)) && (strcasecmp(channel_get_name(channel),text)==0)) return 0; // we don't have to do anything, we are allready in this channel if (conn_set_channel(c,text)<0) conn_set_channel(c,CHANNEL_NAME_BANNED); /* should not fail */ if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT)) conn_update_w3_playerinfo(c); command_set_flags(c); return 0; } static int _handle_rejoin_command(t_connection * c, char const *text) { if (channel_rejoin(c)!=0) message_send_text(c,message_type_error,c,"You are not in a channel."); if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT)) conn_update_w3_playerinfo(c); command_set_flags(c); return 0; } static int _handle_away_command(t_connection * c, char const *text) { text = skip_command(text); if (text[0]=='\0') /* toggle away mode */ { if (!conn_get_awaystr(c)) { message_send_text(c,message_type_info,c,"You are now marked as being away."); conn_set_awaystr(c,"Currently not available"); } else { message_send_text(c,message_type_info,c,"You are no longer marked as away."); conn_set_awaystr(c,NULL); } } else { message_send_text(c,message_type_info,c,"You are now marked as being away."); conn_set_awaystr(c,text); } return 0; } static int _handle_dnd_command(t_connection * c, char const *text) { text = skip_command(text); if (text[0]=='\0') /* toggle dnd mode */ { if (!conn_get_dndstr(c)) { message_send_text(c,message_type_info,c,"Do Not Disturb mode engaged."); conn_set_dndstr(c,"Not available"); } else { message_send_text(c,message_type_info,c,"Do Not Disturb mode cancelled."); conn_set_dndstr(c,NULL); } } else { message_send_text(c,message_type_info,c,"Do Not Disturb mode engaged."); conn_set_dndstr(c,text); } return 0; } static int _handle_squelch_command(t_connection * c, char const *text) { t_account * account; text = skip_command(text); /* D2 puts * before username */ if (text[0]=='*') text++; if (text[0]=='\0') { message_send_text(c,message_type_info,c,"usage: /squelch "); return 0; } if (!(account = accountlist_find_account(text))) { message_send_text(c,message_type_error,c,"No such user."); return 0; } if (conn_get_account(c)==account) { message_send_text(c,message_type_error,c,"You can't squelch yourself."); return 0; } if (conn_add_ignore(c,account)<0) message_send_text(c,message_type_error,c,"Could not squelch user."); else { snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been squelched.",account_get_name(account)); message_send_text(c,message_type_info,c,msgtemp); } return 0; } static int _handle_unsquelch_command(t_connection * c, char const *text) { t_account * account; t_connection * dest_c; text = skip_command(text); /* D2 puts * before username */ if (text[0]=='*') text++; if (text[0]=='\0') { message_send_text(c,message_type_info,c,"usage: /unsquelch "); return 0; } if (!(account = accountlist_find_account(text))) { message_send_text(c,message_type_info,c,"No such user."); return 0; } if (conn_del_ignore(c,account)<0) message_send_text(c,message_type_info,c,"User was not being ignored."); else { t_message * message; message_send_text(c,message_type_info,c,"No longer ignoring."); if ((dest_c = account_get_conn(account))) { if (!(message = message_create(message_type_userflags,dest_c,NULL,NULL))) /* handles NULL text */ return 0; message_send(message,c); message_destroy(message); } } return 0; } static int _handle_kick_command(t_connection * c, char const *text) { char dest[USER_NAME_MAX]; unsigned int i,j; t_channel const * channel; t_connection * kuc; t_account * acc; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */ if (j"); return 0; } if (!(channel = conn_get_channel(c))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return 0; } acc = conn_get_account(c); if (account_get_auth_admin(acc,NULL)!=1 && /* default to false */ account_get_auth_admin(acc,channel_get_name(channel))!=1 && /* default to false */ account_get_auth_operator(acc,NULL)!=1 && /* default to false */ account_get_auth_operator(acc,channel_get_name(channel))!=1 && /* default to false */ !channel_conn_is_tmpOP(channel,account_get_conn(acc))) { message_send_text(c,message_type_error,c,"You have to be at least a Channel Operator or tempOP to use this command."); return 0; } if (!(kuc = connlist_find_connection_by_accountname(dest))) { message_send_text(c,message_type_error,c,"That user is not logged in."); return 0; } if (conn_get_channel(kuc)!=channel) { message_send_text(c,message_type_error,c,"That user is not in this channel."); return 0; } if (account_get_auth_admin(conn_get_account(kuc),NULL)==1 || account_get_auth_admin(conn_get_account(kuc),channel_get_name(channel))==1) { message_send_text(c,message_type_error,c,"You cannot kick administrators."); return 0; } else if (account_get_auth_operator(conn_get_account(kuc),NULL)==1 || account_get_auth_operator(conn_get_account(kuc),channel_get_name(channel))==1) { message_send_text(c,message_type_error,c,"You cannot kick operators."); return 0; } { char const * tname1; char const * tname2; tname1 = conn_get_loggeduser(kuc); tname2 = conn_get_loggeduser(c); if (!tname1 || !tname2) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL username"); return -1; } if (text[i]!='\0') snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been kicked by %-.20s (%.128s).",tname1,tname2,&text[i]); else snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been kicked by %-.20s.",tname1,tname2); channel_message_send(channel,message_type_info,c,msgtemp); } conn_set_channel(kuc,CHANNEL_NAME_KICKED); /* should not fail */ return 0; } static int _handle_ban_command(t_connection * c, char const *text) { char dest[USER_NAME_MAX]; unsigned int i,j; t_channel * channel; t_connection * buc; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */ if (j"); return 0; } if (!(channel = conn_get_channel(c))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return 0; } if (account_get_auth_admin(conn_get_account(c),NULL)!=1 && /* default to false */ account_get_auth_admin(conn_get_account(c),channel_get_name(channel))!=1 && /* default to false */ account_get_auth_operator(conn_get_account(c),NULL)!=1 && /* default to false */ account_get_auth_operator(conn_get_account(c),channel_get_name(channel))!=1) /* default to false */ { message_send_text(c,message_type_error,c,"You have to be at least a Channel Operator to use this command."); return 0; } { t_account * account; if (!(account = accountlist_find_account(dest))) message_send_text(c,message_type_info,c,"That account doesn't currently exist, banning anyway."); else if (account_get_auth_admin(account,NULL)==1 || account_get_auth_admin(account,channel_get_name(channel))==1) { message_send_text(c,message_type_error,c,"You cannot ban administrators."); return 0; } else if (account_get_auth_operator(account,NULL)==1 || account_get_auth_operator(account,channel_get_name(channel))==1) { message_send_text(c,message_type_error,c,"You cannot ban operators."); return 0; } } if (channel_ban_user(channel,dest)<0) { snprintf(msgtemp, sizeof(msgtemp), "Unable to ban %-.20s.",dest); message_send_text(c,message_type_error,c,msgtemp); } else { char const * tname; tname = conn_get_loggeduser(c); if (text[i]!='\0') snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been banned by %-.20s (%.128s).",dest,tname?tname:"unknown",&text[i]); else snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been banned by %-.20s.",dest,tname?tname:"unknown"); channel_message_send(channel,message_type_info,c,msgtemp); } if ((buc = connlist_find_connection_by_accountname(dest)) && conn_get_channel(buc)==channel) conn_set_channel(buc,CHANNEL_NAME_BANNED); return 0; } static int _handle_unban_command(t_connection * c, char const *text) { t_channel * channel; unsigned int i; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='\0') { message_send_text(c,message_type_info,c,"usage: /unban "); return 0; } if (!(channel = conn_get_channel(c))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return 0; } if (account_get_auth_admin(conn_get_account(c),NULL)!=1 && /* default to false */ account_get_auth_admin(conn_get_account(c),channel_get_name(channel))!=1 && /* default to false */ account_get_auth_operator(conn_get_account(c),NULL)!=1 && /* default to false */ account_get_auth_operator(conn_get_account(c),channel_get_name(channel))!=1) /* default to false */ { message_send_text(c,message_type_error,c,"You are not a channel operator."); return 0; } if (channel_unban_user(channel,&text[i])<0) message_send_text(c,message_type_error,c,"That user is not banned."); else { snprintf(msgtemp, sizeof(msgtemp), "%.64s is no longer banned from this channel.",&text[i]); message_send_text(c,message_type_info,c,msgtemp); } return 0; } static int _handle_reply_command(t_connection * c, char const *text) { unsigned int i; char const * dest; if (!(dest = conn_get_lastsender(c))) { message_send_text(c,message_type_error,c,"No one messaged you, use /m instead"); return 0; } for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='\0') { message_send_text(c,message_type_info,c,"usage: /reply "); return 0; } do_whisper(c,dest,&text[i]); return 0; } static int _handle_realmann_command(t_connection * c, char const *text) { unsigned int i; t_realm * realm; t_realm * trealm; t_connection * tc; t_elem const * curr; t_message * message; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (!(realm=conn_get_realm(c))) { message_send_text(c,message_type_info,c,"You must join a realm first"); return 0; } if (text[i]=='\0') { message_send_text(c,message_type_info,c,"usage: /realmann "); return 0; } snprintf(msgtemp, sizeof(msgtemp), "Announcement from %.32s@%.32s: %.128s",conn_get_username(c),realm_get_name(realm),&text[i]); if (!(message = message_create(message_type_broadcast,c,NULL,msgtemp))) { message_send_text(c,message_type_info,c,"Could not broadcast message."); } else { LIST_TRAVERSE_CONST(connlist(),curr) { tc = elem_get_data(curr); if (!tc) continue; if ((trealm = conn_get_realm(tc)) && (trealm==realm)) { message_send(message,tc); } } } return 0; } static int _handle_watch_command(t_connection * c, char const *text) { unsigned int i; t_account * account; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='\0') { message_send_text(c,message_type_info,c,"usage: /watch "); return 0; } if (!(account = accountlist_find_account(&text[i]))) { message_send_text(c,message_type_info,c,"That user does not exist."); return 0; } if (conn_add_watch(c,account,0)<0) /* FIXME: adds all events for now */ message_send_text(c,message_type_error,c,"Add to watch list failed."); else { snprintf(msgtemp, sizeof(msgtemp), "User %.64s added to your watch list.",&text[i]); message_send_text(c,message_type_info,c,msgtemp); } return 0; } static int _handle_unwatch_command(t_connection * c, char const *text) { unsigned int i; t_account * account; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='\0') { message_send_text(c,message_type_info,c,"usage: /unwatch "); return 0; } if (!(account = accountlist_find_account(&text[i]))) { message_send_text(c,message_type_info,c,"That user does not exist."); return 0; } if (conn_del_watch(c,account,0)<0) /* FIXME: deletes all events for now */ message_send_text(c,message_type_error,c,"Removal from watch list failed."); else { snprintf(msgtemp, sizeof(msgtemp), "User %.64s removed from your watch list.",&text[i]); message_send_text(c,message_type_info,c,msgtemp); } return 0; } static int _handle_watchall_command(t_connection * c, char const *text) { t_clienttag clienttag=0; char clienttag_str[5]; text = skip_command(text); if(text[0] != '\0') { if (strlen(text) != 4) { message_send_text(c,message_type_error,c,"You must supply a rank and a valid program ID."); message_send_text(c,message_type_error,c,"Example: /watchall STAR"); return 0; } clienttag = tag_case_str_to_uint(text); } if (conn_add_watch(c,NULL,clienttag)<0) /* FIXME: adds all events for now */ message_send_text(c,message_type_error,c,"Add to watch list failed."); else if(clienttag) { char msgtemp[MAX_MESSAGE_LEN]; snprintf(msgtemp, sizeof(msgtemp), "All %.128s users added to your watch list.", tag_uint_to_str(clienttag_str,clienttag)); message_send_text(c,message_type_info,c,msgtemp); } else message_send_text(c,message_type_info,c,"All users added to your watch list."); return 0; } static int _handle_unwatchall_command(t_connection * c, char const *text) { t_clienttag clienttag=0; char clienttag_str[5]; text = skip_command(text); if(text[0] != '\0') { if (strlen(text) != 4) { message_send_text(c,message_type_error,c,"You must supply a rank and a valid program ID."); message_send_text(c,message_type_error,c,"Example: /unwatchall STAR"); } clienttag = tag_case_str_to_uint(text); } if (conn_del_watch(c,NULL,clienttag)<0) /* FIXME: deletes all events for now */ message_send_text(c,message_type_error,c,"Removal from watch list failed."); else if(clienttag) { char msgtemp[MAX_MESSAGE_LEN]; snprintf(msgtemp, sizeof(msgtemp), "All %.128s users removed from your watch list.", tag_uint_to_str(clienttag_str,clienttag)); message_send_text(c,message_type_info,c,msgtemp); } else message_send_text(c,message_type_info,c,"All users removed from your watch list."); return 0; } static int _handle_lusers_command(t_connection * c, char const *text) { t_channel * channel; t_elem const * curr; char const * banned; unsigned int i; if (!(channel = conn_get_channel(c))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return 0; } strcpy(msgtemp,"Banned users:"); i = strlen(msgtemp); LIST_TRAVERSE_CONST(channel_get_banlist(channel),curr) { banned = elem_get_data(curr); if (i+strlen(banned)+2>sizeof(msgtemp)) /* " ", name, '\0' */ { message_send_text(c,message_type_info,c,msgtemp); i = 0; } sprintf(&msgtemp[i]," %s",banned); i += strlen(&msgtemp[i]); } if (i>0) message_send_text(c,message_type_info,c,msgtemp); return 0; } static int _news_cb(time_t date, t_lstr *lstr, void *data) { char strdate[64]; struct tm *tm; char save, *p, *q; t_connection *c = (t_connection*)data; tm = localtime(&date); if (tm) strftime(strdate, 64,"%B %d, %Y", tm); else strcpy(strdate, "(invalid date)"); message_send_text(c,message_type_info,c,strdate); for (p = lstr_get_str(lstr); *p;) { for(q = p; *q && *q != '\r' && *q != '\n';q++); save = *q; *q = '\0'; message_send_text(c,message_type_info,c,p); *q = save; p = q; for(;*p == '\n' || *p == '\r';p++); } return 0; } static int _handle_news_command(t_connection * c, char const *text) { news_traverse(_news_cb,c); return 0; } struct glist_cb_struct { t_game_difficulty diff; t_clienttag tag; t_connection *c; }; static int _glist_cb(t_game *game, void *data) { struct glist_cb_struct *cbdata = (struct glist_cb_struct*)data; if ((!cbdata->tag || !prefs_get_hide_pass_games() || game_get_flag(game) != game_flag_private) && (!cbdata->tag || game_get_clienttag(game)==cbdata->tag) && (cbdata->diff==game_difficulty_none || game_get_difficulty(game)==cbdata->diff)) { snprintf(msgtemp, sizeof(msgtemp), " %-16.16s %1.1s %-8.8s %-21.21s %5u ", game_get_name(game), game_get_flag(game) != game_flag_private ? "n":"y", game_status_get_str(game_get_status(game)), game_type_get_str(game_get_type(game)), game_get_ref(game)); if (!cbdata->tag) { strcat(msgtemp,clienttag_uint_to_str(game_get_clienttag(game))); strcat(msgtemp," "); } if ((!prefs_get_hide_addr()) || (account_get_command_groups(conn_get_account(cbdata->c)) & command_get_group("/admin-addr"))) /* default to false */ strcat(msgtemp, addr_num_to_addr_str(game_get_addr(game),game_get_port(game))); message_send_text(cbdata->c,message_type_info,cbdata->c,msgtemp); } return 0; } static int _handle_games_command(t_connection * c, char const *text) { unsigned int i; unsigned int j; char clienttag_str[5]; char dest[5]; struct glist_cb_struct cbdata; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */ if (j= MAX_MESSAGE_LEN) break; if (!first) strcat(msgtemp," ,"); strcat(msgtemp,name); if (account_get_auth_admin(acc,NULL)==1) strcat(msgtemp,"(A)"); else if (account_get_auth_operator(acc,NULL)==1) strcat(msgtemp,"(O)"); else if (account_get_auth_admin(acc,channel_get_name(channel))==1) strcat(msgtemp,"(a)"); else if (account_get_auth_operator(acc,channel_get_name(channel))==1) strcat(msgtemp,"(o)"); first = 0; } } message_send_text(c,message_type_info,c,msgtemp); } } return 0; } static int _handle_addacct_command(t_connection * c, char const *text) { unsigned int i,j; t_account * temp; t_hash passhash; char username[USER_NAME_MAX]; char pass[256]; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get username */ if (j "); return 0; } if (account_check_name(username)<0) { message_send_text(c,message_type_error,c,"Account name contains some invalid symbol!"); return 0; } /* FIXME: truncate or err on too long password */ for (i=0; i"); return 0; } temp = accountlist_find_account(username); account = conn_get_account(c); if ((temp==account && account_get_auth_changepass(account)==0) || /* default to true */ (temp!=account && !(account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-chpass")))) /* default to false */ { eventlog(eventlog_level_info,__FUNCTION__,"[%d] password change for \"%s\" refused (no change access)",conn_get_socket(c),username); message_send_text(c,message_type_error,c,"Only admins may change passwords for other accounts."); return 0; } if (!temp) { message_send_text(c,message_type_error,c,"Account does not exist."); return 0; } if (strlen(pass) > USER_PASS_MAX) { snprintf(msgtemp, sizeof(msgtemp), "Maximum password length allowed is %d",USER_PASS_MAX); message_send_text(c,message_type_error,c,msgtemp); return 0; } for (i=0; i"); return 0; } if (!(account = accountlist_find_account(dest))) { message_send_text(c,message_type_error,c,"Invalid user."); return 0; } snprintf(msgtemp, sizeof(msgtemp), "Login: %-16.16s "UID_FORMAT" Sex: %.14s", account_get_name(account), account_get_uid(account), account_get_sex(account)); message_send_text(c,message_type_info,c,msgtemp); if ((clanmemb = account_get_clanmember(account))) { t_clan * clan; char status; if ((clan = clanmember_get_clan(clanmemb))) { snprintf(msgtemp, sizeof(msgtemp), "Clan : %-64.64s",clan_get_name(clan)); if ((status = clanmember_get_status(clanmemb))) { switch (status) { case CLAN_CHIEFTAIN: strcat(msgtemp," Rank: Chieftain"); break; case CLAN_SHAMAN: strcat(msgtemp," Rank: Shaman"); break; case CLAN_GRUNT: strcat(msgtemp," Rank: Grunt"); break; case CLAN_PEON: strcat(msgtemp," Rank: Peon"); break; default:; } } message_send_text(c,message_type_info,c,msgtemp); } } snprintf(msgtemp, sizeof(msgtemp), "Location: %-23.23s Age: %.14s", account_get_loc(account), account_get_age(account)); message_send_text(c,message_type_info,c,msgtemp); if((conn = connlist_find_connection_by_accountname(dest))) { snprintf(msgtemp, sizeof(msgtemp), "Client: %s Ver: %s Country: %s", clienttag_get_title(conn_get_clienttag(conn)), conn_get_clientver(conn), conn_get_country(conn)); message_send_text(c,message_type_info,c,msgtemp); } if (!(ip=account_get_ll_ip(account)) || !(account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr"))) /* default to false */ ip = "unknown"; { time_t then; struct tm * tmthen; then = account_get_ll_time(account); tmthen = localtime(&then); /* FIXME: determine user's timezone */ if (!(conn)) if (tmthen) strftime(msgtemp,sizeof(msgtemp),"Last login %a %b %d %H:%M %Y from ",tmthen); else strcpy(msgtemp,"Last login ? from "); else if (tmthen) strftime(msgtemp,sizeof(msgtemp),"On since %a %b %d %H:%M %Y from ",tmthen); else strcpy(msgtemp,"On since ? from "); } strncat(msgtemp,ip,32); message_send_text(c,message_type_info,c,msgtemp); /* check /admin-addr for admin privileges */ if ( (account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr"))) { /* the player who requested /finger has admin privileges give him more info about the one he querys; is_admin, is_operator, is_locked, email */ snprintf(msgtemp, sizeof(msgtemp), "email:%.128s , is_operator: %d , is_admin: %d , is_acc_locked: %d", account_get_email(account), account_get_auth_operator(account,NULL), account_get_auth_admin(account,NULL), account_get_auth_lock(account)); message_send_text(c,message_type_info,c,msgtemp); } if (conn) { snprintf(msgtemp, sizeof(msgtemp), "Idle %.128s",seconds_to_timestr(conn_get_idletime(conn))); message_send_text(c,message_type_info,c,msgtemp); } strncpy(msgtemp,account_get_desc(account),sizeof(msgtemp)); msgtemp[sizeof(msgtemp)-1] = '\0'; for (tok=strtok(msgtemp,"\r\n"); tok; tok=strtok(NULL,"\r\n")) message_send_text(c,message_type_info,c,tok); message_send_text(c,message_type_info,c,""); return 0; } /* * rewrote command /operator to add and remove operator status [Omega] * * Fixme: rewrite /operators to show Currently logged on Server and/or Channel operators ...?? */ /* static int _handle_operator_command(t_connection * c, char const *text) { t_connection const * opr; t_channel const * channel; if (!(channel = conn_get_channel(c))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return 0; } if (!(opr = channel_get_operator(channel))) strcpy(msgtemp,"There is no operator."); else snprintf(msgtemp, sizeof(msgtemp), "%.64s is the operator.",conn_get_username(opr)); message_send_text(c,message_type_info,c,msgtemp); return 0; } */ /* FIXME: do we want to show just Server Admin or Channel Admin Also? [Omega] */ static int _handle_admins_command(t_connection * c, char const *text) { unsigned int i; t_elem const * curr; t_connection * tc; char const * nick; strcpy(msgtemp,"Currently logged on Administrators:"); i = strlen(msgtemp); LIST_TRAVERSE_CONST(connlist(),curr) { tc = elem_get_data(curr); if (!tc) continue; if (!conn_get_account(tc)) continue; if (account_get_auth_admin(conn_get_account(tc),NULL)==1) { if ((nick = conn_get_username(tc))) { if (i+strlen(nick)+2>sizeof(msgtemp)) /* " ", name, '\0' */ { message_send_text(c,message_type_info,c,msgtemp); i = 0; } sprintf(&msgtemp[i]," %s", nick); i += strlen(&msgtemp[i]); } } } if (i>0) message_send_text(c,message_type_info,c,msgtemp); return 0; } static int _handle_quit_command(t_connection * c, char const *text) { if (conn_get_game(c)) eventlog(eventlog_level_warn, __FUNCTION__,"[%d] user '%s' tried to disconnect while in game, cheat attempt ?", conn_get_socket(c), conn_get_loggeduser(c)); else { message_send_text(c,message_type_info,c,"Connection closed."); conn_set_state(c,conn_state_destroy); } return 0; } static int _handle_kill_command(t_connection * c, char const *text) { unsigned int i,j; t_connection * user; char usrnick[USER_NAME_MAX]; /* max length of nick + \0 */ /* FIXME: Is it somewhere defined? */ for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get nick */ if (j '9'))) { message_send_text(c,message_type_info,c,"usage: /kill {|#} []"); return 0; } if (usrnick[0] == '#') { if (!(user = connlist_find_connection_by_socket(atoi(usrnick + 1)))) { message_send_text(c,message_type_error,c,"That connection doesnt exist."); return 0; } } else { if (!(user = connlist_find_connection_by_accountname(usrnick))) { message_send_text(c,message_type_error,c,"That user is not logged in?"); return 0; } } if (text[i]!='\0' && ipbanlist_add(c,addr_num_to_ip_str(conn_get_addr(user)),ipbanlist_str_to_time_t(c,&text[i]))==0) { ipbanlist_save(prefs_get_ipbanfile()); message_send_text(user,message_type_info,user,"Connection closed by admin and banned your ip."); } else message_send_text(user,message_type_info,user,"Connection closed by admin."); conn_set_state(user,conn_state_destroy); message_send_text(c,message_type_info,c,"Operation successful."); return 0; } static int _handle_killsession_command(t_connection * c, char const *text) { unsigned int i,j; t_connection * user; char session[16]; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get nick */ if (j [min]"); return 0; } if (!isxdigit((int)session[0])) { message_send_text(c,message_type_error,c,"That is not a valid session."); return 0; } if (!(user = connlist_find_connection_by_sessionkey((unsigned int)strtoul(session,NULL,16)))) { message_send_text(c,message_type_error,c,"That session does not exist."); return 0; } if (text[i]!='\0' && ipbanlist_add(c,addr_num_to_ip_str(conn_get_addr(user)),ipbanlist_str_to_time_t(c,&text[i]))==0) { ipbanlist_save(prefs_get_ipbanfile()); message_send_text(user,message_type_info,user,"Connection closed by admin and banned your ip's."); } else message_send_text(user,message_type_info,user,"Connection closed by admin."); conn_set_state(user,conn_state_destroy); return 0; } static int _handle_gameinfo_command(t_connection * c, char const *text) { unsigned int i; t_game const * game; char clienttag_str[5]; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='\0') { if (!(game = conn_get_game(c))) { message_send_text(c,message_type_error,c,"You are not in a game."); return 0; } } else if (!(game = gamelist_find_game(&text[i],conn_get_clienttag(c),game_type_all))) { message_send_text(c,message_type_error,c,"That game does not exist."); return 0; } snprintf(msgtemp, sizeof(msgtemp), "Name: %-20.20s ID: "GAMEID_FORMAT" (%s)",game_get_name(game),game_get_id(game),game_get_flag(game) != game_flag_private ? "public":"private"); message_send_text(c,message_type_info,c,msgtemp); { t_account * owner; char const * tname; char const * namestr; if (!(owner = conn_get_account(game_get_owner(game)))) { tname = NULL; namestr = "none"; } else if (!(tname = conn_get_loggeduser(game_get_owner(game)))) namestr = "unknown"; else namestr = tname; snprintf(msgtemp, sizeof(msgtemp), "Owner: %-20.20s",namestr); } message_send_text(c,message_type_info,c,msgtemp); if (!prefs_get_hide_addr() || (account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr"))) /* default to false */ { unsigned int addr; unsigned short port; unsigned int taddr; unsigned short tport; taddr=addr = game_get_addr(game); tport=port = game_get_port(game); trans_net(conn_get_addr(c),&taddr,&tport); if (taddr==addr && tport==port) snprintf(msgtemp, sizeof(msgtemp), "Address: %.64s", addr_num_to_addr_str(addr,port)); else snprintf(msgtemp, sizeof(msgtemp), "Address: %.64s (trans %.64s)", addr_num_to_addr_str(addr,port), addr_num_to_addr_str(taddr,tport)); message_send_text(c,message_type_info,c,msgtemp); } snprintf(msgtemp, sizeof(msgtemp), "Client: %4s (version %.64s, startver %u)",tag_uint_to_str(clienttag_str,game_get_clienttag(game)),vernum_to_verstr(game_get_version(game)),game_get_startver(game)); message_send_text(c,message_type_info,c,msgtemp); { time_t gametime; struct tm * gmgametime; gametime = game_get_create_time(game); if (!(gmgametime = localtime(&gametime))) strcpy(msgtemp,"Created: ?"); else strftime(msgtemp,sizeof(msgtemp),"Created: "GAME_TIME_FORMAT,gmgametime); message_send_text(c,message_type_info,c,msgtemp); gametime = game_get_start_time(game); if (gametime!=(time_t)0) { if (!(gmgametime = localtime(&gametime))) strcpy(msgtemp,"Started: ?"); else strftime(msgtemp,sizeof(msgtemp),"Started: "GAME_TIME_FORMAT,gmgametime); } else strcpy(msgtemp,"Started: "); message_send_text(c,message_type_info,c,msgtemp); } snprintf(msgtemp, sizeof(msgtemp), "Status: %.64s",game_status_get_str(game_get_status(game))); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Type: %-20.20s",game_type_get_str(game_get_type(game))); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Speed: %.64s",game_speed_get_str(game_get_speed(game))); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Difficulty: %.64s",game_difficulty_get_str(game_get_difficulty(game))); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Option: %.64s",game_option_get_str(game_get_option(game))); message_send_text(c,message_type_info,c,msgtemp); { char const * mapname; if (!(mapname = game_get_mapname(game))) mapname = "unknown"; snprintf(msgtemp, sizeof(msgtemp), "Map: %-20.20s",mapname); message_send_text(c,message_type_info,c,msgtemp); } snprintf(msgtemp, sizeof(msgtemp), "Map Size: %ux%u",game_get_mapsize_x(game),game_get_mapsize_y(game)); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Map Tileset: %.64s",game_tileset_get_str(game_get_tileset(game))); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Map Type: %.64s",game_maptype_get_str(game_get_maptype(game))); message_send_text(c,message_type_info,c,msgtemp); snprintf(msgtemp, sizeof(msgtemp), "Players: %u current, %u total, %u max",game_get_ref(game),game_get_count(game),game_get_maxplayers(game)); message_send_text(c,message_type_info,c,msgtemp); { char const * description; if (!(description = game_get_description(game))) description = ""; snprintf(msgtemp, sizeof(msgtemp), "Description: %-20.20s",description); } return 0; } static int _handle_ladderactivate_command(t_connection * c, char const *text) { ladderlist_make_all_active(); message_send_text(c,message_type_info,c,"Copied current scores to active scores on all ladders."); return 0; } static int _handle_rehash_command(t_connection * c, char const *text) { server_restart_wraper(); return 0; } /* static int _handle_rank_all_accounts_command(t_connection * c, char const *text) { // rank all accounts here accounts_rank_all(); return 0; } */ static int _handle_shutdown_command(t_connection * c, char const *text) { char dest[32]; unsigned int i,j; unsigned int delay; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */ if (j [clienttag]"); return 0; } if (str_to_uint(dest,&rank)<0 || rank<1) { message_send_text(c,message_type_error,c,"Invalid rank."); return 0; } if (text[i]!='\0') { if (strlen(&text[i])!=4) { message_send_text(c,message_type_error,c,"You must supply a rank and a valid program ID."); message_send_text(c,message_type_error,c,"Example: /ladderinfo 1 STAR"); return 0; } clienttag = tag_case_str_to_uint(&text[i]); } else if (!(clienttag = conn_get_clienttag(c))) { message_send_text(c,message_type_error,c,"Unable to determine client game."); return 0; } if (clienttag==CLIENTTAG_STARCRAFT_UINT) { if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_active,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal))) { snprintf(msgtemp, sizeof(msgtemp), "Starcraft active %5u: %-20.20s %u/%u/%u rating %u", rank, account_get_name(account), account_get_ladder_active_wins(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), account_get_ladder_active_losses(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), account_get_ladder_active_disconnects(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), account_get_ladder_active_rating(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal)); } else snprintf(msgtemp, sizeof(msgtemp), "Starcraft active %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_current,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal))) { snprintf(msgtemp, sizeof(msgtemp), "Starcraft current %5u: %-20.20s %u/%u/%u rating %u", rank, account_get_name(account), account_get_ladder_wins(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), account_get_ladder_losses(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), account_get_ladder_disconnects(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), account_get_ladder_rating(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal)); } else snprintf(msgtemp, sizeof(msgtemp), "Starcraft current %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); } else if (clienttag==CLIENTTAG_BROODWARS_UINT) { if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_active,CLIENTTAG_BROODWARS_UINT,ladder_id_normal))) { snprintf(msgtemp, sizeof(msgtemp), "Brood War active %5u: %-20.20s %u/%u/%u rating %u", rank, account_get_name(account), account_get_ladder_active_wins(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal), account_get_ladder_active_losses(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal), account_get_ladder_active_disconnects(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal), account_get_ladder_active_rating(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal)); } else snprintf(msgtemp, sizeof(msgtemp), "Brood War active %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_current,CLIENTTAG_BROODWARS_UINT,ladder_id_normal))) { snprintf(msgtemp, sizeof(msgtemp), "Brood War current %5u: %-20.20s %u/%u/%u rating %u", rank, account_get_name(account), account_get_ladder_wins(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal), account_get_ladder_losses(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal), account_get_ladder_disconnects(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal), account_get_ladder_rating(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal)); } else snprintf(msgtemp, sizeof(msgtemp), "Brood War current %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); } else if (clienttag==CLIENTTAG_WARCIIBNE_UINT) { if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_active,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal))) { snprintf(msgtemp, sizeof(msgtemp), "Warcraft II standard active %5u: %-20.20s %u/%u/%u rating %u", rank, account_get_name(account), account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), account_get_ladder_active_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), account_get_ladder_active_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), account_get_ladder_active_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal)); } else snprintf(msgtemp, sizeof(msgtemp), "Warcraft II standard active %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_active,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman))) { snprintf(msgtemp, sizeof(msgtemp), "Warcraft II IronMan active %5u: %-20.20s %u/%u/%u rating %u", rank, account_get_name(account), account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman), account_get_ladder_active_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman), account_get_ladder_active_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman), account_get_ladder_active_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)); } else snprintf(msgtemp, sizeof(msgtemp), "Warcraft II IronMan active %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_current,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal))) { snprintf(msgtemp, sizeof(msgtemp), "Warcraft II standard current %5u: %-20.20s %u/%u/%u rating %u", rank, account_get_name(account), account_get_ladder_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), account_get_ladder_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), account_get_ladder_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), account_get_ladder_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal)); } else snprintf(msgtemp, sizeof(msgtemp), "Warcraft II standard current %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_current,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman))) { snprintf(msgtemp, sizeof(msgtemp), "Warcraft II IronMan current %5u: %-20.20s %u/%u/%u rating %u", rank, account_get_name(account), account_get_ladder_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman), account_get_ladder_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman), account_get_ladder_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman), account_get_ladder_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)); } else snprintf(msgtemp, sizeof(msgtemp), "Warcraft II IronMan current %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); } // --> aaron else if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT) { unsigned int teamcount = 0; if ((account = ladder_get_account(solo_ladder(clienttag),rank,&teamcount,clienttag))) { snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 Solo %5u: %-20.20s %u/%u/0", rank, account_get_name(account), account_get_ladder_wins(account,clienttag,ladder_id_solo), account_get_ladder_losses(account,clienttag,ladder_id_solo)); } else snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 Solo %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); if ((account = ladder_get_account(team_ladder(clienttag),rank,&teamcount,clienttag))) { snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 Team %5u: %-20.20s %u/%u/0", rank, account_get_name(account), account_get_ladder_wins(account,clienttag,ladder_id_team), account_get_ladder_losses(account,clienttag,ladder_id_team)); } else snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 Team %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); if ((account = ladder_get_account(ffa_ladder(clienttag),rank,&teamcount,clienttag))) { snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 FFA %5u: %-20.20s %u/%u/0", rank, account_get_name(account), account_get_ladder_wins(account,clienttag,ladder_id_ffa), account_get_ladder_losses(account,clienttag,ladder_id_ffa)); } else snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 FFA %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); if ((account = ladder_get_account(at_ladder(clienttag),rank,&teamcount,clienttag))) { /* if (account_get_atteammembers(account,teamcount,clienttag)) snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 AT Team %5u: %-80.80s %u/%u/0", rank, account_get_atteammembers(account,teamcount,clienttag), account_get_atteamwin(account,teamcount,clienttag), account_get_atteamloss(account,teamcount,clienttag)); else */ snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 AT Team %5u: ",rank); } else snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 AT Team %5u: ",rank); message_send_text(c,message_type_info,c,msgtemp); } //<--- else { message_send_text(c,message_type_error,c,"This game does not support win/loss records."); message_send_text(c,message_type_error,c,"You must supply a rank and a valid program ID."); message_send_text(c,message_type_error,c,"Example: /ladderinfo 1 STAR"); } return 0; } static int _handle_timer_command(t_connection * c, char const *text) { unsigned int i,j; unsigned int delta; char deltastr[64]; t_timer_data data; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get comm */ if (j"); return 0; } if (clockstr_to_seconds(deltastr,&delta)<0) { message_send_text(c,message_type_error,c,"Invalid duration."); return 0; } if (text[i]=='\0') data.p = xstrdup("Your timer has expired."); else data.p = xstrdup(&text[i]); if (timerlist_add_timer(c,time(NULL)+(time_t)delta,user_timer_cb,data)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not add timer"); xfree(data.p); message_send_text(c,message_type_error,c,"Could not set timer."); } else { snprintf(msgtemp, sizeof(msgtemp), "Timer set for %.128s",seconds_to_timestr(delta)); message_send_text(c,message_type_info,c,msgtemp); } return 0; } static int _handle_serverban_command(t_connection *c, char const *text) { char dest[USER_NAME_MAX]; t_connection * dest_c; unsigned int i,j; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); // skip command for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) // get dest if (j"); return 0; } if (!(dest_c = connlist_find_connection_by_accountname(dest))) { message_send_text(c,message_type_error,c,"That user is not logged on."); return 0; } snprintf(msgtemp, sizeof(msgtemp), "Banning User %.64s who is using IP %.64s",conn_get_username(dest_c),addr_num_to_ip_str(conn_get_game_addr(dest_c))); message_send_text(c,message_type_info,c,msgtemp); message_send_text(c,message_type_info,c,"Users Account is also LOCKED! Only a Admin can Unlock it!"); snprintf(msgtemp, sizeof(msgtemp), "/ipban a %.64s",addr_num_to_ip_str(conn_get_game_addr(dest_c))); handle_ipban_command(c,msgtemp); account_set_auth_lock(conn_get_account(dest_c),1); //now kill the connection snprintf(msgtemp, sizeof(msgtemp), "You have been banned by Admin: %.64s",conn_get_username(c)); message_send_text(dest_c,message_type_error,dest_c,msgtemp); message_send_text(dest_c,message_type_error,dest_c,"Your account is also LOCKED! Only a admin can UNLOCK it!"); conn_set_state(dest_c, conn_state_destroy); return 0; } static int _handle_netinfo_command(t_connection * c, char const *text) { char dest[USER_NAME_MAX]; unsigned int i,j; t_connection * conn; t_game const * game; unsigned int addr; unsigned short port; unsigned int taddr; unsigned short tport; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); // skip command for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) // get dest if (j"); return 0; } if (!(account = accountlist_find_account(text))) { message_send_text(c,message_type_error,c,"Invalid user."); return 0; } if ((user = connlist_find_connection_by_accountname(text))) message_send_text(user,message_type_info,user,"Your account has just been locked by admin."); account_set_auth_lock(account,1); message_send_text(c,message_type_error,c,"That user account is now locked."); return 0; } static int _handle_unlockacct_command(t_connection * c, char const *text) { t_connection * user; t_account * account; text = skip_command(text); if (text[0]=='\0') { message_send_text(c,message_type_info,c,"usage: /unlockacct "); return 0; } if (!(account = accountlist_find_account(text))) { message_send_text(c,message_type_error,c,"Invalid user."); return 0; } if ((user = connlist_find_connection_by_accountname(text))) message_send_text(user,message_type_info,user,"Your account has just been unlocked by admin."); account_set_auth_lock(account,0); message_send_text(c,message_type_error,c,"That user account is now unlocked."); return 0; } static int _handle_flag_command(t_connection * c, char const *text) { char dest[32]; unsigned int i,j; unsigned int newflag; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */ if (j"); return 0; } newflag = strtoul(dest,NULL,0); conn_set_flags(c,newflag); snprintf(msgtemp, sizeof(msgtemp), "Flags set to 0x%08x.",newflag); message_send_text(c,message_type_info,c,msgtemp); return 0; } static int _handle_tag_command(t_connection * c, char const *text) { char dest[8]; unsigned int i,j; unsigned int newtag; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */ if (j"); return 0; } if (strlen(dest)!=4) { message_send_text(c,message_type_error,c,"Client tag should be four characters long."); return 0; } newtag = tag_case_str_to_uint(dest); if (tag_check_client(newtag)) { unsigned int oldflags = conn_get_flags(c); conn_set_clienttag(c,newtag); if ((newtag==CLIENTTAG_WARCRAFT3_UINT) || (newtag==CLIENTTAG_WAR3XP_UINT)) conn_update_w3_playerinfo(c); channel_rejoin(c); conn_set_flags(c,oldflags); channel_update_userflags(c); snprintf(msgtemp, sizeof(msgtemp), "Client tag set to %.64s.",dest); } else snprintf(msgtemp, sizeof(msgtemp), "Invalid clienttag %.64s specified",dest); message_send_text(c,message_type_info,c,msgtemp); return 0; } static int _handle_set_command(t_connection * c, char const *text) { t_account * account; char *accname; char *key; char *value; char t[MAX_MESSAGE_LEN]; unsigned int i,j; char arg1[256]; char arg2[256]; char arg3[256]; strncpy(t, text, MAX_MESSAGE_LEN - 1); for (i=0; t[i]!=' ' && t[i]!='\0'; i++); /* skip command /set */ for (; t[i]==' '; i++); /* skip spaces */ for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get username */ if (j [value]"); } if (!(account = accountlist_find_account(accname))) { message_send_text(c,message_type_error,c,"Invalid user."); return 0; } if (*value == '\0') { if (account_get_strattr(account,key)) { snprintf(msgtemp, sizeof(msgtemp), "current value of %.64s is \"%.128s\"",key,account_get_strattr(account,key)); message_send_text(c,message_type_error,c,msgtemp); } else message_send_text(c,message_type_error,c,"value currently not set"); return 0; } if (account_set_strattr(account,key,value)<0) message_send_text(c,message_type_error,c,"Unable to set key"); else message_send_text(c,message_type_error,c,"Key set succesfully"); return 0; } static int _handle_motd_command(t_connection * c, char const *text) { char const * filename; FILE * fp; if ((filename = prefs_get_motdfile())) { if ((fp = fopen(filename,"r"))) { message_send_file(c,fp); if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close motd file \"%s\" after reading (fopen: %s)",filename,pstrerror(errno)); } else { eventlog(eventlog_level_error,__FUNCTION__,"could not open motd file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); message_send_text(c,message_type_error,c,"Unable to open motd."); } return 0; } else { message_send_text(c,message_type_error,c,"No motd."); return 0; } } static int _handle_tos_command(t_connection * c, char const * text) { /* handle /tos - shows terms of service by user request -raistlinthewiz */ char * filename=NULL; FILE * fp; filename = buildpath(prefs_get_filedir(),prefs_get_tosfile()); /* FIXME: if user enters relative path to tos file in config, above routine will fail */ if ((fp = fopen(filename,"r"))) { char * buff; int len; while ((buff = file_get_line(fp))) { if ((len=strlen(buff)) < MAX_MESSAGE_LEN) message_send_text(c,message_type_info,c,buff); else { /* lines in TOS file can be > MAX_MESSAGE_LEN, so split them truncating is not an option for TOS -raistlinthewiz */ while ( len > MAX_MESSAGE_LEN - 1) { strncpy(msgtemp,buff,MAX_MESSAGE_LEN-1); msgtemp[MAX_MESSAGE_LEN]='\0'; buff += MAX_MESSAGE_LEN - 1; len -= MAX_MESSAGE_LEN - 1; message_send_text(c,message_type_info,c,msgtemp); } if ( len > 0 ) /* does it exist a small last part ? */ message_send_text(c,message_type_info,c,buff); } } if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close tos file \"%s\" after reading (fopen: %s)",filename,pstrerror(errno)); } else { eventlog(eventlog_level_error,__FUNCTION__,"could not open tos file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); message_send_text(c,message_type_error,c,"Unable to send TOS (terms of service)."); } xfree((void *)filename); return 0; } static int _handle_ping_command(t_connection * c, char const *text) { unsigned int i; t_connection * user; t_game * game; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='\0') { if ((game=conn_get_game(c))) { for (i=0; i []"); return 0; } if (!strcmp(command,"help") || !strcmp(command,"h")) { message_send_text(c,message_type_info,c,"Command Groups (Defines the Groups of Commands a User Can Use.)"); message_send_text(c,message_type_info,c,"Type: /cg add - adds group(s) to user profile"); message_send_text(c,message_type_info,c,"Type: /cg del - deletes group(s) from user profile"); message_send_text(c,message_type_info,c,"Type: /cg list - shows current groups user can use"); return 0; } if (arg2[0] =='\0') { message_send_text(c,message_type_info,c,"usage: /cg []"); return 0; } if (!(account = accountlist_find_account(username))) { message_send_text(c,message_type_error,c,"Invalid user."); return 0; } usergroups = account_get_command_groups(account); if (!strcmp(command,"list") || !strcmp(command,"l")) { if (usergroups & 1) tempgroups[0] = '1'; else tempgroups[0] = ' '; if (usergroups & 2) tempgroups[1] = '2'; else tempgroups[1] = ' '; if (usergroups & 4) tempgroups[2] = '3'; else tempgroups[2] = ' '; if (usergroups & 8) tempgroups[3] = '4'; else tempgroups[3] = ' '; if (usergroups & 16) tempgroups[4] = '5'; else tempgroups[4] = ' '; if (usergroups & 32) tempgroups[5] = '6'; else tempgroups[5] = ' '; if (usergroups & 64) tempgroups[6] = '7'; else tempgroups[6] = ' '; if (usergroups & 128) tempgroups[7] = '8'; else tempgroups[7] = ' '; tempgroups[8] = '\0'; snprintf(msgtemp, sizeof(msgtemp), "%.64s's command group(s): %.128s", username, tempgroups); message_send_text(c,message_type_info,c,msgtemp); return 0; } if (arg3[0] =='\0') { message_send_text(c,message_type_info,c,"usage: /cg []"); return 0; } for (i=0; arg3[i] != '\0'; i++) { if (arg3[i] == '1') groups |= 1; else if (arg3[i] == '2') groups |= 2; else if (arg3[i] == '3') groups |= 4; else if (arg3[i] == '4') groups |= 8; else if (arg3[i] == '5') groups |= 16; else if (arg3[i] == '6') groups |= 32; else if (arg3[i] == '7') groups |= 64; else if (arg3[i] == '8') groups |= 128; else { snprintf(msgtemp, sizeof(msgtemp), "got bad group: %c", arg3[i]); message_send_text(c,message_type_info,c,msgtemp); return 0; } } if (!strcmp(command,"add") || !strcmp(command,"a")) { account_set_command_groups(account, usergroups | groups); snprintf(msgtemp, sizeof(msgtemp), "groups %.128s has been added to user: %.64s", arg3, username); message_send_text(c,message_type_info,c,msgtemp); return 0; } if (!strcmp(command,"del") || !strcmp(command,"d")) { account_set_command_groups(account, usergroups & (255 - groups)); snprintf(msgtemp, sizeof(msgtemp), "groups %.128s has been deleted from user: %.64s", arg3, username); message_send_text(c,message_type_info,c,msgtemp); return 0; } snprintf(msgtemp, sizeof(msgtemp), "got unknown command: %.64s", command); message_send_text(c,message_type_info,c,msgtemp); return 0; } static int _handle_topic_command(t_connection * c, char const * text) { char const * channel_name; char const * topic; char * tmp; t_channel * channel; int do_save = NO_SAVE_TOPIC; channel_name = skip_command(text); if ((topic = strchr(channel_name,'"'))) { tmp = (char *)topic; for (tmp--;tmp[0]==' ';tmp--); tmp[1]='\0'; topic++; tmp = strchr(topic,'"'); if (tmp) tmp[0]='\0'; } if (!(conn_get_channel(c))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return -1; } if (channel_name[0]=='\0') { if (channel_get_topic(channel_get_name(conn_get_channel(c)))) { snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: %.128s",channel_get_name(conn_get_channel(c)),channel_get_topic(channel_get_name(conn_get_channel(c)))); } else { snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: no topic",channel_get_name(conn_get_channel(c))); } message_send_text(c,message_type_info,c,msgtemp); return 0; } if (!(topic)) { if (channel_get_topic(channel_name)) { snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: %.128s",channel_name, channel_get_topic(channel_name)); } else { snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: no topic",channel_name); } message_send_text(c,message_type_info,c,msgtemp); return 0; } if (!(channel = channellist_find_channel_by_name(channel_name,conn_get_country(c),realm_get_name(conn_get_realm(c))))) { message_send_text(c,message_type_error,c,"no such channel, can't set topic"); return -1; } if (strlen(topic) >= MAX_TOPIC_LEN) { snprintf(msgtemp, sizeof(msgtemp), "max topic length exceeded (max %d symbols)", MAX_TOPIC_LEN); message_send_text(c,message_type_error,c,msgtemp); return -1; } channel_name = channel_get_name(channel); if (!(account_is_operator_or_admin(conn_get_account(c),channel_name))) { snprintf(msgtemp, sizeof(msgtemp), "You must be at least a Channel Operator of %.64s to set the topic",channel_name); message_send_text(c,message_type_error,c,msgtemp); return -1; } if (channel_get_permanent(channel)) do_save = DO_SAVE_TOPIC; channel_set_topic(channel_name, topic, do_save); snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: %.128s",channel_name, topic); message_send_text(c,message_type_info,c,msgtemp); return 0; } static int _handle_moderate_command(t_connection * c, char const * text) { t_channel_flags oldflags; t_channel * channel; if (!(channel = conn_get_channel(c))) { message_send_text(c,message_type_error,c,"This command can only be used inside a channel."); return -1; } if (!(account_is_operator_or_admin(conn_get_account(c),channel_get_name(channel)))) { message_send_text(c,message_type_error,c,"You must be at least a Channel Operator to use this command."); return -1; } oldflags = channel_get_flags(channel); if (channel_set_flags(channel, oldflags ^ channel_flags_moderated)) { eventlog(eventlog_level_error,__FUNCTION__,"could not set channel %s flags",channel_get_name(channel)); message_send_text(c,message_type_error,c,"Unable to change channel flags."); return -1; } else { if (oldflags & channel_flags_moderated) channel_message_send(channel,message_type_info,c,"Channel is now unmoderated"); else channel_message_send(channel,message_type_info,c,"Channel is now moderated"); } return 0; } static void _reset_d1_stats(t_account *account, t_clienttag ctag, t_connection *c) { account_set_normal_level(account,ctag,0); account_set_normal_strength(account,ctag,0), account_set_normal_magic(account,ctag,0), account_set_normal_dexterity(account,ctag,0), account_set_normal_vitality(account,ctag,0), account_set_normal_gold(account,ctag,0); snprintf(msgtemp, sizeof(msgtemp), "Resetted %.64s's %.64s Stats",account_get_name(account),clienttag_get_title(ctag)); message_send_text(c,message_type_info,c,msgtemp); } static void _reset_scw2_stats(t_account *account, t_clienttag ctag, t_connection *c) { account_set_normal_wins(account,ctag,0); account_set_normal_losses(account,ctag,0); account_set_normal_disconnects(account,ctag,0); if (account_get_ladder_rating(account,ctag,ladder_id_normal)>0) { account_set_ladder_wins(account,ctag,ladder_id_normal,0); account_set_ladder_losses(account,ctag,ladder_id_normal,0); account_set_ladder_disconnects(account,ctag,ladder_id_normal,0); account_set_ladder_rating(account,ctag,ladder_id_normal,0); } if (account_get_ladder_rating(account,ctag,ladder_id_ironman)>0) { account_set_ladder_wins(account,ctag,ladder_id_ironman,0); account_set_ladder_losses(account,ctag,ladder_id_ironman,0); account_set_ladder_disconnects(account,ctag,ladder_id_ironman,0); account_set_ladder_rating(account,ctag,ladder_id_ironman,0); } snprintf(msgtemp, sizeof(msgtemp), "Resetted %.64s's %.64s Stats",account_get_name(account),clienttag_get_title(ctag)); message_send_text(c,message_type_info,c,msgtemp); } static void _reset_w3_stats(t_account *account, t_clienttag ctag, t_connection *c) { account_set_ladder_level(account,ctag,ladder_id_solo,0); account_set_ladder_xp(account,ctag,ladder_id_solo,0); account_set_ladder_wins(account,ctag,ladder_id_solo,0); account_set_ladder_losses(account,ctag,ladder_id_solo,0); account_set_ladder_rank(account,ctag,ladder_id_solo,0); account_set_ladder_level(account,ctag,ladder_id_team,0); account_set_ladder_xp(account,ctag,ladder_id_team,0); account_set_ladder_wins(account,ctag,ladder_id_team,0); account_set_ladder_losses(account,ctag,ladder_id_team,0); account_set_ladder_rank(account,ctag,ladder_id_team,0); account_set_ladder_level(account,ctag,ladder_id_ffa,0); account_set_ladder_xp(account,ctag,ladder_id_ffa,0); account_set_ladder_wins(account,ctag,ladder_id_ffa,0); account_set_ladder_losses(account,ctag,ladder_id_ffa,0); account_set_ladder_rank(account,ctag,ladder_id_ffa,0); // this would now need a way to delete the team for all members now //account_set_atteamcount(account,ctag,0); snprintf(msgtemp, sizeof(msgtemp), "Resetted %.64s's %.64s Stats",account_get_name(account),clienttag_get_title(ctag)); message_send_text(c,message_type_info,c,msgtemp); } static int _handle_clearstats_command(t_connection *c, char const *text) { char dest[USER_NAME_MAX]; unsigned int i,j,all; t_account * account; t_clienttag ctag = 0; for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (!text[i]) { message_send_text(c,message_type_error,c,"Missing user, syntax error."); message_send_text(c,message_type_error,c,"Usage example: /clearstats "); message_send_text(c,message_type_error,c," where can be any valid client or ALL for all clients"); return 0; } for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */ if (j "); message_send_text(c,message_type_error,c," where can be any valid client or ALL for all clients"); return 0; } if (strcasecmp(text + i,"all")) { if (strlen(text + i) != 4) { message_send_text(c,message_type_error,c,"Invalid clienttag, syntax error."); return 0; } ctag = tag_case_str_to_uint(text + i); all = 0; } else all = 1; if (all || ctag == CLIENTTAG_DIABLORTL_UINT) _reset_d1_stats(account,CLIENTTAG_DIABLORTL_UINT,c); if (all || ctag == CLIENTTAG_DIABLOSHR_UINT) _reset_d1_stats(account,CLIENTTAG_DIABLOSHR_UINT,c); if (all || ctag == CLIENTTAG_WARCIIBNE_UINT) _reset_scw2_stats(account,CLIENTTAG_WARCIIBNE_UINT,c); if (all || ctag == CLIENTTAG_STARCRAFT_UINT) _reset_scw2_stats(account,CLIENTTAG_STARCRAFT_UINT,c); if (all || ctag == CLIENTTAG_BROODWARS_UINT) _reset_scw2_stats(account,CLIENTTAG_BROODWARS_UINT,c); if (all || ctag == CLIENTTAG_SHAREWARE_UINT) _reset_scw2_stats(account,CLIENTTAG_SHAREWARE_UINT,c); if (all || ctag == CLIENTTAG_WARCRAFT3_UINT) _reset_w3_stats(account,CLIENTTAG_WARCRAFT3_UINT,c); if (all || ctag == CLIENTTAG_WAR3XP_UINT) _reset_w3_stats(account,CLIENTTAG_WAR3XP_UINT,c); return 0; } pvpgn-1.8.5/src/bnetd/attrlayer.c0000644000175000017500000001070511151345317015703 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_ASSERT_H # include #endif #include "common/eventlog.h" #include "common/flags.h" #define ATTRGROUP_INTERNAL_ACCESS #include "attr.h" #include "attrgroup.h" #include "attrlayer.h" #include "storage.h" #include "prefs.h" #include "common/setup_after.h" static t_attrgroup *defattrs = NULL; static DECLARE_ELIST_INIT(loadedlist); static DECLARE_ELIST_INIT(dirtylist); static int attrlayer_unload_default(void); extern int attrlayer_init(void) { elist_init(&loadedlist); elist_init(&dirtylist); attrlayer_load_default(); return 0; } extern int attrlayer_cleanup(void) { attrlayer_flush(FS_FORCE | FS_ALL); attrlayer_unload_default(); return 0; } extern int attrlayer_load_default(void) { if (defattrs) attrlayer_unload_default(); defattrs = attrgroup_create_storage(storage->get_defacct()); if (!defattrs) { eventlog(eventlog_level_error,__FUNCTION__,"could not create attrgroup"); return -1; } return attrgroup_load(defattrs); } static int attrlayer_unload_default(void) { attrgroup_destroy(defattrs); defattrs = NULL; return 0; } /* FIXME: dont copy most of the functionality, a good place for a C++ template ;) */ extern int attrlayer_flush(int flags) { static t_elist *curr = &loadedlist; static t_elist *next = NULL; t_attrgroup *attrgroup; unsigned int fcount; unsigned int tcount; fcount = tcount = 0; if (curr == &loadedlist || FLAG_ISSET(flags, FS_ALL)) { curr = elist_next(&loadedlist); next = elist_next(curr); } /* elist_for_each_safe splitted into separate startup for userstep function */ for (; curr != &loadedlist; curr = next, next = elist_next(curr)) { if (!FLAG_ISSET(flags, FS_ALL) && tcount >= prefs_get_user_step()) break; attrgroup = elist_entry(curr, t_attrgroup, loadedlist); switch(attrgroup_flush(attrgroup, flags)) { case -1: eventlog(eventlog_level_error, __FUNCTION__, "could not flush account"); break; case 1: fcount++; break; case 0: default: break; } tcount++; } if (fcount>0) eventlog(eventlog_level_debug, __FUNCTION__, "flushed %u of %u user accounts", fcount, tcount); if (!FLAG_ISSET(flags, FS_ALL) && curr != &loadedlist) return 1; return 0; } extern int attrlayer_save(int flags) { static t_elist *curr = &dirtylist; static t_elist *next = NULL; t_attrgroup *attrgroup; unsigned int scount; unsigned int tcount; scount = tcount = 0; if (curr == &dirtylist || FLAG_ISSET(flags, FS_ALL)) { curr = elist_next(&dirtylist); next = elist_next(curr); } /* elist_for_each_safe splitted into separate startup for userstep function */ for (; curr != &dirtylist; curr = next, next = elist_next(curr)) { if (!FLAG_ISSET(flags, FS_ALL) && tcount >= prefs_get_user_step()) break; attrgroup = elist_entry(curr, t_attrgroup, dirtylist); switch(attrgroup_save(attrgroup, flags)) { case -1: eventlog(eventlog_level_error, __FUNCTION__, "could not save account"); break; case 1: scount++; break; case 0: default: break; } tcount++; } if (scount>0) eventlog(eventlog_level_debug, __FUNCTION__, "saved %u of %u user accounts", scount, tcount); if (!FLAG_ISSET(flags, FS_ALL) && curr != &dirtylist) return 1; return 0; } extern void attrlayer_add_loadedlist(t_elist *what) { elist_add_tail(&loadedlist, what); } extern void attrlayer_del_loadedlist(t_elist *what) { elist_del(what); } extern void attrlayer_add_dirtylist(t_elist *what) { elist_add_tail(&dirtylist, what); } extern void attrlayer_del_dirtylist(t_elist *what) { elist_del(what); } extern t_attrgroup * attrlayer_get_defattrgroup(void) { return defattrs; } pvpgn-1.8.5/src/bnetd/tournament.c0000644000175000017500000005222111151345317016067 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "common/eventlog.h" #include "common/packet.h" #include "common/tag.h" #include "common/list.h" #include "common/util.h" #include "common/xalloc.h" #include "compat/strerror.h" #include "account.h" #include "anongame_maplists.h" #include "tournament.h" #include "common/setup_after.h" static t_tournament_info * tournament_info = NULL; static t_list * tournament_head=NULL; static int tournamentlist_create(void); static int gamelist_destroy(void); static t_tournament_user * tournament_get_user(t_account * account); //static int tournament_get_in_game_status(t_account * account); /*****/ static int tournamentlist_create(void) { tournament_head = list_create(); return 0; } static int gamelist_destroy(void) { t_elem * curr; t_tournament_user * user; if (tournament_head) { LIST_TRAVERSE(tournament_head,curr) { if (!(user = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"tournament list contains NULL item"); continue; } if (list_remove_elem(tournament_head,&curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); if (user->name) xfree((void *)user->name); /* avoid warning */ xfree(user); } if (list_destroy(tournament_head)<0) return -1; tournament_head = NULL; } return 0; } /*****/ extern int tournament_check_client(t_clienttag clienttag) { if (clienttag==CLIENTTAG_WAR3XP_UINT && tournament_info->game_client==2) return 1; if (clienttag==CLIENTTAG_WARCRAFT3_UINT && tournament_info->game_client==1) return 1; return -1; } extern int tournament_signup_user(t_account * account) { t_tournament_user * user; if (!(account)) return -1; if ((user = tournament_get_user(account))) { eventlog(eventlog_level_info,__FUNCTION__,"user \"%s\" already signed up in tournament",account_get_name(account)); return 0; } user = xmalloc(sizeof(t_tournament_user)); user->name = xstrdup(account_get_name(account)); user->wins = 0; user->losses = 0; user->ties = 0; user->in_game = 0; user->in_finals = 0; list_prepend_data(tournament_head,user); eventlog(eventlog_level_info,__FUNCTION__,"added user \"%s\" to tournament",account_get_name(account)); return 0; } static t_tournament_user * tournament_get_user(t_account * account) { t_elem const * curr; t_tournament_user * user; if (tournament_head) LIST_TRAVERSE(tournament_head,curr) { user = elem_get_data(curr); if (strcmp(user->name, account_get_name(account)) == 0) return user; } return NULL; } extern int tournament_user_signed_up(t_account * account) { if (!(tournament_get_user(account))) return -1; return 0; } extern int tournament_add_stat(t_account * account, int stat) { t_tournament_user * user; if (!(user = tournament_get_user(account))) return -1; if (stat == 1) user->wins++; if (stat == 2) user->losses++; if (stat == 3) user->ties++; return 0; } extern int tournament_get_stat(t_account * account, int stat) { t_tournament_user * user; if (!(user = tournament_get_user(account))) return 0; if (stat == 1) return user->wins; if (stat == 2) return user->losses; if (stat == 3) return user->ties; return 0; } extern int tournament_get_player_score(t_account * account) { t_tournament_user * user; int score; if (!(user = tournament_get_user(account))) return 0; score = user->wins * 3 + user->ties - user->losses; if (score < 0) return 0; return score; } extern int tournament_set_in_game_status(t_account * account, int status) { t_tournament_user * user; if (!(user = tournament_get_user(account))) return -1; user->in_game = status; return 0; } /* static int tournament_get_in_game_status(t_account * account) { t_tournament_user * user; if (!(user = tournament_get_user(account))) return 0; return user->in_game; } */ extern int tournament_get_in_finals_status(t_account * account) { t_tournament_user * user; if (!(user = tournament_get_user(account))) return 0; return user->in_finals; } extern int tournament_get_game_in_progress(void) { t_elem const * curr; t_tournament_user * user; if (tournament_head) LIST_TRAVERSE_CONST(tournament_head,curr) { user = elem_get_data(curr); if (user->in_game == 1) return 1; } return 0; } extern int tournament_is_arranged(void) { if (tournament_info->game_selection == 2) return 1; else return 0; } extern int tournament_get_totalplayers(void) { return tournament_info->game_type * 2; } void tournament_check_date(unsigned int *mon, unsigned int *mday, unsigned int *year, unsigned int *hour, unsigned int *min, unsigned int *sec, char const * caller) { if (*mon>12) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid month (%u) in %s",*mon,caller); *mon = 12; } if (*mday>31) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid mday (%u) in %s",*mday,caller); *mday = 31; } if (*hour>23) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid hour (%u) from %s",*hour,caller); *hour = 23; } if (*min >59) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid min (%u) from %s",*min,caller); *min = 59; } if (*sec >59) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid sec (%u) from %s",*sec,caller); *sec = 59; } return; } /*****/ extern int tournament_init(char const * filename) { FILE * fp; unsigned int line,pos,mon,day,year,hour,min,sec; char *buff,*temp,*pointer,*value; char format[30]; char *variable; char *sponsor = NULL; char *have_sponsor = NULL; char *have_icon = NULL; struct tm * timestamp = xmalloc(sizeof(struct tm)); sprintf(format,"%%02u/%%02u/%%04u %%02u:%%02u:%%02u"); tournament_info = xmalloc(sizeof(t_tournament_info)); tournament_info->start_preliminary = 0; tournament_info->end_signup = 0; tournament_info->end_preliminary = 0; tournament_info->start_round_1 = 0; tournament_info->start_round_2 = 0; tournament_info->start_round_3 = 0; tournament_info->start_round_4 = 0; tournament_info->tournament_end = 0; tournament_info->game_selection = 1; /* Default to PG */ tournament_info->game_type = 1; /* Default to 1v1 */ tournament_info->game_client = 2; /* Default to FT */ tournament_info->races = 0x3F; /* Default to all races */ tournament_info->format = xstrdup(""); tournament_info->sponsor = xstrdup(""); tournament_info->thumbs_down = 0; anongame_tournament_maplists_destroy(); if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); xfree((void *)timestamp); return -1; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); xfree((void *)timestamp); return -1; } for (line=1; (buff = file_get_line(fp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if ((temp = strrchr(buff,'#'))) { unsigned int len; unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } if (strcmp(buff,"[MAPS]") == 0) { char *clienttag, *mapname, *mname; t_clienttag ctag; for (; (buff = file_get_line(fp));) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if ((temp = strrchr(buff,'#'))) { unsigned int len; unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } /* FIXME: use next_token() */ if (!(clienttag = strtok(buff, " \t"))) { /* strtok modifies the string it is passed */ continue; } if (strlen(clienttag) != 4) { continue; } if (strcmp(buff,"[ENDMAPS]") == 0) { break; } if (!(mapname = strtok(NULL," \t"))) { continue; } if (!tag_check_client((ctag = tag_case_str_to_uint(clienttag)))) { continue; } mname = xstrdup(mapname); anongame_add_tournament_map(ctag, mname); eventlog(eventlog_level_trace,__FUNCTION__,"added tournament map \"%s\" for %s",mname,clienttag); xfree(mname); } } else { variable = buff; pointer = strchr(variable,'='); for(pointer--;pointer[0]==' ' || pointer[0]=='\t';pointer--); pointer[1]='\0'; pointer++; pointer++; pointer = strchr(pointer,'='); pointer++; if (strcmp(variable,"start_preliminary") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; sscanf(value,format,&mon,&day,&year,&hour,&min,&sec); tournament_check_date(&mon,&day,&year,&hour,&min,&sec,variable); timestamp->tm_mon = mon-1; timestamp->tm_mday = day; timestamp->tm_year = year-1900; timestamp->tm_hour = hour; timestamp->tm_min = min; timestamp->tm_sec = sec; timestamp->tm_isdst = -1; tournament_info->start_preliminary = mktime(timestamp); } else if (strcmp(variable,"end_signup") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; sscanf(value,format,&mon,&day,&year,&hour,&min,&sec); tournament_check_date(&mon,&day,&year,&hour,&min,&sec,variable); timestamp->tm_mon = mon-1; timestamp->tm_mday = day; timestamp->tm_year = year-1900; timestamp->tm_hour = hour; timestamp->tm_min = min; timestamp->tm_sec = sec; timestamp->tm_isdst = -1; tournament_info->end_signup = mktime(timestamp); } else if (strcmp(variable,"end_preliminary") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; sscanf(value,format,&mon,&day,&year,&hour,&min,&sec); tournament_check_date(&mon,&day,&year,&hour,&min,&sec,variable); timestamp->tm_mon = mon-1; timestamp->tm_mday = day; timestamp->tm_year = year-1900; timestamp->tm_hour = hour; timestamp->tm_min = min; timestamp->tm_sec = sec; timestamp->tm_isdst = -1; tournament_info->end_preliminary = mktime(timestamp); } else if (strcmp(variable,"start_round_1") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; sscanf(value,format,&mon,&day,&year,&hour,&min,&sec); tournament_check_date(&mon,&day,&year,&hour,&min,&sec,variable); timestamp->tm_mon = mon-1; timestamp->tm_mday = day; timestamp->tm_year = year-1900; timestamp->tm_hour = hour; timestamp->tm_min = min; timestamp->tm_sec = sec; timestamp->tm_isdst = -1; tournament_info->start_round_1 = mktime(timestamp); } else if (strcmp(variable,"start_round_2") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; sscanf(value,format,&mon,&day,&year,&hour,&min,&sec); tournament_check_date(&mon,&day,&year,&hour,&min,&sec,variable); timestamp->tm_mon = mon-1; timestamp->tm_mday = day; timestamp->tm_year = year-1900; timestamp->tm_hour = hour; timestamp->tm_min = min; timestamp->tm_sec = sec; timestamp->tm_isdst = -1; tournament_info->start_round_2 = mktime(timestamp); } else if (strcmp(variable,"start_round_3") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; sscanf(value,format,&mon,&day,&year,&hour,&min,&sec); tournament_check_date(&mon,&day,&year,&hour,&min,&sec,variable); timestamp->tm_mon = mon-1; timestamp->tm_mday = day; timestamp->tm_year = year-1900; timestamp->tm_hour = hour; timestamp->tm_min = min; timestamp->tm_sec = sec; timestamp->tm_isdst = -1; tournament_info->start_round_3 = mktime(timestamp); } else if (strcmp(variable,"start_round_4") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; sscanf(value,format,&mon,&day,&year,&hour,&min,&sec); tournament_check_date(&mon,&day,&year,&hour,&min,&sec,variable); timestamp->tm_mon = mon-1; timestamp->tm_mday = day; timestamp->tm_year = year-1900; timestamp->tm_hour = hour; timestamp->tm_min = min; timestamp->tm_sec = sec; timestamp->tm_isdst = -1; tournament_info->start_round_4 = mktime(timestamp); } else if (strcmp(variable,"tournament_end") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; sscanf(value,format,&mon,&day,&year,&hour,&min,&sec); tournament_check_date(&mon,&day,&year,&hour,&min,&sec,variable); timestamp->tm_mon = mon-1; timestamp->tm_mday = day; timestamp->tm_year = year-1900; timestamp->tm_hour = hour; timestamp->tm_min = min; timestamp->tm_sec = sec; timestamp->tm_isdst = -1; tournament_info->tournament_end = mktime(timestamp); } else if (strcmp(variable,"game_selection") == 0) { if (atoi(pointer) >= 1 && atoi(pointer) <= 2) tournament_info->game_selection = atoi(pointer); } else if (strcmp(variable,"game_type") == 0) { if (atoi(pointer) >= 1 && atoi(pointer) <= 4) tournament_info->game_type = atoi(pointer); } else if (strcmp(variable,"game_client") == 0) { if (atoi(pointer) >= 1 && atoi(pointer) <= 2) tournament_info->game_client = atoi(pointer); } else if (strcmp(variable,"format") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; if (tournament_info->format) xfree((void *)tournament_info->format); tournament_info->format = xstrdup(value); } else if (strcmp(variable,"races") == 0) { unsigned int intvalue = 0; unsigned int i; pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; for(i=0;iraces = intvalue; } else if (strcmp(variable,"sponsor") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; have_sponsor = xstrdup(value); } else if (strcmp(variable,"icon") == 0) { pointer = strchr(pointer,'\"'); pointer++; value = pointer; pointer = strchr(pointer,'\"'); pointer[0]='\0'; have_icon = xstrdup(value); } else if (strcmp(variable,"thumbs_down") == 0) { tournament_info->thumbs_down = atoi(pointer); } else eventlog(eventlog_level_error,__FUNCTION__,"bad option \"%s\" in \"%s\"",variable,filename); if (have_sponsor && have_icon) { sponsor = xmalloc(strlen(have_sponsor)+6); if (strlen(have_icon) == 4) sprintf(sponsor, "%c%c%c%c,%s",have_icon[3],have_icon[2],have_icon[1],have_icon[0],have_sponsor); else if (strlen(have_icon) == 2) sprintf(sponsor, "%c%c3W,%s",have_icon[1],have_icon[0],have_sponsor); else { sprintf(sponsor, "PX3W,%s",have_sponsor); /* default to standard FT icon */ eventlog(eventlog_level_warn,__FUNCTION__,"bad icon length, using W3XP"); } if (tournament_info->sponsor) xfree((void *)tournament_info->sponsor); tournament_info->sponsor = xstrdup(sponsor); xfree((void *)have_sponsor); xfree((void *)have_icon); xfree((void *)sponsor); have_sponsor = NULL; have_icon = NULL; } } } if (have_sponsor) xfree((void *)have_sponsor); if (have_icon) xfree((void *)have_icon); xfree((void *)timestamp); file_get_line(NULL); // clear file_get_line buffer fclose(fp); /* check if we have timestamps for all the times */ /* if not disable tournament by setting "start_preliminary" to 0 */ if (tournament_info->end_signup == 0 || tournament_info->end_preliminary == 0 || tournament_info->start_round_1 == 0 || tournament_info->start_round_2 == 0 || tournament_info->start_round_3 == 0 || tournament_info->start_round_4 == 0 || tournament_info->tournament_end == 0) { tournament_info->start_preliminary = 0; eventlog(eventlog_level_warn,__FUNCTION__,"one or more timestamps for tournaments is not valid, tournament has been disabled"); } else { tournamentlist_create(); } return 0; } extern int tournament_destroy(void) { if (tournament_info->format) xfree((void *)tournament_info->format); if (tournament_info->sponsor) xfree((void *)tournament_info->sponsor); if (tournament_info) xfree((void *)tournament_info); tournament_info = NULL; gamelist_destroy(); return 0; } extern int tournament_reload(char const * filename) { time_t tm; time(&tm); if((tm >= tournament_info->start_preliminary) && (tm <= tournament_info->tournament_end)) { eventlog(eventlog_level_info,__FUNCTION__,"unable to reload tournament, tournament is in process"); return -1; } tournament_destroy(); return tournament_init(filename); } /*****/ extern unsigned int tournament_get_start_preliminary(void) { return tournament_info->start_preliminary; } extern unsigned int tournament_get_end_signup(void) { return tournament_info->end_signup; } extern unsigned int tournament_get_end_preliminary(void) { return tournament_info->end_preliminary; } extern unsigned int tournament_get_start_round_1(void) { return tournament_info->start_round_1; } extern unsigned int tournament_get_start_round_2(void) { return tournament_info->start_round_2; } extern unsigned int tournament_get_start_round_3(void) { return tournament_info->start_round_3; } extern unsigned int tournament_get_start_round_4(void) { return tournament_info->start_round_4; } extern unsigned int tournament_get_tournament_end(void) { return tournament_info->tournament_end; } extern unsigned int tournament_get_game_selection(void) { return tournament_info->game_selection; } extern unsigned int tournament_get_game_type(void) { return tournament_info->game_type; } extern unsigned int tournament_get_races(void) { return tournament_info->races; } extern char * tournament_get_format(void) { return tournament_info->format; } extern char * tournament_get_sponsor(void) { return tournament_info->sponsor; } extern unsigned int tournament_get_thumbs_down(void) { return tournament_info->thumbs_down; } /****/ pvpgn-1.8.5/src/bnproxy/0000755000175000017500000000000011151345372014133 5ustar aaronaaronpvpgn-1.8.5/src/bnproxy/virtconn.h0000644000175000017500000001063211151345317016147 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_VIRTCONN_TYPES #define INCLUDED_VIRTCONN_TYPES typedef enum { virtconn_class_bnet, virtconn_class_file, virtconn_class_bot, virtconn_class_none } t_virtconn_class; typedef enum { virtconn_state_empty, virtconn_state_initial, virtconn_state_connected, virtconn_state_connecting } t_virtconn_state; #ifdef VIRTCONN_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES #include "common/queue.h" #else #define JUST_NEED_TYPES #include "common/queue.h" #undef JUST_NEED_TYPES #endif #endif typedef struct virtconn #ifdef VIRTCONN_INTERNAL_ACCESS { int csd; /* client side socket descriptor */ int ssd; /* server side socket descriptor */ t_virtconn_class class; /* normal, file, or bot */ t_virtconn_state state; /* initial, connected, etc */ unsigned short udpport; /* real port # to send UDP to */ unsigned int udpaddr; /* real IP # to send UDP to */ t_queue * coutqueue; /* client packets waiting to be sent */ unsigned int coutsize; /* client amount sent from the current output packet */ t_queue * cinqueue; /* client packet waiting to be processed */ unsigned int cinsize; /* client amount received into the current input packet */ t_queue * soutqueue; /* server packets waiting to be sent */ unsigned int soutsize; /* server amount sent from the current output packet */ t_queue * sinqueue; /* server packet waiting to be processed */ unsigned int sinsize; /* server amount received into the current input packet */ unsigned int fileleft; /* number of bytes in file download from server left */ } #endif t_virtconn; #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_VIRTCONN_PROTOS #define INCLUDED_VIRTCONN_PROTOS #define JUST_NEED_TYPES #include "common/packet.h" #include "common/queue.h" #include "common/list.h" #undef JUST_NEED_TYPES extern t_virtconn * virtconn_create(int csd, int ssd, unsigned int udpaddr, unsigned short udpport) ; extern void virtconn_destroy(t_virtconn * vc); extern t_virtconn_class virtconn_get_class(t_virtconn const * vc); extern void virtconn_set_class(t_virtconn * vc, t_virtconn_class class); extern t_virtconn_state virtconn_get_state(t_virtconn const * vc); extern void virtconn_set_state(t_virtconn * vc, t_virtconn_state state); extern unsigned int virtconn_get_udpaddr(t_virtconn const * vc); extern unsigned short virtconn_get_udpport(t_virtconn const * vc); extern t_queue * * virtconn_get_clientin_queue(t_virtconn * vc); extern int virtconn_get_clientin_size(t_virtconn const * vc); extern void virtconn_set_clientin_size(t_virtconn * vc, unsigned int size); extern t_queue * * virtconn_get_clientout_queue(t_virtconn * vc); extern int virtconn_get_clientout_size(t_virtconn const * vc); extern void virtconn_set_clientout_size(t_virtconn * vc, unsigned int size); extern int virtconn_get_client_socket(t_virtconn const * vc); extern t_queue * * virtconn_get_serverin_queue(t_virtconn * vc); extern int virtconn_get_serverin_size(t_virtconn const * vc); extern void virtconn_set_serverin_size(t_virtconn * vc, unsigned int size); extern t_queue * * virtconn_get_serverout_queue(t_virtconn * vc); extern int virtconn_get_serverout_size(t_virtconn const * vc); extern void virtconn_set_serverout_size(t_virtconn * vc, unsigned int size); extern int virtconn_get_server_socket(t_virtconn const * vc); extern void virtconn_set_fileleft(t_virtconn * vc, unsigned int size); extern unsigned int virtconn_get_fileleft(t_virtconn const * vc); extern int virtconnlist_create(void); extern int virtconnlist_destroy(void); extern t_list * virtconnlist(void); #endif #endif pvpgn-1.8.5/src/bnproxy/virtconn.c0000644000175000017500000002073111151345317016143 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define VIRTCONN_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include "compat/socket.h" #include "compat/psock.h" #include "common/queue.h" #include "common/list.h" #include "common/eventlog.h" #include "virtconn.h" #include "common/setup_after.h" static t_list * virtconn_head=NULL; extern t_virtconn * virtconn_create(int csd, int ssd, unsigned int udpaddr, unsigned short udpport) { t_virtconn * temp=NULL; if (csd<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad client socket"); return NULL; } if (ssd<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad server socket"); return NULL; } if (!(temp = malloc(sizeof(t_virtconn)))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for temp"); return NULL; } temp->csd = csd; temp->ssd = ssd; temp->udpport = udpport; temp->udpaddr = udpaddr; temp->class = virtconn_class_none; temp->state = virtconn_state_initial; temp->coutqueue = NULL; temp->coutsize = 0; temp->cinqueue = NULL; temp->cinsize = 0; temp->soutqueue = NULL; temp->soutsize = 0; temp->sinqueue = NULL; temp->sinsize = 0; temp->fileleft = 0; if (list_prepend_data(virtconn_head,temp)<0) { free(temp); eventlog(eventlog_level_error,__FUNCTION__,"could not prepend temp"); return NULL; } return temp; } extern void virtconn_destroy(t_virtconn * vc) { t_elem * curr; if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return; } if (list_remove_data(virtconn_head,vc, &curr)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); vc->state = virtconn_state_empty; psock_close(vc->ssd); psock_close(vc->csd); /* clear out the packet queues */ queue_clear(&vc->sinqueue); queue_clear(&vc->soutqueue); queue_clear(&vc->cinqueue); queue_clear(&vc->coutqueue); eventlog(eventlog_level_info,__FUNCTION__,"[%d] closed server connection (%d) class=%d",vc->ssd,vc->csd,(int)vc->class); eventlog(eventlog_level_info,__FUNCTION__,"[%d] closed client connection (%d) class=%d",vc->csd,vc->ssd,(int)vc->class); free(vc); } extern t_virtconn_class virtconn_get_class(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return virtconn_class_none; } return vc->class; } extern void virtconn_set_class(t_virtconn * vc, t_virtconn_class class) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return; } vc->class = class; } extern t_virtconn_state virtconn_get_state(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return virtconn_state_empty; } return vc->state; } extern void virtconn_set_state(t_virtconn * vc, t_virtconn_state state) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return; } vc->state = state; } extern unsigned int virtconn_get_udpaddr(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return 0; } return vc->udpaddr; } extern unsigned short virtconn_get_udpport(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return 0; } return vc->udpport; } extern t_queue * * virtconn_get_clientin_queue(t_virtconn * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return &vc->cinqueue; } extern int virtconn_get_clientin_size(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } return vc->cinsize; } extern void virtconn_set_clientin_size(t_virtconn * vc, unsigned int size) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } vc->cinsize = size; } extern t_queue * * virtconn_get_clientout_queue(t_virtconn * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return &vc->coutqueue; } extern int virtconn_get_clientout_size(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } return vc->coutsize; } extern void virtconn_set_clientout_size(t_virtconn * vc, unsigned int size) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } vc->coutsize = size; } extern int virtconn_get_client_socket(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return -1; } return vc->csd; } extern t_queue * * virtconn_get_serverin_queue(t_virtconn * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return &vc->sinqueue; } extern int virtconn_get_serverin_size(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } return vc->sinsize; } extern void virtconn_set_serverin_size(t_virtconn * vc, unsigned int size) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } vc->sinsize = size; } extern t_queue * * virtconn_get_serverout_queue(t_virtconn * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return NULL; } return &vc->soutqueue; } extern int virtconn_get_serverout_size(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } return vc->soutsize; } extern void virtconn_set_serverout_size(t_virtconn * vc, unsigned int size) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } vc->soutsize = size; } extern int virtconn_get_server_socket(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return -1; } return vc->ssd; } extern void virtconn_set_fileleft(t_virtconn * vc, unsigned int size) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return; } vc->fileleft = size; } extern unsigned int virtconn_get_fileleft(t_virtconn const * vc) { if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL virtconn"); return 0; } return vc->fileleft; } extern int virtconnlist_create(void) { if (!(virtconn_head = list_create())) return -1; return 0; } extern int virtconnlist_destroy(void) { if (list_destroy(virtconn_head)<0) return -1; virtconn_head = NULL; return 0; } extern t_list * virtconnlist(void) { return virtconn_head; } pvpgn-1.8.5/src/bnproxy/bnproxy.c0000644000175000017500000010327311151345317016005 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #include "compat/exitstatus.h" #ifdef HAVE_UNISTD_H # include #endif #include "compat/stdfileno.h" #ifdef HAVE_FCNTL_H # include #else # ifdef HAVE_SYS_FILE_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memset.h" #include "compat/memcpy.h" #include #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/recv.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #ifdef HAVE_NETDB_H # include #endif #include "compat/psock.h" #include "common/packet.h" #include "common/init_protocol.h" #include "common/hexdump.h" #include "common/eventlog.h" #include "common/bn_type.h" #include "common/queue.h" #include "common/network.h" #include "common/list.h" #include "common/util.h" #include "virtconn.h" #include "common/version.h" #include "common/setup_after.h" FILE * hexstrm=NULL; /* FIXME: This code is horribly unreadable. The UDP stuff is a hack for now. */ #define PROXY_FLAG_UDP 1 static int init_virtconn(t_virtconn * vc, struct sockaddr_in servaddr); static int proxy_process(unsigned short server_listen_port, struct sockaddr_in servaddr); static void usage(char const * progname); static int init_virtconn(t_virtconn * vc, struct sockaddr_in servaddr) { int addlen; char connect_type; /* determine connection type by first character sent by client */ addlen = psock_recv(virtconn_get_client_socket(vc),&connect_type,sizeof(char),0); if (addlen<0 && (psock_errno()==PSOCK_EINTR || psock_errno()==PSOCK_EAGAIN || psock_errno()==PSOCK_EWOULDBLOCK)) return 0; /* error occurred or connection lost */ if (addlen<1) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not get virtconn class (closing connection) (psock_recv: %s)",virtconn_get_client_socket(vc),pstrerror(psock_errno())); return -1; } switch (connect_type) { case CLIENT_INITCONN_CLASS_BNET: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated normal connection",virtconn_get_client_socket(vc)); virtconn_set_class(vc,virtconn_class_bnet); break; case CLIENT_INITCONN_CLASS_FILE: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated file download connection",virtconn_get_client_socket(vc)); virtconn_set_class(vc,virtconn_class_file); break; case CLIENT_INITCONN_CLASS_BOT: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated chat bot connection",virtconn_get_client_socket(vc)); virtconn_set_class(vc,virtconn_class_bot); break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] client initiated unknown connection type 0x%02hx (length %d) (closing connection)",virtconn_get_client_socket(vc),(unsigned short)connect_type,addlen); return -1; } /* now connect to the real server */ if (psock_connect(virtconn_get_server_socket(vc),(struct sockaddr *)&servaddr,(psock_t_socklen)sizeof(servaddr))<0) { if (psock_errno()!=PSOCK_EINPROGRESS) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not connect to server (psock_connect: %s)\n",virtconn_get_client_socket(vc),pstrerror(psock_errno())); return -1; } virtconn_set_state(vc,virtconn_state_connecting); } else virtconn_set_state(vc,virtconn_state_connected); { t_packet * packet; if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create packet",virtconn_get_client_socket(vc)); return -1; } packet_append_data(packet,&connect_type,1); queue_push_packet(virtconn_get_serverout_queue(vc),packet); packet_del_ref(packet); } return 0; } static int proxy_process(unsigned short server_listen_port, struct sockaddr_in servaddr) { int lsock; struct sockaddr_in laddr; t_psock_fd_set rfds, wfds; int highest_fd; int udpsock; t_virtconn * vc; t_elem const * curr; int csocket; int ssocket; if ((udpsock = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_DGRAM,PSOCK_IPPROTO_UDP))<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create UDP socket (psock_socket: %s)",pstrerror(psock_errno())); return -1; } if (psock_ctl(udpsock,PSOCK_NONBLOCK)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set UDP listen socket to non-blocking mode (psock_ctl: %s)",pstrerror(psock_errno())); if ((lsock = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create listening socket (psock_socket: %s)",pstrerror(psock_errno())); psock_close(udpsock); return -1; } { int val=1; if (psock_setsockopt(lsock,PSOCK_SOL_SOCKET,PSOCK_SO_REUSEADDR,&val,(psock_t_socklen)sizeof(int))<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set socket option SO_REUSEADDR (psock_setsockopt: %s)",lsock,pstrerror(psock_errno())); /* not a fatal error... */ } memset(&laddr,0,sizeof(laddr)); laddr.sin_family = PSOCK_AF_INET; laddr.sin_port = htons(server_listen_port); laddr.sin_addr.s_addr = htonl(INADDR_ANY); if (psock_bind(lsock,(struct sockaddr *)&laddr,(psock_t_socklen)sizeof(laddr))<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not bind socket to address 0.0.0.0:%hu TCP (psock_bind: %s)",server_listen_port,pstrerror(psock_errno())); psock_close(udpsock); psock_close(lsock); return -1; } memset(&laddr,0,sizeof(laddr)); laddr.sin_family = PSOCK_AF_INET; laddr.sin_port = htons(server_listen_port); laddr.sin_addr.s_addr = htonl(INADDR_ANY); if (psock_bind(udpsock,(struct sockaddr *)&laddr,(psock_t_socklen)sizeof(laddr))<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not bind socket to address 0.0.0.0:%hu UDP (psock_bind: %s)",server_listen_port,pstrerror(psock_errno())); psock_close(udpsock); psock_close(lsock); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"bound to UDP port %hu",server_listen_port); /* tell socket to listen for connections */ if (psock_listen(lsock,LISTEN_QUEUE)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not listen (psock_listen: %s)",pstrerror(psock_errno())); psock_close(udpsock); psock_close(lsock); return -1; } if (psock_ctl(lsock,PSOCK_NONBLOCK)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not set TCP listen socket to non-blocking mode (psock_ctl: %s)",pstrerror(psock_errno())); eventlog(eventlog_level_info,__FUNCTION__,"listening on TCP port %hu",server_listen_port); for (;;) { /* loop over all connections to create the sets for select() */ PSOCK_FD_ZERO(&rfds); PSOCK_FD_ZERO(&wfds); highest_fd = lsock; PSOCK_FD_SET(lsock,&rfds); if (udpsock>highest_fd) highest_fd = udpsock; PSOCK_FD_SET(udpsock,&rfds); LIST_TRAVERSE_CONST(virtconnlist(),curr) { vc = elem_get_data(curr); csocket = virtconn_get_client_socket(vc); if (queue_get_length((t_queue const * const *)virtconn_get_clientout_queue(vc))>0) PSOCK_FD_SET(csocket,&wfds); /* pending output, also check for writeability */ PSOCK_FD_SET(csocket,&rfds); if (csocket>highest_fd) highest_fd = csocket; switch (virtconn_get_state(vc)) { case virtconn_state_connecting: eventlog(eventlog_level_debug,__FUNCTION__,"waiting for %d to finish connecting",ssocket); ssocket = virtconn_get_server_socket(vc); PSOCK_FD_SET(ssocket,&wfds); /* wait for connect to complete */ if (ssocket>highest_fd) highest_fd = ssocket; break; case virtconn_state_connected: eventlog(eventlog_level_debug,__FUNCTION__,"checking for reading on connected socket %d",ssocket); ssocket = virtconn_get_server_socket(vc); if (queue_get_length((t_queue const * const *)virtconn_get_serverout_queue(vc))>0) PSOCK_FD_SET(ssocket,&wfds); /* pending output, also check for writeability */ PSOCK_FD_SET(ssocket,&rfds); if (ssocket>highest_fd) highest_fd = ssocket; break; default: /* avoid warning */ break; } } /* find which sockets need servicing */ if (psock_select(highest_fd+1,&rfds,&wfds,NULL,NULL)<0) { if (errno!=PSOCK_EINTR) eventlog(eventlog_level_error,__FUNCTION__,"select failed (select: %s)",pstrerror(errno)); continue; } /* check for incoming connection */ if (PSOCK_FD_ISSET(lsock,&rfds)) { int asock; struct sockaddr_in caddr; psock_t_socklen caddr_len; /* accept the connection */ caddr_len = sizeof(caddr); if ((asock = psock_accept(lsock,(struct sockaddr *)&caddr,&caddr_len))<0) { if (psock_errno()==PSOCK_EWOULDBLOCK || psock_errno()==PSOCK_ECONNABORTED) /* BSD, POSIX error for aborted connections, SYSV often uses EAGAIN */ eventlog(eventlog_level_error,__FUNCTION__,"client aborted connection (psock_accept: %s)",pstrerror(psock_errno())); else /* EAGAIN can mean out of resources _or_ connection aborted */ if (psock_errno()!=PSOCK_EINTR) eventlog(eventlog_level_error,__FUNCTION__,"could not accept new connection (psock_accept: %s)",pstrerror(psock_errno())); } else { int ssd; int val=1; eventlog(eventlog_level_info,__FUNCTION__,"[%d] accepted connection from %s:%hu",asock,inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port)); if (psock_setsockopt(asock,PSOCK_SOL_SOCKET,PSOCK_SO_KEEPALIVE,&val,(psock_t_socklen)sizeof(val))<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set socket option SO_KEEPALIVE (psock_setsockopt: %s)",asock,pstrerror(psock_errno())); /* not a fatal error */ if (psock_ctl(asock,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set TCP socket to non-blocking mode (closing connection) (psock_ctl: %s)",asock,pstrerror(psock_errno())); psock_close(asock); } else if ((ssd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could create TCP socket (closing connection) (psock_socket: %s)",asock,pstrerror(psock_errno())); psock_close(asock); } else if (psock_ctl(ssd,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set TCP socket to non-blocking mode (closing connection) (psock_ctl: %s)",asock,pstrerror(psock_errno())); psock_close(ssd); psock_close(asock); } else if (!(vc = virtconn_create(asock,ssd,ntohl(caddr.sin_addr.s_addr),BNETD_MIN_TEST_PORT))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to create new connection (closing connection)",asock); psock_close(ssd); psock_close(asock); } else { memset(&caddr,0,sizeof(caddr)); caddr.sin_family = PSOCK_AF_INET; caddr.sin_port = htons(virtconn_get_udpport(vc)); caddr.sin_addr.s_addr = htonl(virtconn_get_udpaddr(vc)); eventlog(eventlog_level_info,__FUNCTION__,"[%d] addr now %s:%hu",asock,inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port)); } } } eventlog(eventlog_level_debug,__FUNCTION__,"checking for incoming UDP"); if (PSOCK_FD_ISSET(udpsock,&rfds)) { t_packet * upacket; struct sockaddr_in toaddr; struct sockaddr_in fromaddr; psock_t_socklen fromlen; int len; if (!(upacket = packet_create(packet_class_raw))) eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input"); else { /* packet_set_flags(upacket,PROXY_FLAG_UDP);*/ fromlen = sizeof(fromaddr); if ((len = psock_recvfrom(udpsock,packet_get_raw_data_build(upacket,0),MAX_PACKET_SIZE,0,(struct sockaddr *)&fromaddr,&fromlen))<0) { if (psock_errno()!=PSOCK_EINTR && psock_errno()!=PSOCK_EAGAIN && psock_errno()!=PSOCK_EWOULDBLOCK) eventlog(eventlog_level_error,__FUNCTION__,"could not recv UDP datagram (psock_recvfrom: %s)",pstrerror(psock_errno())); } else { if (fromaddr.sin_family!=PSOCK_AF_INET) eventlog(eventlog_level_error,__FUNCTION__,"got UDP datagram with bad address family %d",fromaddr.sin_family); else { char tempa[32]; char tempb[32]; packet_set_size(upacket,len); if (fromaddr.sin_addr.s_addr==servaddr.sin_addr.s_addr) /* from server */ { if ((curr = list_get_first_const(virtconnlist()))) /* hack.. find proper client */ { vc = elem_get_data(curr); memset(&toaddr,0,sizeof(toaddr)); toaddr.sin_family = PSOCK_AF_INET; toaddr.sin_port = htons(virtconn_get_udpport(vc)); toaddr.sin_addr.s_addr = htonl(virtconn_get_udpaddr(vc)); eventlog(eventlog_level_info,__FUNCTION__,"[%d] addr by UDP send is %s:%hu",virtconn_get_client_socket(vc),inet_ntoa(toaddr.sin_addr),ntohs(toaddr.sin_port)); if (hexstrm) { strcpy(tempa,inet_ntoa(fromaddr.sin_addr)); strcpy(tempb,inet_ntoa(toaddr.sin_addr)); fprintf(hexstrm,"%d: srv prot=UDP from=%s:%hu to=%s:%hu length=%d\n", udpsock, tempa, ntohs(fromaddr.sin_port), tempb, ntohs(toaddr.sin_port), len); hexdump(hexstrm,packet_get_raw_data(upacket,0),len); } /*queue_push_packet(virtconn_get_clientout_queue(__));*/ /* where to queue ... */ for (;;) /* hack.. just block for now */ { if (psock_sendto(udpsock,packet_get_raw_data_const(upacket,0),len,0, (struct sockaddr *)&toaddr,(psock_t_socklen)sizeof(toaddr))0) { if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw file packet for input"); continue; } if (fileleft>MAX_PACKET_SIZE) packet_set_size(packet,MAX_PACKET_SIZE); else packet_set_size(packet,fileleft); } else { if (!(packet = packet_create(packet_class_file))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate file packet for input"); continue; } } } break; case virtconn_class_bot: if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input"); continue; } packet_set_size(packet,MAX_PACKET_SIZE); /* read as much as possible */ break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] connection has bad type (closing connection)",virtconn_get_client_socket(vc)); virtconn_destroy(vc); continue; } queue_push_packet(virtconn_get_serverin_queue(vc),packet); packet_del_ref(packet); if (!queue_get_length(virtconn_get_serverin_queue(vc))) continue; /* push failed */ currsize = 0; } packet = queue_peek_packet((t_queue const * const *)virtconn_get_serverin_queue(vc)); /* avoid warning */ switch (net_recv_packet(ssocket,packet,&currsize)) { case -1: virtconn_destroy(vc); continue; case 0: /* still working on it */ virtconn_set_serverin_size(vc,currsize); if (virtconn_get_class(vc)!=virtconn_class_bot || currsize<1) break; else packet_set_size(packet,currsize); /* fallthough... we take what we can get with the bot data */ case 1: /* done reading */ packet = queue_pull_packet(virtconn_get_serverin_queue(vc)); if (virtconn_get_class(vc)==virtconn_class_file) { unsigned int len=virtconn_get_fileleft(vc); if (len) virtconn_set_fileleft(vc,len-currsize); else if (packet_get_type(packet)==SERVER_FILE_REPLY && packet_get_size(packet)>=sizeof(t_server_file_reply)) virtconn_set_fileleft(vc,bn_int_get(packet->u.server_file_reply.filelen)); } queue_push_packet(virtconn_get_clientout_queue(vc),packet); packet_del_ref(packet); virtconn_set_serverin_size(vc,0); } } eventlog(eventlog_level_debug,__FUNCTION__,"checking %d for client writeability",csocket); if (PSOCK_FD_ISSET(csocket,&wfds)) { currsize = virtconn_get_clientout_size(vc); switch (net_send_packet(csocket,queue_peek_packet((t_queue const * const *)virtconn_get_clientout_queue(vc)),&currsize)) /* avoid warning */ { case -1: virtconn_destroy(vc); continue; case 0: /* still working on it */ virtconn_set_clientout_size(vc,currsize); break; case 1: /* done sending */ packet = queue_pull_packet(virtconn_get_clientout_queue(vc)); if (hexstrm) { fprintf(hexstrm,"%d: srv class=%s[0x%04hx] type=%s[0x%04hx] length=%hu\n", csocket, packet_get_class_str(packet),packet_get_class(packet), packet_get_type_str(packet,packet_dir_from_server),packet_get_type(packet), packet_get_size(packet)); hexdump(hexstrm,packet_get_raw_data(packet,0),packet_get_size(packet)); } packet_del_ref(packet); virtconn_set_clientout_size(vc,0); } } eventlog(eventlog_level_debug,__FUNCTION__,"checking %d for server writeability",ssocket); if (ssocket!=-1 && PSOCK_FD_ISSET(ssocket,&wfds)) { if (virtconn_get_state(vc)==virtconn_state_connecting) { int err; psock_t_socklen errlen; err = 0; errlen = sizeof(err); if (psock_getsockopt(ssocket,PSOCK_SOL_SOCKET,PSOCK_SO_ERROR,&err,&errlen)<0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to read socket error (psock_getsockopt[psock_connect]: %s)",virtconn_get_client_socket(vc),pstrerror(psock_errno())); virtconn_destroy(vc); continue; } if (errlen==0 || err==0) virtconn_set_state(vc,virtconn_state_connected); else { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not connect to server (psock_getsockopt[psock_connect]: %s)",virtconn_get_client_socket(vc),pstrerror(err)); virtconn_destroy(vc); continue; } } else { currsize = virtconn_get_serverout_size(vc); switch (net_send_packet(ssocket,queue_peek_packet((t_queue const * const *)virtconn_get_serverout_queue(vc)),&currsize)) /* avoid warning */ { case -1: virtconn_destroy(vc); continue; case 0: /* still working on it */ virtconn_set_serverout_size(vc,currsize); break; case 1: /* done sending */ packet = queue_pull_packet(virtconn_get_serverout_queue(vc)); packet_del_ref(packet); virtconn_set_serverout_size(vc,0); } } } } eventlog(eventlog_level_debug,__FUNCTION__,"done checking"); } return 0; } static void usage(char const * progname) { fprintf(stderr, "usage: %s [] []\n" " -d FILE, --hexdump=FILE do hex dump of packets into FILE\n" " -l FILE, --logfile=FILE save eventlog lines into FILE\n" " -p PORT, --port=PORT listen for connections on port PORT\n" #ifdef DO_DAEMONIZE " -f, --foreground don't daemonize\n" #else " -f, --foreground don't daemonize (default)\n" #endif " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n", progname); exit(STATUS_FAILURE); } extern int main(int argc, char * argv[]) { int a; char const * logfile=NULL; char const * hexfile=NULL; int foreground=0; unsigned short port=0; char const * servname=NULL; unsigned short servport=0; struct hostent * host; struct sockaddr_in servaddr; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } for (a=1; a=argc) { if (str_to_ushort(argv[a],&servport)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (!servname && argv[a][0]!='-' && a+2>=argc) servname = argv[a]; else if (strncmp(argv[a],"--hexdump=",10)==0) { if (hexfile) { fprintf(stderr,"%s: hexdump file was already specified as \"%s\"\n",argv[0],hexfile); usage(argv[0]); } hexfile = &argv[a][10]; } else if (strcmp(argv[a],"-d")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (hexfile) { fprintf(stderr,"%s: hexdump file was already specified as \"%s\"\n",argv[0],hexfile); usage(argv[0]); } a++; hexfile = argv[a]; } else if (strncmp(argv[a],"--logfile=",10)==0) { if (logfile) { fprintf(stderr,"%s: eventlog file was already specified as \"%s\"\n",argv[0],logfile); usage(argv[0]); } logfile = &argv[a][10]; } else if (strcmp(argv[a],"-l")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (logfile) { fprintf(stderr,"%s: eventlog file was already specified as \"%s\"\n",argv[0],logfile); usage(argv[0]); } a++; logfile = argv[a]; } else if (strncmp(argv[a],"--port=",7)==0) { if (port>0) { fprintf(stderr,"%s: listen port was already specified as \"%hu\"\n",argv[0],port); usage(argv[0]); } if (str_to_ushort(&argv[a][7],&port)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (strcmp(argv[a],"-p")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (port>0) { fprintf(stderr,"%s: eventlog file was already specified as \"%hu\"\n",argv[0],port); usage(argv[0]); } a++; if (str_to_ushort(argv[a],&port)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (strcmp(argv[a],"-f")==0 || strcmp(argv[a],"--foreground")==0) foreground = 1; else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage")==0) usage(argv[0]); else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0) { printf("version "PVPGN_VERSION"\n"); return STATUS_SUCCESS; } else if (strcmp(argv[a],"--hexdump")==0 || strcmp(argv[a],"--logfile")==0 || strcmp(argv[a],"--port")==0) { fprintf(stderr,"%s: option \"%s\" requires and argument.\n",argv[0],argv[a]); usage(argv[0]); } else { fprintf(stderr,"%s: bad option \"%s\"\n",argv[0],argv[a]); usage(argv[0]); } if (port==0) port = BNETD_SERV_PORT; if (servport==0) servport = BNETD_SERV_PORT; if (!servname) servname = BNETD_DEFAULT_HOST; if (psock_init()<0) { fprintf(stderr,"%s: could not initialize socket functions\n",argv[0]); return STATUS_FAILURE; } if (!(host = gethostbyname(servname))) { fprintf(stderr,"%s: unknown host \"%s\"\n",argv[0],servname); return STATUS_FAILURE; } memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = PSOCK_AF_INET; servaddr.sin_port = htons(servport); memcpy(&servaddr.sin_addr.s_addr,host->h_addr_list[0],host->h_length); eventlog_set(stderr); /* errors to eventlog from here on... */ if (logfile) { eventlog_clear_level(); eventlog_add_level("error"); eventlog_add_level("warn"); eventlog_add_level("info"); eventlog_add_level("debug"); if (eventlog_open(logfile)<0) { eventlog(eventlog_level_fatal,__FUNCTION__,"could not use file \"%s\" for the eventlog (exiting)",logfile); return STATUS_FAILURE; } } #ifdef DO_DAEMONIZE if (!foreground) { if (chdir("/")<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not change working directory to / (chdir: %s)",pstrerror(errno)); return STATUS_FAILURE; } switch (fork()) { case -1: eventlog(eventlog_level_error,__FUNCTION__,"could not fork (fork: %s)",pstrerror(errno)); return STATUS_FAILURE; case 0: /* child */ break; default: /* parent */ return STATUS_SUCCESS; } close(STDINFD); close(STDOUTFD); close(STDERRFD); # ifdef HAVE_SETPGID if (setpgid(0,0)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgid: %s)",pstrerror(errno)); return STATUS_FAILURE; } # else # ifdef HAVE_SETPGRP # ifdef SETPGRP_VOID if (setpgrp()<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)",pstrerror(errno)); return STATUS_FAILURE; } # else if (setpgrp(0,0)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)",pstrerror(errno)); return STATUS_FAILURE; } # endif # else # ifdef HAVE_SETSID if (setsid()<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setsid: %s)",pstrerror(errno)); return STATUS_FAILURE; } # else # error "One of setpgid(), setpgrp(), or setsid() is required" # endif # endif # endif } #endif if (hexfile) if (!(hexstrm = fopen(hexfile,"w"))) eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for writing the hexdump (fopen: %s)",hexfile,pstrerror(errno)); if (proxy_process(port,servaddr)<0) { eventlog(eventlog_level_fatal,__FUNCTION__,"failed to initialize network (exiting)"); return STATUS_FAILURE; } if (hexstrm) if (fclose(hexstrm)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close hexdump file \"%s\" after writing (fclose: %s)",hexfile,pstrerror(errno)); return STATUS_SUCCESS; } pvpgn-1.8.5/src/zlib/0000755000175000017500000000000011151345372013372 5ustar aaronaaronpvpgn-1.8.5/src/zlib/zlib_license.html0000644000175000017500000000646711151345317016736 0ustar aaronaaron zlib License

zlib

License

/* zlib.h -- interface of the 'zlib' general purpose compression library
  version 1.2.1, November 17th, 2003

  Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

  Jean-loup Gailly jloup@gzip.org
  Mark Adler madler@alumni.caltech.edu

*/


Click here to return to the zlib Home Page.
Last modified 22 November 2003
Send all questions about zlib or its license to zlib@gzip.org

Web page copyright © 1996-2003 Greg Roelofs, Jean-loup Gailly and Mark Adler.
zlib software copyright © 1995-2003 Jean-loup Gailly and Mark Adler.
Primary site hosted by France Teaser.
zlib.org domain name donated by Andrew Green.
pvpgn-1.8.5/src/zlib/pvpgn_zlib.h0000644000175000017500000003643111151345317015723 0ustar aaronaaron/* zlib.h -- interface of the 'zlib' general purpose compression library version 1.1.4, March 11th, 2002 Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). */ #ifndef _ZLIB_H #define _ZLIB_H #include "zlib/pvpgn_zconf.h" #ifdef __cplusplus extern "C" { #endif #define ZLIB_VERSION "1.1.4" /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough (for example if an input file is mmap'ed), or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total nb of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total nb of bytes output so far */ char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: ascii or binary */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use in the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 /* Allowed flush values; see deflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative * values are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_ASCII 1 #define Z_UNKNOWN 2 /* Possible values of the data_type field */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ ZEXTERN const char * ZEXPORT pvpgn_zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT pvpgn_deflate OF((z_streamp strm, int flush)); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade the compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space; if deflate returns with Z_OK, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least 0.1% larger than avail_in plus 12 bytes. If deflate does not return Z_STREAM_END, then it must be called again as described above. deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). deflate() may update data_type if it can make a good guess about the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). */ ZEXTERN int ZEXPORT pvpgn_deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ ZEXTERN int ZEXPORT pvpgn_deflateReset OF((z_streamp strm)); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate all the internal compression state. The stream will keep the same compression level and any other attributes that may have been set by deflateInit2. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ ZEXTERN uLong ZEXPORT pvpgn_adler32 OF((uLong adler, const Bytef *buf, uInt len)); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. If buf is NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ ZEXTERN int ZEXPORT pvpgn_deflateInit_ OF((z_streamp strm, int level, const char *version, int stream_size)); ZEXTERN int ZEXPORT pvpgn_deflateInit2_ OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size)); #define pvpgn_deflateInit(strm, level) \ pvpgn_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) #define pvpgn_inflateInit(strm) \ pvpgn_inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) #define pvpgn_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ pvpgn_deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, sizeof(z_stream)) #define pvpgn_inflateInit2(strm, windowBits) \ pvpgn_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) #if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state {int dummy;}; /* hack for buggy compilers */ #endif ZEXTERN const char * ZEXPORT pvpgn_zError OF((int err)); ZEXTERN const uLongf * ZEXPORT pvpgn_get_crc_table OF((void)); #ifdef __cplusplus } #endif #endif /* _ZLIB_H */ pvpgn-1.8.5/src/zlib/pvpgn_zutil.h0000644000175000017500000001336211151345317016130 0ustar aaronaaron/* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-2002 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ #ifndef _Z_UTIL_H #define _Z_UTIL_H #include "common/setup_before.h" #include "zlib/pvpgn_zlib.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef NO_ERRNO_H extern int errno; #else # include #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ typedef unsigned char uch; typedef uch FAR uchf; typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; extern const char *pvpgn_z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) pvpgn_z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ return (strm->msg = (char*)ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 /* The three kinds of block type */ #define MIN_MATCH 3 #define MAX_MATCH 258 /* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ /* target dependencies */ #ifdef MSDOS # define OS_CODE 0x00 # if defined(__TURBOC__) || defined(__BORLANDC__) # if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) /* Allow compilation with ANSI keywords only enabled */ void _Cdecl farfree( void *block ); void *_Cdecl farmalloc( unsigned long nbytes ); # else # include # endif # else /* MSC or DJGPP */ # include # endif #endif #ifdef OS2 # define OS_CODE 0x06 #endif #ifdef WIN32 /* Window 95 & Windows NT */ # define OS_CODE 0x0b #endif #if defined(VAXC) || defined(VMS) # define OS_CODE 0x02 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif #ifdef AMIGA # define OS_CODE 0x01 #endif #if defined(ATARI) || defined(atarist) # define OS_CODE 0x05 #endif #if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 0x07 # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */ # else # ifndef fdopen # define fdopen(fd,mode) NULL /* No fdopen() */ # endif # endif #endif #ifdef __50SERIES /* Prime/PRIMOS */ # define OS_CODE 0x0F #endif #ifdef TOPS20 # define OS_CODE 0x0a #endif #if defined(_BEOS_) || defined(RISCOS) # define fdopen(fd,mode) NULL /* No fdopen() */ #endif #if (defined(_MSC_VER) && (_MSC_VER > 600)) # define fdopen(fd,type) _fdopen(fd,type) #endif /* Common defaults */ #ifndef OS_CODE # define OS_CODE 0x03 /* assume Unix */ #endif #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ #ifdef HAVE_STRERROR extern char *strerror OF((int)); # define zstrerror(errnum) strerror(errnum) #else # define zstrerror(errnum) "" #endif #if defined(pyr) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) /* Use our own functions for small and medium model with MSC <= 5.0. * You may have to use the same strategy for Borland C (untested). * The __SC__ check is for Symantec. */ # define NO_MEMCPY #endif #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) # define HAVE_MEMCPY #endif #ifdef HAVE_MEMCPY # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ # define zmemcpy _fmemcpy # define zmemcmp _fmemcmp # define zmemzero(dest, len) _fmemset(dest, 0, len) # else # define zmemcpy memcpy # define zmemcmp memcmp # define zmemzero(dest, len) memset(dest, 0, len) # endif #else extern void pvpgn_zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); extern int pvpgn_zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); extern void pvpgn_zmemzero OF((Bytef* dest, uInt len)); #endif /* Diagnostic functions */ #ifdef DEBUG # include extern int pvpgn_z_verbose; extern void pvpgn_z_error OF((char *m)); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracevv(x) {if (z_verbose>1) fprintf x ;} # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) #endif typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, uInt len)); voidpf pvpgn_zcalloc OF((voidpf opaque, unsigned items, unsigned size)); void pvpgn_zcfree OF((voidpf opaque, voidpf ptr)); #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} #endif /* _Z_UTIL_H */ pvpgn-1.8.5/src/zlib/pvpgn_adler32.c0000644000175000017500000000237611151345317016213 0ustar aaronaaron/* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "common/setup_before.h" #include "zlib/pvpgn_zlib.h" #define BASE 65521L /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {s1 += buf[i]; s2 += s1;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); /* ========================================================================= */ uLong ZEXPORT pvpgn_adler32(adler, buf, len) uLong adler; const Bytef *buf; uInt len; { unsigned long s1 = adler & 0xffff; unsigned long s2 = (adler >> 16) & 0xffff; int k; if (buf == Z_NULL) return 1L; while (len > 0) { k = len < NMAX ? len : NMAX; len -= k; while (k >= 16) { DO16(buf); buf += 16; k -= 16; } if (k != 0) do { s1 += *buf++; s2 += s1; } while (--k); s1 %= BASE; s2 %= BASE; } return (s2 << 16) | s1; } pvpgn-1.8.5/src/zlib/pvpgn_deflate.h0000644000175000017500000002665611151345317016377 0ustar aaronaaron/* deflate.h -- internal compression state * Copyright (C) 1995-2002 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ #ifndef _DEFLATE_H #define _DEFLATE_H #include "common/setup_before.h" #include "zlib/pvpgn_zutil.h" /* =========================================================================== * Internal compression state. */ #define LENGTH_CODES 29 /* number of length codes, not counting the special END_BLOCK code */ #define LITERALS 256 /* number of literal bytes 0..255 */ #define L_CODES (LITERALS+1+LENGTH_CODES) /* number of Literal or Length codes, including the END_BLOCK code */ #define D_CODES 30 /* number of distance codes */ #define BL_CODES 19 /* number of codes used to transfer the bit lengths */ #define HEAP_SIZE (2*L_CODES+1) /* maximum heap size */ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ #define INIT_STATE 42 #define BUSY_STATE 113 #define FINISH_STATE 666 /* Stream status */ /* Data structure describing a single value and its code string. */ typedef struct ct_data_s { union { ush freq; /* frequency count */ ush code; /* bit string */ } fc; union { ush dad; /* father node in Huffman tree */ ush len; /* length of bit string */ } dl; } FAR ct_data; #define Freq fc.freq #define Code fc.code #define Dad dl.dad #define Len dl.len typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; typedef Pos FAR Posf; typedef unsigned IPos; /* A Pos is an index in the character window. We use short instead of int to * save space in the various tables. IPos is used only for parameter passing. */ typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ int pending; /* nb of bytes in the pending buffer */ int noheader; /* suppress zlib header and adler32 */ Byte data_type; /* UNKNOWN, BINARY or ASCII */ Byte method; /* STORED (for zip only) or DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ uInt w_size; /* LZ77 window size (32K by default) */ uInt w_bits; /* log2(w_size) (8..16) */ uInt w_mask; /* w_size - 1 */ Bytef *window; /* Sliding window. Input bytes are read into the second half of the window, * and move to the first half later to keep a dictionary of at least wSize * bytes. With this organization, matches are limited to a distance of * wSize-MAX_MATCH bytes, but this ensures that IO is always * performed with a length multiple of the block size. Also, it limits * the window size to 64K, which is quite useful on MSDOS. * To do: use the user input buffer as sliding window. */ ulg window_size; /* Actual size of window: 2*wSize, except when the user input buffer * is directly used as sliding window. */ Posf *prev; /* Link to older string with same hash index. To limit the size of this * array to 64K, this link is maintained only for the last 32K strings. * An index in this array is thus a window index modulo 32K. */ Posf *head; /* Heads of the hash chains or NIL. */ uInt ins_h; /* hash index of string to be inserted */ uInt hash_size; /* number of elements in hash table */ uInt hash_bits; /* log2(hash_size) */ uInt hash_mask; /* hash_size-1 */ uInt hash_shift; /* Number of bits by which ins_h must be shifted at each input * step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: * hash_shift * MIN_MATCH >= hash_bits */ long block_start; /* Window position at the beginning of the current output block. Gets * negative when the window is moved backwards. */ uInt match_length; /* length of best match */ IPos prev_match; /* previous match */ int match_available; /* set if previous match exists */ uInt strstart; /* start of string to insert */ uInt match_start; /* start of matching string */ uInt lookahead; /* number of valid bytes ahead in window */ uInt prev_length; /* Length of the best match at previous step. Matches not greater than this * are discarded. This is used in the lazy match evaluation. */ uInt max_chain_length; /* To speed up deflation, hash chains are never searched beyond this * length. A higher limit improves compression ratio but degrades the * speed. */ uInt max_lazy_match; /* Attempt to find a better match only when the current match is strictly * smaller than this value. This mechanism is used only for compression * levels >= 4. */ # define max_insert_length max_lazy_match /* Insert new strings in the hash table only if the match length is not * greater than this length. This saves time but degrades compression. * max_insert_length is used only for compression levels <= 3. */ int level; /* compression level (1..9) */ int strategy; /* favor or force Huffman coding*/ uInt good_match; /* Use a faster search when the previous match is longer than this */ int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ /* Didn't use ct_data typedef below to supress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ struct tree_desc_s l_desc; /* desc. for literal tree */ struct tree_desc_s d_desc; /* desc. for distance tree */ struct tree_desc_s bl_desc; /* desc. for bit length tree */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ int heap_len; /* number of elements in the heap */ int heap_max; /* element of largest frequency */ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. * The same heap array is used to build all trees. */ uch depth[2*L_CODES+1]; /* Depth of each subtree used as tie breaker for trees of equal frequency */ uchf *l_buf; /* buffer for literals or lengths */ uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for * limiting lit_bufsize to 64K: * - frequencies can be kept in 16 bit counters * - if compression is not successful for the first block, all input * data is still in the window so we can still emit a stored block even * when input comes from standard input. (This can also be done for * all blocks if lit_bufsize is not greater than 32K.) * - if compression is not successful for a file smaller than 64K, we can * even emit a stored file instead of a stored block (saving 5 bytes). * This is applicable only for zip (not gzip or zlib). * - creating new Huffman trees less frequently may not provide fast * adaptation to changes in the input data statistics. (Take for * example a binary file with poorly compressible code followed by * a highly compressible string table.) Smaller buffer sizes give * fast adaptation but have of course the overhead of transmitting * trees more frequently. * - I can't count above 4 */ uInt last_lit; /* running index in l_buf */ ushf *d_buf; /* Buffer for distances. To simplify the code, d_buf and l_buf have * the same number of elements. To use different lengths, an extra flag * array would be necessary. */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ int last_eob_len; /* bit length of EOB code for last block */ #ifdef DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif ush bi_buf; /* Output buffer. bits are inserted starting at the bottom (least * significant bits). */ int bi_valid; /* Number of valid bits in bi_buf. All bits above the last valid bit * are always zero. */ } FAR deflate_state; /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ #define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) /* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. */ /* in trees.c */ void pvpgn_tr_init OF((deflate_state *s)); int pvpgn_tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); void pvpgn_tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, int eof)); void pvpgn_tr_align OF((deflate_state *s)); void pvpgn_tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, int eof)); #define d_code(dist) \ ((dist) < 256 ? pvpgn_dist_code[dist] : pvpgn_dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. _dist_code[256] and _dist_code[257] are never * used. */ #ifndef DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) extern uch pvpgn_length_code[]; extern uch pvpgn_dist_code[]; #else extern const uch pvpgn_length_code[]; extern const uch pvpgn_dist_code[]; #endif # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->d_buf[s->last_lit] = 0; \ s->l_buf[s->last_lit++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (length); \ ush dist = (distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ s->dyn_ltree[pvpgn_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ flush = _tr_tally(s, distance, length) #endif #endif pvpgn-1.8.5/src/zlib/pvpgn_trees.c0000644000175000017500000012536511151345317016105 0ustar aaronaaron/* trees.c -- output deflated data using Huffman coding * Copyright (C) 1995-2002 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process uses several Huffman trees. The more * common source values are represented by shorter bit sequences. * * Each code tree is stored in a compressed form which is itself * a Huffman encoding of the lengths of all the code strings (in * ascending order by source values). The actual code strings are * reconstructed from the lengths in the inflate process, as described * in the deflate specification. * * REFERENCES * * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc * * Storer, James A. * Data Compression: Methods and Theory, pp. 49-50. * Computer Science Press, 1988. ISBN 0-7167-8156-5. * * Sedgewick, R. * Algorithms, p290. * Addison-Wesley, 1983. ISBN 0-201-06672-6. */ /* #define GEN_TREES_H */ #include "common/setup_before.h" #include "zlib/pvpgn_deflate.h" #ifdef DEBUG # include #endif /* =========================================================================== * Constants */ #define MAX_BL_BITS 7 /* Bit length codes must not exceed MAX_BL_BITS bits */ #define END_BLOCK 256 /* end of block literal code */ #define REP_3_6 16 /* repeat previous bit length 3-6 times (2 bits of repeat count) */ #define REPZ_3_10 17 /* repeat a zero length 3-10 times (3 bits of repeat count) */ #define REPZ_11_138 18 /* repeat a zero length 11-138 times (7 bits of repeat count) */ local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; local const int extra_dbits[D_CODES] /* extra bits for each distance code */ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; local const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; /* The lengths of the bit length codes are sent in order of decreasing * probability, to avoid transmitting the lengths for unused bit length codes. */ #define Buf_size (8 * 2*sizeof(char)) /* Number of bits used within bi_buf. (bi_buf might be implemented on * more than 16 bits on some systems.) */ /* =========================================================================== * Local data. These are initialized only once. */ #define DIST_CODE_LEN 512 /* see definition of array dist_code below */ #if defined(GEN_TREES_H) || !defined(STDC) /* non ANSI compilers may not accept trees.h */ local ct_data static_ltree[L_CODES+2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However * The codes 286 and 287 are needed to build a canonical tree (see _tr_init * below). */ local ct_data static_dtree[D_CODES]; /* The static distance tree. (Actually a trivial tree since all codes use * 5 bits.) */ uch pvpgn_dist_code[DIST_CODE_LEN]; /* Distance codes. The first 256 values correspond to the distances * 3 .. 258, the last 256 values correspond to the top 8 bits of * the 15 bit distances. */ uch pvpgn_length_code[MAX_MATCH-MIN_MATCH+1]; /* length code for each normalized match length (0 == MIN_MATCH) */ local int base_length[LENGTH_CODES]; /* First normalized length for each code (0 = MIN_MATCH) */ local int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ #else # include "zlib/pvpgn_trees.h" #endif /* GEN_TREES_H */ struct static_tree_desc_s { const ct_data *static_tree; /* static tree or NULL */ const intf *extra_bits; /* extra bits for each code or NULL */ int extra_base; /* base index for extra_bits */ int elems; /* max number of elements in the tree */ int max_length; /* max bit length for the codes */ }; local static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; local static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; local static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== * Local (static) routines in this file. */ local void tr_static_init OF((void)); local void init_block OF((deflate_state *s)); local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); local void build_tree OF((deflate_state *s, tree_desc *desc)); local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, int blcodes)); local void compress_block OF((deflate_state *s, ct_data *ltree, ct_data *dtree)); local void set_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); local void bi_flush OF((deflate_state *s)); local void copy_block OF((deflate_state *s, charf *buf, unsigned len, int header)); #ifdef GEN_TREES_H local void gen_trees_header OF((void)); #endif #ifndef DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ #else /* DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } #endif /* =========================================================================== * Output a short LSB first on the stream. * IN assertion: there is enough room in pendingBuf. */ #define put_short(s, w) { \ put_byte(s, (uch)((w) & 0xff)); \ put_byte(s, (uch)((ush)(w) >> 8)); \ } /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef DEBUG local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits(s, value, length) deflate_state *s; int value; /* value to send */ int length; /* number of bits */ { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { s->bi_buf |= (value << s->bi_valid); put_short(s, s->bi_buf); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); s->bi_valid += length - Buf_size; } else { s->bi_buf |= value << s->bi_valid; s->bi_valid += length; } } #else /* !DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ int val = value;\ s->bi_buf |= (val << s->bi_valid);\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ s->bi_valid += len - Buf_size;\ } else {\ s->bi_buf |= (value) << s->bi_valid;\ s->bi_valid += len;\ }\ } #endif /* DEBUG */ #define MAX(a,b) (a >= b ? a : b) /* the arguments must not have side effects */ /* =========================================================================== * Initialize the various 'constant' tables. */ local void tr_static_init() { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ int code; /* code value */ int dist; /* distance index */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ if (static_init_done) return; /* For some embedded targets, global variables are not initialized: */ static_l_desc.static_tree = static_ltree; static_l_desc.extra_bits = extra_lbits; static_d_desc.static_tree = static_dtree; static_d_desc.extra_bits = extra_dbits; static_bl_desc.extra_bits = extra_blbits; /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { _dist_code[256 + dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: 256+dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) */ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = bi_reverse((unsigned)n, 5); } static_init_done = 1; # ifdef GEN_TREES_H gen_trees_header(); # endif #endif /* defined(GEN_TREES_H) || !defined(STDC) */ } /* =========================================================================== * Genererate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef DEBUG # include # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width)-1 ? ",\n" : ", ")) void pvpgn_gen_trees_header() { FILE *header = fopen("trees.h", "w"); int i; Assert (header != NULL, "Can't open trees.h"); fprintf(header, "/* header created automatically with -DGEN_TREES_H */\n\n"); fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); for (i = 0; i < L_CODES+2; i++) { fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); } fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); } fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); for (i = 0; i < DIST_CODE_LEN; i++) { fprintf(header, "%2u%s", _dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { fprintf(header, "%2u%s", _length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); } fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); for (i = 0; i < LENGTH_CODES; i++) { fprintf(header, "%1u%s", base_length[i], SEPARATOR(i, LENGTH_CODES-1, 20)); } fprintf(header, "local const int base_dist[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "%5u%s", base_dist[i], SEPARATOR(i, D_CODES-1, 10)); } fclose(header); } #endif /* GEN_TREES_H */ /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ void pvpgn_tr_init(s) deflate_state *s; { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; s->l_desc.stat_desc = &static_l_desc; s->d_desc.dyn_tree = s->dyn_dtree; s->d_desc.stat_desc = &static_d_desc; s->bl_desc.dyn_tree = s->bl_tree; s->bl_desc.stat_desc = &static_bl_desc; s->bi_buf = 0; s->bi_valid = 0; s->last_eob_len = 8; /* enough lookahead for inflate */ #ifdef DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif /* Initialize the first block of the first file: */ init_block(s); } /* =========================================================================== * Initialize a new block. */ local void init_block(s) deflate_state *s; { int n; /* iterates over tree elements */ /* Initialize the trees. */ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; s->last_lit = s->matches = 0; } #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ /* =========================================================================== * Remove the smallest element from the heap and recreate the heap with * one less element. Updates heap and heap_len. */ #define pqremove(s, tree, top) \ {\ top = s->heap[SMALLEST]; \ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ pqdownheap(s, tree, SMALLEST); \ } /* =========================================================================== * Compares to subtrees, using the tree depth as tie breaker when * the subtrees have equal frequency. This minimizes the worst case length. */ #define smaller(tree, n, m, depth) \ (tree[n].Freq < tree[m].Freq || \ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) /* =========================================================================== * Restore the heap property by moving down the tree starting at node k, * exchanging a node with the smallest of its two sons if necessary, stopping * when the heap property is re-established (each father smaller than its * two sons). */ local void pqdownheap(s, tree, k) deflate_state *s; ct_data *tree; /* the tree to restore */ int k; /* node to move down */ { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ if (smaller(tree, v, s->heap[j], s->depth)) break; /* Exchange v with the smallest son */ s->heap[k] = s->heap[j]; k = j; /* And continue down the tree, setting j to the left son of k */ j <<= 1; } s->heap[k] = v; } /* =========================================================================== * Compute the optimal bit lengths for a tree and update the total bit length * for the current block. * IN assertion: the fields freq and dad are set, heap[heap_max] and * above are the tree nodes sorted by increasing frequency. * OUT assertions: the field len is set to the optimal bit length, the * array bl_count contains the frequencies for each bit length. * The length opt_len is updated; static_len is also updated if stree is * not null. */ local void gen_bitlen(s, desc) deflate_state *s; tree_desc *desc; /* the tree descriptor */ { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; const intf *extra = desc->stat_desc->extra_bits; int base = desc->stat_desc->extra_base; int max_length = desc->stat_desc->max_length; int h; /* heap index */ int n, m; /* iterate over the tree elements */ int bits; /* bit length */ int xbits; /* extra bits */ ush f; /* frequency */ int overflow = 0; /* number of elements with bit length too large */ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ for (h = s->heap_max+1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].Len = (ush)bits; /* We overwrite tree[n].Dad which is no longer needed */ if (n > max_code) continue; /* not a leaf node */ s->bl_count[bits]++; xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].Freq; s->opt_len += (ulg)f * (bits + xbits); if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); } if (overflow == 0) return; Trace((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { bits = max_length-1; while (s->bl_count[bits] == 0) bits--; s->bl_count[bits]--; /* move one leaf down the tree */ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; } while (overflow > 0); /* Now recompute all bit lengths, scanning in increasing frequency. * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all * lengths instead of fixing only the wrong ones. This idea is taken * from 'ar' written by Haruhiko Okumura.) */ for (bits = max_length; bits != 0; bits--) { n = s->bl_count[bits]; while (n != 0) { m = s->heap[--h]; if (m > max_code) continue; if (tree[m].Len != (unsigned) bits) { Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); s->opt_len += ((long)bits - (long)tree[m].Len) *(long)tree[m].Freq; tree[m].Len = (ush)bits; } n--; } } } /* =========================================================================== * Generate the codes for a given tree and bit counts (which need not be * optimal). * IN assertion: the array bl_count contains the bit length statistics for * the given tree and the field len is set for all tree elements. * OUT assertion: the field code is set for all tree elements of non * zero code length. */ local void gen_codes (tree, max_code, bl_count) ct_data *tree; /* the tree to decorate */ int max_code; /* largest code with non zero frequency */ ushf *bl_count; /* number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ ush code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ /* The distribution counts are first used to generate the code values * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { next_code[bits] = code = (code + bl_count[bits-1]) << 1; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node; /* new node being created */ /* Construct the initial heap, with least frequent element in * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. * heap[0] is not used. */ s->heap_len = 0, s->heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].Freq != 0) { s->heap[++(s->heap_len)] = max_code = n; s->depth[n] = 0; } else { tree[n].Len = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while (s->heap_len < 2) { node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); tree[node].Freq = 1; s->depth[node] = 0; s->opt_len--; if (stree) s->static_len -= stree[node].Len; /* node is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ node = elems; /* next internal node of the tree */ do { pqremove(s, tree, n); /* n = node of least frequency */ m = s->heap[SMALLEST]; /* m = node of next least frequency */ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ s->heap[--(s->heap_max)] = m; /* Create a new node father of n and m */ tree[node].Freq = tree[n].Freq + tree[m].Freq; s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); tree[n].Dad = tree[m].Dad = (ush)node; #ifdef DUMP_BL_TREE if (tree == s->bl_tree) { fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); } #endif /* and insert the new node in the heap */ s->heap[SMALLEST] = node++; pqdownheap(s, tree, SMALLEST); } while (s->heap_len >= 2); s->heap[--(s->heap_max)] = s->heap[SMALLEST]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen(s, (tree_desc *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes ((ct_data *)tree, max_code, s->bl_count); } /* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ local void scan_tree (s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; tree[max_code+1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { s->bl_tree[curlen].Freq += count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; } else if (count <= 10) { s->bl_tree[REPZ_3_10].Freq++; } else { s->bl_tree[REPZ_11_138].Freq++; } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ local void send_tree (s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ /* tree[max_code+1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(s, curlen, s->bl_tree); } while (--count != 0); } else if (curlen != 0) { if (curlen != prevlen) { send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); } else if (count <= 10) { send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); } else { send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ local int build_bl_tree(s) deflate_state *s; { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); /* opt_len now includes the length of the tree representations, except * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format * requires that at least 4 bit length codes be sent. (appnote.txt says * 3 but the actual value used is 4.) */ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ s->opt_len += 3*(max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); return max_blindex; } /* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ local void send_all_trees(s, lcodes, dcodes, blcodes) deflate_state *s; int lcodes, dcodes, blcodes; /* number of codes for each tree */ { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ send_bits(s, dcodes-1, 5); send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } /* =========================================================================== * Send a stored block */ void pvpgn_tr_stored_block(s, buf, stored_len, eof) deflate_state *s; charf *buf; /* input block */ ulg stored_len; /* length of input block */ int eof; /* true if this is the last block for a file */ { send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ #ifdef DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; #endif copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. * The current inflate code requires 9 bits of lookahead. If the * last two codes for the previous block (real code plus EOB) were coded * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode * the last real code. In this case we send two empty static blocks instead * of one. (There are no problems if the previous block is stored or fixed.) * To simplify the code, we assume the worst case of last real code encoded * on one bit only. */ void pvpgn_tr_align(s) deflate_state *s; { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); /* Of the 10 bits for the empty block, we have already sent * (10 - bi_valid) bits. The lookahead for the last real code (before * the EOB of the previous block) was thus at least one plus the length * of the EOB plus what we have just sent of the empty static block. */ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; #endif bi_flush(s); } s->last_eob_len = 7; } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. */ void pvpgn_tr_flush_block(s, buf, stored_len, eof) deflate_state *s; charf *buf; /* input block, or NULL if too old */ ulg stored_len; /* length of input block */ int eof; /* true if this is the last block for a file */ { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { /* Check if the file is ascii or binary */ if (s->data_type == Z_UNKNOWN) set_data_type(s); /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); build_tree(s, (tree_desc *)(&(s->d_desc))); Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute first the block length in bytes*/ opt_lenb = (s->opt_len+3+7)>>3; static_lenb = (s->static_len+3+7)>>3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->last_lit)); if (static_lenb <= opt_lenb) opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ } #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else if (stored_len+4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ pvpgn_tr_stored_block(s, buf, stored_len, eof); #ifdef FORCE_STATIC } else if (static_lenb >= 0) { /* force static trees */ #else } else if (static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+eof, 3); compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif } else { send_bits(s, (DYN_TREES<<1)+eof, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif } Assert (s->compressed_len == s->bits_sent, "bad compressed size"); /* The above check is made mod 2^32, for files larger than 512 MB * and uLong implemented on 32 bits. */ init_block(s); if (eof) { bi_windup(s); #ifdef DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, s->compressed_len-7*eof)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ int pvpgn_tr_tally (s, dist, lc) deflate_state *s; unsigned dist; /* distance of matched string */ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ { s->d_buf[s->last_lit] = (ush)dist; s->l_buf[s->last_lit++] = (uch)lc; if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; } else { s->matches++; /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST(s) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); s->dyn_ltree[pvpgn_length_code[lc]+LITERALS+1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } #ifdef TRUNCATE_BLOCK /* Try to guess if it is profitable to stop the current block here */ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { /* Compute an upper bound for the compressed length */ ulg out_length = (ulg)s->last_lit*8L; ulg in_length = (ulg)((long)s->strstart - s->block_start); int dcode; for (dcode = 0; dcode < D_CODES; dcode++) { out_length += (ulg)s->dyn_dtree[dcode].Freq * (5L+extra_dbits[dcode]); } out_length >>= 3; Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", s->last_lit, in_length, out_length, 100L - out_length*100L/in_length)); if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; } #endif return (s->last_lit == s->lit_bufsize-1); /* We avoid equality with lit_bufsize because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. */ } /* =========================================================================== * Send the block data compressed using the given Huffman trees */ local void compress_block(s, ltree, dtree) deflate_state *s; ct_data *ltree; /* literal tree */ ct_data *dtree; /* distance tree */ { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned lx = 0; /* running index in l_buf */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if (s->last_lit != 0) do { dist = s->d_buf[lx]; lc = s->l_buf[lx++]; if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ code = pvpgn_length_code[lc]; send_code(s, code+LITERALS+1, ltree); /* send the length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; send_bits(s, lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); Assert (code < D_CODES, "bad d_code"); send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { dist -= base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); } while (lx < s->last_lit); send_code(s, END_BLOCK, ltree); s->last_eob_len = ltree[END_BLOCK].Len; } /* =========================================================================== * Set the data type to ASCII or BINARY, using a crude approximation: * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. * IN assertion: the fields freq of dyn_ltree are set and the total of all * frequencies does not exceed 64K (to fit in an int on 16 bit machines). */ local void set_data_type(s) deflate_state *s; { int n = 0; unsigned ascii_freq = 0; unsigned bin_freq = 0; while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); } /* =========================================================================== * Reverse the first len bits of a code, using straightforward code (a faster * method would use a table) * IN assertion: 1 <= len <= 15 */ local unsigned bi_reverse(code, len) unsigned code; /* the value to invert */ int len; /* its bit length */ { register unsigned res = 0; do { res |= code & 1; code >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } /* =========================================================================== * Flush the bit buffer, keeping at most 7 bits in it. */ local void bi_flush(s) deflate_state *s; { if (s->bi_valid == 16) { put_short(s, s->bi_buf); s->bi_buf = 0; s->bi_valid = 0; } else if (s->bi_valid >= 8) { put_byte(s, (Byte)s->bi_buf); s->bi_buf >>= 8; s->bi_valid -= 8; } } /* =========================================================================== * Flush the bit buffer and align the output on a byte boundary */ local void bi_windup(s) deflate_state *s; { if (s->bi_valid > 8) { put_short(s, s->bi_buf); } else if (s->bi_valid > 0) { put_byte(s, (Byte)s->bi_buf); } s->bi_buf = 0; s->bi_valid = 0; #ifdef DEBUG s->bits_sent = (s->bits_sent+7) & ~7; #endif } /* =========================================================================== * Copy a stored block, storing first the length and its * one's complement if requested. */ local void copy_block(s, buf, len, header) deflate_state *s; charf *buf; /* the input data */ unsigned len; /* its length */ int header; /* true if block header must be written */ { bi_windup(s); /* align on byte boundary */ s->last_eob_len = 8; /* enough lookahead for inflate */ if (header) { put_short(s, (ush)len); put_short(s, (ush)~len); #ifdef DEBUG s->bits_sent += 2*16; #endif } #ifdef DEBUG s->bits_sent += (ulg)len<<3; #endif while (len--) { put_byte(s, *buf++); } } pvpgn-1.8.5/src/zlib/pvpgn_trees.h0000644000175000017500000002040611151345317016100 0ustar aaronaaron/* header created automatically with -DGEN_TREES_H */ local const ct_data static_ltree[L_CODES+2] = { {{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, {{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, {{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, {{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, {{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, {{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, {{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, {{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, {{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, {{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, {{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, {{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, {{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, {{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, {{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, {{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, {{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, {{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, {{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, {{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, {{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, {{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, {{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, {{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, {{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, {{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, {{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, {{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, {{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, {{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, {{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, {{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, {{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, {{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, {{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, {{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, {{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, {{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, {{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, {{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, {{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, {{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, {{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, {{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, {{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, {{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, {{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, {{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, {{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, {{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, {{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, {{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, {{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, {{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, {{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, {{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, {{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, {{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} }; local const ct_data static_dtree[D_CODES] = { {{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, {{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, {{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, {{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, {{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} }; const uch pvpgn_dist_code[DIST_CODE_LEN] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; const uch pvpgn_length_code[MAX_MATCH-MIN_MATCH+1]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 }; local const int base_length[LENGTH_CODES] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 }; local const int base_dist[D_CODES] = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; pvpgn-1.8.5/src/zlib/pvpgn_zconf.h0000644000175000017500000001722211151345317016077 0ustar aaronaaron/* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2002 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ #ifndef _ZCONF_H #define _ZCONF_H #include "common/setup_before.h" /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. */ #ifdef Z_PREFIX # define deflateInit_ z_deflateInit_ # define deflate z_deflate # define deflateEnd z_deflateEnd # define inflateInit_ z_inflateInit_ # define inflate z_inflate # define inflateEnd z_inflateEnd # define deflateInit2_ z_deflateInit2_ # define deflateSetDictionary z_deflateSetDictionary # define deflateCopy z_deflateCopy # define deflateReset z_deflateReset # define deflateParams z_deflateParams # define inflateInit2_ z_inflateInit2_ # define inflateSetDictionary z_inflateSetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateReset z_inflateReset # define compress z_compress # define compress2 z_compress2 # define uncompress z_uncompress # define adler32 z_adler32 # define crc32 z_crc32 # define get_crc_table z_get_crc_table # define Byte z_Byte # define uInt z_uInt # define uLong z_uLong # define Bytef z_Bytef # define charf z_charf # define intf z_intf # define uIntf z_uIntf # define uLongf z_uLongf # define voidpf z_voidpf # define voidp z_voidp #endif #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) # define WIN32 #endif #if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) # ifndef __32BIT__ # define __32BIT__ # endif #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #if defined(MSDOS) && !defined(__32BIT__) # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) # define STDC #endif #if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) # ifndef STDC # define STDC # endif #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const # endif #endif /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) # define NO_DUMMY_DECL #endif /* Old Borland C incorrectly complains about missing returns: */ #if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) # define NEED_DUMMY_RETURN #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus a few kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif #endif #if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) # ifndef __32BIT__ # define SMALL_MEDIUM # define FAR _far # endif #endif /* Compile with -DZLIB_DLL for Windows DLL support */ #if defined(ZLIB_DLL) # if defined(_WINDOWS) || defined(WINDOWS) # ifdef FAR # undef FAR # endif # include # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR _cdecl _export # endif # endif # if defined (__BORLANDC__) # if (__BORLANDC__ >= 0x0500) && defined (WIN32) # include # define ZEXPORT __declspec(dllexport) WINAPI # define ZEXPORTRVA __declspec(dllexport) WINAPIV # else # if defined (_Windows) && defined (__DLL__) # define ZEXPORT _export # define ZEXPORTVA _export # endif # endif # endif #endif #if defined (__BEOS__) # if defined (ZLIB_DLL) # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef FAR # define FAR #endif #if !defined(MACOS) && !defined(TARGET_OS_MAC) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #ifdef HAVE_UNISTD_H # include /* for off_t */ # include /* for SEEK_* and off_t */ # define z_off_t off_t #endif #ifndef SEEK_SET # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) # pragma map(deflateInit_,"DEIN") # pragma map(deflateInit2_,"DEIN2") # pragma map(deflateEnd,"DEEND") # pragma map(inflateInit_,"ININ") # pragma map(inflateInit2_,"ININ2") # pragma map(inflateEnd,"INEND") # pragma map(inflateSync,"INSY") # pragma map(inflateSetDictionary,"INSEDI") # pragma map(inflate_blocks,"INBL") # pragma map(inflate_blocks_new,"INBLNE") # pragma map(inflate_blocks_free,"INBLFR") # pragma map(inflate_blocks_reset,"INBLRE") # pragma map(inflate_codes_free,"INCOFR") # pragma map(inflate_codes,"INCO") # pragma map(inflate_fast,"INFA") # pragma map(inflate_flush,"INFLU") # pragma map(inflate_mask,"INMA") # pragma map(inflate_set_dictionary,"INSEDI2") # pragma map(inflate_copyright,"INCOPY") # pragma map(inflate_trees_bits,"INTRBI") # pragma map(inflate_trees_dynamic,"INTRDY") # pragma map(inflate_trees_fixed,"INTRFI") # pragma map(inflate_trees_free,"INTRFR") #endif #endif /* _ZCONF_H */ pvpgn-1.8.5/src/zlib/pvpgn_zutil.c0000644000175000017500000001233711151345317016124 0ustar aaronaaron/* zutil.c -- target dependent utility functions for the compression library * Copyright (C) 1995-2002 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ #include "common/setup_before.h" #include "zlib/pvpgn_zutil.h" struct internal_state {int dummy;}; /* for buggy compilers */ #ifndef STDC extern void exit OF((int)); #endif const char *pvpgn_z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ "file error", /* Z_ERRNO (-1) */ "stream error", /* Z_STREAM_ERROR (-2) */ "data error", /* Z_DATA_ERROR (-3) */ "insufficient memory", /* Z_MEM_ERROR (-4) */ "buffer error", /* Z_BUF_ERROR (-5) */ "incompatible version",/* Z_VERSION_ERROR (-6) */ ""}; const char * ZEXPORT pvpgn_zlibVersion() { return ZLIB_VERSION; } #ifdef DEBUG # ifndef verbose # define verbose 0 # endif int pvpgn_z_verbose = verbose; void pvpgn_z_error (m) char *m; { fprintf(stderr, "%s\n", m); exit(1); } #endif /* exported to allow conversion of error code to string for compress() and * uncompress() */ const char * ZEXPORT pvpgn_zError(err) int err; { return ERR_MSG(err); } #ifndef HAVE_MEMCPY void pvpgn_zmemcpy(dest, source, len) Bytef* dest; const Bytef* source; uInt len; { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } int pvpgn_zmemcmp(s1, s2, len) const Bytef* s1; const Bytef* s2; uInt len; { uInt j; for (j = 0; j < len; j++) { if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; } return 0; } void pvpgn_zmemzero(dest, len) Bytef* dest; uInt len; { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } #endif #ifdef __TURBOC__ #if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) /* Small and medium model in Turbo C are for now limited to near allocation * with reduced MAX_WBITS and MAX_MEM_LEVEL */ # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes * and farmalloc(64K) returns a pointer with an offset of 8, so we * must fix the pointer. Warning: the pointer must be put back to its * original form in order to free it, use zcfree(). */ #define MAX_PTR 10 /* 10*64K = 640K */ local int next_ptr = 0; typedef struct ptr_table_s { voidpf org_ptr; voidpf new_ptr; } ptr_table; local ptr_table table[MAX_PTR]; /* This table is used to remember the original form of pointers * to large buffers (64K). Such pointers are normalized with a zero offset. * Since MSDOS is not a preemptive multitasking OS, this table is not * protected from concurrent access. This hack doesn't work anyway on * a protected system like OS/2. Use Microsoft C instead. */ voidpf pvpgn_zcalloc (voidpf opaque, unsigned items, unsigned size) { voidpf buf = opaque; /* just to make some compilers happy */ ulg bsize = (ulg)items*size; /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ if (bsize < 65520L) { buf = farmalloc(bsize); if (*(ush*)&buf != 0) return buf; } else { buf = farmalloc(bsize + 16L); } if (buf == NULL || next_ptr >= MAX_PTR) return NULL; table[next_ptr].org_ptr = buf; /* Normalize the pointer to seg:0 */ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; *(ush*)&buf = 0; table[next_ptr++].new_ptr = buf; return buf; } void pvpgn_zcfree (voidpf opaque, voidpf ptr) { int n; if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; } /* Find the original pointer */ for (n = 0; n < next_ptr; n++) { if (ptr != table[n].new_ptr) continue; farfree(table[n].org_ptr); while (++n < next_ptr) { table[n-1] = table[n]; } next_ptr--; return; } ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } #endif #endif /* __TURBOC__ */ #if defined(M_I86) && !defined(__32BIT__) /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC #if (!defined(_MSC_VER) || (_MSC_VER <= 600)) # define _halloc halloc # define _hfree hfree #endif voidpf pvpgn_zcalloc (voidpf opaque, unsigned items, unsigned size) { if (opaque) opaque = 0; /* to make compiler happy */ return _halloc((long)items, size); } void pvpgn_zcfree (voidpf opaque, voidpf ptr) { if (opaque) opaque = 0; /* to make compiler happy */ _hfree(ptr); } #endif /* MSC */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif voidpf pvpgn_zcalloc (opaque, items, size) voidpf opaque; unsigned items; unsigned size; { if (opaque) items += size - size; /* make compiler happy */ return (voidpf)calloc(items, size); } void pvpgn_zcfree (opaque, ptr) voidpf opaque; voidpf ptr; { free(ptr); if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ pvpgn-1.8.5/src/zlib/pvpgn_deflate.c0000644000175000017500000013330111151345317016354 0ustar aaronaaron/* deflate.c -- compress data using the deflation algorithm * Copyright (C) 1995-2002 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process depends on being able to identify portions * of the input text which are identical to earlier input (within a * sliding window trailing behind the input currently being processed). * * The most straightforward technique turns out to be the fastest for * most input files: try all possible matches and select the longest. * The key feature of this algorithm is that insertions into the string * dictionary are very simple and thus fast, and deletions are avoided * completely. Insertions are performed at each input character, whereas * string matches are performed only when the previous match ends. So it * is preferable to spend more time in matches to allow very fast string * insertions and avoid deletions. The matching algorithm for small * strings is inspired from that of Rabin & Karp. A brute force approach * is used to find longer strings when a small match has been found. * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze * (by Leonid Broukhis). * A previous version of this file used a more sophisticated algorithm * (by Fiala and Greene) which is guaranteed to run in linear amortized * time, but has a larger average cost, uses more memory and is patented. * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * * ACKNOWLEDGEMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. * Thanks to many people for bug reports and testing. * * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". * Available in ftp://ds.internic.net/rfc/rfc1951.txt * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. * * Fiala,E.R., and Greene,D.H. * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 * */ #include "common/setup_before.h" #include "zlib/pvpgn_deflate.h" const char deflate_copyright[] = " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* =========================================================================== * Function prototypes. */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ } block_state; typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); local block_state deflate_slow OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV void pvpgn_match_init OF((void)); /* asm code initialization */ uInt pvpgn_longest_match OF((deflate_state *s, IPos cur_match)); #else local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif #ifdef DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, int length)); #endif /* =========================================================================== * Local data */ #define NIL 0 /* Tail of hash chains */ #ifndef TOO_FAR # define TOO_FAR 4096 #endif /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ /* Values for max_lazy_match, good_match and max_chain_length, depending on * the desired pack level (0..9). The values given below have been tuned to * exclude worst case performance for pathological files. Better values may be * found for specific files. */ typedef struct config_s { ush good_length; /* reduce lazy search above this match length */ ush max_lazy; /* do not perform lazy search above this match length */ ush nice_length; /* quit search above this match length */ ush max_chain; compress_func func; } config; local const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, /* 3 */ {4, 6, 32, 32, deflate_fast}, /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, /* 7 */ {8, 32, 128, 256, deflate_slow}, /* 8 */ {32, 128, 258, 1024, deflate_slow}, /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ #define EQUAL 0 /* result of memcmp for equal strings */ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. * IN assertion: all calls to to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ s->head[s->hash_size-1] = NIL; \ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* ========================================================================= */ int ZEXPORT pvpgn_deflateInit_(strm, level, version, stream_size) z_streamp strm; int level; const char *version; int stream_size; { return pvpgn_deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ int ZEXPORT pvpgn_deflateInit2_(strm, level, method, windowBits, memLevel, strategy, version, stream_size) z_streamp strm; int level; int method; int windowBits; int memLevel; int strategy; const char *version; int stream_size; { deflate_state *s; int noheader = 0; static const char* my_version = ZLIB_VERSION; ushf *overlay; /* We overlay pending_buf and d_buf+l_buf. This works since the average * output size for (length,distance) codes is <= 24 bits. */ if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; } if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; if (strm->zalloc == Z_NULL) { strm->zalloc = pvpgn_zcalloc; strm->opaque = (voidpf)0; } if (strm->zfree == Z_NULL) strm->zfree = pvpgn_zcfree; if (level == Z_DEFAULT_COMPRESSION) level = 6; #ifdef FASTEST level = 1; #endif if (windowBits < 0) { /* undocumented feature: suppress zlib header */ noheader = 1; windowBits = -windowBits; } if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { return Z_STREAM_ERROR; } s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; s->noheader = noheader; s->w_bits = windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; s->hash_bits = memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); s->pending_buf = (uchf *) overlay; s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); pvpgn_deflateEnd (strm); return Z_MEM_ERROR; } s->d_buf = overlay + s->lit_bufsize/sizeof(ush); s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; s->level = level; s->strategy = strategy; s->method = (Byte)method; return pvpgn_deflateReset(strm); } /* ========================================================================= */ int ZEXPORT pvpgn_deflateReset (strm) z_streamp strm; { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; strm->total_in = strm->total_out = 0; strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ strm->data_type = Z_UNKNOWN; s = (deflate_state *)strm->state; s->pending = 0; s->pending_out = s->pending_buf; if (s->noheader < 0) { s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ } s->status = s->noheader ? BUSY_STATE : INIT_STATE; strm->adler = 1; s->last_flush = Z_NO_FLUSH; pvpgn_tr_init(s); lm_init(s); return Z_OK; } /* ========================================================================= * Put a short in the pending buffer. The 16-bit value is put in MSB order. * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ local void putShortMSB (s, b) deflate_state *s; uInt b; { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= * Flush as much pending output as possible. All deflate() output goes * through this function so some applications may wish to modify it * to avoid allocating a large strm->next_out buffer and copying into it. * (See also read_buf()). */ local void flush_pending(strm) z_streamp strm; { unsigned len = strm->state->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; zmemcpy(strm->next_out, strm->state->pending_out, len); strm->next_out += len; strm->state->pending_out += len; strm->total_out += len; strm->avail_out -= len; strm->state->pending -= len; if (strm->state->pending == 0) { strm->state->pending_out = strm->state->pending_buf; } } /* ========================================================================= */ int ZEXPORT pvpgn_deflate (strm, flush) z_streamp strm; int flush; { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || flush > Z_FINISH || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; /* Write the zlib header */ if (s->status == INIT_STATE) { uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; uInt level_flags = (s->level-1) >> 1; if (level_flags > 3) level_flags = 3; header |= (level_flags << 6); if (s->strstart != 0) header |= PRESET_DICT; header += 31 - (header % 31); s->status = BUSY_STATE; putShortMSB(s, header); /* Save the adler32 of the preset dictionary: */ if (s->strstart != 0) { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } strm->adler = 1L; } /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); if (strm->avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and * avail_in equal to zero. There won't be anything to do, * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ s->last_flush = -1; return Z_OK; } /* Make sure there is something to do and avoid duplicate consecutive * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUFF_ERROR. */ } else if (strm->avail_in == 0 && flush <= old_flush && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } /* User must not provide more input after the first FINISH: */ if (s->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; bstate = (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; } if (bstate == need_more || bstate == finish_started) { if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ } return Z_OK; /* If flush != Z_NO_FLUSH && avail_out == 0, the next call * of deflate should use the same flush parameter to make sure * that the flush is complete. So we don't have to output an * empty block here, this will be done at next call. This also * ensures that for a very small output buffer, we emit at most * one empty block. */ } if (bstate == block_done) { if (flush == Z_PARTIAL_FLUSH) { pvpgn_tr_align(s); } else { /* FULL_FLUSH or SYNC_FLUSH */ pvpgn_tr_stored_block(s, (char*)0, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if (flush == Z_FULL_FLUSH) { CLEAR_HASH(s); /* forget history */ } } flush_pending(strm); if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ return Z_OK; } } } Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->noheader) return Z_STREAM_END; /* Write the zlib trailer (adler32) */ putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); flush_pending(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ s->noheader = -1; /* write the trailer only once! */ return s->pending != 0 ? Z_OK : Z_STREAM_END; } /* ========================================================================= */ int ZEXPORT pvpgn_deflateEnd (strm) z_streamp strm; { int status; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; status = strm->state->status; if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) { return Z_STREAM_ERROR; } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } /* ========================================================================= * Copy the source state to the destination state. * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ int ZEXPORT pvpgn_deflateCopy (dest, source) z_streamp dest; z_streamp source; { #ifdef MAXSEG_64K return Z_STREAM_ERROR; #else deflate_state *ds; deflate_state *ss; ushf *overlay; if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { return Z_STREAM_ERROR; } ss = source->state; *dest = *source; ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; *ds = *ss; ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); ds->pending_buf = (uchf *) overlay; if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { pvpgn_deflateEnd (dest); return Z_MEM_ERROR; } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; ds->bl_desc.dyn_tree = ds->bl_tree; return Z_OK; #endif } /* =========================================================================== * Read a new buffer from the current input stream, update the adler32 * and total number of bytes read. All deflate() input goes through * this function so some applications may wish to modify it to avoid * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ local int read_buf(strm, buf, size) z_streamp strm; Bytef *buf; unsigned size; { unsigned len = strm->avail_in; if (len > size) len = size; if (len == 0) return 0; strm->avail_in -= len; if (!strm->state->noheader) { strm->adler = pvpgn_adler32(strm->adler, strm->next_in, len); } zmemcpy(buf, strm->next_in, len); strm->next_in += len; strm->total_in += len; return (int)len; } /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ local void lm_init (s) deflate_state *s; { s->window_size = (ulg)2L*s->w_size; CLEAR_HASH(s); /* Set the default configuration parameters: */ s->max_lazy_match = configuration_table[s->level].max_lazy; s->good_match = configuration_table[s->level].good_length; s->nice_match = configuration_table[s->level].nice_length; s->max_chain_length = configuration_table[s->level].max_chain; s->strstart = 0; s->block_start = 0L; s->lookahead = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; #ifdef ASMV match_init(); /* initialize the asm code */ #endif } /* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, * in which case the result is equal to prev_length and match_start is * garbage. * IN assertions: cur_match is the head of the hash chain for the current * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ #ifndef ASMV /* For 80x86 and 680x0, an optimized version will be provided in match.asm or * match.S. The code will be functionally equivalent. */ #ifndef FASTEST local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ int best_len = s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Posf *prev = s->prev; uInt wmask = s->w_mask; #ifdef UNALIGNED_OK /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; register ush scan_end = *(ushf*)(scan+best_len-1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; register Byte scan_end1 = scan[best_len-1]; register Byte scan_end = scan[best_len]; #endif /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); /* Do not waste too much time if we already have a good match: */ if (s->prev_length >= s->good_match) { chain_length >>= 2; } /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2: */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ if (*(ushf*)(match+best_len-1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at * strstart+3, +5, ... up to strstart+257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ /* Here, scan <= window+strstart+257 */ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend-scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len-1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK scan_end = *(ushf*)(scan+best_len-1); #else scan_end1 = scan[best_len-1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for level == 1 only */ local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ register Bytef *strend = s->window + s->strstart + MAX_MATCH; /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Return failure if the match length is less than 2: */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match += 2; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); if (len < MIN_MATCH) return MIN_MATCH - 1; s->match_start = cur_match; return len <= s->lookahead ? len : s->lookahead; } #endif /* FASTEST */ #endif /* ASMV */ #ifdef DEBUG /* =========================================================================== * Check that the match at match_start is indeed a match. */ local void check_match(s, start, match, length) deflate_state *s; IPos start, match; int length; { /* check that the match is indeed a match */ if (zmemcmp(s->window + match, s->window + start, length) != EQUAL) { fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); do { fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); } while (--length != 0); z_error("invalid match"); } if (z_verbose > 1) { fprintf(stderr,"\\[%d,%d]", start-match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } #else # define check_match(s, start, match, length) #endif /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead. * * IN assertion: lookahead < MIN_LOOKAHEAD * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD * At least one byte has been read, or avail_in == 0; reads are * performed for at least two bytes (required for the zip translate_eol * option -- not supported here). */ local void fill_window(s) deflate_state *s; { register unsigned n, m; register Posf *p; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); /* Deal with !@#$% 64K limit: */ if (more == 0 && s->strstart == 0 && s->lookahead == 0) { more = wsize; } else if (more == (unsigned)(-1)) { /* Very unlikely, but possible on 16 bit machine if strstart == 0 * and lookahead == 1 (input done one byte at time) */ more--; /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ } else if (s->strstart >= wsize+MAX_DIST(s)) { zmemcpy(s->window, s->window+wsize, (unsigned)wsize); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; /* Slide the hash table (could be avoided with 32 bit values at the expense of memory usage). We slide even when level == 0 to keep the hash table consistent if we switch back to level > 0 later. (Using level 0 permanently is not an optimal usage of zlib, so we don't care about this pathological case.) */ n = s->hash_size; p = &s->head[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); } while (--n); n = wsize; #ifndef FASTEST p = &s->prev[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); /* If n is not on any hash chain, prev[n] is garbage but * its value will never be used. */ } while (--n); #endif more += wsize; } if (s->strm->avail_in == 0) return; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && * more == window_size - lookahead - strstart * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) * => more >= window_size - 2*WSIZE + 2 * In the BIG_MEM or MMAP case (not yet supported), * window_size == input_size + MIN_LOOKAHEAD && * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. * Otherwise, window_size == 2*WSIZE so more >= 2. * If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ Assert(more >= 2, "more < 2"); n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ if (s->lookahead >= MIN_MATCH) { s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. */ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); } /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. */ #define FLUSH_BLOCK_ONLY(s, eof) { \ pvpgn_tr_flush_block(s, (s->block_start >= 0L ? \ (charf *)&s->window[(unsigned)s->block_start] : \ (charf *)Z_NULL), \ (ulg)((long)s->strstart - s->block_start), \ (eof)); \ s->block_start = s->strstart; \ flush_pending(s->strm); \ Tracev((stderr,"[FLUSH]")); \ } /* Same but force premature exit if necessary. */ #define FLUSH_BLOCK(s, eof) { \ FLUSH_BLOCK_ONLY(s, eof); \ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ } /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. * This function does not insert new strings in the dictionary since * uncompressible data is probably not useful. This function is used * only for the level=0 compression option. * NOTE: this function should be optimized to avoid extra copying from * window to pending_buf. */ local block_state deflate_stored(s, flush) deflate_state *s; int flush; { /* Stored blocks are limited to 0xffff bytes, pending_buf is limited * to pending_buf_size, and each stored block has a 5 byte header: */ ulg max_block_size = 0xffff; ulg max_start; if (max_block_size > s->pending_buf_size - 5) { max_block_size = s->pending_buf_size - 5; } /* Copy as much as possible from input to output: */ for (;;) { /* Fill the window as much as possible: */ if (s->lookahead <= 1) { Assert(s->strstart < s->w_size+MAX_DIST(s) || s->block_start >= (long)s->w_size, "slide too late"); fill_window(s); if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; if (s->lookahead == 0) break; /* flush the current block */ } Assert(s->block_start >= 0L, "block gone"); s->strstart += s->lookahead; s->lookahead = 0; /* Emit a stored block if pending_buf will be full: */ max_start = s->block_start + max_block_size; if (s->strstart == 0 || (ulg)s->strstart >= max_start) { /* strstart == 0 is possible when wraparound on 16-bit machine */ s->lookahead = (uInt)(s->strstart - max_start); s->strstart = (uInt)max_start; FLUSH_BLOCK(s, 0); } /* Flush if we may have to slide, otherwise block_start may become * negative and the data will be gone: */ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { FLUSH_BLOCK(s, 0); } } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } /* =========================================================================== * Compress as much as possible from the input stream, return the current * block state. * This function does not perform lazy evaluation of matches and inserts * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ local block_state deflate_fast(s, flush) deflate_state *s; int flush; { IPos hash_head = NIL; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < MIN_MATCH */ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ if (s->strategy != Z_HUFFMAN_ONLY) { s->match_length = longest_match (s, hash_head); } /* longest_match() sets match_start */ } if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ #ifndef FASTEST if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) { s->match_length--; /* string at strstart already in hash table */ do { s->strstart++; INSERT_STRING(s, s->strstart, hash_head); /* strstart never exceeds WSIZE-MAX_MATCH, so there are * always MIN_MATCH bytes ahead. */ } while (--s->match_length != 0); s->strstart++; } else #endif { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ local block_state deflate_slow(s, flush) deflate_state *s; int flush; { IPos hash_head = NIL; /* head of hash chain */ int bflush; /* set if current block must be flushed */ /* Process the input block. */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. */ s->prev_length = s->match_length, s->prev_match = s->match_start; s->match_length = MIN_MATCH-1; if (hash_head != NIL && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ if (s->strategy != Z_HUFFMAN_ONLY) { s->match_length = longest_match (s, hash_head); } /* longest_match() sets match_start */ if (s->match_length <= 5 && (s->strategy == Z_FILTERED || (s->match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR))) { /* If prev_match is also MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ s->match_length = MIN_MATCH-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart-1, s->prev_match, s->prev_length); _tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. * strstart-1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ s->lookahead -= s->prev_length-1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { INSERT_STRING(s, s->strstart, hash_head); } } while (--s->prev_length != 0); s->match_available = 0; s->match_length = MIN_MATCH-1; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } else if (s->match_available) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; s->lookahead--; if (s->strm->avail_out == 0) return need_more; } else { /* There is no previous match to compare with, wait for * the next step to decide. */ s->match_available = 1; s->strstart++; s->lookahead--; } } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } pvpgn-1.8.5/src/bntrackd/0000755000175000017500000000000011151345372014222 5ustar aaronaaronpvpgn-1.8.5/src/bntrackd/servers.xsl0000644000175000017500000000356611151345317016454 0ustar aaronaaron PvPGN XML Server List

Download(bntrackd.c,XSL,PHP)servers.xsl

AddressLocationDescriptionURLUptimeContactSoftwareUsersGamesChannels
:     
pvpgn-1.8.5/src/bntrackd/bntrackd.c0000644000175000017500000005671011151345317016166 0ustar aaronaaron/* * Copyright (C) 1999 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define TRACKER_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/exitstatus.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memset.h" #ifdef HAVE_UNISTD_H # include #endif #include "compat/stdfileno.h" #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/send.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_ntoa.h" #include "compat/psock.h" #include "common/list.h" #include "common/version.h" #include "common/eventlog.h" #include "common/util.h" #include "common/tracker.h" #include "common/xalloc.h" #include "common/bn_type.h" #include "common/setup_after.h" /****************************************************************************** * TYPES *****************************************************************************/ typedef struct { struct in_addr address; time_t updated; t_trackpacket info; } t_server; typedef struct { int foreground; int debug; int XML_mode; unsigned int expire; unsigned int update; unsigned short port; char const * outfile; char const * pidfile; char const * logfile; char const * process; } t_prefs; /****************************************************************************** * STATIC FUNCTION PROTOTYPES *****************************************************************************/ static int server_process(int sockfd); static void usage(char const * progname); static void getprefs(int argc, char * argv[]); static void fixup_str(bn_byte * str, unsigned int size); /****************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ static t_prefs prefs; extern int main(int argc, char * argv[]) { int sockfd; if (argc<1 || !argv || !argv[0]) { fprintf(stderr,"bad arguments\n"); return STATUS_FAILURE; } getprefs(argc,argv); if (!prefs.debug) eventlog_del_level("debug"); if (prefs.logfile) { eventlog_set(stderr); if (eventlog_open(prefs.logfile)<0) { eventlog(eventlog_level_fatal,__FUNCTION__,"could not use file \"%s\" for the eventlog (exiting)",prefs.logfile); return STATUS_FAILURE; } } #ifdef DO_DAEMONIZE if (!prefs.foreground) { switch (fork()) { case -1: eventlog(eventlog_level_error,__FUNCTION__,"could not fork (fork: %s)\n",pstrerror(errno)); return STATUS_FAILURE; case 0: /* child */ break; default: /* parent */ return STATUS_SUCCESS; } close(STDINFD); close(STDOUTFD); close(STDERRFD); # ifdef HAVE_SETPGID if (setpgid(0,0)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgid: %s)\n",pstrerror(errno)); return STATUS_FAILURE; } # else # ifdef HAVE_SETPGRP # ifdef SETPGRP_VOID if (setpgrp()<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)\n",pstrerror(errno)); return STATUS_FAILURE; } # else if (setpgrp(0,0)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)\n",pstrerror(errno)); return STATUS_FAILURE; } # endif # else # ifdef HAVE_SETSID if (setsid()<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setsid: %s)\n",pstrerror(errno)); return STATUS_FAILURE; } # else # error "One of setpgid(), setpgrp(), or setsid() is required" # endif # endif # endif } #endif if (prefs.pidfile) { #ifdef HAVE_GETPID FILE * fp; if (!(fp = fopen(prefs.pidfile,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to open pid file \"%s\" for writing (fopen: %s)",prefs.pidfile,pstrerror(errno)); prefs.pidfile = NULL; } else { fprintf(fp,"%u",(unsigned int)getpid()); if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close pid file \"%s\" after writing (fclose: %s)",prefs.pidfile,pstrerror(errno)); } #else eventlog(eventlog_level_warn,__FUNCTION__,"no getpid() system call, do not use the -P or the --pidfile option"); prefs.pidfile = NULL; #endif } #ifdef HAVE_GETPID eventlog(eventlog_level_info,__FUNCTION__,"bntrackd version "PVPGN_VERSION" process %u",(unsigned int)getpid()); #else eventlog(eventlog_level_info,__FUNCTION__,"bntrackd version "PVPGN_VERSION); #endif if (psock_init()<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not initialize socket functions"); return STATUS_FAILURE; } /* create the socket */ if ((sockfd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_DGRAM,PSOCK_IPPROTO_UDP))<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not create UDP listen socket (psock_socket: %s)\n",pstrerror(psock_errno())); return STATUS_FAILURE; } { struct sockaddr_in servaddr; /* bind the socket to correct port and interface */ memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = PSOCK_AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(prefs.port); if (psock_bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not bind to UDP port %hu (psock_bind: %s)\n",prefs.port,pstrerror(psock_errno())); return STATUS_FAILURE; } } if (server_process(sockfd)<0) return STATUS_FAILURE; return STATUS_SUCCESS; } static int server_process(int sockfd) { t_list * serverlist_head; t_elem * curr; t_server * server; struct sockaddr_in cliaddr; t_psock_fd_set rfds; struct timeval tv; time_t last; FILE * outfile; psock_t_socklen len; t_trackpacket packet; if (!(serverlist_head = list_create())) { eventlog(eventlog_level_error,__FUNCTION__,"could not create server list"); return -1; } /* the main loop */ last = time(NULL) - prefs.update; for (;;) { /* time to dump our list to disk and call the process command */ /* (I'm making the assumption that this won't take very long.) */ if (last+(signed)prefs.updateupdated+(signed)prefs.expire\n\t
%s
\n",inet_ntoa(server->address)); fprintf(outfile,"\t%hu\n",bn_short_nget(server->info.port)); fprintf(outfile,"\t%s\n",server->info.server_location); fprintf(outfile,"\t%s\n",server->info.software); fprintf(outfile,"\t%s\n",server->info.version); fprintf(outfile,"\t%lu\n",bn_int_nget(server->info.users)); fprintf(outfile,"\t%lu\n",bn_int_nget(server->info.channels)); fprintf(outfile,"\t%lu\n",bn_int_nget(server->info.games)); fprintf(outfile,"\t%s\n",server->info.server_desc); fprintf(outfile,"\t%s\n",server->info.platform); fprintf(outfile,"\t%s\n",server->info.server_url); fprintf(outfile,"\t%s\n",server->info.contact_name); fprintf(outfile,"\t%s\n",server->info.contact_email); fprintf(outfile,"\t%lu\n",bn_int_nget(server->info.uptime)); fprintf(outfile,"\t%lu\n",bn_int_nget(server->info.total_games)); fprintf(outfile,"\t%lu\n",bn_int_nget(server->info.total_logins)); fprintf(outfile,"\n"); } else { fprintf(outfile,"%s\n##\n",inet_ntoa(server->address)); fprintf(outfile,"%hu\n##\n",bn_short_nget(server->info.port)); fprintf(outfile,"%s\n##\n",server->info.server_location); fprintf(outfile,"%s\n##\n",server->info.software); fprintf(outfile,"%s\n##\n",server->info.version); fprintf(outfile,"%lu\n##\n",bn_int_nget(server->info.users)); fprintf(outfile,"%lu\n##\n",bn_int_nget(server->info.channels)); fprintf(outfile,"%lu\n##\n",bn_int_nget(server->info.games)); fprintf(outfile,"%s\n##\n",server->info.server_desc); fprintf(outfile,"%s\n##\n",server->info.platform); fprintf(outfile,"%s\n##\n",server->info.server_url); fprintf(outfile,"%s\n##\n",server->info.contact_name); fprintf(outfile,"%s\n##\n",server->info.contact_email); fprintf(outfile,"%lu\n##\n",bn_int_nget(server->info.uptime)); fprintf(outfile,"%lu\n##\n",bn_int_nget(server->info.total_games)); fprintf(outfile,"%lu\n##\n",bn_int_nget(server->info.total_logins)); fprintf(outfile,"###\n"); } } } if (fclose(outfile)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close output file \"%s\" after writing (fclose: %s)",prefs.outfile,pstrerror(errno)); if (prefs.process[0]!='\0') system(prefs.process); } /* select socket to operate on */ PSOCK_FD_ZERO(&rfds); PSOCK_FD_SET(sockfd,&rfds); tv.tv_sec = BNTRACKD_GRANULARITY; tv.tv_usec = 0; switch (psock_select(sockfd+1,&rfds,NULL,NULL,&tv)) { case -1: /* error */ if ( #ifdef PSOCK_EINTR errno!=PSOCK_EINTR && #endif 1) eventlog(eventlog_level_error,__FUNCTION__,"select failed (select: %s)",pstrerror(errno)); case 0: /* timeout and no sockets ready */ continue; } /* New tracking packet */ if (PSOCK_FD_ISSET(sockfd,&rfds)) { len = sizeof(cliaddr); if (psock_recvfrom(sockfd,&packet,sizeof(packet),0,(struct sockaddr *)&cliaddr,&len)>=0) { if (bn_short_nget(packet.packet_version)>=TRACK_VERSION) { bn_byte_set(&packet.software[sizeof(packet.software)-1],'\0'); fixup_str(packet.software,sizeof(packet.software)); bn_byte_set(&packet.version[sizeof(packet.version)-1],'\0'); fixup_str(packet.version,sizeof(packet.version)); bn_byte_set(&packet.platform[sizeof(packet.platform)-1],'\0'); fixup_str(packet.platform,sizeof(packet.platform)); bn_byte_set(&packet.server_desc[sizeof(packet.server_desc)-1],'\0'); fixup_str(packet.server_desc,sizeof(packet.server_desc)); bn_byte_set(&packet.server_location[sizeof(packet.server_location)-1],'\0'); fixup_str(packet.server_location,sizeof(packet.server_location)); bn_byte_set(&packet.server_url[sizeof(packet.server_url)-1],'\0'); fixup_str(packet.server_url,sizeof(packet.server_url)); bn_byte_set(&packet.contact_name[sizeof(packet.contact_name)-1],'\0'); fixup_str(packet.contact_name,sizeof(packet.contact_name)); bn_byte_set(&packet.contact_email[sizeof(packet.contact_email)-1],'\0'); fixup_str(packet.contact_email,sizeof(packet.contact_email)); /* Find this server's slot */ LIST_TRAVERSE(serverlist_head,curr) { server = elem_get_data(curr); if (!memcmp(&server->address,&cliaddr.sin_addr,sizeof(struct in_addr))) { if (bn_int_nget(packet.flags)&TF_SHUTDOWN) { list_remove_elem(serverlist_head,&curr); xfree(server); } else { /* update in place */ server->info = packet; server->updated = time(NULL); } break; } } /* Not found? Make a new slot */ if (!(bn_int_nget(packet.flags)&TF_SHUTDOWN) && !curr) { server = xmalloc(sizeof(t_server)); server->address = cliaddr.sin_addr; server->info = packet; server->updated = time(NULL); list_append_data(serverlist_head,server); } eventlog(eventlog_level_debug,__FUNCTION__, "Packet received from %s:" " packet_version=%u" " flags=0x%08lx" " port=%hu" " software=\"%s\"" " version=\"%s\"" " platform=\"%s\"" " server_desc=\"%s\"" " server_location=\"%s\"" " server_url=\"%s\"" " contact_name=\"%s\"" " contact_email=\"%s\"" " uptime=%lu" " total_games=%lu" " total_logins=%lu", inet_ntoa(cliaddr.sin_addr), bn_short_nget(packet.packet_version), bn_int_nget(packet.flags), bn_short_nget(packet.port), packet.software, packet.version, packet.platform, packet.server_desc, packet.server_location, packet.server_url, packet.contact_name, packet.contact_email, bn_int_nget(packet.uptime), bn_int_nget(packet.total_games), bn_int_nget(packet.total_logins)); } } } } } static void usage(char const * progname) { fprintf(stderr,"usage: %s []\n",progname); fprintf(stderr, " -c COMMAND, --command=COMMAND execute COMMAND update\n" " -d, --debug turn on debug mode\n" " -e SECS, --expire SECS forget a list entry after SEC seconds\n" #ifdef DO_DAEMONIZE " -f, --foreground don't daemonize\n" #else " -f, --foreground don't daemonize (default)\n" #endif " -l FILE, --logfile=FILE write event messages to FILE\n" " -o FILE, --outfile=FILE write server list to FILE\n"); fprintf(stderr, " -p PORT, --port=PORT listen for announcments on UDP port PORT\n" " -P FILE, --pidfile=FILE write pid to FILE\n" " -u SECS, --update SECS write output file every SEC seconds\n" " -x, --XML write output file in XML format\n" " -h, --help, --usage show this information and exit\n" " -v, --version print version number and exit\n"); exit(STATUS_FAILURE); } static void getprefs(int argc, char * argv[]) { int a; prefs.foreground = 0; prefs.debug = 0; prefs.expire = 0; prefs.update = 0; prefs.port = 0; prefs.XML_mode = 0; prefs.outfile = NULL; prefs.pidfile = NULL; prefs.process = NULL; prefs.logfile = NULL; for (a=1; a=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (prefs.process) { fprintf(stderr,"%s: processing command was already specified as \"%s\"\n",argv[0],prefs.process); usage(argv[0]); } a++; prefs.process = argv[a]; } else if (strcmp(argv[a],"-d")==0 || strcmp(argv[a],"--debug")==0) prefs.debug = 1; else if (strncmp(argv[a],"--expire=",9)==0) { if (prefs.expire) { fprintf(stderr,"%s: expiration period was already specified as \"%u\"\n",argv[0],prefs.expire); usage(argv[0]); } if (str_to_uint(&argv[a][9],&prefs.expire)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],&argv[a][9]); usage(argv[0]); } } else if (strcmp(argv[a],"-e")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (prefs.expire) { fprintf(stderr,"%s: expiration period was already specified as \"%u\"\n",argv[0],prefs.expire); usage(argv[0]); } a++; if (str_to_uint(argv[a],&prefs.expire)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (strcmp(argv[a],"-f")==0 || strcmp(argv[a],"--foreground")==0) prefs.foreground = 1; else if (strcmp(argv[a],"-x")==0 || strcmp(argv[a],"--XML")==0) prefs.XML_mode = 1; else if (strncmp(argv[a],"--logfile=",10)==0) { if (prefs.logfile) { fprintf(stderr,"%s: eventlog file was already specified as \"%s\"\n",argv[0],prefs.logfile); usage(argv[0]); } prefs.logfile = &argv[a][10]; } else if (strcmp(argv[a],"-l")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (prefs.logfile) { fprintf(stderr,"%s: eventlog file was already specified as \"%s\"\n",argv[0],prefs.logfile); usage(argv[0]); } a++; prefs.logfile = argv[a]; } else if (strncmp(argv[a],"--outfile=",10)==0) { if (prefs.outfile) { fprintf(stderr,"%s: output file was already specified as \"%s\"\n",argv[0],prefs.outfile); usage(argv[0]); } prefs.outfile = &argv[a][10]; } else if (strcmp(argv[a],"-o")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (prefs.outfile) { fprintf(stderr,"%s: output file was already specified as \"%s\"\n",argv[0],prefs.outfile); usage(argv[0]); } a++; prefs.outfile = argv[a]; } else if (strncmp(argv[a],"--pidfile=",10)==0) { if (prefs.pidfile) { fprintf(stderr,"%s: pid file was already specified as \"%s\"\n",argv[0],prefs.pidfile); usage(argv[0]); } prefs.pidfile = &argv[a][10]; } else if (strncmp(argv[a],"--port=",7)==0) { if (prefs.port) { fprintf(stderr,"%s: port number was already specified as \"%hu\"\n",argv[0],prefs.port); usage(argv[0]); } if (str_to_ushort(&argv[a][7],&prefs.port)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],&argv[a][7]); usage(argv[0]); } } else if (strcmp(argv[a],"-p")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (prefs.port) { fprintf(stderr,"%s: port number was already specified as \"%hu\"\n",argv[0],prefs.port); usage(argv[0]); } a++; if (str_to_ushort(argv[a],&prefs.port)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (strcmp(argv[a],"-P")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (prefs.pidfile) { fprintf(stderr,"%s: pid file was already specified as \"%s\"\n",argv[0],prefs.pidfile); usage(argv[0]); } a++; prefs.pidfile = argv[a]; } else if (strncmp(argv[a],"--update=",9)==0) { if (prefs.update) { fprintf(stderr,"%s: update period was already specified as \"%u\"\n",argv[0],prefs.expire); usage(argv[0]); } if (str_to_uint(&argv[a][9],&prefs.update)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],&argv[a][9]); usage(argv[0]); } } else if (strcmp(argv[a],"-u")==0) { if (a+1>=argc) { fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]); usage(argv[0]); } if (prefs.update) { fprintf(stderr,"%s: update period was already specified as \"%u\"\n",argv[0],prefs.expire); usage(argv[0]); } a++; if (str_to_uint(argv[a],&prefs.update)<0) { fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]); usage(argv[0]); } } else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage") ==0) usage(argv[0]); else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0) { printf("version "PVPGN_VERSION"\n"); exit(0); } else if (strcmp(argv[a],"--command")==0 || strcmp(argv[a],"--expire")==0 || strcmp(argv[a],"--logfile")==0 || strcmp(argv[a],"--outfile")==0 || strcmp(argv[a],"--port")==0 || strcmp(argv[a],"--pidfile")==0 || strcmp(argv[a],"--update")==0) { fprintf(stderr,"%s: option \"%s\" requires and argument.\n",argv[0],argv[a]); usage(argv[0]); } else { fprintf(stderr,"%s: unknown option \"%s\"\n",argv[0],argv[a]); usage(argv[0]); } if (!prefs.process) prefs.process = BNTRACKD_PROCESS; if (prefs.expire==0) prefs.expire = BNTRACKD_EXPIRE; if (!prefs.logfile) prefs.logfile = BNTRACKD_LOGFILE; if (!prefs.outfile) prefs.outfile = BNTRACKD_OUTFILE; if (prefs.port==0) prefs.port = BNTRACKD_SERVER_PORT; if (!prefs.pidfile) prefs.pidfile = BNTRACKD_PIDFILE; if (prefs.expire==0) prefs.update = BNTRACKD_UPDATE; if (prefs.logfile[0]=='\0') prefs.logfile = NULL; if (prefs.pidfile[0]=='\0') prefs.pidfile = NULL; } void fixup_str(bn_byte * str, unsigned int size) { bn_byte prev; unsigned int i; bn_byte_set(&prev,'\0'); for (i=0; i #endif /* access to it's members */ #define elist_next(ptr) ((ptr)->next) #define elist_prev(ptr) ((ptr)->prev) #define __elist_init(elist,val) { (elist)->next = (elist)->prev = (val); } #define elist_init(elist) __elist_init(elist,elist) #define DECLARE_ELIST_INIT(var) \ t_elist var = { &var, &var }; /* link an new node just after "where" */ static inline void elist_add(t_elist *where, t_elist *what) { what->next = where->next; where->next->prev = what; what->prev = where; where->next = what; } /* link a new node just before "where" (usefull in creating queues) */ static inline void elist_add_tail(t_elist *where, t_elist *what) { what->prev = where->prev; where->prev->next = what; what->next = where; where->prev = what; } /* unlink "what" from it's list */ static inline void elist_del(t_elist *what) { what->next->prev = what->prev; what->prev->next = what->next; } /* finds out the container address by computing it from the list node * address substracting the offset inside the container of the list node * member */ #define elist_entry(ptr,type,member) ((type*)(((char*)ptr)-offsetof(type,member))) /* DONT remove while traversing with this ! */ #define elist_for_each(pos,head) \ for (pos = (head)->next; pos != (head); pos = pos->next) #define elist_for_each_rev(pos,head) \ for (pos = (head)->prev; pos != (head); pos = pos->prev) /* safe for removals while traversing */ #define elist_for_each_safe(pos,head,save) \ for (pos = (head)->next, save = pos->next; pos != (head); \ pos = save, save = pos->next) #define elist_for_each_safe_rev(pos,head,save) \ for (pos = (head)->prev, save = pos->prev; pos != (head); \ pos = save, save = pos->prev) #define elist_empty(ptr) ((ptr)->next == (ptr)) #define hlist_next(ptr) elist_next(ptr) #define __hlist_init(hlist,val) { (hlist)->next = (val); } #define hlist_init(hlist) __hlist_init(hlist,hlist) #define DECLARE_HLIST_INIT(var) \ t_hlist var = { &var }; /* link an new node just after "where" */ static inline void hlist_add(t_hlist *where, t_hlist *what) { what->next = where->next; where->next = what; } /* unlink "what" from it's list, prev->next = what */ static inline void hlist_del(t_hlist *what, t_hlist *prev) { prev->next = what->next; } /* move "what" back in the list with one position, never NULL * prev: the previous element in the list, never NULL * prev2: the previous element of "prev", if NULL means "what" is first */ static inline void hlist_promote(t_hlist *what, t_hlist *prev, t_hlist *prev2) { if (prev2) { prev->next = what->next; prev2->next = what; what->next = prev; } } /* finds out the container address by computing it from the list node * address substracting the offset inside the container of the list node * member */ #define hlist_entry(ptr,type,member) elist_entry(ptr,type,member) /* DONT remove while traversing with this ! */ #define hlist_for_each(pos,head) elist_for_each(pos,head) /* safe for removals while traversing */ #define hlist_for_each_safe(pos,head,save) elist_for_each_safe(pos,head,save) #define hlist_empty(ptr) elist_empty(ptr) #endif /* INCLUDED_ELIST_PROTOS */ pvpgn-1.8.5/src/common/flags.h0000644000175000017500000000175011151345317015171 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_FLAGS_H #define INCLUDED_FLAGS_H #define FLAG_ZERO(var) *(var) = 0 #define FLAG_SET(var,flag) *(var) |= flag #define FLAG_CLEAR(var,flag) *(var) &= ~flag #define FLAG_ISSET(var,flag) (var & flag) #endif /* INCLUDED_FLAGS_H */ pvpgn-1.8.5/src/common/hashtable.h0000644000175000017500000001011111151345317016017 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_HASHTABLE_TYPES #define INCLUDED_HASHTABLE_TYPES #ifdef HASHTABLE_INTERNAL_ACCESS struct hashtable; /* forward reference for t_entry */ #endif #ifdef HASHTABLE_INTERNAL_ACCESS typedef struct internentry { void * data; struct internentry * next; } t_internentry; #endif typedef struct entry #ifdef HASHTABLE_INTERNAL_ACCESS { unsigned int row; t_internentry * real; struct hashtable const * hashtable; } #endif t_entry; typedef struct hashtable #ifdef HASHTABLE_INTERNAL_ACCESS { unsigned int num_rows; unsigned int len; unsigned int zombies; t_internentry * * rows; } #endif t_hashtable; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_HASHTABLE_PROTOS #define INCLUDED_HASHTABLE_PROTOS extern t_hashtable * hashtable_create(unsigned int num_rows) ; extern int hashtable_destroy(t_hashtable * hashtable); extern int hashtable_purge(t_hashtable * hashtable); extern int hashtable_check(t_hashtable const * hashtable); extern unsigned int hashtable_get_length(t_hashtable const * hashtable); extern int hashtable_insert_data(t_hashtable * hashtable, void * data, unsigned int hash); extern t_entry * hashtable_get_entry_by_data(t_hashtable const * hashtable, void const * data, unsigned int hash); extern t_entry const * hashtable_get_entry_by_data_const(t_hashtable const * hashtable, void const * data, unsigned int hash); extern int hashtable_remove_data(t_hashtable * hashtable, void const * data, unsigned int hash); /* delete matching item */ extern int hashtable_remove_entry(t_hashtable * hashtable, t_entry * entry); extern void * hashtable_get_data_by_pos(t_hashtable const * hashtable, unsigned int pos); extern void * entry_get_data(t_entry const * entry); #ifdef HASHTABLE_DEBUG extern t_entry * hashtable_match_get_first_real(t_hashtable const * hashtable, unsigned int hash, char const * fn, unsigned int ln); # define hashtable_match_get_first(L,H) hashtable_match_get_first_real(L,H,__FILE__,__LINE__) #else extern t_entry * hashtable_match_get_first(t_hashtable const * hashtable, unsigned int hash); #endif extern t_entry * entry_match_get_next(t_entry const * entry, unsigned int hash); #ifdef HASHTABLE_DEBUG extern t_entry * hashtable_get_first_real(t_hashtable const * hashtable, char const * fn, unsigned int ln); # define hashtable_get_first(L) hashtable_get_first_real(L,__FILE__,__LINE__) #else extern t_entry * hashtable_get_first(t_hashtable const * hashtable); #endif extern t_entry * entry_get_next(t_entry * entry); #ifdef HASHTABLE_DEBUG extern t_entry * hashtable_get_first_matching_real(t_hashtable const * hashtable, unsigned int hash, char const * fn, unsigned int ln); # define hashtable_get_first_matching(L,H) hashtable_get_first_matching_real(L,H,__FILE__,__LINE__) #else extern t_entry * hashtable_get_first_matching(t_hashtable const * hashtable, unsigned int hash); #endif extern t_entry * entry_get_next_matching(t_entry * entry); extern int hashtable_entry_release(t_entry * entry); extern int hashtable_stats(t_hashtable * hashtable); #define HASHTABLE_TRAVERSE(hashtable,curr) for (curr=hashtable_get_first(hashtable); curr; curr=entry_get_next(curr)) #define HASHTABLE_TRAVERSE_MATCHING(hashtable,curr,hash) for (curr=hashtable_get_first_matching(hashtable,hash); curr; curr=entry_get_next_matching(curr)) #endif #endif pvpgn-1.8.5/src/common/queue.h0000644000175000017500000000316711151345317015225 0ustar aaronaaron/* * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_QUEUE_TYPES #define INCLUDED_QUEUE_TYPES #ifdef QUEUE_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include "common/packet.h" #else # define JUST_NEED_TYPES # include "common/packet.h" # undef JUST_NEED_TYPES #endif #endif typedef struct queue #ifdef QUEUE_INTERNAL_ACCESS { unsigned ulen, alen; t_packet ** ring; unsigned head, tail; } #endif t_queue; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_QUEUE_PROTOS #define INCLUDED_QUEUE_PROTOS #define JUST_NEED_TYPES #include "common/packet.h" #undef JUST_NEED_TYPES extern t_packet * queue_pull_packet(t_queue * * queue); extern t_packet * queue_peek_packet(t_queue const * const * queue); extern void queue_push_packet(t_queue * * queue, t_packet * packet); extern int queue_get_length(t_queue const * const * queue); extern void queue_clear(t_queue * * queue); #endif #endif pvpgn-1.8.5/src/common/rlimit.c0000644000175000017500000000405511151345317015371 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_UNISTD_H # include #endif #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_SYS_RESOURCE_H # include #endif #include "common/eventlog.h" #include "common/bn_type.h" #include "common/setup_after.h" /* file descriptor limit has different name on BSD and Linux */ #ifdef RLIMIT_NOFILE # define RLIM_NUMFILES RLIMIT_NOFILE #else # ifdef RLIMIT_OFILE # define RLIM_NUMFILES RLIMIT_OFILE # endif #endif extern int get_socket_limit(void) { int socklimit = 0; #ifdef HAVE_GETRLIMIT struct rlimit rlim; if(getrlimit(RLIM_NUMFILES, &rlim) < 0) eventlog(eventlog_level_error, __FUNCTION__, "getrlimit returned error: %s", pstrerror(errno)); socklimit = rlim.rlim_cur; #else /* FIXME: WIN32: somehow get WSAData win32 socket limit here */ #endif #if !(defined HAVE_POLL || defined HAVE_KQUEUE || defined HAVE_EPOLL) if(!socklimit || FD_SETSIZE < socklimit) socklimit = FD_SETSIZE; #endif /* make socket limit smaller than file limit to make sure log files, db connections and save files will still work */ socklimit -= 64; return socklimit; } pvpgn-1.8.5/src/common/d2char_file.h0000644000175000017500000000417011151345317016236 0ustar aaronaaron#define D2CHARFILE_PADBYTE 0xff typedef struct { /* Finish copying from bnet_protocol.h/t_d2_char_info */ bn_long experience; bn_byte reservedxp[30]; bn_long invgold; bn_long bankgold; bn_long stashgold; bn_long reservedgold[8]; bn_byte skilllvls[30]; bn_byte reservedskills[30]; bn_short strength; bn_short vitaility; bn_short dexterity; bn_short energy; bn_short reservedattr[4]; bn_byte questflags[4]; /* 1 byte/8 bits each act */ bn_byte reservedquestflags[16]; bn_byte waypoints[4][3]; /* 3 bytes/24 bits each act */ bn_byte reservedwaypoints[4][3]; /* stuff like HP, Mana are calculated dynamically... */ bn_byte inventory[80]; /* backpack got 40 spaces, double that to be safe */ bn_byte reservedinv[80]; /* space for expanding */ bn_byte belt[32]; /* largest belt holds 16, double that to be safe */ bn_byte reservedbelt[32]; /* space for expanding */ bn_int deathcount; bn_byte body1unknownb1; /* For dead body... */ bn_byte body1unknownb2; bn_byte body1helmgfx; bn_byte body1bodygfx; bn_byte body1leggfx; bn_byte body1lhandweapon; bn_byte body1lhandgfx; bn_byte body1rhandweapon; bn_byte body1rhandgfx; bn_byte body1unknownb3; bn_byte body1unknownb4; bn_byte body1unknownb5; bn_byte body1unknownb6; bn_byte body1unknownb7; bn_byte body1unknownb8; bn_byte body1unknownb9; bn_byte body1unknownb10; bn_byte body1unknownb11; bn_byte body1inventory[80]; /* backpack got 40 spaces, double that to be safe */ bn_byte body1reservedinv[80]; /* space for expanding */ bn_byte body1belt[32]; /* largest belt holds 16, double that to be safe */ bn_byte body1reservedbelt[32]; /* space for expanding */ bn_byte stashinv[100]; /* Forgot how big the stash is.... */ bn_byte reservedstash[200]; } t_d2char_record; /* item description base type (1 byte) item quality (unknown size) Magic (blue name) modifer level magic dword 1 magic dword 2 */ pvpgn-1.8.5/src/common/give_up_root_privileges.c0000644000175000017500000001073711151345317021027 0ustar aaronaaron/* * Copyright (C) 2001 Hakan Tandogan (hakan@gurkensalat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_PWD_H # include #endif #ifdef HAVE_GRP_H # include #endif #ifdef HAVE_STRING_H # include #endif #include #include "compat/strerror.h" #include "common/eventlog.h" #include "common/give_up_root_privileges.h" #include "common/setup_after.h" #define ILLEGAL_ID -1 static int gurp_gname2id(const char *name); static int gurp_uname2id(const char *name); extern int give_up_root_privileges(char const * user_name, char const * group_name) { int user_id = 0; int group_id = 0; eventlog(eventlog_level_debug,__FUNCTION__,"about to give up root privileges"); if (user_name) { if ((user_id = gurp_uname2id(user_name))==ILLEGAL_ID) { return -1; } else { eventlog(eventlog_level_debug,__FUNCTION__,"should change to user = '%s' (%d)", user_name, user_id); } } if (group_name) { if ((group_id = gurp_gname2id(group_name))==ILLEGAL_ID) { return -1; } else { eventlog(eventlog_level_debug,__FUNCTION__,"should change to group = '%s' (%d)", group_name, group_id); } } /* Change first the group ID, later we might not be able to anymore * We can use setgid safely because we don't want to return to root * privileges anymore */ #ifdef HAVE_SETGID if (group_name) { if (-1 == setgid(group_id)) { eventlog(eventlog_level_fatal,__FUNCTION__,"could not set gid to %d (setgid: %s)", group_id, pstrerror(errno)); return -1; } # ifdef HAVE_GETUID eventlog(eventlog_level_info,__FUNCTION__,"Changed privileges to gid = %d", getgid()); # endif } #endif #ifdef HAVE_SETUID if (user_name) { if (-1 == setuid(user_id)) { eventlog(eventlog_level_fatal,__FUNCTION__,"could not set uid to %d (setuid: %s)", user_id, pstrerror(errno)); return -1; } # ifdef HAVE_GETGID eventlog(eventlog_level_info,__FUNCTION__,"Changed privileges to uid = %d", getuid()); # endif } #endif return 0; } static int gurp_uname2id(const char *name) { int id = ILLEGAL_ID; if (name != NULL) { if (name[0] == '#') { id = atoi(&name[1]); } else { #ifdef HAVE_GETPWNAM struct passwd * ent; eventlog(eventlog_level_debug,__FUNCTION__,"about to getpwnam(%s)", name); if (!(ent = getpwnam(name))) { eventlog(eventlog_level_fatal,__FUNCTION__,"cannot get password file entry for '%s' (getpwnam: %s)", name, pstrerror(errno)); return id; } id = ent->pw_uid; #else return id; #endif } } return id; } static int gurp_gname2id(const char *name) { int id = ILLEGAL_ID; if (name != NULL) { if (name[0] == '#') { id = atoi(&name[1]); } else { #ifdef HAVE_GETGRNAM struct group * ent; eventlog(eventlog_level_debug,__FUNCTION__,"about to getgrnam(%s)", name); if (!(ent = getgrnam(name))) { eventlog(eventlog_level_fatal,__FUNCTION__,"cannot get group file entry for '%s' (getgrnam: %s)", name, pstrerror(errno)); return id; } id = ent->gr_gid; #else return id; #endif } } return id; } pvpgn-1.8.5/src/common/rcm.c0000644000175000017500000000357711151345317014662 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_ASSERT_H # include #endif #include "common/xalloc.h" #include "common/elist.h" #include "common/rcm.h" #include "common/setup_after.h" extern void rcm_init(t_rcm *rcm) { assert(rcm); elist_init(&rcm->refs); rcm->count = 0; } extern void rcm_regref_init(t_rcm_regref *regref, t_chref_cb cb, void *data) { assert(regref); elist_init(®ref->refs_link); regref->chref = cb; regref->data = data; } extern void rcm_get(t_rcm *rcm, t_rcm_regref *regref) { assert(rcm); assert(regref); rcm->count++; elist_add_tail(&rcm->refs,®ref->refs_link); } extern void rcm_put(t_rcm *rcm, t_rcm_regref *regref) { assert(rcm); assert(regref); assert(rcm->count); /* might use eventlog but I want this stopped fast */ rcm->count--; elist_del(®ref->refs_link); } extern void rcm_chref(t_rcm *rcm, void *newref) { t_elist *curr, *save; t_rcm_regref *regref; assert(rcm); elist_for_each_safe(curr,&rcm->refs,save) { regref = elist_entry(curr,t_rcm_regref,refs_link); if (regref->chref) regref->chref(regref->data,newref); } } pvpgn-1.8.5/src/common/bnethash.c0000644000175000017500000001250311151345317015662 0ustar aaronaaron/* * Copyright (C) 1999 Descolada (dyn1-tnt9-237.chicago.il.ameritech.net) * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/uint.h" #include "common/introtate.h" #include "common/eventlog.h" #include "common/bnethash.h" #include "common/setup_after.h" static void hash_init(t_hash * hash); static void do_hash(t_hash * hash, t_uint32 * tmp); static void hash_set_16(t_uint32 * dst, unsigned char const * src, unsigned int count); static void hash_init(t_hash * hash) { (*hash)[0] = 0x67452301; (*hash)[1] = 0xefcdab89; (*hash)[2] = 0x98badcfe; (*hash)[3] = 0x10325476; (*hash)[4] = 0xc3d2e1f0; } static void do_hash(t_hash * hash, t_uint32 * tmp) { unsigned int i; t_uint32 a,b,c,d,e,g; for (i=0; i<64; i++) tmp[i+16] = ROTL32(1,tmp[i] ^ tmp[i+8] ^ tmp[i+2] ^ tmp[i+13]); a = (*hash)[0]; b = (*hash)[1]; c = (*hash)[2]; d = (*hash)[3]; e = (*hash)[4]; for (i=0; i<20*1; i++) { g = tmp[i] + ROTL32(a,5) + e + ((b & c) | (~b & d)) + 0x5a827999; e = d; d = c; c = ROTL32(b,30); b = a; a = g; } for (; i<20*2; i++) { g = (d ^ c ^ b) + e + ROTL32(g,5) + tmp[i] + 0x6ed9eba1; e = d; d = c; c = ROTL32(b,30); b = a; a = g; } for (; i<20*3; i++) { g = tmp[i] + ROTL32(g,5) + e + ((c & b) | (d & c) | (d & b)) - 0x70e44324; e = d; d = c; c = ROTL32(b,30); b = a; a = g; } for (; i<20*4; i++) { g = (d ^ c ^ b) + e + ROTL32(g,5) + tmp[i] - 0x359d3e2a; e = d; d = c; c = ROTL32(b,30); b = a; a = g; } (*hash)[0] += g; (*hash)[1] += b; (*hash)[2] += c; (*hash)[3] += d; (*hash)[4] += e; } /* * Fill 16 elements of the array of 32 bit values with the bytes from * dst up to count in little endian order. Fill left over space with * zeros */ static void hash_set_16(t_uint32 * dst, unsigned char const * src, unsigned int count) { unsigned int i; unsigned int pos; for (pos=0,i=0; i<16; i++) { dst[i] = 0; if (pos0 && !datain) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL datain with size=%u",size); return -1; } hash_init(hashout); data = datain; while (size>0) { if (size>64) inc = 64; else inc = size; hash_set_16(tmp,data,inc); do_hash(hashout,tmp); data += inc; size -= inc; } return 0; } extern int hash_eq(t_hash const h1, t_hash const h2) { unsigned int i; if (!h1 || !h2) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash"); return -1; } for (i=0; i<5; i++) if (h1[i]!=h2[i]) return 0; return 1; } extern char const * hash_get_str(t_hash const hash) { static char temp[8*5+1]; /* each of 5 ints to 8 chars + null */ unsigned int i; if (!hash) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash"); return NULL; } for (i=0; i<5; i++) sprintf(&temp[i*8],"%08x",hash[i]); return temp; } extern int hash_set_str(t_hash * hash, char const * str) { unsigned int i; if (!hash) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash pointer"); return -1; } if (!*hash) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash"); return -1; } if (!str) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL str"); return -1; } if (strlen(str)!=5*8) { eventlog(eventlog_level_error,__FUNCTION__,"got string with length %u (should be %u)",strlen(str),5*8); return -1; } for (i=0; i<5; i++) if (sscanf(&str[i*8],"%8x",&(*hash)[i])!=1) { eventlog(eventlog_level_error,__FUNCTION__,"got bad string"); return -1; } return 0; } pvpgn-1.8.5/src/common/field_sizes.h0000644000175000017500000000640711151345317016401 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_FIELD_SIZES_TYPES #define INCLUDED_FIELD_SIZES_TYPES #define MAX_PACKET_SIZE 3072 #define MAX_NORMAL_TYPE 0xffff #define MAX_FILE_TYPE 0xffff #define MAX_AUTH_TYPE 0xff #define MAX_GAMES_LIST 20 #define MAX_MESSAGE_LEN 255 #define MAX_COMMAND_LEN 32 #define USER_NAME_MAX 16 /* including terminating NUL char */ #define USER_NAME_MIN 2 #define USER_PASS_MAX 12 /* max password length as allowed by clients */ #define UNCHECKED_NAME_STR 32 /* including terminating NUL char */ /* (longer than USER_NAME_MAX and CHAR_NAME_LEN so that * proper error packets can be returned) */ #define CLANSHORT_NAME_MAX 4 #define CLAN_NAME_MAX 24 /* including terminating NUL char */ #define CLAN_MOTD_MAX 224 /* including terminating NUL char */ #define CHANNEL_NAME_LEN 64 #define CHAR_NAME_LEN 16 /* including terminating NUL char */ #define REALM_NAME_LEN 32 #define GAME_NAME_LEN 32 #define GAME_PASS_LEN 32 #define GAME_INFO_LEN 128 #define MAP_NAME_LEN 64 #define BNETHASH_LEN 20 /* uint32*5, see bnethash.h */ #define MAX_EXEINFO_STR 256 /* including terminating NUL char */ #define MAX_OWNER_STR 128 /* including terminating NUL char */ #define MAX_CDKEY_STR 128 /* including terminating NUL char */ #define MAX_EMAIL_STR 128 /* including terminating NUL char */ #define MAX_WINHOST_STR 128 /* including terminating NUL char */ #define MAX_WINUSER_STR 128 /* including terminating NUL char */ #define MAX_LANG_STR 64 /* including terminating NUL char */ #define MAX_COUNTRYNAME_STR 128 /* including terminating NUL char */ #define MAX_FILENAME_STR 2048 /* including terminating NUL char */ #define MAX_GAMEREP_HEAD_STR 2048 /* including terminating NUL char */ #define MAX_GAMEREP_BODY_STR 8192 /* including terminating NUL char */ #define MAX_PLAYERINFO_STR 2048 /* including terminating NUL char */ #define MAX_COUNTRYCODE_STR 32 /* including terminating NUL char */ #define MAX_COUNTRY_STR 32 /* including terminating NUL char */ #define MAX_ATTRKEY_STR 1024 /* including terminating NUL char */ #define MAX_ATTRVAL_STR 4096 /* including terminating NUL char */ #define MAX_IRC_MESSAGE_LEN 512 /* including CRLF (according to RFC 2812) */ #define MAX_TOPIC_LEN 201 /* including terminating NUL char */ #endif pvpgn-1.8.5/src/common/give_up_root_privileges.h0000644000175000017500000000170311151345317021025 0ustar aaronaaron/* * Copyright (C) 2001 Hakan Tandogan (hakan@gurkensalat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_GIVE_UP_ROOT_PRIVILEGES #define INCLUDED_GIVE_UP_ROOT_PRIVILEGES extern int give_up_root_privileges(char const * user_name, char const * group_name); #endif pvpgn-1.8.5/src/common/trans.c0000644000175000017500000002405511151345317015222 0ustar aaronaaron/* * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define TRANS_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strrchr.h" #include #include "compat/strerror.h" #include "common/eventlog.h" #include "common/list.h" #include "common/addr.h" #include "common/util.h" #include "common/xalloc.h" #include "trans.h" #include "common/setup_after.h" #define DEBUG_TRANS static t_list * trans_head=NULL; extern int trans_load(char const * filename, int program) { FILE *fp; unsigned int line; unsigned int pos; char *buff; char *temp; char const *input; char const *output; char const *exclude; char const *include; unsigned int npos; char *network; char *tmp; char tmp1[32]; char tmp2[32]; char tmp3[32]; t_trans *entry; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return -1; } trans_head = list_create(); for (line=1; (buff = file_get_line(fp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if ((temp = strrchr(buff,'#'))) { unsigned int len; unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } if (!(input = strtok(buff," \t"))) { /* strtok modifies the string it is passed */ eventlog(eventlog_level_error,__FUNCTION__,"missing input line %u of file \"%s\"",line,filename); continue; } /* check for port number - this tells us what programs will use this entry */ if (!(temp = strrchr(input,':'))) { eventlog(eventlog_level_error,__FUNCTION__,"missing port # on input line %u of file \"%s\"",line,filename); continue; } temp++; /* bnetd doesn't want the port 4000 entries */ if (program==TRANS_BNETD && strcmp(temp,"4000")==0) { #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__,"d2gs input (ignoring) \"%s\"",input); #endif continue; } /* d2cs only wants the port 4000 entries */ if (program==TRANS_D2CS && strcmp(temp,"4000")!=0) { #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__,"non d2gs input (ignoring) \"%s\"",input); #endif continue; } if (!(output = strtok(NULL," \t"))) { eventlog(eventlog_level_error,__FUNCTION__,"missing output on line %u of file \"%s\"",line,filename); continue; } if (!(exclude = strtok(NULL," \t"))) { eventlog(eventlog_level_error,__FUNCTION__,"missing exclude on line %u of file \"%s\"",line,filename); continue; } if (!(include = strtok(NULL," \t"))) { eventlog(eventlog_level_error,__FUNCTION__,"missing include on line %u of file \"%s\"",line,filename); continue; } /* add exlude networks */ tmp = xstrdup(exclude); npos=0; while (tmp[npos]) { network = &tmp[npos]; for (; tmp[npos]!=',' && tmp[npos]!='\0'; npos++); if (tmp[npos]=='\0') npos--; else tmp[npos]='\0'; if (strcmp(network,"NONE")==0) { npos++; continue; } entry = xmalloc(sizeof(t_trans)); if (!(entry->input = addr_create_str(input,0,0))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for input address"); xfree(entry); npos++; continue; } if (!(entry->output = addr_create_str(input,0,0))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for output address"); addr_destroy(entry->input); xfree(entry); npos++; continue; } if (strcmp(network,"ANY")==0) { if (!(entry->network = netaddr_create_str("0.0.0.0/0"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for network address"); addr_destroy(entry->output); addr_destroy(entry->input); xfree(entry); npos++; continue; } } else { if (!(entry->network = netaddr_create_str(network))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for network address"); addr_destroy(entry->output); addr_destroy(entry->input); xfree(entry); npos++; continue; } } #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__, "Adding Host -> %s, Output -> %s, Network %s - (exclude)", addr_get_addr_str(entry->input,tmp1,sizeof(tmp1)), addr_get_addr_str(entry->output,tmp2,sizeof(tmp2)), netaddr_get_addr_str(entry->network,tmp3,sizeof(tmp3))); #endif list_append_data(trans_head,entry); npos++; } xfree(tmp); /* add include networks */ tmp = xstrdup(include); npos=0; while (tmp[npos]) { network = &tmp[npos]; for (; tmp[npos]!=',' && tmp[npos]!='\0'; npos++); if (tmp[npos]=='\0') npos--; else tmp[npos]='\0'; if (strcmp(network,"NONE")==0) { npos++; continue; } entry = xmalloc(sizeof(t_trans)); if (!(entry->input = addr_create_str(input,0,0))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for input address"); xfree(entry); npos++; continue; } if (!(entry->output = addr_create_str(output,0,0))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for output address"); addr_destroy(entry->input); xfree(entry); npos++; continue; } if (strcmp(network,"ANY")==0) { if (!(entry->network = netaddr_create_str("0.0.0.0/0"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for network address"); addr_destroy(entry->output); addr_destroy(entry->input); xfree(entry); npos++; continue; } } else { if (!(entry->network = netaddr_create_str(network))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for network address"); addr_destroy(entry->output); addr_destroy(entry->input); xfree(entry); npos++; continue; } } #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__, "Adding Host -> %s, Output -> %s, Network %s - (include)", addr_get_addr_str(entry->input,tmp1,sizeof(tmp1)), addr_get_addr_str(entry->output,tmp2,sizeof(tmp2)), netaddr_get_addr_str(entry->network,tmp3,sizeof(tmp3))); #endif list_append_data(trans_head,entry); npos++; } xfree(tmp); } file_get_line(NULL); // clear file_get_line buffer fclose(fp); eventlog(eventlog_level_info,__FUNCTION__,"trans file loaded"); return 0; } extern int trans_unload(void) { t_elem *curr; t_trans *entry; if (trans_head) { LIST_TRAVERSE(trans_head,curr) { if (!(entry = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); } else { netaddr_destroy(entry->network); addr_destroy(entry->output); addr_destroy(entry->input); xfree(entry); } list_remove_elem(trans_head,&curr); } list_destroy(trans_head); trans_head = NULL; } return 0; } extern int trans_reload(char const * filename, int program) { trans_unload(); if(trans_load(filename,program)<0) return -1; return 0; } extern int trans_net(unsigned int clientaddr, unsigned int *addr, unsigned short *port) { t_elem const *curr; t_trans *entry; char temp1[32]; char temp2[32]; char temp3[32]; char temp4[32]; #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__,"checking %s for client %s ...", addr_num_to_addr_str(*addr, *port), addr_num_to_ip_str(clientaddr)); #endif if (trans_head) { LIST_TRAVERSE_CONST(trans_head,curr) { if (!(entry = elem_get_data(curr))) { eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list"); continue; } #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__,"against entry -> %s output %s network %s", addr_get_addr_str(entry->input,temp1,sizeof(temp1)), addr_get_addr_str(entry->output,temp2,sizeof(temp2)), netaddr_get_addr_str(entry->network,temp3,sizeof(temp3))); #endif if (addr_get_ip(entry->input)!=*addr || addr_get_port(entry->input)!=*port) { #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__,"entry does match input address"); #endif continue; } if (netaddr_contains_addr_num(entry->network,clientaddr)==0) { #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__,"client is not in the correct network"); #endif continue; } #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__,"%s translated to %s", addr_num_to_addr_str(*addr, *port), addr_get_addr_str(entry->output,temp4,sizeof(temp4))); #endif *addr = addr_get_ip(entry->output); *port = addr_get_port(entry->output); return 1; /* match found in list */ } } #ifdef DEBUG_TRANS eventlog(eventlog_level_debug,__FUNCTION__,"no match found for %s (not translated)", addr_num_to_addr_str(*addr, *port)); #endif return 0; /* no match found in list */ } pvpgn-1.8.5/src/common/xalloc.c0000644000175000017500000000535411151345317015356 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifndef XALLOC_SKIP #ifdef HAVE_STDDEF_H # include #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strdup.h" #include "common/eventlog.h" #include "common/xalloc.h" #define XALLOC_INTERNAL_ACCESS #include "common/setup_after.h" #undef XALLOC_INTERNAL_ACCESS static t_oom_cb oom_cb = NULL; void *xmalloc_real(size_t size, const char *fn, unsigned ln) { void *res; res = malloc(size); if (!res) { eventlog(eventlog_level_fatal, __FUNCTION__, "out of memory (from %s:%u)",fn,ln); if (oom_cb && oom_cb() && (res = malloc(size))) return res; abort(); } return res; } void *xcalloc_real(size_t nmemb, size_t size, const char *fn, unsigned ln) { void *res; res = calloc(nmemb,size); if (!res) { eventlog(eventlog_level_fatal, __FUNCTION__, "out of memory (from %s:%u)",fn,ln); if (oom_cb && oom_cb() && (res = calloc(nmemb,size))) return res; abort(); } return res; } void *xrealloc_real(void *ptr, size_t size, const char *fn, unsigned ln) { void *res; res = realloc(ptr,size); if (!res) { eventlog(eventlog_level_fatal, __FUNCTION__, "out of memory (from %s:%u)",fn,ln); if (oom_cb && oom_cb() && (res = realloc(ptr,size))) return res; abort(); } return res; } char *xstrdup_real(const char *str, const char *fn, unsigned ln) { char *res; res = strdup(str); if (!res) { eventlog(eventlog_level_fatal, __FUNCTION__, "out of memory (from %s:%u)",fn,ln); if (oom_cb && oom_cb() && (res = strdup(str))) return res; abort(); } return res; } void xfree_real(void *ptr, const char *fn, unsigned ln) { if (!ptr) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL ptr (from %s:%u)",fn,ln); return; } free(ptr); } void xalloc_setcb(t_oom_cb cb) { oom_cb = cb; } #endif /* XALLOC_SKIP */ pvpgn-1.8.5/src/common/proginfo.h0000644000175000017500000000231511151345317015716 0ustar aaronaaron/* * Copyright (C) 2001 Ross Combs (ross@bnetd.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_PROGINFO_TYPES #define INCLUDED_PROGINFO_TYPES #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_PROGINFO_PROTOS #define INCLUDED_PROGINFO_PROTOS extern int verparts_to_vernum(unsigned short v1, unsigned short v2, unsigned short v3, unsigned short v4, unsigned long * vernum); extern int verstr_to_vernum(char const * verstr, unsigned long * vernum); extern char const * vernum_to_verstr(unsigned long vernum); #endif #endif pvpgn-1.8.5/src/common/bot_protocol.h0000644000175000017500000000615611151345317016607 0ustar aaronaaron/* * Copyright (C) 1999,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_BOT_PROTOCOL_PROTOS #define INCLUDED_BOT_PROTOCOL_PROTOS /* * The bot protocol has no real structure. It basically different ASCII * formatted lines. */ /*********************************** */ #define EID_SHOWUSER 1001 /***********************************/ /*********************************** */ #define EID_JOIN 1002 /***********************************/ /*********************************** */ #define EID_LEAVE 1003 /***********************************/ /*********************************** */ #define EID_WHISPER 1004 /***********************************/ /*********************************** */ #define EID_TALK 1005 /***********************************/ /*********************************** */ #define EID_BROADCAST 1006 /***********************************/ /*********************************** */ #define EID_CHANNEL 1007 /***********************************/ /*********************************** */ #define EID_USERFLAGS 1009 /***********************************/ /*********************************** */ #define EID_WHISPERSENT 1010 /***********************************/ /*********************************** */ #define EID_CHANNELFULL 1013 /***********************************/ /*********************************** */ #define EID_CHANNELDOESNOTEXIST 1014 /***********************************/ /*********************************** */ #define EID_CHANNELRESTRICTED 1015 /***********************************/ /*********************************** 1018 INFO "You are Anonymous#11, using Chat in a private game." */ #define EID_INFO 1018 /* 1016? */ /***********************************/ /*********************************** 1019 ERROR "That is not a valid command. Type /help or /? for more info." */ #define EID_ERROR 1019 /***********************************/ /*********************************** */ #define EID_EMOTE 1023 /***********************************/ /*********************************** 2000 NULL */ #define EID_NULL 2000 /***********************************/ /*********************************** 2010 NAME Anonymous#11 */ #define EID_UNIQUENAME 2010 /***********************************/ #endif #endif pvpgn-1.8.5/src/common/fdwatch.c0000644000175000017500000001176211151345317015514 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "common/eventlog.h" #define FDWATCH_BACKEND #include "fdwatch.h" #ifdef HAVE_SELECT #include "fdwatch_select.h" #endif #ifdef HAVE_POLL #include "fdwatch_poll.h" #endif #ifdef HAVE_KQUEUE #include "fdwatch_kqueue.h" #endif #ifdef HAVE_EPOLL #include "fdwatch_epoll.h" #endif #include "common/rlimit.h" #include "common/xalloc.h" #include "common/setup_after.h" int fdw_maxcons; t_fdwatch_fd *fdw_fds = NULL; static t_fdw_backend * fdw = NULL; static DECLARE_ELIST_INIT(freelist); static DECLARE_ELIST_INIT(uselist); extern int fdwatch_init(int maxcons) { int i, maxsys; maxsys = get_socket_limit(); if (maxsys > 0) maxcons = (maxcons < maxsys) ? maxcons : maxsys; if (maxcons < 32) { eventlog(eventlog_level_fatal, __FUNCTION__, "too few sockets available (%d)",maxcons); return -1; } fdw_maxcons = maxcons; fdw_fds = xmalloc(sizeof(t_fdwatch_fd) * fdw_maxcons); memset(fdw_fds, 0, sizeof(t_fdwatch_fd) * fdw_maxcons); /* add all slots to the freelist */ for(i = 0; i < fdw_maxcons; i++) elist_add_tail(&freelist,&(fdw_fds[i].freelist)); #ifdef HAVE_EPOLL fdw = &fdw_epoll; if (!fdw->init(fdw_maxcons)) goto ok; #endif #ifdef HAVE_KQUEUE fdw = &fdw_kqueue; if (!fdw->init(fdw_maxcons)) goto ok; #endif #ifdef HAVE_POLL fdw = &fdw_poll; if (!fdw->init(fdw_maxcons)) goto ok; goto ok; #endif #ifdef HAVE_SELECT fdw = &fdw_select; if (!fdw->init(fdw_maxcons)) goto ok; #endif eventlog(eventlog_level_fatal, __FUNCTION__, "Found no working fdwatch layer"); fdw = NULL; fdwatch_close(); return -1; ok: return 0; } extern int fdwatch_close(void) { if (fdw) { fdw->close(); fdw = NULL; } if (fdw_fds) { xfree((void*)fdw_fds); fdw_fds = NULL; } elist_init(&freelist); elist_init(&uselist); return 0; } extern int fdwatch_add_fd(int fd, t_fdwatch_type rw, fdwatch_handler h, void *data) { t_fdwatch_fd *cfd; if (elist_empty(&freelist)) return -1; /* max sockets reached */ cfd = elist_entry(elist_next(&freelist),t_fdwatch_fd,freelist); fdw_fd(cfd) = fd; if (fdw->add_fd(fdw_idx(cfd), rw)) return -1; /* add it to used sockets list, remove it from free list */ elist_add_tail(&uselist,&cfd->uselist); elist_del(&cfd->freelist); fdw_rw(cfd) = rw; fdw_data(cfd) = data; fdw_hnd(cfd) = h; return fdw_idx(cfd); } extern int fdwatch_update_fd(int idx, t_fdwatch_type rw) { if (idx<0 || idx>=fdw_maxcons) { eventlog(eventlog_level_error,__FUNCTION__,"out of bounds idx [%d] (max: %d)",idx, fdw_maxcons); return -1; } /* do not allow completly reset the access because then backend codes * can get confused */ if (!rw) { eventlog(eventlog_level_error,__FUNCTION__,"tried to reset rw, not allowed"); return -1; } if (!fdw_rw(fdw_fds + idx)) { eventlog(eventlog_level_error,__FUNCTION__,"found reseted rw"); return -1; } if (fdw->add_fd(idx, rw)) return -1; fdw_rw(&fdw_fds[idx]) = rw; return 0; } extern int fdwatch_del_fd(int idx) { t_fdwatch_fd *cfd; if (idx<0 || idx>=fdw_maxcons) { eventlog(eventlog_level_error,__FUNCTION__,"out of bounds idx [%d] (max: %d)",idx, fdw_maxcons); return -1; } cfd = fdw_fds + idx; if (!fdw_rw(cfd)) { eventlog(eventlog_level_error,__FUNCTION__,"found reseted rw"); return -1; } fdw->del_fd(idx); /* remove it from uselist, add it to freelist */ elist_del(&cfd->uselist); elist_add_tail(&freelist,&cfd->freelist); fdw_fd(cfd) = 0; fdw_rw(cfd) = 0; fdw_data(cfd) = NULL; fdw_hnd(cfd) = NULL; return 0; } extern int fdwatch(long timeout_msec) { return fdw->watch(timeout_msec); } extern void fdwatch_handle(void) { fdw->handle(); } extern void fdwatch_traverse(t_fdw_cb cb, void *data) { t_elist *curr; elist_for_each(curr,&uselist) { if (cb(elist_entry(curr,t_fdwatch_fd,uselist),data)) break; } } pvpgn-1.8.5/src/common/rcm.h0000644000175000017500000000412311151345317014653 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Reference Change Mechanism * an abstract interface to implement safe management of references of objects * which do not share any specific dependencies */ #ifndef __RCM_H_TYPES__ #define __RCM_H_TYPES__ #include "common/elist.h" /* reference change mechanism main object * an object which wishes to be referenced using RCM has to include this */ typedef struct { unsigned count; t_elist refs; /* list of registered references */ } t_rcm; /* callback called when the object referenced is moved/deleted */ typedef int (*t_chref_cb)(void *data, void *newref); /* registered reference object * an object which wants to register it's references to an rcm enabled object * will have to include one of this for every rcm enabled referenced object */ typedef struct { t_chref_cb chref; void *data; t_elist refs_link; } t_rcm_regref; #endif /* __RCM_H_TYPES__ */ #ifndef __RCM_H_PROTOS__ #define __RCM_H_PROTOS__ extern void rcm_init(t_rcm *rcm); extern void rcm_regref_init(t_rcm_regref *regref, t_chref_cb cb, void *data); extern void rcm_get(t_rcm *rcm, t_rcm_regref *regref); extern void rcm_put(t_rcm *rcm, t_rcm_regref *regref); /* the main function, cycles through the registered references and calls the * registered callback with the new reference */ extern void rcm_chref(t_rcm *rcm, void *newref); #endif /* __RCM_H_PROTOS__ */ pvpgn-1.8.5/src/common/fdwatch_poll.h0000644000175000017500000000204611151345317016542 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * poll() based backend * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __INCLUDED_FDWATCH_POLL__ #define __INCLUDED_FDWATCH_POLL__ extern t_fdw_backend fdw_poll; #endif /* __INCLUDED_FDWATCH_POLL__ */ pvpgn-1.8.5/src/common/tracker.h0000644000175000017500000000614011151345317015526 0ustar aaronaaron/* * Copyright (C) 1999 Mark Baysinger (mbaysing@ucsd.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_TRACKER_TYPES #define INCLUDED_TRACKER_TYPES #ifdef TRACKER_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES #include "common/bn_type.h" #else #define JUST_NEED_TYPES #include "common/bn_type.h" #undef JUST_NEED_TYPES #endif #endif /* * * Here's how this works: * * Bnetd sends a UDP ClientPacket to each track server port on a regular basis. * Simple. * */ #ifdef TRACKER_INTERNAL_ACCESS typedef struct { bn_short packet_version; /* set to TRACK_VERSION, network byte order */ bn_short port; /* port server is listening on, network byte order */ bn_int flags; /* see below, network byte order */ bn_byte software[32]; /* example: Bnetd, NUL terminated */ bn_byte version[16]; /* example: 0.4, NUL terminated */ bn_byte platform[32]; /* Windows, Linux, etc., NUL terminated */ bn_byte server_desc[64]; /* description, NUL terminated */ bn_byte server_location[64]; /* geographical location, NUL terminated */ bn_byte server_url[96]; /* web address: http://..., NUL terminated */ bn_byte contact_name[64]; /* name of operator, NUL terminated */ bn_byte contact_email[64]; /* e-mail address of operator, NUL terminated */ bn_int users; /* current number of users, network byte order */ bn_int channels; /* current number of channels, network byte order */ bn_int games; /* current number of games, network byte order */ bn_int uptime; /* daemon uptime in seconds, network byte order */ bn_int total_games; /* total number of games served */ bn_int total_logins; /* total number of client logins */ /* new versions will add fields to end of packet */ } t_trackpacket; /* packet_version */ #define TRACK_VERSION 2 /* flags */ #define TF_SHUTDOWN 0x1 /* send packet with this flag set when * shutting down (Currently ignored) */ #define TF_PRIVATE 0x2 /* server is private and should not be * listed (Currently ignored) */ #endif #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_TRACKER_PROTOS #define INCLUDED_TRACKER_PROTOS #define JUST_NEED_TYPES #include "addr.h" #undef JUST_NEED_TYPES extern int tracker_set_servers(char const * servers); extern int tracker_send_report(t_addrlist const * addrs); #endif #endif pvpgn-1.8.5/src/common/version.h0000644000175000017500000000152411151346771015566 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PVPGN_VERSION #define PVPGN_VERSION "1.8.5" #endif #ifndef PVPGN_SOFTWARE #define PVPGN_SOFTWARE "PvPGN BnetD Mod" #endif pvpgn-1.8.5/src/common/xstr.c0000644000175000017500000000566711151345317015103 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * * lstr is a structure to be used for cached string lengths for speed * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "common/xstr.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "common/xalloc.h" #include "common/setup_after.h" /* how many bytes allocate at once on enlarging a xstr */ #define XSTR_INCREMENT 256 /* enlarge "dst" enough so it can hold more "size" characters (not including terminator) */ static void xstr_enlarge(t_xstr* dst, int size) { if (dst->alen - dst->ulen < size + 1) { int nalen = ((dst->ulen + size + 10) / XSTR_INCREMENT + 1) * XSTR_INCREMENT; dst->str = xrealloc(dst->str, nalen); dst->alen = nalen; } } extern t_xstr* xstr_alloc(void) { t_xstr* xstr = (t_xstr*)xmalloc(sizeof(t_xstr)); xstr_init(xstr); return xstr; } extern void xstr_free(t_xstr* xstr) { assert(xstr); if (xstr->str) xfree(xstr->str); xfree(xstr); } extern t_xstr * xstr_cpy_str(t_xstr * dst, const char * src) { int len; assert(dst); dst->ulen = 0; /* so if we cpy a NULL string we delete the old one :) */ if (!src) return dst; len = strlen(src); /* need to enlarge dst ? */ xstr_enlarge(dst, len); memcpy(dst->str, src, len + 1); dst->ulen = len; return dst; } extern t_xstr* xstr_cat_xstr(t_xstr* dst, const t_xstr* src) { assert(dst); if (!src || !src->ulen) return dst; /* need to enlarge dst ? */ xstr_enlarge(dst, src->ulen); memcpy(dst->str + dst->ulen, src->str, src->ulen + 1); dst->ulen += src->ulen; return dst; } extern t_xstr* xstr_cat_str(t_xstr* dst, const char* src) { int len; assert(dst); if (!src) return dst; len = strlen(src); /* need to enlarge dst ? */ xstr_enlarge(dst, len); memcpy(dst->str + dst->ulen, src, len + 1); dst->ulen += len; return dst; } extern t_xstr* xstr_ncat_str(t_xstr * dst, const char * src, int len) { const char *p; assert(dst); if (!src || len < 1 || !src[0]) return dst; for(p = src; *p && p - src < len; ++p) xstr_cat_char(dst, *p); return dst; } extern t_xstr* xstr_cat_char(t_xstr * dst, const char ch) { assert(dst); xstr_enlarge(dst, 1); dst->str[dst->ulen++] = ch; dst->str[dst->ulen] = '\0'; return dst; } pvpgn-1.8.5/src/common/fdwatch_poll.c0000644000175000017500000001154511151345317016541 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * poll(2) based backend * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_POLL_H # include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #include "fdwatch.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" #ifdef HAVE_POLL static int sr; static struct pollfd *fds = NULL; /* working set */ static int *_rridx = NULL; static int *_ridx = NULL; static unsigned nofds; static int fdw_poll_init(int nfds); static int fdw_poll_close(void); static int fdw_poll_add_fd(int idx, t_fdwatch_type rw); static int fdw_poll_del_fd(int idx); static int fdw_poll_watch(long timeout_msecs); static void fdw_poll_handle(void); t_fdw_backend fdw_poll = { fdw_poll_init, fdw_poll_close, fdw_poll_add_fd, fdw_poll_del_fd, fdw_poll_watch, fdw_poll_handle }; static int fdw_poll_init(int nfds) { int i; _ridx = xmalloc(sizeof(int) * nfds); fds = xmalloc(sizeof(struct pollfd) * nfds); _rridx = xmalloc(sizeof(int) * nfds); memset(fds, 0, sizeof(struct pollfd) * nfds); memset(_rridx, 0, sizeof(int) * nfds); /* I would use a memset with 255 but that is dirty and doesnt gain us anything */ for(i = 0; i < nfds; i++) _ridx[i] = -1; nofds = sr = 0; eventlog(eventlog_level_info, __FUNCTION__, "fdwatch poll() based layer initialized (max %d sockets)", nfds); return 0; } static int fdw_poll_close(void) { if (fds) { xfree((void *)fds); fds = NULL; } if (_ridx) { xfree((void *)_ridx); _ridx = NULL; } if (_rridx) { xfree((void *)_rridx); _rridx = NULL; } nofds = sr = 0; return 0; } static int fdw_poll_add_fd(int idx, t_fdwatch_type rw) { static int ridx; // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); if (_ridx[idx] < 0) { ridx = nofds++; fds[ridx].fd = fdw_fd(fdw_fds + idx); _ridx[idx] = ridx; _rridx[ridx] = idx; // eventlog(eventlog_level_trace, __FUNCTION__, "adding new fd on %d", ridx); } else { if (fds[_ridx[idx]].fd != fdw_fd(fdw_fds + idx)) { eventlog(eventlog_level_error,__FUNCTION__,"BUG: found existent poll_fd entry for same idx with different fd"); return -1; } ridx = _ridx[idx]; // eventlog(eventlog_level_trace, __FUNCTION__, "updating fd on %d", ridx); } fds[ridx].events = 0; if (rw & fdwatch_type_read) fds[ridx].events |= POLLIN; if (rw & fdwatch_type_write) fds[ridx].events |= POLLOUT; return 0; } static int fdw_poll_del_fd(int idx) { // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd); if (_ridx[idx] < 0 || !nofds) return -1; if (sr > 0) eventlog(eventlog_level_error, __FUNCTION__, "BUG: called while still handling sockets"); /* move the last entry to the deleted one and decrement nofds count */ nofds--; if (_ridx[idx] < nofds) { // eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", tfds[nofds].fd); _ridx[_rridx[nofds]] = _ridx[idx]; _rridx[_ridx[idx]] = _rridx[nofds]; memcpy(fds + _ridx[idx], fds + nofds, sizeof(struct pollfd)); } _ridx[idx] = -1; return 0; } static int fdw_poll_watch(long timeout_msec) { return (sr = poll(fds, nofds, timeout_msec)); } static void fdw_poll_handle(void) { register unsigned i; int changed; t_fdwatch_fd *cfd; for(i = 0; i < nofds && sr; i++) { changed = 0; cfd = fdw_fds + _rridx[i]; if (fdw_rw(cfd) & fdwatch_type_read && fds[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) { if (fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_read) == -2) { sr--; continue; } changed = 1; } if (fdw_rw(cfd) & fdwatch_type_write && fds[i].revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)) { fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_write); changed = 1; } if (changed) sr--; } } #endif /* HAVE_POLL */ pvpgn-1.8.5/src/common/setup_before.h0000644000175000017500000003261311151345317016561 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef INCLUDED_SETUP_AFTER_H # error "This file must be included before all other header files" #endif #ifndef INCLUDED_SETUP_BEFORE_H #define INCLUDED_SETUP_BEFORE_H /* get autoconf defines */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef WIN32 # include "win32/configwin.h" #endif /* This file contains compile-time configuration parameters including * debugging options, default configuration values, and format strings. */ #include "version.h" /***************************************************************/ /* Debugging options */ /* print bad calling locations of account functions */ #define DEBUG_ACCOUNT /* make bnchat, etc. print debug messages */ #define CLIENTDEBUG /* make the routines call xxx_check() and notice xxx_purge() calls during list traversal */ #undef LIST_DEBUG #undef HASHTABLE_DEBUG /* this will use GCC evensions to verify that all module arguments to eventlog() are correct. */ #undef DEBUGMODSTRINGS /* After you compile, use this script: strings bnetd | egrep '@\([^@]*@@[a-z_]*\)@' | sed -e 's/@(\([^:]*\):\([a-z_]*\)@@\([a-z_]*\))@/\1 \2 \3/g' | awk '{ if ( $2 != $3 ) printf("%s: %s->%s\n",$1,$2,$3); }' */ /* this will test get/unget memory management in account.c */ #undef TESTUNGET /* check ladders for impossible combinations when returning them */ #define LADDER_DEBUG /***************************************************************/ /* compile-time options */ /* how long do we wait for the UDP test reply? */ #define CLIENT_MAX_UDPTEST_WAIT 5 /* length of listen socket queue */ /* #define LISTEN_QUEUE SOMAXCONN */ #define LISTEN_QUEUE 10 /* the format for account numbers */ #define UID_FORMAT "#%08u" #define UID_MAXLEN 8 /* the format for game ids */ #define GAMEID_FORMAT "#%06u" #define GAMEID_MAXLEN 8 /* the format of timestamps in the logfile */ #define EVENT_TIME_FORMAT "%b %d %H:%M:%S" #define EVENT_TIME_MAXLEN 32 /* the format of the stat times in bnstat */ #define STAT_TIME_FORMAT "%Y %b %d %H:%M:%S" #define STAT_TIME_MAXLEN 32 /* the format of the file modification time in bnftp */ #define FILE_TIME_FORMAT "%Y %b %d %H:%M:%S" #define FILE_TIME_MAXLEN 32 /* the format of the dates in the game report and for /gameinfo */ #define GAME_TIME_FORMAT "%a %b %d %H:%M:%S %Z" #define GAME_TIME_MAXLEN 32 /* the format of the timestamps for the start/end of channel log files */ #define CHANLOG_TIME_FORMAT "%Y %b %d %H:%M:%S %Z" #define CHANLOG_TIME_MAXLEN 32 /* the format of the timestamps for lines in the channel log files */ #define CHANLOGLINE_TIME_FORMAT "%b %d %H:%M:%S" #define CHANLOGLINE_TIME_MAXLEN 32 /* adjustable constants */ #define BNETD_LADDER_DEFAULT_TIME "19764578 0" /* 0:00 1 Jan 1970 GMT */ /* for clients if ioctl(TIOCGWINSZ) fails and $LINES and $COLUMNS aren't set */ #define DEF_SCREEN_WIDTH 80 #define DEF_SCREEN_HEIGHT 24 /***************************************************************/ /* default values for bnetd.conf */ /* default Boolean setup values */ #define BNETD_CHANLOG 0 /* default path configuration values */ #ifndef BNETD_DEFAULT_CONF_FILE # define BNETD_DEFAULT_CONF_FILE "conf/bnetd.conf" #endif #define BNETD_FILE_DIR "files" #define BNETD_STORAGE_PATH "" #define BNETD_REPORT_DIR "reports" #define BNETD_LOG_FILE "logs/bnetd.log" #define BNETD_MOTD_FILE "conf/bnmotd.txt" #define BNETD_NEWS_DIR "news" #define BNETD_AD_FILE "conf/ad.conf" #define BNETD_CHANNEL_FILE "conf/channel.conf" #define BNETD_PID_FILE "" /* this means "none" */ #define BNETD_ACCOUNT_TMP ".bnetd_acct_temp" #define BNETD_IPBAN_FILE "conf/bnban.conf" #define BNETD_HELP_FILE "conf/bnhelp.conf" #define BNETD_FORTUNECMD "/usr/games/fortune" #define BNETD_TRANS_FILE "conf/address_translation.conf" #define BNETD_CHANLOG_DIR "chanlogs" #define BNETD_REALM_FILE "conf/realm.conf" #define BNETD_ISSUE_FILE "conf/bnissue.txt" #define BNETD_MAIL_DIR "var/bnmail" #define PVPGN_VERSIONCHECK "conf/versioncheck.conf" #define BNETD_LADDER_DIR "var/ladders" #define BNETD_STATUS_DIR "var/status" #define BNETD_TOPIC_FILE "var/topics" #define BNETD_DBLAYOUT_FILE "conf/sql_DB_layout.conf" #define BNETD_SUPPORT_FILE "conf/supportfile.conf" #define BNETD_COMMAND_GROUPS_FILE "conf/command_groups.conf" #define BNETD_TOURNAMENT_FILE "conf/tournament.conf" #define BNETD_ALIASFILE "conf/bnalias.conf" /* ADDED BY UNDYING SOULZZ 4/9/02 */ /* default identify timeout value */ #define W3_IDENTTIMEOUT 15 /* seconds */ /* Added by Soar */ /* time limit for new member as newer(whom cannot be promoted) in clan, (hrs) */ #define CLAN_NEWER_TIME 168 #define CLAN_DEFAULT_MAX_MEMBERS 50 /* hardcoded limits in the client */ #define CLAN_MIN_MEMBERS 10 #define CLAN_MAX_MEMBERS 100 /* moved from account.h */ #define MAX_FRIENDS 20 /* maximum ammount of bytes sent in a single server.c/sd_tcpoutput call */ #define BNETD_MAX_OUTBURST 16384 /* default files relative to FILE_DIR */ #define BNETD_TOS_FILE "tos.txt" #define BNETD_ICON_FILE "icons.bni" #define BNETD_WAR3_ICON_FILE "icons-WAR3.bni" #define BNETD_STAR_ICON_FILE "icons_STAR.bni" #define BNETD_MPQ_FILE "autoupdate" /* other default configuration values */ #define BNETD_LOG_LEVELS "warn,error" #define BNETD_SERV_ADDRS "" /* this means none */ #define BNETD_SERV_PORT 6112 #define BNETD_W3ROUTE_ADDR "0.0.0.0" #define BNETD_W3ROUTE_PORT 6200 #define BNETD_SERVERNAME "PvPGN Realm" #define BNETD_IRC_ADDRS "" /* this means none */ #define BNETD_IRC_PORT 6667 /* used if port not specified */ #define BNETD_IRC_NETWORK_NAME "PvPGN" #define BNETD_WOL_ADDRS "" #define BNETD_WOL_PORT 4005 #define BNETD_TRACK_ADDRS "track.pvpgn.org" #define BNETD_TRACK_PORT 6114 /* use this port if not specified */ #define BNETD_DEF_TEST_PORT 6112 /* default guess for UDP test port */ #define BNETD_MIN_TEST_PORT 6112 #define BNETD_MAX_TEST_PORT 6500 #define BNETD_USERSYNC 300 /* s */ #define BNETD_USERFLUSH 1000 #define BNETD_USERSTEP 100 /* check 100 users per call in accountlist_save() */ #define BNETD_LATENCY 600 /* s */ #define BNETD_IRC_LATENCY 180 /* s */ /* Ping timeout for IRC connections */ #define BNETD_DEF_NULLMSG 120 /* s */ #define BNETD_TRACK_TIME 0 #define BNETD_POLL_INTERVAL 20 /* 20 ms */ #define BNETD_JIFFIES 50 /* 50 ms jiffies time quantum */ #define BNETD_SHUTDELAY 300 /* s */ #define BNETD_SHUTDECR 60 /* s */ #define BNETD_DEFAULT_OWNER "PvPGN" #define BNETD_DEFAULT_KEY "3310541526205" #define BNETD_DEFAULT_HOST "localhost" #define BNETD_QUOTA_DOBAE 7 /* lines */ #define BNETD_QUOTA_LINES 5 /* lines */ #define BNETD_QUOTA_TIME 5 /* s */ #define BNETD_QUOTA_WLINE 40 /* chars */ #define BNETD_QUOTA_MLINE 200 /* chars */ #define BNETD_LADDER_INIT_RAT 1000 #define BNETD_MAIL_SUPPORT 0 #define BNETD_MAIL_QUOTA 5 #define BNETD_LOG_NOTICE "*** Please note this channel is logged! ***" #define BNETD_HASHTABLE_SIZE 61 #define BNETD_REALM_PORT 6113 /* where D2CS listens */ #define BNETD_TELNET_ADDRS "" /* this means none */ #define BNETD_TELNET_PORT 23 /* used if port not specified */ #define BNETD_EXEINFO_MATCH "exact" #define PVPGN_VERSION_TIMEDIV 0 /* no timediff check by default */ #define PVPGN_CACHE_MEMLIMIT 5000000 /* bytes */ #define PVPGN_DEFAULT_SYMB "-_[]" /***************************************************************/ /* default values for the tracking server */ #define BNTRACKD_EXPIRE 600 #define BNTRACKD_UPDATE 150 #define BNTRACKD_GRANULARITY 5 #define BNTRACKD_SERVER_PORT 6114 #define BNTRACKD_PIDFILE "" /* this means "none" */ #define BNTRACKD_OUTFILE "pvpgnlist.txt" #ifdef WIN32 #define BNTRACKD_PROCESS "process.pl" #define BNTRACKD_LOGFILE "bntrackd.log" #else #define BNTRACKD_PROCESS "scripts/process.pl" #define BNTRACKD_LOGFILE "logs/bntrackd.log" #endif /***************************************************************/ /* default values for W3XP anongameinfo packet */ #define PVPGN_DEFAULT_URL "www.pvpgn.org" #define PVPGN_PG_1V1_DESC "Solo Games" #define PVPGN_AT_2V2_DESC "2 player team" #define PVPGN_AT_3V3_DESC "3 player team" #define PVPGN_AT_4V4_DESC "4 player team" #define PVPGN_PG_TEAM_DESC "Team Games" #define PVPGN_PG_FFA_DESC "Free for All Games" #define PVPGN_CLAN_1V1_DESC "Solo Games" #define PVPGN_CLAN_2V2_DESC "2 player team" #define PVPGN_CLAN_3V3_DESC "3 player team" #define PVPGN_CLAN_4V4_DESC "4 player team" #define PVPGN_1V1_GT_DESC "One vs. One" #define PVPGN_1V1_GT_LONG "Two players fight to the death" #define PVPGN_2V2_GT_DESC "Two vs. Two" #define PVPGN_2V2_GT_LONG "Two teams of two vie for dominance" #define PVPGN_3V3_GT_DESC "Three vs. Three" #define PVPGN_3V3_GT_LONG "Two teams of three face off on the battlefield" #define PVPGN_4V4_GT_DESC "Four vs. Four" #define PVPGN_4V4_GT_LONG "Two teams of four head to battle" #define PVPGN_5V5_GT_DESC "Five vs. Five" #define PVPGN_5V5_GT_LONG "Two teams of five - who will prevail?" #define PVPGN_6V6_GT_DESC "Six vs. Six" #define PVPGN_6V6_GT_LONG "Two teams of six - get ready to rumble!" #define PVPGN_SFFA_GT_DESC "Small Free for All" #define PVPGN_SFFA_GT_LONG "Can you defeat 3-5 opponents alone?" #define PVPGN_TFFA_GT_DESC "Team Free for All" #define PVPGN_TFFA_GT_LONG "Can your team defeat 1-2 others?" #define PVPGN_2V2V2_GT_DESC "Two vs. Two vs. Two" #define PVPGN_2V2V2_GT_LONG "Three teams of two, can you handle it?" #define PVPGN_3V3V3_GT_DESC "Three vs. Three vs. Three" #define PVPGN_3V3V3_GT_LONG "Three teams of three battle each other " #define PVPGN_4V4V4_GT_DESC "Four vs. Four vs. Four" #define PVPGN_4V4V4_GT_LONG "Three teams of four - things getting crowded?" #define PVPGN_2V2V2V2_GT_DESC "Two vs. Two vs. Two vs. Two" #define PVPGN_2V2V2V2_GT_LONG "Four teams of two, is this a challenge?" #define PVPGN_3V3V3V3_GT_DESC "Three vs. Three vs. Three vs. Three" #define PVPGN_3V3V3V3_GT_LONG "Four teams of three, the ultimate challenge!" #define PVPGN_AINFO_FILE "conf/anongame_infos.conf" /* max number of players in an anongame match [Omega] */ #define ANONGAME_MAX_GAMECOUNT 12 /* max level of players*/ #define ANONGAME_MAX_LEVEL 100 /***************************************************************/ /* platform dependent features */ /* conditionally enabled features */ #if defined(HAVE_SIGACTION) && defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGADDSET) # define DO_POSIXSIG #endif #if defined(HAVE_FORK) && defined(HAVE_PIPE) # define DO_SUBPROC #endif #if defined(HAVE_FORK) && defined(HAVE_CHDIR) && (defined(HAVE_SETPGID) || defined(HAVE_SETPGRP)) # define DO_DAEMONIZE #endif /* GCC attributes */ /* enable format mismatch warnings from gcc */ #if defined(__GNUC__) && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2) # if __GNUC__ == 2 && __GNUC_MINOR__ < 7 /* namespace clean versions were available starting in 2.6.4 */ # define __format__ format # define __printf__ printf # endif # define PRINTF_ATTR(FMTARG,VARG) __attribute__((__format__(printf,FMTARG,VARG))) #else # define PRINTF_ATTR(FMTARG,VARG) #endif /* type attributes */ /* set GCC machine storage mode */ #if defined(__GNUC__) && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 7) || __GNUC__ > 2) # define MODE_ATTR(M) __attribute__((__mode__(M))) # define HAVE_MODE_ATTR #else # define MODE_ATTR(M) #endif /* avoid using padding on GCC, for other compilers you need alternate solutions */ #if defined(__GNUC__) # define PACKED_ATTR() __attribute__((__packed__)) #else # define PACKED_ATTR() #endif /* default maxim number of sockets in the fdwatch pool */ #define BNETD_MAX_SOCKETS 1000 /* Used for FDSETSIZE redefine (only on WIN32 so so far) */ #define BNETD_MAX_SOCKVAL 8192 /* * select() hackery... works most places, need to add autoconf checks * because some systems may redefine FD_SETSIZE, have it as a variable, * or not have the concept of such a value. * dizzy: this is a total hack. only WIN32 so far specifies this as beeing * "legal"; in UNIX in general it should be NOT because the kernel interface * of select will never notice your userland changes to the fd_sets */ /* Win32 defaults to 64, BSD and Linux default to 1024 */ /* FIXME: how big can this be before things break? */ #ifdef WIN32 # define FD_SETSIZE BNETD_MAX_SOCKVAL #endif #ifdef HAVE_EPOLL_CREATE # define HAVE_EPOLL 1 #endif #if defined(WITH_SQL_MYSQL) || defined(WITH_SQL_PGSQL) || defined(WITH_SQL_SQLITE3) || defined(WITH_SQL_ODBC) #define WITH_SQL 1 #endif #endif pvpgn-1.8.5/src/common/lstr.h0000644000175000017500000000256711151345317015070 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * lstr is a structure to be used for cached string lengths for speed * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_LSTR_TYPES #define INCLUDED_LSTR_TYPES typedef struct lstr { char *str; unsigned len; } t_lstr; #endif /* INCLUDED_LSTR_TYPES */ #ifndef INCLUDED_LSTR_PROTOS #define INCLUDED_LSTR_PROTOS static inline void lstr_set_str(t_lstr *lstr, char *str) { lstr->str = str; } static inline char *lstr_get_str(t_lstr *lstr) { return lstr->str; } static inline void lstr_set_len(t_lstr *lstr, unsigned len) { lstr->len = len; } static inline unsigned lstr_get_len(t_lstr *lstr) { return lstr->len; } #endif /* INCLUDED_LSTR_PROTOS */ pvpgn-1.8.5/src/common/addr.c0000644000175000017500000003263211151345317015005 0ustar aaronaaron/* * Copyright (C) 1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define ADDR_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memset.h" #include "compat/memcpy.h" #include "compat/strrchr.h" #include "compat/strdup.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #ifdef HAVE_ARPA_INET_H # include #endif #include "compat/inet_aton.h" #include "compat/inet_ntoa.h" #ifdef HAVE_NETDB_H # include #endif #ifdef HAVE_ASSERT_H # include #endif #include "compat/psock.h" #include "common/eventlog.h" #include "common/list.h" #include "common/util.h" #include "common/xalloc.h" #include "common/addr.h" #include "common/setup_after.h" static char const * netaddr_num_to_addr_str(unsigned int netipaddr, unsigned int netmask); #define HACK_SIZE 4 /* both arguments are in host byte order */ extern char const * addr_num_to_addr_str(unsigned int ipaddr, unsigned short port) { static unsigned int curr=0; static char temp[HACK_SIZE][64]; struct sockaddr_in tsa; curr = (curr+1)%HACK_SIZE; memset(&tsa,0,sizeof(tsa)); tsa.sin_family = PSOCK_AF_INET; tsa.sin_port = htons((unsigned short)0); tsa.sin_addr.s_addr = htonl(ipaddr); sprintf(temp[curr],"%.32s:%hu",inet_ntoa(tsa.sin_addr),port); return temp[curr]; } /* ipaddr is in host byte order */ extern char const * addr_num_to_ip_str(unsigned int ipaddr) { static unsigned int curr=0; static char temp[HACK_SIZE][64]; struct sockaddr_in tsa; curr = (curr+1)%HACK_SIZE; memset(&tsa,0,sizeof(tsa)); tsa.sin_family = PSOCK_AF_INET; tsa.sin_port = htons((unsigned short)0); tsa.sin_addr.s_addr = htonl(ipaddr); sprintf(temp[curr],"%.32s",inet_ntoa(tsa.sin_addr)); return temp[curr]; } static char const * netaddr_num_to_addr_str(unsigned int netipaddr, unsigned int netmask) { static unsigned int curr=0; static char temp[HACK_SIZE][64]; struct sockaddr_in tsa; curr = (curr+1)%HACK_SIZE; memset(&tsa,0,sizeof(tsa)); tsa.sin_family = PSOCK_AF_INET; tsa.sin_port = htons((unsigned short)0); tsa.sin_addr.s_addr = htonl(netipaddr); sprintf(temp[curr],"%.32s/0x%08x",inet_ntoa(tsa.sin_addr),netmask); return temp[curr]; } extern char const * host_lookup(char const * hoststr, unsigned int * ipaddr) { struct sockaddr_in tsa; #ifdef HAVE_GETHOSTBYNAME struct hostent * hp; #endif if (!hoststr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hoststr"); return NULL; } if (!ipaddr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL ipaddr"); return NULL; } memset(&tsa,0,sizeof(tsa)); tsa.sin_family = PSOCK_AF_INET; tsa.sin_port = htons(0); #ifdef HAVE_GETHOSTBYNAME #ifdef WIN32 psock_init(); #endif hp = gethostbyname(hoststr); if (!hp || !hp->h_addr_list) #endif { if (inet_aton(hoststr,&tsa.sin_addr)) { *ipaddr = ntohl(tsa.sin_addr.s_addr); return hoststr; /* We could call gethostbyaddr() on tsa to try and get the official hostname but most systems would have already found it when sending a dotted-quad to gethostbyname(). This is good enough when that fails. */ } eventlog(eventlog_level_error,__FUNCTION__,"could not lookup host \"%s\"",hoststr); return NULL; } #ifdef HAVE_GETHOSTBYNAME memcpy(&tsa.sin_addr,(void *)hp->h_addr_list[0],sizeof(struct in_addr)); /* avoid warning */ *ipaddr = ntohl(tsa.sin_addr.s_addr); if (hp->h_name) return hp->h_name; return hoststr; #endif } extern t_addr * addr_create_num(unsigned int ipaddr, unsigned short port) { t_addr * temp; temp = xmalloc(sizeof(t_addr)); temp->str = xstrdup(addr_num_to_addr_str(ipaddr,port)); temp->str = NULL; temp->ip = ipaddr; temp->port = port; temp->data.p = NULL; return temp; } extern t_addr * addr_create_str(char const * str, unsigned int defipaddr, unsigned short defport) { char * tstr; t_addr * temp; unsigned int ipaddr; unsigned short port; char const * hoststr; char * portstr; char const * hostname; if (!str) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL str"); return NULL; } tstr = xstrdup(str); if ((portstr = strrchr(tstr,':'))) { char * protstr; *portstr = '\0'; portstr++; if ((protstr = strrchr(portstr,'/'))) { *protstr = '\0'; protstr++; } if (portstr[0]!='\0') { if (str_to_ushort(portstr,&port)<0) { #ifdef HAVE_GETSERVBYNAME struct servent * sp; if (!(sp = getservbyname(portstr,protstr?protstr:"tcp"))) #endif { eventlog(eventlog_level_error,__FUNCTION__,"could not convert \"%s\" to a port number",portstr); xfree(tstr); return NULL; } #ifdef HAVE_GETSERVBYNAME port = ntohs(sp->s_port); #endif } } else port = defport; } else port = defport; if (tstr[0]!='\0') hoststr = tstr; else { struct sockaddr_in tsa; tsa.sin_addr.s_addr = htonl(defipaddr); hoststr = inet_ntoa(tsa.sin_addr); } if (!(hostname = host_lookup(hoststr,&ipaddr))) { eventlog(eventlog_level_error,__FUNCTION__,"could not lookup host \"%s\"",hoststr); xfree(tstr); return NULL; } temp = xmalloc(sizeof(t_addr)); temp->str = xstrdup(hostname); xfree(tstr); temp->ip = ipaddr; temp->port = port; temp->data.p = NULL; return temp; } extern int addr_destroy(t_addr const * addr) { if (!addr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL addr"); return -1; } if (addr->str) xfree((void *)addr->str); /* avoid warning */ xfree((void *)addr); /* avoid warning */ return 0; } /* hostname or IP */ extern char * addr_get_host_str(t_addr const * addr, char * str, unsigned int len) { if (!addr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL addr"); return NULL; } if (!str) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL str"); return NULL; } if (len<2) { eventlog(eventlog_level_error,__FUNCTION__,"str too short"); return NULL; } if (!addr->str) { eventlog(eventlog_level_error,__FUNCTION__,"addr has NULL str"); return NULL; } strncpy(str,addr->str,len-1); str[len-1] = '\0'; return str; } /* IP:port */ extern char * addr_get_addr_str(t_addr const * addr, char * str, unsigned int len) { if (!addr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL addr"); return NULL; } if (!str) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL str"); return NULL; } if (len<2) { eventlog(eventlog_level_error,__FUNCTION__,"str too short"); return NULL; } strncpy(str,addr_num_to_addr_str(addr->ip,addr->port),len-1); str[len-1] = '\0'; return str; } extern unsigned int addr_get_ip(t_addr const * addr) { if (!addr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL addr"); return 0; } return addr->ip; } extern unsigned short addr_get_port(t_addr const * addr) { if (!addr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL addr"); return 0; } return addr->port; } extern int addr_set_data(t_addr * addr, t_addr_data data) { if (!addr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL addr"); return -1; } addr->data = data; return 0; } extern t_addr_data addr_get_data(t_addr const * addr) { t_addr_data tdata; if (!addr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL addr"); tdata.p = NULL; return tdata; } return addr->data; } extern t_netaddr * netaddr_create_str(char const * netstr) { t_netaddr * netaddr; char * temp; char const * netipstr; char const * netmaskstr; unsigned int netip; unsigned int netmask; if (!netstr) { eventlog(eventlog_level_error,__FUNCTION__,"unable to allocate memory for netaddr"); return NULL; } temp = xstrdup(netstr); if (!(netipstr = strtok(temp,"/"))) { xfree(temp); return NULL; } if (!(netmaskstr = strtok(NULL,"/"))) { xfree(temp); return NULL; } netaddr = xmalloc(sizeof(t_netaddr)); /* FIXME: call getnetbyname() first, then host_lookup() */ if (!host_lookup(netipstr,&netip)) { eventlog(eventlog_level_error,__FUNCTION__,"could not lookup net"); xfree(netaddr); xfree(temp); return NULL; } netaddr->ip = netip; if (str_to_uint(netmaskstr,&netmask)<0) { struct sockaddr_in tsa; if (inet_aton(netmaskstr,&tsa.sin_addr)) netmask = ntohl(tsa.sin_addr.s_addr); else { eventlog(eventlog_level_error,__FUNCTION__,"could not convert mask"); xfree(netaddr); xfree(temp); return NULL; } } else { if (netmask>32) { eventlog(eventlog_level_error,__FUNCTION__,"network bits must be less than or equal to 32 (%u)",netmask); xfree(netaddr); xfree(temp); return NULL; } /* for example, 8 -> 11111111000000000000000000000000 */ if (netmask!=0) netmask = ~((1<<(32-netmask))-1); } netaddr->mask = netmask; xfree(temp); // [zap-zero] 20020731 - (hopefully) fixed memory leak return netaddr; } extern int netaddr_destroy(t_netaddr const * netaddr) { if (!netaddr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL netaddr"); return -1; } xfree((void *)netaddr); /* avoid warning */ return 0; } extern char * netaddr_get_addr_str(t_netaddr const * netaddr, char * str, unsigned int len) { if (!netaddr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL netaddr"); return NULL; } if (!str) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL str"); return NULL; } if (len<2) { eventlog(eventlog_level_error,__FUNCTION__,"str too short"); return NULL; } strncpy(str,netaddr_num_to_addr_str(netaddr->ip,netaddr->mask),len-1); /* FIXME: format nicely with x.x.x.x/bitcount */ str[len-1] = '\0'; return str; } extern int netaddr_contains_addr_num(t_netaddr const * netaddr, unsigned int ipaddr) { if (!netaddr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL netaddr"); return -1; } return (ipaddr&netaddr->mask)==netaddr->ip; } extern int addrlist_append(t_addrlist * addrlist, char const * str, unsigned int defipaddr, unsigned short defport) { t_addr * addr; char * tstr; char * tok; assert(addrlist != NULL); if (!str) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL str"); return -1; } tstr = xstrdup(str); for (tok=strtok(tstr,","); tok; tok=strtok(NULL,",")) /* strtok modifies the string it is passed */ { if (!(addr = addr_create_str(tok,defipaddr,defport))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create addr"); xfree(tstr); return -1; } list_append_data(addrlist,addr); } xfree(tstr); return 0; } extern t_addrlist * addrlist_create(char const * str, unsigned int defipaddr, unsigned short defport) { t_addrlist * addrlist; if (!str) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL str"); return NULL; } addrlist = list_create(); if (addrlist_append(addrlist,str,defipaddr,defport)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not append to newly created addrlist"); list_destroy(addrlist); return NULL; } return addrlist; } extern int addrlist_destroy(t_addrlist * addrlist) { t_elem * curr; t_addr * addr; if (!addrlist) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL addrlist"); return -1; } LIST_TRAVERSE(addrlist,curr) { if (!(addr = elem_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL addr in list"); else addr_destroy(addr); list_remove_elem(addrlist,&curr); } return list_destroy(addrlist); } extern int addrlist_get_length(t_addrlist const * addrlist) { return list_get_length(addrlist); } pvpgn-1.8.5/src/common/addr.h0000644000175000017500000000637011151345317015012 0ustar aaronaaron/* * Copyright (C) 1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_ADDR_TYPES #define INCLUDED_ADDR_TYPES #ifdef JUST_NEED_TYPES # include "common/list.h" #else # define JUST_NEED_TYPES # include "common/list.h" # undef JUST_NEED_TYPES #endif typedef union { unsigned long n; int i; void * p; } t_addr_data; typedef struct addr_struct #ifdef ADDR_INTERNAL_ACCESS { char const * str; /* hostname or ip */ unsigned int ip; unsigned int port; t_addr_data data; /* data argument */ } #endif t_addr; typedef struct netaddr_struct #ifdef ADDR_INTERNAL_ACCESS { unsigned int ip; unsigned int mask; } #endif t_netaddr; typedef t_list t_addrlist; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_ADDR_PROTOS #define INCLUDED_ADDR_PROTOS /* ipaddr and port are in host byte order */ extern char const * addr_num_to_addr_str(unsigned int ipaddr, unsigned short port); /* ipaddr is in host byte order */ extern char const * addr_num_to_ip_str(unsigned int ipaddr); extern char const * host_lookup(char const * hoststr, unsigned int * ipaddr); /* ipaddr and port are in host byte order */ extern t_addr * addr_create_num(unsigned int ipaddr, unsigned short port) ; /* defipaddr and defport are in host byte order */ extern t_addr * addr_create_str(char const * str, unsigned int defipaddr, unsigned short defport) ; extern int addr_destroy(t_addr const * addr); extern char * addr_get_host_str(t_addr const * addr, char * str, unsigned int len); extern char * addr_get_addr_str(t_addr const * addr, char * str, unsigned int len); /* returned in host byte order */ extern unsigned int addr_get_ip(t_addr const * addr); /* returned in host byte order */ extern unsigned short addr_get_port(t_addr const * addr); extern int addr_set_data(t_addr * addr, t_addr_data data); extern t_addr_data addr_get_data(t_addr const * addr); extern t_netaddr * netaddr_create_str(char const * str) ; extern int netaddr_destroy(t_netaddr const * netaddr); extern char * netaddr_get_addr_str(t_netaddr const * netaddr, char * str, unsigned int len); extern int netaddr_contains_addr_num(t_netaddr const * netaddr, unsigned int ipaddr); /* defipaddr and defport are in host byte order */ extern int addrlist_append(t_addrlist * addrlist, char const * str, unsigned int defipaddr, unsigned short defport); extern t_addrlist * addrlist_create(char const * str, unsigned int defipaddr, unsigned short defport) ; extern int addrlist_destroy(t_addrlist * addrlist); extern int addrlist_get_length(t_addrlist const * addrlist); #endif #endif pvpgn-1.8.5/src/common/fdwatch_epoll.h0000644000175000017500000000206211151345317016705 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * Linux epoll(4) based backend * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __INCLUDED_FDWATCH_EPOLL__ #define __INCLUDED_FDWATCH_EPOLL__ extern t_fdw_backend fdw_epoll; #endif /* __INCLUDED_FDWATCH_EPOLL__ */ pvpgn-1.8.5/src/common/tag.c0000644000175000017500000001617611151345317014653 0ustar aaronaaron/* * Copyright (C) 2004 Aaron * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "errno.h" #include "compat/strerror.h" #include "common/eventlog.h" #include "common/tag.h" #include "common/setup_after.h" /* fixme: have all functions call tag_str_to_uint() */ extern t_clienttag clienttag_str_to_uint(char const * clienttag) { if (!clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag"); return CLIENTTAG_UNKNOWN_UINT; } return tag_str_to_uint(clienttag); } /* fixme: have all fuctions call tag_uint_to_str() */ extern char const * clienttag_uint_to_str(t_clienttag clienttag) { switch (clienttag) { case CLIENTTAG_BNCHATBOT_UINT: return CLIENTTAG_BNCHATBOT; case CLIENTTAG_STARCRAFT_UINT: return CLIENTTAG_STARCRAFT; case CLIENTTAG_BROODWARS_UINT: return CLIENTTAG_BROODWARS; case CLIENTTAG_SHAREWARE_UINT: return CLIENTTAG_SHAREWARE; case CLIENTTAG_DIABLORTL_UINT: return CLIENTTAG_DIABLORTL; case CLIENTTAG_DIABLOSHR_UINT: return CLIENTTAG_DIABLOSHR; case CLIENTTAG_WARCIIBNE_UINT: return CLIENTTAG_WARCIIBNE; case CLIENTTAG_DIABLO2DV_UINT: return CLIENTTAG_DIABLO2DV; case CLIENTTAG_STARJAPAN_UINT: return CLIENTTAG_STARJAPAN; case CLIENTTAG_DIABLO2ST_UINT: return CLIENTTAG_DIABLO2ST; case CLIENTTAG_DIABLO2XP_UINT: return CLIENTTAG_DIABLO2XP; case CLIENTTAG_WARCRAFT3_UINT: return CLIENTTAG_WARCRAFT3; case CLIENTTAG_WAR3XP_UINT: return CLIENTTAG_WAR3XP; case CLIENTTAG_IIRC_UINT: return CLIENTTAG_IIRC; case CLIENTTAG_WWOL_UINT: return CLIENTTAG_WWOL; default: return CLIENTTAG_UNKNOWN; } } /*****/ /* make all letters in string upper case - used in command.c*/ extern t_tag tag_case_str_to_uint(char const * tag_str) { unsigned int i, len; char temp_str[5]; len = strlen(tag_str); if (len != 4) eventlog(eventlog_level_warn,__FUNCTION__,"got unusual sized clienttag '%s'",tag_str); for (i=0; i>24) ); tag_str[1] = ((unsigned char)(tag_uint>>16)&0xff); tag_str[2] = ((unsigned char)(tag_uint>> 8)&0xff); tag_str[3] = ((unsigned char)(tag_uint )&0xff); tag_str[4] = '\0'; return tag_str; } extern char * tag_uint_to_revstr(char * tag_str, t_tag tag_uint) { if (!tag_uint) /* return "UNKN" if tag_uint = 0 */ return TAG_UNKNOWN; tag_str[0] = ((unsigned char)(tag_uint )&0xff); tag_str[1] = ((unsigned char)(tag_uint>> 8)&0xff); tag_str[2] = ((unsigned char)(tag_uint>>16)&0xff); tag_str[3] = ((unsigned char)(tag_uint>>24) ); tag_str[4] = '\0'; return tag_str; } extern int tag_check_arch(t_tag tag_uint) { switch (tag_uint) { case ARCHTAG_WINX86_UINT: case ARCHTAG_MACPPC_UINT: case ARCHTAG_OSXPPC_UINT: return 1; default: return 0; } } extern int tag_check_client(t_tag tag_uint) { switch (tag_uint) { case CLIENTTAG_BNCHATBOT_UINT: case CLIENTTAG_STARCRAFT_UINT: case CLIENTTAG_BROODWARS_UINT: case CLIENTTAG_SHAREWARE_UINT: case CLIENTTAG_DIABLORTL_UINT: case CLIENTTAG_DIABLOSHR_UINT: case CLIENTTAG_WARCIIBNE_UINT: case CLIENTTAG_DIABLO2DV_UINT: case CLIENTTAG_STARJAPAN_UINT: case CLIENTTAG_DIABLO2ST_UINT: case CLIENTTAG_DIABLO2XP_UINT: case CLIENTTAG_WARCRAFT3_UINT: case CLIENTTAG_WAR3XP_UINT: case CLIENTTAG_IIRC_UINT: case CLIENTTAG_WWOL_UINT: return 1; default: return 0; } } extern int tag_check_gamelang(t_tag gamelang) { switch (gamelang) { case GAMELANG_ENGLISH_UINT: /* enUS */ case GAMELANG_GERMAN_UINT: /* deDE */ case GAMELANG_CZECH_UINT: /* csCZ */ case GAMELANG_SPANISH_UINT: /* esES */ case GAMELANG_FRENCH_UINT: /* frFR */ case GAMELANG_ITALIAN_UINT: /* itIT */ case GAMELANG_JAPANESE_UINT: /* jaJA */ case GAMELANG_KOREAN_UINT: /* koKR */ case GAMELANG_POLISH_UINT: /* plPL */ case GAMELANG_RUSSIAN_UINT: /* ruRU */ case GAMELANG_CHINESE_S_UINT: /* zhCN */ case GAMELANG_CHINESE_T_UINT: /* zhTW */ return 1; default: return 0; } } extern char const * clienttag_get_title(t_clienttag clienttag) { switch (clienttag) { case CLIENTTAG_WAR3XP_UINT: return "Warcraft III Frozen Throne"; case CLIENTTAG_WARCRAFT3_UINT: return "Warcraft III"; case CLIENTTAG_DIABLO2XP_UINT: return "Diablo II Lord of Destruction"; case CLIENTTAG_DIABLO2DV_UINT: return "Diablo II"; case CLIENTTAG_STARJAPAN_UINT: return "Starcraft (Japan)"; case CLIENTTAG_WARCIIBNE_UINT: return "Warcraft II"; case CLIENTTAG_DIABLOSHR_UINT: return "Diablo I (Shareware)"; case CLIENTTAG_DIABLORTL_UINT: return "Diablo I"; case CLIENTTAG_SHAREWARE_UINT: return "Starcraft (Shareware)"; case CLIENTTAG_BROODWARS_UINT: return "Starcraft: Brood War"; case CLIENTTAG_STARCRAFT_UINT: return "Starcraft"; case CLIENTTAG_BNCHATBOT_UINT: return "Chat"; case CLIENTTAG_IIRC_UINT: return "Internet Relay Chat"; case CLIENTTAG_WWOL_UINT: return "Westwood Online"; default: return "Unknown"; } } pvpgn-1.8.5/src/common/bn_type.c0000644000175000017500000003352611151345317015536 0ustar aaronaaron/* * Copyright (C) 1998,1999,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memcpy.h" #include "common/eventlog.h" #include "common/bn_type.h" #include "common/setup_after.h" /************************************************************/ extern int bn_byte_tag_get(bn_byte const * src, char * dst, unsigned int len) { unsigned int i; if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst"); return -1; } if (!src) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL src"); return -1; } if (len<1) { eventlog(eventlog_level_error,__FUNCTION__,"got zero len"); return -1; } for (i=0; i> 8) ); return 0; } extern int bn_short_nset(bn_short * dst, t_uint16 src) { if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst"); return -1; } (*dst)[0] = (unsigned char)((src>> 8) ); (*dst)[1] = (unsigned char)((src )&0xff); return 0; } extern int bn_int_set(bn_int * dst, t_uint32 src) { if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst"); return -1; } (*dst)[0] = (unsigned char)((src )&0xff); (*dst)[1] = (unsigned char)((src>> 8)&0xff); (*dst)[2] = (unsigned char)((src>>16)&0xff); (*dst)[3] = (unsigned char)((src>>24) ); return 0; } extern int bn_int_nset(bn_int * dst, t_uint32 src) { if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst"); return -1; } (*dst)[0] = (unsigned char)((src>>24) ); (*dst)[1] = (unsigned char)((src>>16)&0xff); (*dst)[2] = (unsigned char)((src>> 8)&0xff); (*dst)[3] = (unsigned char)((src )&0xff); return 0; } #ifdef HAVE_T_LONG extern int bn_long_set(bn_long * dst, t_uint64 src) { if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst"); return -1; } (*dst)[0] = (unsigned char)((src )&0xff); (*dst)[1] = (unsigned char)((src>> 8)&0xff); (*dst)[2] = (unsigned char)((src>>16)&0xff); (*dst)[3] = (unsigned char)((src>>24)&0xff); (*dst)[4] = (unsigned char)((src>>32)&0xff); (*dst)[5] = (unsigned char)((src>>40)&0xff); (*dst)[6] = (unsigned char)((src>>48)&0xff); (*dst)[7] = (unsigned char)((src>>56) ); return 0; } extern int bn_long_nset(bn_long * dst, t_uint64 src) { if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst"); return -1; } (*dst)[0] = (unsigned char)((src>>56) ); (*dst)[1] = (unsigned char)((src>>48)&0xff); (*dst)[2] = (unsigned char)((src>>40)&0xff); (*dst)[3] = (unsigned char)((src>>32)&0xff); (*dst)[4] = (unsigned char)((src>>24)&0xff); (*dst)[5] = (unsigned char)((src>>16)&0xff); (*dst)[6] = (unsigned char)((src>> 8)&0xff); (*dst)[7] = (unsigned char)((src )&0xff); return 0; } #endif extern int bn_long_set_a_b(bn_long * dst, t_uint32 srca, t_uint32 srcb) { if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst"); return -1; } (*dst)[0] = (unsigned char)((srcb )&0xff); (*dst)[1] = (unsigned char)((srcb>> 8)&0xff); (*dst)[2] = (unsigned char)((srcb>>16)&0xff); (*dst)[3] = (unsigned char)((srcb>>24)&0xff); (*dst)[4] = (unsigned char)((srca )&0xff); (*dst)[5] = (unsigned char)((srca>> 8)&0xff); (*dst)[6] = (unsigned char)((srca>>16)&0xff); (*dst)[7] = (unsigned char)((srca>>24) ); return 0; } extern int bn_long_nset_a_b(bn_long * dst, t_uint32 srca, t_uint32 srcb) { if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst"); return -1; } (*dst)[0] = (unsigned char)((srca>>24) ); (*dst)[1] = (unsigned char)((srca>>16)&0xff); (*dst)[2] = (unsigned char)((srca>> 8)&0xff); (*dst)[3] = (unsigned char)((srca )&0xff); (*dst)[4] = (unsigned char)((srcb>>24)&0xff); (*dst)[5] = (unsigned char)((srcb>>16)&0xff); (*dst)[6] = (unsigned char)((srcb>> 8)&0xff); (*dst)[7] = (unsigned char)((srcb )&0xff); return 0; } /************************************************************/ extern int bn_raw_set(void * dst, void const * src, unsigned int len) { if (!dst) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst"); return -1; } if (!src) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL src"); return -1; } memcpy(dst,src,len); return 0; } /************************************************************/ extern int bn_byte_tag_eq(bn_byte const src, char const * tag) { bn_byte temp; if (!src) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL src"); return -1; } if (!tag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL tag"); return -1; } if (bn_byte_tag_set(&temp,tag)<0) return -1; if (bn_byte_get(src)==bn_byte_get(temp)) return 0; return -1; } extern int bn_short_tag_eq(bn_short const src, char const * tag) { bn_short temp; if (!src) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL src"); return -1; } if (!tag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL tag"); return -1; } if (bn_short_tag_set(&temp,tag)<0) return -1; if (bn_short_get(src)==bn_short_get(temp)) return 0; return -1; } extern int bn_int_tag_eq(bn_int const src, char const * tag) { bn_int temp; if (!src) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL src"); return -1; } if (!tag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL tag"); return -1; } if (bn_int_tag_set(&temp,tag)<0) return -1; if (bn_int_get(src)==bn_int_get(temp)) return 0; return -1; } extern int bn_long_tag_eq(bn_long const src, char const * tag) { bn_long temp; if (!src) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL src"); return -1; } if (!tag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL tag"); return -1; } if (bn_long_tag_set(&temp,tag)<0) return -1; if (bn_long_get_a(src)==bn_long_get_a(temp) && bn_long_get_b(src)==bn_long_get_b(temp)) return 0; return -1; } /************************************************************/ extern int uint32_to_int(t_uint32 num) { if (num<(1UL<<30)) return (int)num; return (-(int)((~(num))+1)); } pvpgn-1.8.5/src/common/trans.h0000644000175000017500000000273411151345317015227 0ustar aaronaaron/* * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_TRANS_TYPES #define INCLUDED_TRANS_TYPES #ifdef TRANS_INTERNAL_ACCESS #ifdef JUST_NEED_TYPES # include "common/addr.h" #else # define JUST_NEED_TYPES # include "common/addr.h" # undef JUST_NEED_TYPES #endif typedef struct { t_addr *input; t_addr *output; t_netaddr *network; } t_trans; #endif #endif #ifndef JUST_NEED_TYPES #ifndef INCLUDED_TRANS_PROTOS #define INCLUDED_TRANS_PROTOS #define TRANS_BNETD 1 #define TRANS_D2CS 2 extern int trans_load(char const * filename, int program); extern int trans_unload(void); extern int trans_reload(char const * filename, int program); extern int trans_net(unsigned int clientaddr, unsigned int *addr, unsigned short *port); #endif #endif pvpgn-1.8.5/src/common/xstr.h0000644000175000017500000000373611151345317015103 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * * xstr is a module trying to offer some high-level string functionality * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_XSTR_TYPES #define INCLUDED_XSTR_TYPES typedef struct { unsigned alen, ulen; char *str; } t_xstr; #define DECLARE_XSTR(var) \ t_xstr var = { 0, 0, NULL }; #endif /* INCLUDED_XSTR_TYPES */ #ifndef INCLUDED_XSTR_PROTOS #define INCLUDED_XSTR_PROTOS /* for NULL */ #include extern t_xstr* xstr_alloc(void); extern void xstr_free(t_xstr*); extern t_xstr* xstr_cpy_str(t_xstr* dst, const char* src); extern t_xstr* xstr_cat_xstr(t_xstr* dst, const t_xstr* src); extern t_xstr* xstr_cat_str(t_xstr* dst, const char* src); extern t_xstr* xstr_ncat_str(t_xstr* dst, const char* src, int len); extern t_xstr* xstr_cat_char(t_xstr* dst, const char ch); static inline void xstr_init(t_xstr* xstr) { xstr->alen = xstr->ulen = 0; xstr->str = NULL; } static inline const char* xstr_get_str(t_xstr* xstr) { if (xstr->alen && xstr->ulen) return xstr->str; return NULL; } static inline unsigned xstr_get_len(t_xstr* xstr) { return xstr->alen ? xstr->ulen : 0; } static inline t_xstr* xstr_clear(t_xstr* xstr) { /* reset the string content, don't touch the allocation space */ xstr->ulen = 0; return xstr; } #endif /* INCLUDED_STR_PROTOS */ pvpgn-1.8.5/src/common/rlimit.h0000644000175000017500000000137711151345317015402 0ustar aaronaaron/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ extern int get_socket_limit(void); pvpgn-1.8.5/src/common/fdwatch.h0000644000175000017500000000435211151345317015516 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __FDWATCH_INCLUDED__ #define __FDWATCH_INCLUDED__ #include "common/elist.h" typedef enum { fdwatch_type_none = 0, fdwatch_type_read = 1, fdwatch_type_write = 2 } t_fdwatch_type; typedef int (*fdwatch_handler)(void *data, t_fdwatch_type); typedef struct { int fd; int rw; fdwatch_handler hnd; void *data; t_elist uselist; t_elist freelist; } t_fdwatch_fd; #ifdef FDWATCH_BACKEND typedef int (*t_fdw_cb)(t_fdwatch_fd *cfd, void *data); #endif typedef struct { int (*init)(int nfds); int (*close)(void); int (*add_fd)(int idx, t_fdwatch_type rw); int (*del_fd)(int idx); int (*watch)(long timeout_msecs); void (*handle)(void); } t_fdw_backend; extern int fdw_maxcons; extern t_fdwatch_fd *fdw_fds; #define fdw_idx(ptr) ((ptr) - fdw_fds) #define fdw_fd(ptr) ((ptr)->fd) #define fdw_rw(ptr) ((ptr)->rw) #define fdw_data(ptr) ((ptr)->data) #define fdw_hnd(ptr) ((ptr)->hnd) extern int fdwatch_init(int maxcons); extern int fdwatch_close(void); extern int fdwatch_add_fd(int fd, t_fdwatch_type rw, fdwatch_handler h, void *data); extern int fdwatch_update_fd(int idx, t_fdwatch_type rw); extern int fdwatch_del_fd(int idx); extern int fdwatch(long timeout_msecs); extern void fdwatch_handle(void); #ifdef FDWATCH_BACKEND extern void fdwatch_traverse(t_fdw_cb cb, void *data); #endif #endif /* __FDWATCH_INCLUDED__ */ pvpgn-1.8.5/src/common/asnprintf.h0000644000175000017500000000362411151345317016103 0ustar aaronaaron/* * Copyright (C) 2005 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ASNPRINTF_H #define ASNPRINTF_H #include "compat/vargs.h" #define ZEROPAD 1 /* pad with zero */ #define SIGN 2 /* unsigned/signed long */ #define PLUS 4 /* show plus */ #define SPACE 8 /* space if plus */ #define LEFT 16 /* left justified */ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ typedef struct { const char* trans; /* points to the translation of the format */ unsigned translen; /* how many chars in this translation */ const char* fmt; /* points to the fmt location of this format spec */ unsigned fmtlen; /* how many chars in this fmt spec */ } t_fmtentry; /* "array" snprintf - this function prints all vargs into the prepared buffer, * each of them as a \0 terminated string. The prepared char* [] locations will * contain the starting position of each seperate string afterwards. * The function returns the number of vargs that have been printed. */ int asnprintf(char * buffer, size_t size, t_fmtentry *entries, unsigned entlen, const char *fmt, ...); int vasnprintf(char * buffer, size_t size, t_fmtentry *entries, unsigned entlen, const char *fmt, va_list args); #endif pvpgn-1.8.5/src/common/tag.h0000644000175000017500000001203211151345317014643 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_TAG_TYPES #define INCLUDED_TAG_TYPES #ifdef JUST_NEED_TYPES #include "compat/uint.h" #else #define JUST_NEED_TYPES #include "compat/uint.h" #undef JUST_NEED_TYPES #endif typedef t_uint32 t_tag; typedef t_tag t_archtag; typedef t_tag t_clienttag; typedef t_tag t_gamelang; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_TAG_PROTOS #define INCLUDED_TAG_PROTOS /* Software tags */ #define CLIENTTAG_BNCHATBOT "CHAT" /* CHAT bot */ #define CLIENTTAG_BNCHATBOT_UINT 0x43484154 #define CLIENTTAG_STARCRAFT "STAR" /* Starcraft (original) */ #define CLIENTTAG_STARCRAFT_UINT 0x53544152 #define CLIENTTAG_BROODWARS "SEXP" /* Starcraft EXpansion Pack */ #define CLIENTTAG_BROODWARS_UINT 0x53455850 #define CLIENTTAG_SHAREWARE "SSHR" /* Starcraft Shareware */ #define CLIENTTAG_SHAREWARE_UINT 0x53534852 #define CLIENTTAG_DIABLORTL "DRTL" /* Diablo ReTaiL */ #define CLIENTTAG_DIABLORTL_UINT 0x4452544C #define CLIENTTAG_DIABLOSHR "DSHR" /* Diablo SHaReware */ #define CLIENTTAG_DIABLOSHR_UINT 0x44534852 #define CLIENTTAG_WARCIIBNE "W2BN" /* WarCraft II Battle.net Edition */ #define CLIENTTAG_WARCIIBNE_UINT 0x5732424E #define CLIENTTAG_DIABLO2DV "D2DV" /* Diablo II Diablo's Victory */ #define CLIENTTAG_DIABLO2DV_UINT 0x44324456 #define CLIENTTAG_STARJAPAN "JSTR" /* Starcraft (Japan) */ #define CLIENTTAG_STARJAPAN_UINT 0x4A535452 #define CLIENTTAG_DIABLO2ST "D2ST" /* Diablo II Stress Test */ #define CLIENTTAG_DIABLO2ST_UINT 0x44325354 #define CLIENTTAG_DIABLO2XP "D2XP" /* Diablo II Extension Pack */ #define CLIENTTAG_DIABLO2XP_UINT 0x44325850 /* FIXME: according to FSGS: SJPN==Starcraft (Japanese) SSJP==Starcraft (Japanese,Spawn) */ #define CLIENTTAG_WARCRAFT3 "WAR3" /* WarCraft III */ #define CLIENTTAG_WARCRAFT3_UINT 0x57415233 #define CLIENTTAG_WAR3XP "W3XP" /* WarCraft III Expansion */ #define CLIENTTAG_WAR3XP_UINT 0x57335850 #define CLIENTTAG_IIRC "IIRC"/* IRC */ #define CLIENTTAG_IIRC_UINT 0x49495243 #define CLIENTTAG_WWOL "WWOL"/* Westwood Online */ #define CLIENTTAG_WWOL_UINT 0x57574F4C /* BNETD-specific software tags - we try to use lowercase to avoid collisions */ #define CLIENTTAG_FREECRAFT "free" /* FreeCraft http://www.freecraft.com/ */ #define CLIENTTAG_UNKNOWN "UNKN" #define CLIENTTAG_UNKNOWN_UINT 0x554E4B4E /* Architecture tags */ #define ARCHTAG_WINX86 "IX86" /* MS Windows on Intel x86 */ #define ARCHTAG_MACPPC "PMAC" /* MacOS on PowerPC */ #define ARCHTAG_OSXPPC "XMAC" /* MacOS X on PowerPC */ #define ARCHTAG_WINX86_UINT 0x49583836 /* IX86 */ #define ARCHTAG_MACPPC_UINT 0x504D4143 /* PMAC */ #define ARCHTAG_OSXPPC_UINT 0x584D4143 /* XMAC */ /* game languages */ #define GAMELANG_ENGLISH_UINT 0x656E5553 /* enUS */ #define GAMELANG_GERMAN_UINT 0x64654445 /* deDE */ #define GAMELANG_CZECH_UINT 0x6373435A /* csCZ */ #define GAMELANG_SPANISH_UINT 0x65734553 /* esES */ #define GAMELANG_FRENCH_UINT 0x66724652 /* frFR */ #define GAMELANG_ITALIAN_UINT 0x69744954 /* itIT */ #define GAMELANG_JAPANESE_UINT 0x6A614A41 /* jaJA */ #define GAMELANG_KOREAN_UINT 0x6B6F4B52 /* koKR */ #define GAMELANG_POLISH_UINT 0x706C504C /* plPL */ #define GAMELANG_RUSSIAN_UINT 0x72755255 /* ruRU */ #define GAMELANG_CHINESE_S_UINT 0x7A68434E /* zhCN */ #define GAMELANG_CHINESE_T_UINT 0x7A685457 /* zhTW */ #define TAG_UNKNOWN_UINT 0x554E4B4E /* UNKN */ #define TAG_UNKNOWN "UNKN" /* Server tag */ #define BNETTAG "bnet" /* Battle.net */ /* Filetype tags (note these are "backwards") */ #define EXTENSIONTAG_PCX "xcp." #define EXTENSIONTAG_SMK "kms." #define EXTENSIONTAG_MNG "gnm." extern t_clienttag clienttag_str_to_uint(char const * clienttag); extern char const * clienttag_uint_to_str(t_clienttag clienttag); extern char const * clienttag_get_title(t_clienttag clienttag); extern t_tag tag_str_to_uint(char const * tag_str); extern t_tag tag_case_str_to_uint(char const * tag_str); extern char * tag_uint_to_str(char * tag_str, t_tag tag_uint); extern char * tag_uint_to_revstr(char * tag_str, t_tag tag_uint); extern int tag_check_arch(t_tag tag_uint); extern int tag_check_client(t_tag tag_uint); extern int tag_check_gamelang(t_tag tag_uint); #endif #endif pvpgn-1.8.5/src/common/xstring.c0000644000175000017500000001252711151345317015572 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/memcpy.h" #include "compat/memmove.h" #include "compat/strdup.h" #include "common/xalloc.h" #include "xstring.h" #include "common/setup_after.h" extern char * strtolower(char * str) { unsigned int i; unsigned char ch; if (!str) return NULL; for (i=0; (ch=str[i]); i++) { if ((isupper(ch))) str[i]=ch+('a'-'A'); } return str; } extern unsigned char xtoi(unsigned char ch) { unsigned char retval; if (isalpha(ch)) retval=tolower(ch); else retval=ch; if (retval < 'A') retval -= ('0'-0); else retval -= ('a' - 0xa); return retval; } extern char * str_strip_affix(char * str, char const * affix) { unsigned int i, j, n; int match; if (!str) return NULL; if (!affix) return str; for (i=0; str[i]; i++) { match=0; for (n=0; affix[n]; n++) { if (str[i]==affix[n]) { match=1; break; } } if (!match) break; } for (j=strlen(str)-1; j>=i; j--) { match=0; for (n=0; affix[n]; n++) { if (str[j]==affix[n]) { match=1; break; } } if (!match) break; } if (i>j) { str[0]='\0'; } else { memmove(str,str+i,j-i+1); str[j-i+1]='\0'; } return str; } extern char * hexstrdup(unsigned char const * src) { char * dest; int len; if (!src) return NULL; dest=xstrdup(src); len=hexstrtoraw(src,dest,strlen(dest)+1); dest[len]='\0'; return dest; } extern unsigned int hexstrtoraw(unsigned char const * src, char * data, unsigned int datalen) { unsigned char ch; unsigned int i, j; for (i=0, j=0; j=n ) { n += SPLIT_STRING_INCREASEMENT; pindex=(int *)xrealloc(pindex,n * sizeof(int)); } pindex[*count]=j; (*count)++; if (str[i]=='"') { i++; while (str[i]) { if (str[i]=='\\') { i++; if (!str[i]) break; } else if (str[i]=='"') { i++; break; } temp[j++]=str[i++]; } } else { while (str[i] && str[i] != ' ' && str[i] != '\t') { temp[j++]=str[i++]; } } temp[j++]='\0'; } index_size= *count * sizeof(char *); if (!index_size) { xfree(temp); xfree(pindex); return NULL; } result=xmalloc(j+index_size); memcpy(result+index_size,temp,j); ptrindex=xmalloc(*count * sizeof (char*)); for (i=0; i< *count; i++) { ptrindex[i] = result + index_size + pindex[i]; } memcpy(result,ptrindex,index_size); xfree(temp); xfree(pindex); xfree(ptrindex); return (char * *)result; } #define COMBINE_STRING_INIT_LEN 1024 #define COMBINE_STRING_INCREASEMENT 1024 extern char * arraytostr(char * * array, char const * delim, int count) { int i; unsigned int n; char * result; int need_delim; if (!delim || !array) return NULL; n=COMBINE_STRING_INIT_LEN; result=xmalloc(n); result[0]='\0'; need_delim=0; for (i=0; i=n) { n+=COMBINE_STRING_INCREASEMENT; result=xrealloc(result,n); } if (need_delim) { strcat(result,delim); } strcat(result,array[i]); need_delim=1; } result=xrealloc(result,strlen(result)+1); return result; } pvpgn-1.8.5/src/common/bnettime.h0000644000175000017500000000410411151345317015700 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_BNETTIME_TYPES #define INCLUDED_BNETTIME_TYPES typedef struct { #ifdef BNETTIME_INTERNAL_ACCESS unsigned int u; unsigned int l; #else unsigned int _private1; unsigned int _private2; #endif } t_bnettime; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_BNETTIME_PROTOS #define INCLUDED_BNETTIME_PROTOS #define JUST_NEED_TYPES #ifdef TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include "common/bn_type.h" #undef JUST_NEED_TYPES extern t_bnettime secs_to_bnettime(double secs) ; extern double bnettime_to_secs(t_bnettime bntime) ; extern t_bnettime time_to_bnettime(time_t stdtime, unsigned int usec) ; extern time_t bnettime_to_time(t_bnettime bntime) ; extern t_bnettime bnettime(void); extern char const * bnettime_get_str(t_bnettime bntime); extern int bnettime_set_str(t_bnettime * bntime, char const * timestr); extern int local_tzbias(void); extern t_bnettime bnettime_add_tzbias(t_bnettime bntime, int tzbias); extern void bnettime_to_bn_long(t_bnettime in, bn_long * out); extern void bn_long_to_bnettime(bn_long in, t_bnettime * out); #endif #endif pvpgn-1.8.5/src/common/bnethash.h0000644000175000017500000000266211151345317015674 0ustar aaronaaron/* * Copyright (C) 1999 Descolada (dyn1-tnt9-237.chicago.il.ameritech.net) * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_BNETHASH_TYPES #define INCLUDED_BNETHASH_TYPES #ifdef JUST_NEED_TYPES # include "compat/uint.h" #else # define JUST_NEED_TYPES # include "compat/uint.h" # undef JUST_NEED_TYPES #endif typedef t_uint32 t_hash[5]; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_BNETHASH_PROTOS #define INCLUDED_BNETHASH_PROTOS extern int bnet_hash(t_hash * hashout, unsigned int size, void const * data); extern int hash_eq(t_hash const h1, t_hash const h2) ; extern char const * hash_get_str(t_hash const hash); extern int hash_set_str(t_hash * hash, char const * str); #endif #endif pvpgn-1.8.5/src/common/token.c0000644000175000017500000000456011151345317015212 0ustar aaronaaron/* * Copyright (C) 2001 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define PREFS_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include #include "token.h" #include "common/eventlog.h" #include "common/setup_after.h" /* * Given a string and an integer pointer skip past pos characters and return * the next white-space delimited string, setting pos to the new position. */ extern char * next_token(char * ptr, unsigned int * pos) { unsigned int i; unsigned int start; int quoted; if (!ptr || !pos) return NULL; /* skip leading whitespace */ for (i=*pos; isspace((int)ptr[i]); i++); if (ptr[i]=='\0') return NULL; /* if after whitespace, we're done */ if (ptr[i]=='"') { quoted = 1; i++; } else quoted = 0; start = i; for (;;) { if (ptr[i]=='\0') break; if (quoted) /* FIXME: add handling of escape chars so quotes can be in tokens */ { if (ptr[i]=='"') break; } else if (isspace((int)ptr[i])) break; i++; } if (ptr[i]!='\0') { ptr[i] = '\0'; /* terminate the string */ *pos = i+1; /* remember the position of the next char */ } else *pos = i; /* this was the last token, just remember the NUL */ return &ptr[start]; } pvpgn-1.8.5/src/common/udp_protocol.h0000644000175000017500000000574411151345317016615 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_UDP_PROTOCOL_TYPES #define INCLUDED_UDP_PROTOCOL_TYPES /* * This file describes the UDP chat packets. The game packets aren't * in here and would probably go in another file. The first 4 bytes * seem to be a little-endian 32 bit integer id for the packet type. * FIXME: add more UDP packet types */ /******************************************************/ typedef struct { bn_int type; } PACKED_ATTR() t_udp_header; /******************************************************/ /******************************************************/ typedef struct { t_udp_header h; } PACKED_ATTR() t_udp_generic; /******************************************************/ /******************************************************/ /* client echos back with UDPOK packet */ /* 05 00 00 00 74 65 6E 62 ....tenb */ #define SERVER_UDPTEST 0x00000005 typedef struct { t_udp_header h; bn_int bnettag; /* 74 65 6E 62 */ } PACKED_ATTR() t_server_udptest; /******************************************************/ /******************************************************/ /* 07 00 00 00 49 41 19 00 ....IA.. 07 00 00 00 11 60 1D 00 .....`.. */ #define CLIENT_UDPPING 0x00000007 typedef struct { t_udp_header h; bn_int unknown1; /* time? */ } PACKED_ATTR() t_client_udpping; /******************************************************/ /******************************************************/ /* From Brood War 1.04 08 00 00 00 75 EC A0 28 ....u..( */ #define CLIENT_SESSIONADDR1 0x00000008 typedef struct { t_udp_header h; bn_int sessionkey; } PACKED_ATTR() t_client_sessionaddr1; /******************************************************/ /******************************************************/ /* From Brood War 1.07 09 00 00 00 7A 11 07 ED 9D DF 01 00 ....z....... */ #define CLIENT_SESSIONADDR2 0x00000009 typedef struct { t_udp_header h; bn_int sessionkey; bn_int sessionnum; } PACKED_ATTR() t_client_sessionaddr2; /******************************************************/ #endif pvpgn-1.8.5/src/common/proginfo.c0000644000175000017500000000507211151345317015714 0ustar aaronaaron/* * Copyright (C) 2000 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 2001 Ross Combs (ross@bnetd.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #endif #include "compat/strtoul.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strchr.h" #include "common/proginfo.h" #include "common/setup_after.h" extern int verparts_to_vernum(unsigned short v1, unsigned short v2, unsigned short v3, unsigned short v4, unsigned long * vernum) { if (!vernum) return -1; *vernum = (((unsigned long)v4)<<24) | (((unsigned long)v3)<<16) | (((unsigned long)v2)<< 8) | (((unsigned long)v1) ); return 0; } extern int verstr_to_vernum(char const * verstr, unsigned long * vernum) { unsigned long v1,v2,v3,v4; if (!vernum) return -1; if (strchr(verstr,'.')) { int count; count = sscanf(verstr,"%lu.%lu.%lu.%lu",&v4,&v3,&v2,&v1); if (count<4) { v1 = 0; if (count<3) { v2 = 0; if (count<2) return -1; /* no data */ } } } else { unsigned long temp; temp = strtoul(verstr,NULL,10); v4 = (temp/100); v3 = (temp/ 10)%10; v2 = (temp )%10; v1 = 0; } if (v1>255 || v2>255 || v3>255 || v4>255) return -1; *vernum = (v4<<24) | (v3<<16) | (v2<< 8) | (v1 ); return 0; } extern char const * vernum_to_verstr(unsigned long vernum) { static char verstr[16]; sprintf(verstr,"%lu.%lu.%lu.%lu", (vernum>>24) , (vernum>>16)&0xff, (vernum>> 8)&0xff, (vernum )&0xff); return verstr; } pvpgn-1.8.5/src/common/hexdump.c0000644000175000017500000000530011151345317015535 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2004 Donny Redmond (dredmond@linuxmail.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #include "common/packet.h" #include "common/hexdump.h" #include "common/eventlog.h" #include "common/setup_after.h" extern void hexdump(FILE * stream, void const * data, unsigned int len) { unsigned int i; char dst[100]; unsigned char * datac; if (!data) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL data"); return; } if (!stream) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL stream"); return; } for (i = 0, datac = (char*)data ; i < len; i += 16, datac += 16) { hexdump_string(datac, (len - i < 16) ? (len - i) : 16, dst, i); fprintf(stream, "%s\n", dst); fflush(stream); } } extern void hexdump_string(unsigned char * data, unsigned int datalen, char * dst, unsigned int counter) { unsigned int c; int tlen = 0; unsigned char *datatmp; datatmp = data; tlen += sprintf((dst+tlen), "%04X: ", counter); for (c=0; c<8; c++) /* left half of hex dump */ if (c=32 && *datatmp<127) tlen += sprintf((dst+tlen), "%c", *datatmp); else tlen += sprintf((dst+tlen), "."); /* put this for non-printables */ } } pvpgn-1.8.5/src/common/token.h0000644000175000017500000000165311151345317015217 0ustar aaronaaron/* * Copyright (C) 2001 Rob Crittenden (rcrit@greyoak.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_TOKEN_PROTOS #define INCLUDED_TOKEN_PROTOS extern char * next_token(char * ptr, unsigned int * pos); #endif #endif pvpgn-1.8.5/src/common/fdwatch_epoll.c0000644000175000017500000001051711151345317016704 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * Linux epoll(4) based backend * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_EPOLL #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_SYS_EPOLL_H # include "compat/uint.h" # include #endif #include "fdwatch.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" static int sr; static int epfd; static struct epoll_event *epevents = NULL; /* events to investigate */ static struct epoll_event tmpev; static int fdw_epoll_init(int nfds); static int fdw_epoll_close(void); static int fdw_epoll_add_fd(int idx, t_fdwatch_type rw); static int fdw_epoll_del_fd(int idx); static int fdw_epoll_watch(long timeout_msecs); static void fdw_epoll_handle(void); t_fdw_backend fdw_epoll = { fdw_epoll_init, fdw_epoll_close, fdw_epoll_add_fd, fdw_epoll_del_fd, fdw_epoll_watch, fdw_epoll_handle }; static int fdw_epoll_init(int nfds) { if ((epfd = epoll_create(nfds)) < 0) return -1; epevents = (struct epoll_event *) xmalloc(sizeof(struct epoll_event) * nfds); memset(epevents, 0, sizeof(struct epoll_event) * nfds); sr = 0; eventlog(eventlog_level_info, __FUNCTION__, "fdwatch epoll() based layer initialized (max %d sockets)", nfds); return 0; } static int fdw_epoll_close(void) { if (epevents != NULL) xfree((void *) epevents); sr = 0; return 0; } static int fdw_epoll_add_fd(int idx, t_fdwatch_type rw) { int op; // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); tmpev.events = 0; if (rw & fdwatch_type_read) tmpev.events |= EPOLLIN; if (rw & fdwatch_type_write) tmpev.events |= EPOLLOUT; if (fdw_rw(fdw_fds + idx)) op = EPOLL_CTL_MOD; else op = EPOLL_CTL_ADD; tmpev.data.fd = idx; if (epoll_ctl(epfd, op, fdw_fd(fdw_fds + idx), &tmpev)) { eventlog(eventlog_level_error, __FUNCTION__, "got error from epoll_ctl()"); return -1; } return 0; } static int fdw_epoll_del_fd(int idx) { // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd); if (sr > 0) eventlog(eventlog_level_error, __FUNCTION__, "BUG: called while still handling sockets"); if (fdw_rw(fdw_fds + idx)) { tmpev.events = 0; tmpev.data.fd = idx; if (epoll_ctl(epfd, EPOLL_CTL_DEL, fdw_fd(fdw_fds + idx), &tmpev)) { eventlog(eventlog_level_error, __FUNCTION__, "got error from epoll_ctl()"); return -1; } } return 0; } static int fdw_epoll_watch(long timeout_msec) { return (sr = epoll_wait(epfd, epevents, fdw_maxcons, timeout_msec)); } static void fdw_epoll_handle(void) { struct epoll_event *ev; t_fdwatch_fd *cfd; // eventlog(eventlog_level_trace, __FUNCTION__, "called"); for (ev = epevents; sr; sr--, ev++) { // eventlog(eventlog_level_trace, __FUNCTION__, "checking %d ident: %d read: %d write: %d", i, kqevents[i].ident, kqevents[i].filter & EVFILT_READ, kqevents[i].filter & EVFILT_WRITE); cfd = fdw_fds + ev->data.fd; if (fdw_rw(cfd) & fdwatch_type_read && ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP)) if (fdw_hnd(cfd) (fdw_data(cfd), fdwatch_type_read) == -2) continue; if (fdw_rw(cfd) & fdwatch_type_write && ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) fdw_hnd(cfd) (fdw_data(cfd), fdwatch_type_write); } sr = 0; } #endif /* HAVE_EPOLL */ pvpgn-1.8.5/src/common/hexdump.h0000644000175000017500000000235211151345317015546 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2004 Donny Redmond (dredmond@linuxmail.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_HEXDUMP_PROTOS #define INCLUDED_HEXDUMP_PROTOS #define JUST_NEED_TYPES #include #undef JUST_NEED_TYPES extern void hexdump(FILE * stream, void const * data, unsigned int len); extern void hexdump_string(unsigned char * data, unsigned int datalen, char * dst, unsigned int counter); #endif #endif pvpgn-1.8.5/src/common/d2game_protocol.h0000644000175000017500000003734311151345317017164 0ustar aaronaaron/* * Copyright (C) 2000 Otto Chan (kenshin_@hotmail.com) * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2GAME_PROTOCOL_TYPES #define INCLUDED_D2GAME_PROTOCOL_TYPES #ifdef JUST_NEED_TYPES # include "bn_type.h" #else # define JUST_NEED_TYPES # include "bn_type.h" # undef JUST_NEED_TYPES #endif /* * The protocol for communicating between a Diablo II client * and game server. * FIXME: put the #define's into the PROTO section */ /******************************************************/ typedef struct { #ifdef NOTONLYER bn_short magic; bn_short size; bn_byte type; /* FIXME: the two sets of packets don't jive... did the beta have a different game protocol or am I just confused (could easily be the later). */ #else bn_byte type; #endif } t_d2game_header; /******************************************************/ /******************************************************/ typedef struct { t_d2game_header h; } t_d2game_generic; /******************************************************/ /******************************************************/ /* D2 00 05 00 00 */ #define SERVER_00 0x00 /* beta-only? */ typedef struct { t_d2game_header h; bn_byte unknown1; /* data request #? */ } PACKED_ATTR() t_server_00_req; #define SERVER_00 0x00 /******************************************************/ /******************************************************/ /* D2 00 20 00 01 E2 5E 13 BE 4C 02 04 CA 00 00 00 .........L...... 6C 69 6C 6A 6F 65 00 00 64 25 42 00 1C E9 50 00 liljoe..d.B...P. */ #define CLIENT_01 0x01 /* beta-only? */ typedef struct /* game select? */ { t_d2game_header h; bn_byte unknown1; /* data reply #? */ bn_int gameid1; /* same as in auth 04 reply */ bn_short gameid2; /* same as in auth 04 reply */ bn_byte unknown2[5]; /* character name */ /* 00 64 25 42 00 1C E9 50 00 unknown... string or numeric? */ } PACKED_ATTR() t_client_01; /******************************************************/ /******************************************************/ /* 0030 22 38 32 5D 00 00 97 20 20 20 20 20 "82]........ */ #define D2GAME_SERVER_WELCOME 0x97 typedef struct { t_d2game_header h; } t_d2game_server_welcome; /* 0000: 60 00 27 04 18 79 27 04 A8 00 00 00 07 02 00 00 `.'..y'......... 0010: B0 01 01 00 00 6F 6E 6C 79 65 72 00 B8 6A F7 BF .....onlyer..j.. 0020: 00 00 00 00 34 00 00 04 00 00 00 00 00 ....4........ 0000: 60 00 27 04 18 79 27 04 30 0D 00 00 07 02 00 00 `.'..y'.0....... 0010: B0 01 04 00 01 41 4C 42 45 52 54 00 B8 6A F7 BF .....ALBERT..j.. 0020: 00 00 00 00 34 00 00 04 00 00 00 00 00 ....4........ 0000: 60 00 27 04 18 79 27 04 A0 0A 00 00 07 02 00 00 `.'..y'......... 0010: B0 01 04 00 02 41 4C 42 45 52 54 00 B8 6A F7 BF .....ALBERT..j.. 0020: 00 00 00 00 34 00 00 04 00 00 00 00 00 ....4........ 0000: 60 00 AB 04 18 79 AB 04 DE 00 9F 00 0C 02 00 00 `....y.......... 0010: 60 01 04 00 00 62 62 62 00 71 DF 77 A6 C0 E6 77 `....bbb.q.w...w 0020: A6 C0 E6 77 34 05 00 04 00 00 00 00 00 ...w4........ */ #define D2GAME_CLIENT_CREATEGAMEREQ 0x60 typedef bn_basic bn_charname[16]; typedef struct { t_d2game_header h; char gamename[16]; bn_byte servertype; /* servertype=0, data not send to client and have no host */ /* creator changed to newbie data saved in server machine*/ /* servertype=1, data send to client and have host */ /* servertype=2, data send to client and have no host */ /* servertype=3, client all newbie,seems to be wrong */ /* data is saved in server machine */ /* client is loaded from server machine */ bn_byte class; bn_byte template; /* character template */ /* affect the reply in 0x01 */ /* should less than the lines of excel/CharTemplate.txt */ bn_byte difficulty; bn_charname charname; bn_short arena; bn_int gameflag; bn_byte unknownb2; /* unused */ bn_byte unknownb3; /* unused */ } t_d2game_client_creategamereq; typedef struct { bn_byte flag1; /* "test gameflag,06" should not be zero,or will be bad gameflag */ /* flag1 should be set with bit 0x04 or will fail or crash */ /* bit 0x10,0x20,0x08 is ignored in reply */ bn_byte flag2; /* hardcore and softcore */ /* 0x0 means softcore,0x1 template mode,0x8 means hardcore */ /* bit 0x02,0x04,0xF0 is ignored in reply */ /* have sth to do with char template */ /* opengame */ bn_byte flag3; /* guild data (not in reply) */ /* 0x01 means have guild */ /* others bits seems all unused */ bn_byte flag4; /* seems to be unused */ } t_d2game_gameflag; /* 0030 22 37 86 D7 00 00 61 65 00 00 00 00 00 01 03 00 "7....ae........ 0040 00 00 6F 6E 6C 79 65 72 2D 63 6E 61 61 00 24 E0 ..onlyer-cnaa.$. 0050 7B 05 {. */ #define D2GAME_CLIENT_JOINGAMEREQ 0x61 typedef struct { t_d2game_header h; bn_int token; bn_short gameid; bn_byte charclass; /* 00=Amazon 01=Sor 02=Nec 03=Pal 04=Bar */ bn_int version; bn_charname charname; /* 16 bytes playe name (including 0x0 ending) */ } t_d2game_client_joingamereq; /* 0030 22 1C C9 65 00 00 20 20 20 20 20 20 "..e........ */ #define D2GAME_SERVER_NOOP 0x20 typedef struct { t_d2game_header h; /* 5 \x20 noop */ } t_d2game_server_noop; /* 0030 22 37 17 07 00 00 66 91 4B A1 00 00 00 00 00 "7....f.K...... */ #define D2GAME_CLIENT_UNKNOWN_66 0x66 /* echo message? */ typedef struct { t_d2game_header h; bn_int unknown1; bn_int unknown2; } t_d2game_client_unknown_66; /* 0000: 8F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0020: 00 . */ #define D2GAME_SERVER_UNKNOWN_8F 0x8f /* echo reply? */ typedef struct { t_d2game_header h; bn_int unknown1; bn_int unknown2; bn_int unknown3; bn_int unknown4; bn_int unknown5; bn_int unknown6; bn_int unknown7; /* all here for open char is zero */ } t_d2game_server_unknown_8f; /* 0030 22 1C C4 53 00 00 01 00 04 00 00 00 00 02 "..S.......... */ #define D2GAME_SERVER_JOINOK 0x01 /* this message will appear after * 1. CLIENT_CREATEGAEM valid * 2. CLIENT_JOINGAME valid */ typedef struct { t_d2game_header h; bn_byte difficulty; bn_short gameflag; bn_byte template; bn_short unknown1; bn_short unknown2; } t_d2game_server_joinok; /* 0030 22 2F 65 38 00 00 64 "/e8..d */ #define D2GAME_CLIENT_JOINACTREQ 0x64 typedef struct { t_d2game_header h; /* none */ } t_d2game_client_joinactreq; #define D2GAME_SERVER_UNKNOWN_59 0x59 typedef struct { t_d2game_header h; } t_d2game_server_unknown_59; /* 0030 22 0E 0C 01 00 00 65 82 82 00 00 00 55 AA 55 AA ".....e.....U.U. 0040 47 00 00 00 6F 6E 6C 79 65 72 2D 63 6E 61 00 00 G...onlyer-cna.. 0050 00 00 00 00 01 00 00 00 DD 00 10 00 82 00 01 00 ................ 0060 01 00 01 01 01 01 01 FF FF FF 01 01 FF FF FF FF ................ 0070 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ 0080 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FC ............... */ #define D2GAME_CLIENT_PLAYERSAVE 0x65 typedef struct { t_d2game_header h; bn_byte size; bn_int total_size; /* player save file */ /* an append */ } t_d2game_client_playersave; #define D2GAME_SERVER_ERROR 0x9c typedef struct { t_d2game_header h; bn_int errorno; } t_d2game_server_error; #define D2GAME_SERVER_ERROR_UNKNOWN_FAILURE 0 /* error biger than 22 is also unknown */ #define D2GAME_SERVER_ERROR_CHAR_VER 1 #define D2GAME_SERVER_ERROR_QUEST_DATA 2 #define D2GAME_SERVER_ERROR_WP_DATA 3 #define D2GAME_SERVER_ERROR_STAT_DATA 4 #define D2GAME_SERVER_ERROR_SKILL_DATA 5 #define D2GAME_SERVER_ERROR_UNABLE_ENTER 6 #define D2GAME_SERVER_ERROR_INVENTORY_DATA 7 #define D2GAME_SERVER_ERROR_DEAD_BODY 8 #define D2GAME_SERVER_ERROR_HEADER 9 #define D2GAME_SERVER_ERROR_HIREABLES 10 #define D2GAME_SERVER_ERROR_INTRO_DATA 11 #define D2GAME_SERVER_ERROR_ITEM 12 #define D2GAME_SERVER_ERROR_DEAD_BODY_ITEM 13 #define D2GAME_SERVER_ERROR_GENERIC_BAD_FILE 14 #define D2GAME_SERVER_ERROR_GAME_FULL 15 #define D2GAME_SERVER_ERROR_GAME_VER 16 #define D2GAME_SERVER_ERROR_NIGHTMARE 17 #define D2GAME_SERVER_ERROR_HELL 18 #define D2GAME_SERVER_ERROR_NORMAL_HARDCORE 19 #define D2GAME_SERVER_ERROR_HARDCORE_NORMAL 20 #define D2GAME_SERVER_ERROR_DEAD_HARDCORE 21 /* 0000: 15 01 00 69 20 77 69 6C 6C 20 67 6F 00 00 00 ...i will go... 0000: 15 01 00 74 68 61 6E 6B 73 20 66 6F 72 20 79 6F ...thanks for yo 0010: 75 72 20 68 65 6C 70 00 00 00 ur help... 0000: 15 01 00 73 65 65 20 75 00 00 00 ...see u... */ #define D2GAME_CLIENT_CHAT_MESSAGE 0x15 typedef struct { t_d2game_header h; bn_short unknown1; /* chat message */ } t_d2game_client_chat_message; /* 0000: 26 01 00 02 00 00 00 00 00 01 6F 6E 6C 79 65 72 &.........onlyer 0010: 2D 63 6E 61 61 00 69 20 77 69 6C 6C 20 67 6F 00 -cnaa.i will go. 0000: 26 01 00 02 00 00 00 00 00 01 6F 6E 6C 79 65 72 &.........onlyer 0010: 2D 63 6E 61 61 00 74 68 61 6E 6B 73 20 66 6F 72 -cnaa.thanks for 0020: 20 79 6F 75 72 20 68 65 6C 70 00 your help. 0000: 26 01 00 02 00 00 00 00 00 01 6F 6E 6C 79 65 72 &.........onlyer 0010: 2D 63 6E 61 61 00 73 65 65 20 75 00 -cnaa.see u. 0000: 26 01 00 02 00 00 00 00 00 17 63 63 00 62 79 65 &.........cc.bye 0010: 00 67 49 00 00 00 01 86 17 32 12 01 00 07 00 05 .gI......2...... */ #define D2GAME_SERVER_CHAT_MESSAGE 0x26 typedef struct { t_d2game_header h; bn_short unknown1; bn_int unknown2; bn_short unknown3; bn_byte unknown4; /* id or token? a fixed number for each char*/ /* player name */ /* message */ } t_d2game_server_chat_message; #define D2GAME_SERVER_CHAT_MESSAGE_UNKNOWN1 0x0001 #define D2GAME_SERVER_CHAT_MESSAGE_UNKNOWN2 0x00000002 #define D2GAME_SERVER_CHAT_MESSAGE_UNKNOWN3 0x0000 #define D2GAME_SERVER_CHAT_MESSAGE_UNKNOWN4 0x01 /* 0000: 62 b */ #define D2GAME_CLIENT_QUITGAME 0x62 typedef struct { t_d2game_header h; } t_d2game_client_quitgame; /* 0000: 9B FF 01 4E 03 00 00 55 AA 55 AA 47 00 00 00 6F ...N...U.U.G...o 0010: 6E 6C 79 65 72 2D 63 6E 61 61 00 00 00 00 00 00 nlyer-cnaa...... 0020: 00 00 00 DD 00 10 00 82 00 01 00 01 00 FF FF FF ................ 0030: FF FF 53 FF FF FF FF FF FF FF FF FF FF FF FF FF ..S............. 0040: FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 FF ................ 0050: 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 00 24 00 ..............$. 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0080: 00 00 00 00 00 5E 17 41 5F 57 6F 6F 21 06 00 00 .....^.A_Woo!... 0090: 00 2A 01 01 00 00 00 00 00 00 00 00 00 00 00 00 .*.............. 00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0100: 00 00 00 00 00 00 ...... */ #define D2GAME_SERVER_PLAYERSAVE 0x9b typedef struct { t_d2game_header h; bn_byte size; bn_byte start; bn_int total_size; /* player save file */ } t_d2game_server_playersave; /* 0000: 98 05 06 */ #define D2GAME_SERVER_CLOSEGAME 0x98 typedef struct { t_d2game_header h; bn_short unknown1; } t_d2game_server_closegame; /* 0000: 5A 02 04 00 00 00 00 03 61 72 63 68 5F 6E 61 67 Z.......arch_nag 0010: 61 00 00 00 B0 FD B6 08 00 FF FF FF 78 07 39 04 a...........x.9. 0020: D5 16 2D 04 01 FD B6 08 ..-..... */ #define D2GAME_SERVER_JOINGAME_MESSAGE 0x5a typedef struct { t_d2game_header h; bn_byte unknown1; bn_byte unknown2; bn_int unknown3; bn_byte unknown4; /* char name */ } t_d2game_joingame_message; #define D2GAME_CLIENT_DIE 0x41 typedef struct { t_d2game_header h; } t_d2game_client_die; /* 0000: 02 73 00 00 00 4E 00 8B 0F 7B 14 00 00 .s...N...{... #define D2GAME_SERVER_UNKNOWN_2 0x2 */ /* 0000: 67 06 00 00 00 01 B2 0F 6B 14 01 00 07 00 05 g.......k...... 0000: 67 06 00 00 00 01 B2 0F 71 14 01 00 07 00 05 g.......q...... 0000: 67 0A 00 00 00 01 72 0F 63 14 01 00 07 00 05 g.....r.c...... #define D2GAME_SERVER_UNKNOWN_67 0x67 */ /* 0000: 6D 0A 00 00 00 76 0F 64 14 80 m....v.d.. 0000: 6D 0A 00 00 00 72 0F 63 14 80 m....r.c.. 0000: 6D 06 00 00 00 B2 0F 71 14 80 8A 01 0B 00 00 00 m......q........ 0000: 6D 06 00 00 00 B2 0F 6B 14 80 m......k.. #define D2GAME_SERVER_UNKNOWN_6D 0x6d */ /* 0000: 8A 01 0B 00 00 00 6D 0B 00 00 00 9B 0F 70 14 80 ......m......p.. 0010: 2C 01 0B 00 00 00 11 00 ,....... 0000: 8A 01 0B 00 00 00 ...... #define D2GAME_SERVER_UNKNOWN_8A 0x8a */ /* 0000: 96 59 80 CC 07 36 8A 4C 36 .Y...6.L6 #define D2GAME_SERVER_UNKNOWN_96 0x96 */ /* 0000: 24 62 00 00 00 $b... #define D2GAME_CLIENT_UNKNOWN_24 0x24 */ /* CLIENT: 0000: 2F 01 00 00 00 49 00 00 00 /....I... 0000: 31 49 00 00 00 00 00 00 00 1I....... 0000: 30 01 00 00 00 49 00 00 00 0....I... 0000: 03 8C 17 2E 12 ..... 0000: 03 87 17 27 12 ...'. command ? SERVER: */ #endif pvpgn-1.8.5/src/common/conf.c0000644000175000017500000001452711151345317015023 0ustar aaronaaron/* * Copyright (C) 2004,2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_ASSERT_H # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "common/eventlog.h" #include "common/xalloc.h" #include "common/util.h" #include "common/conf.h" #include "compat/snprintf.h" #include "common/setup_after.h" extern int conf_set_int(unsigned *pint, const char *valstr, unsigned def) { if (!valstr) *pint = def; else { unsigned temp; if (str_to_uint(valstr,&temp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"invalid integer value '%s'",valstr); return -1; } else *pint = temp; } return 0; } extern int conf_set_bool(unsigned *pbool, const char *valstr, unsigned def) { if (!valstr) *pbool = def; else { switch(str_get_bool(valstr)) { case 1: *pbool = 1; break; case 0: *pbool = 0; break; default: eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value '%s'",valstr); return -1; } } return 0; } extern int conf_set_str(const char **pstr, const char *valstr, const char *def) { if (*pstr) xfree((void*)*pstr); if (!valstr && !def) *pstr = NULL; else *pstr = xstrdup(valstr ? valstr : def); return 0; } extern int conf_set_timestr(time_t* ptime, const char *valstr, time_t def) { if (!valstr) *ptime = def; else if (timestr_to_time(valstr,ptime)<0) { eventlog(eventlog_level_error,__FUNCTION__,"invalid timestr value '%s'",valstr); return -1; } return 0; } extern const char* conf_get_int(unsigned ival) { static char tmpbuf[128]; snprintf(tmpbuf, sizeof(tmpbuf), "%u", ival); return tmpbuf; } extern const char* conf_get_bool(unsigned ival) { return ival ? "true" : "false"; } static void _conf_reset_defaults(t_conf_entry *conftab) { t_conf_entry *curr; assert(conftab); for(curr = conftab;curr->name;curr++) curr->setdef(); } static char * _get_value(char *str, unsigned lineno) { char *cp, prev; if (*str == '"') { for(cp=++str, prev = '\0'; *cp; cp++) { switch(*cp) { case '"': if (prev != '\\') break; prev = '"'; continue; case '\\': if (prev == '\\') prev = '\0'; else prev = '\\'; continue; default: prev = *cp; continue; } break; } if (*cp != '"') { eventlog(eventlog_level_error,__FUNCTION__,"missing end quota at line %u", lineno); return NULL; } *cp = '\0'; cp = str_skip_space(cp + 1); if (*cp) { eventlog(eventlog_level_error,__FUNCTION__,"extra characters in value after ending quote at line %u", lineno); return NULL; } } else { cp = str_skip_word(str); if (*cp) { *cp = '\0'; cp = str_skip_space(cp + 1); if (*cp) { eventlog(eventlog_level_error,__FUNCTION__,"extra characters after the value at line %u", lineno); return NULL; } } } return str; } static void _process_option(const char *key, const char *val, t_conf_entry *conftab) { t_conf_entry *curr; for(curr = conftab; curr->name; curr++) if (!strcmp(key,curr->name)) { curr->set(val); return; } eventlog(eventlog_level_error,__FUNCTION__,"option '%s' unknown",key); } extern int conf_load_file(FILE *fd, t_conf_entry *conftab) { char *buff, *directive, *value, *cp; unsigned cflag, lineno; if (!fd) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL file"); return -1; } if (!conftab) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conftab"); return -1; } /* restore defaults */ _conf_reset_defaults(conftab); for(lineno = 1; (buff = file_get_line(fd)); lineno++) { cflag = 1; for(cp = buff; *cp; cp++) { switch(*cp) { case '\\': if (!*(++cp)) cflag = 0; break; case '"': switch(cflag) { case 1: cflag = 2; break; case 2: cflag = 1; break; } break; case '#': if (cflag == 1) cflag = 0; break; } if (!cflag) break; } if (*cp == '#') *cp = '\0'; cp = str_skip_space(buff); if (!*cp) continue; directive = cp; cp = str_skip_word(cp + 1); if (*cp) *(cp++) = '\0'; cp = str_skip_space(cp); if (*cp != '=') { eventlog(eventlog_level_error,__FUNCTION__,"missing = on line %u",lineno); continue; } cp = str_skip_space(cp + 1); if (!*cp) { eventlog(eventlog_level_error,__FUNCTION__,"missing value at line %u",lineno); continue; } value = _get_value(cp,lineno); if (!value) continue; _process_option(directive,value,conftab); } return 0; } extern void conf_unload(t_conf_entry *conftab) { t_conf_entry *curr; if (!conftab) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conftab"); return; } for(curr = conftab;curr->name;curr++) curr->set(NULL); } extern int conf_load_cmdline(int argc, char **argv, t_conf_entry *conftab) { int i; char *key, *val, *newkey; if (!conftab) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conftab"); return -1; } /* restore defaults */ _conf_reset_defaults(conftab); for(i = 1; i < argc; ++i) { newkey = NULL; key = argv[i]; if (*(key++) != '-') /* skip non options */ continue; if (*key == '-') key++; /* allow both - and -- options */ if ((val = strchr(key, '='))) { /* we got option=value format */ newkey = xstrdup(key); key = newkey; val = strchr(key, '='); *(val++) = '\0'; } else if (i + 1 < argc && argv[i + 1][0] != '-') { val = argv[++i]; } if (!val) /* option without argument, so it's like boolean */ val = "true"; _process_option(key, val, conftab); if (newkey) xfree(newkey); } return 0; } pvpgn-1.8.5/src/common/bnet_protocol.h0000644000175000017500000046205011151345317016752 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_BNET_PROTOCOL_TYPES #define INCLUDED_BNET_PROTOCOL_TYPES #ifdef JUST_NEED_TYPES # include "common/bn_type.h" #else # define JUST_NEED_TYPES # include "common/bn_type.h" # undef JUST_NEED_TYPES #endif /* * The "bnet" protocol (previously known as "normal") that is used for * chatting, ladder info, game listings, etc. * FIXME: put the #define's into the PROTO section */ /******************************************************/ typedef struct { bn_short type; bn_short size; } PACKED_ATTR() t_bnet_header; /******************************************************/ /* [zap-zero] 20020529 - added support for war3 anongame routing packets */ /******************************************************/ typedef struct { bn_short type; bn_short size; } PACKED_ATTR() t_w3route_header; /******************************************************/ /******************************************************/ typedef struct { t_bnet_header h; } PACKED_ATTR() t_bnet_generic; /******************************************************/ /******************************************************/ typedef struct { t_w3route_header h; } PACKED_ATTR() t_w3route_generic; /******************************************************/ /* for unhandled pmap packets */ #define CLIENT_NULL 0xfeff /******************************************************/ /* 14: recv class=w3route[0x0c] type=unknown[0x00f7] length=53 0000: F7 1E 35 00 02 02 00 00 68 BF 0B 08 00 E0 17 01 ..5.....h....... 0010: 00 00 00 42 6C 61 63 6B 72 61 74 00 08 81 3E 0C ...Blackrat...>. 0020: 00 20 00 00 00 02 00 17 E1 C0 A8 00 01 00 00 00 . .............. 0030: 00 00 00 00 00 ..... */ #define CLIENT_W3ROUTE_REQ 0x1ef7 typedef struct { t_w3route_header h; bn_int unknown1; bn_int id; /* unique id sent by server */ bn_byte unknown2; bn_short port; bn_int handle; /* handle/descriptor for client <-> client communication */ /* player name, ... */ } PACKED_ATTR() t_client_w3route_req; /******************************************************/ /******************************************************/ /* f7 23 04 00 */ #define CLIENT_W3ROUTE_LOADINGDONE 0x23f7 typedef struct { t_w3route_header h; } PACKED_ATTR() t_client_w3route_loadingdone; /******************************************************/ /******************************************************/ /* f7 14 05 00 00 */ #define SERVER_W3ROUTE_READY 0x14f7 typedef struct { t_w3route_header h; bn_byte unknown1; } PACKED_ATTR() t_server_w3route_ready; /******************************************************/ /******************************************************/ /* f7 21 08 00 01 00 00 00 */ #define CLIENT_W3ROUTE_ABORT 0x21f7 typedef struct { t_w3route_header h; bn_int unknown1; /* count? */ } PACKED_ATTR() t_client_w3route_abort; /******************************************************/ /* f7 08 05 00 02 */ #define SERVER_W3ROUTE_LOADINGACK 0x08f7 typedef struct { t_w3route_header h; bn_byte playernum; } PACKED_ATTR() t_server_w3route_loadingack; /******************************************************/ /******************************************************/ /* f7 3b 06 00 09 00 */ #define CLIENT_W3ROUTE_CONNECTED 0x3bf7 typedef struct { t_w3route_header h; bn_short unknown1; } PACKED_ATTR() t_client_w3route_connected; /******************************************************/ /******************************************************/ /* f7 01 08 00 2e 85 2d 7b */ #define SERVER_W3ROUTE_ECHOREQ 0x01f7 typedef struct { t_w3route_header h; bn_int ticks; } PACKED_ATTR() t_server_w3route_echoreq; /******************************************************/ #define CLIENT_W3ROUTE_ECHOREPLY 0x46f7 /******************************************************/ /* 13: recv class=w3route[0x0c] type=unknown[0x2ef7] length=107 0000: F7 2E 6B 00 01 01 03 00 00 00 20 00 00 00 5C 01 ..k....... ...\. 0010: 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 1A ................ 0020: 04 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 ................ 0030: 00 00 00 01 00 00 00 00 00 00 00 05 00 00 00 00 ................ 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0060: 00 00 00 00 00 00 00 00 00 00 00 ........... */ #define CLIENT_W3ROUTE_GAMERESULT 0x2ef7 /* F7 3A-84 00 02 01 04 00 00 00 0x0040 20 00 00 00 83 09 00 00-00 00 00 00 02 03 00 00 0x0050 00 20 00 00 00 2C 01 00-00 00 00 00 00 5C 04 00 0x0060 00 00 03 00 00 00 00 00-00 00 01 00 00 00 CC 0B 0x0070 00 00 00 00 00 00 72 0B-00 00 0E 00 00 00 00 00 0x0080 00 00 04 00 00 00 01 00-00 00 15 00 00 00 00 00 0x0090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 0x00A0 00 00 46 0A 00 00 2C 01-00 00 00 00 00 00 00 00 0x00B0 00 00 00 00 00 00 00 00-00 00 F7 3A-84 00 02 02 03 00 00 00 0x0040 20 00 00 00 2C 01 00 00-00 00 00 00 01 04 00 00 0x0050 00 20 00 00 00 83 09 00-00 00 00 00 00 5C 04 00 0x0060 00 00 01 00 00 00 01 00-00 00 00 00 00 00 39 03 0x0070 00 00 00 00 00 00 00 00-00 00 05 00 00 00 00 00 0x0080 00 00 01 00 00 00 00 00-00 00 05 00 00 00 00 00 0x0090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 0x00A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 0x00B0 00 00 00 00 00 00 00 00-00 00 */ #define CLIENT_W3ROUTE_GAMERESULT_W3XP 0x3af7 typedef struct { t_w3route_header h; bn_byte number_of_results; /* t_client_w3route_gameresult_player players[]; 1-n times t_client_w3route_gameresult_part2 part2; t_client_w3route_gameresult_hero heroes[]; 0-n times t_client_w3route_gameresult_part3 part3; */ } PACKED_ATTR() t_client_w3route_gameresult; /******************************************************/ /* [zap-zero] what value is DRAW? */ #define W3_GAMERESULT_LOSS 0x00000003 #define W3_GAMERESULT_WIN 0x00000004 typedef struct { bn_byte number; bn_int result; bn_int race; bn_int unknown1; bn_int unknown2; } PACKED_ATTR() t_client_w3route_gameresult_player; typedef struct { bn_byte unknown0; /* but could also contain info about result */ bn_int unknown1; bn_int unknown2; bn_int unknown3; bn_int unknown4; bn_int unit_score; bn_int heroes_score; bn_int resource_score; bn_int units_produced; bn_int units_killed; bn_int buildings_produced; bn_int buildings_razed; bn_int largest_army; bn_int heroes_used_count; } PACKED_ATTR() t_client_w3route_gameresult_part2; typedef struct { bn_short level; bn_int race_and_name; bn_int hero_xp; } PACKED_ATTR() t_client_w3route_gameresult_hero; typedef struct { bn_int heroes_killed; bn_int items_obtained; bn_int mercenaries_hired; bn_int total_hero_xp; bn_int gold_mined; bn_int lumber_harvested; bn_int resources_traded_given; bn_int resources_traded_taken; bn_int tech_percentage; bn_int gold_lost_to_upkeep; } PACKED_ATTR() t_client_w3route_gameresult_part3; /******************************************************/ /* f7 04 1e 00 07 00 00 b2 72 76 ..............rv 0040 ec cc cc 02 02 00 04 0b d9 e9 5f ac 00 00 00 00 .........._..... 0050 00 00 00 00 .... */ #define SERVER_W3ROUTE_ACK 0x04f7 typedef struct { t_w3route_header h; bn_byte unknown1; /* 07 */ bn_short unknown2; /* 00 00 */ bn_int unknown3; /* random stuff */ bn_short unknown4; /* cc cc */ bn_byte playernum; /* 1-4 */ bn_short unknown5; /* 0x0002 */ bn_short port; /* client port */ bn_int ip; /* client ip */ bn_int unknown7; /* 00 00 00 00 */ bn_int unknown8; /* 00 00 00 00 */ } PACKED_ATTR() t_server_w3route_ack; /******************************************************/ #define SERVER_W3ROUTE_ACK_UNKNOWN3 0x484e2637 /******************************************************/ /* f7 06 3b 00 01 00 00 00 01 ** ........;......P 0040 ** ** ** ** ** ** ** 00 08 2d 09 9d 04 08 00 00 layer00..-...... 0050 00 02 00 17 e0 [censored] 00 00 00 00 00 00 00 .......g........ 0060 00 02 00 17 e0 [censored] 00 00 00 00 00 00 00 .......g........ 0070 00 */ #define SERVER_W3ROUTE_PLAYERINFO 0x06f7 typedef struct { t_w3route_header h; bn_int handle; bn_byte playernum; /* then: opponent name playerinfo2 playerinfo_addr (external addr) playerinfo_addr (local lan addr) */ } PACKED_ATTR() t_server_w3route_playerinfo; typedef struct { bn_byte unknown1; /* 8 (length?) */ bn_int id; /* id from FINDANONGAME_SEARCH packet */ bn_int race; /* see defines */ } PACKED_ATTR() t_server_w3route_playerinfo2; #define SERVER_W3ROUTE_LEVELINFO 0x47f7 typedef struct { t_w3route_header h; bn_byte numplayers; /* then: levelinfo2 for each player */ } PACKED_ATTR() t_server_w3route_levelinfo; typedef struct { bn_byte plnum; bn_byte unknown1; /* 3 (length?) */ bn_byte level; bn_short unknown2; } PACKED_ATTR() t_server_w3route_levelinfo2; typedef struct { bn_short unknown1; /* 2 */ bn_short port; bn_int ip; bn_int unknown2; /* 0 */ bn_int unknown3; /* 0 */ } PACKED_ATTR() t_server_w3route_playerinfo_addr; typedef struct { t_w3route_header h; /* f7 0a 04 00 */ } PACKED_ATTR() t_server_w3route_startgame1; #define SERVER_W3ROUTE_STARTGAME1 0x0af7 typedef struct { t_w3route_header h; /* f7 0b 04 00 */ } PACKED_ATTR() t_server_w3route_startgame2; #define SERVER_W3ROUTE_STARTGAME2 0x0bf7 /*******************************************************/ /* ALL ANONGAME PACKET INFO (0x44ff) MOVED TO anongame_protocol.h [Omega] */ /******************************************************/ /* These two dumps are from the original unpatched Starcraft client: FF 05 28 00 01 00 00 00 ..(..... D1 43 88 AA DA 9D 1B 00 9A F7 69 AB 4A 41 32 30 .C........i.JA20 35 43 2D 30 34 00 6C 61 62 61 73 73 69 73 74 00 5C-04.labassist. FF 05 24 00 01 00 00 00 D1 43 88 AA DA 9D 1B 00 ..$......C...... 9A F7 69 AB 42 4F 42 20 20 20 20 20 20 20 20 00 ..i.BOB . 42 6F 62 00 Bob. ??? note it sends NO host and user strings FF 05 14 00 01 00 00 00 D8 94 F6 07 B3 2C 6E 02 .............,n. B4 E0 3B 6C ..;l ??? sent right after it... request for session key? FF 28 08 00 F6 0F 08 00 .(...... Diablo II 1.03 ... note it sends NO host and user strings FF 05 14 00 01 00 00 00 D1 43 88 AA DA 9D ...... ...C.... 1B 00 9A F7 69 AB ....i. */ #define CLIENT_COMPINFO1 0x05ff typedef struct { t_bnet_header h; bn_int reg_version; /* 01 00 00 00 */ bn_int reg_auth; /* D1 43 88 AA */ /* looks like server ip */ bn_int client_id; /* DA 9D 1B 00 */ bn_int client_token; /* 9A F7 69 AB */ /* host */ /* optional */ /* user */ /* optional */ } PACKED_ATTR() t_client_compinfo1; #define CLIENT_COMPINFO1_REG_VERSION 0x00000001 #define CLIENT_COMPINFO1_REG_AUTH 0xaa8843d1 #define CLIENT_COMPINFO1_CLIENT_ID 0x001b9dda #define CLIENT_COMPINFO1_CLIENT_TOKEN 0xab69f79a /******************************************************/ /******************************************************/ /* CLIENT_COMPINFO2 was first seen in Starcraft 1.05 FF 1E 24 00 01 00 00 00 ..$..... 01 00 00 00 D1 43 88 AA 1C B9 48 00 31 8A F2 89 .....C....H.1... 43 4C 4F 55 44 00 63 6C 6F 75 64 00 CLOUD.cloud. FF 1E 28 00 01 00 00 00 01 00 00 00 D1 43 88 AA ..(..........C.. DA 9D 1B 00 9A F7 69 AB 42 4F 42 20 20 20 20 20 ......i.BOB 20 20 20 00 42 6F 62 00 .Bob. Diablo II 1.03 ... note it sends empty host and user strings FF 1E 1A 00 01 00 00 00 01 00 00 00 D1 43 ............C 88 AA DA 9D 1B 00 9A F7 69 AB 00 00 .......i... */ #define CLIENT_COMPINFO2 0x1eff typedef struct { t_bnet_header h; bn_int unknown1; /* 01 00 00 00 */ /* ??? Version */ bn_int reg_version; /* 01 00 00 00 */ bn_int reg_auth; /* D1 43 88 AA */ /* looks like server ip */ bn_int client_id; /* 1C B9 48 00 */ /* DA 9D 1B 00 */ bn_int client_token; /* 31 8A f2 89 */ /* 9A F7 69 AB */ /* host */ /* user */ } PACKED_ATTR() t_client_compinfo2; #define CLIENT_COMPINFO2_UNKNOWN1 0x00000001 #define CLIENT_COMPINFO2_REG_VERSION 0x00000001 #define CLIENT_COMPINFO2_REG_AUTH 0xaa8843d1 #define CLIENT_COMPINFO2_CLIENT_ID 0x001b9dda #define CLIENT_COMPINFO2_CLIENT_TOKEN 0xab69f79a /******************************************************/ /******************************************************/ /* Sent in response to CLIENT_COMPINFO[12] along with sessionkey FF 05 14 00 01 00 00 00 ........ D1 43 88 AA 1C B9 48 00 31 8A F2 89 .C....H.1... FF 05 14 00 01 00 00 00 D8 94 F6 07 3F 62 6E 02 ............?bn. CA A4 0D 99 .... FF 05 14 00 01 00 00 00 D8 94 F6 07 B3 2C 6E 02 .............,n. B4 E0 3B 6C ..;l To D2 Beta 1.02: FF 05 14 00 01 00 00 00 D1 43 88 AA 42 8D 2E 02 .........C..B... 2B 81 8C 2B +..+ */ #define SERVER_COMPREPLY 0x05ff typedef struct { t_bnet_header h; bn_int reg_version; /* 01 00 00 00 */ bn_int reg_auth; /* D1 43 88 AA */ /* looks like server ip */ bn_int client_id; /* DA 9D 1B 00 */ /* 1C B9 48 00 */ bn_int client_token; /* 9A F7 69 AB */ /* 31 8A F2 89 */ } PACKED_ATTR() t_server_compreply; #define SERVER_COMPREPLY_REG_VERSION 0x00000001 #define SERVER_COMPREPLY_REG_AUTH 0xaa8843d1 #define SERVER_COMPREPLY_CLIENT_ID 0x001b9dda #define SERVER_COMPREPLY_CLIENT_TOKEN 0xab69f79a /******************************************************/ /******************************************************/ /* Sent in repsonse to COMPINFO1 along with COMPINFOREPLY. Used for password hashing by the client. */ #define SERVER_SESSIONKEY1 0x28ff typedef struct { t_bnet_header h; bn_int sessionkey; } PACKED_ATTR() t_server_sessionkey1; /******************************************************/ /******************************************************/ /* Sent in response to COMPINFO2 along with COMPINFOREPLY. Used for password hashing by the client. FF 1D 0C 00 40 24 02 00 ....@$.. 99 F3 FD 78 ...x FF 1D 0C 00 0C 67 08 00 7A 3C D8 75 .....g..z<.u FF 1D 0C 00 58 77 00 00 27 45 44 7A ....Xw..'EDz FF 1D 0C 00 9D DF 01 00 7A 11 07 ED ........z... */ #define SERVER_SESSIONKEY2 0x1dff typedef struct { t_bnet_header h; bn_int sessionnum; bn_int sessionkey; } PACKED_ATTR() t_server_sessionkey2; #define SERVER_SESSIONKEY2_UNKNOWN1 0x00004df3 /******************************************************/ /******************************************************/ /* FF 12 3C 00 E0 28 02 E4 0A 37 BE 01 E0 50 A3 37 ..<..(...7...P.7 D0 36 BE 01 A4 01 00 00 09 04 00 00 09 04 00 00 .6.............. 09 04 00 00 65 6E 75 00 31 00 55 53 41 00 55 6E ....enu.1.USA.Un 69 74 65 64 20 53 74 61 74 65 73 00 ited States. still original client, but at a later date FF 12 3C 00 60 C5 4B 8B 19 DE BE 01 60 55 B1 40 ..<.`.K.....`U.@ E7 DD BE 01 A4 01 00 00 09 04 00 00 09 04 00 00 ................ 09 04 00 00 65 6E 75 00 31 00 55 53 41 00 55 6E ....enu.1.USA.Un 69 74 65 64 20 53 74 61 74 65 73 00 ited States. FF 12 3C 00 60 EA 02 23 F5 DE BE 01 60 7A 68 D8 ..<.`..#....`zh. C2 DE BE 01 A4 01 00 00 09 04 00 00 09 04 00 00 ................ 09 04 00 00 65 6E 75 00 31 00 55 53 41 00 55 6E ....enu.1.USA.Un 69 74 65 64 20 53 74 61 74 65 73 00 ited States. FF 12 35 00 ..5. 20 BA B0 55 F2 7B BE 01 20 62 98 C5 3D 7C BE 01 ..U.{.. b..=|.. E4 FD FF FF 12 04 00 00 12 04 00 00 12 04 00 00 ................ 6B 6F 72 00 38 32 00 4B 4F 52 00 4B 6F 72 65 61 kor.82.KOR.Korea 00 . FF 12 37 00 E0 D4 72 97 2F 8C BF 01 E0 3C 37 F9 ..7...r./....<7. 37 8C BF 01 C4 FF FF FF 07 04 00 00 07 04 00 00 7............... 07 04 00 00 64 65 75 00 34 39 00 44 45 55 00 47 ....deu.49.DEU.G 65 72 6D 61 6E 79 00 ermany. FF 12 36 00 20 F3 31 08 40 A7 BF 01 20 C3 BA CB ..6. .1.@... ... 50 A7 BF 01 C4 FF FF FF 1D 04 00 00 1D 04 00 00 P............... 1D 04 00 00 73 76 65 00 34 36 00 53 57 45 00 53 ....sve.46.SWE.S 77 65 64 65 6E 00 weden. Diablo II 1.03 FF 12 39 00 A0 DB AA 45 51 3F C0 01 A0 EB ..9....EQ?.... 56 17 A5 3F C0 01 A8 FD FF FF 09 0C 00 00 09 0C V..?............ 00 00 09 0C 00 00 65 6E 61 00 36 31 00 41 55 53 ......ena.61.AUS 00 41 75 73 74 72 61 6C 69 61 00 .Australia. */ #define CLIENT_COUNTRYINFO1 0x12ff typedef struct { t_bnet_header h; bn_long systemtime; /* GMT */ bn_long localtime; /* time in local timezone */ bn_int bias; /* (gmt-local)/60 (using signed math) */ bn_int langid1; /* 09 04 00 00 */ /* 12 04 00 00 */ bn_int langid2; /* 09 04 00 00 */ /* 12 04 00 00 */ bn_int langid3; /* 09 04 00 00 */ /* 12 04 00 00 */ /* langstr */ /* countrycode (long distance phone) */ /* countryabbrev */ /* countryname */ } PACKED_ATTR() t_client_countryinfo1; /******************************************************/ /******************************************************/ /* First seen in Diablo II (and LoD) 1.09 FF 50 34 00 00 00 00 00 36 38 58 49 50 58 32 44 .P4.....68XIPX2D 09 00 00 00 00 00 00 00 00 00 00 00 C4 FF FF FF ................ 07 04 00 00 07 04 00 00 44 45 55 00 47 65 72 6D ........DEU.Germ 61 6E 79 00 any. FF 50 47 00 00 00 00 00 36 38 58 49 56 44 32 44 .PG.....68XIVD2D 09 00 00 00 00 00 00 00 00 00 00 00 20 FE FF FF ............ ... 04 08 00 00 04 08 00 00 43 48 4E 00 50 65 6F 70 ........CHN.Peop 6C 65 27 73 20 52 65 70 75 62 6C 69 63 20 6F 66 le's Republic of 20 43 68 69 6E 61 00 China. */ #define CLIENT_COUNTRYINFO_109 0x50ff typedef struct { t_bnet_header h; bn_int protocol; /* 00 00 00 00 always zero */ bn_int archtag; bn_int clienttag; bn_int versionid; /* 09 00 00 00 */ /* FIXME: what is this? */ bn_int gamelang; /* 00 00 00 00 always zero */ bn_int localip; /* 00 00 00 00 always zero */ bn_int bias; /* (gmt-local)/60 (using signed math) */ bn_int lcid; /* Win32 LCID */ bn_int langid; /* Win32 LangID */ /* langstr */ /* countryname */ } PACKED_ATTR() t_client_countryinfo_109; /******************************************************/ /******************************************************/ /* FF 2A 20 00 91 4F 93 DF 57 74 B5 C8 48 0F 4D 9B .* ..O..Wt..H.M. A2 28 A6 03 C1 D9 DA 11 42 69 6D 42 6F 3A 29 00 .(......BimBo:). */ #define CLIENT_CREATEACCTREQ1 0x2aff typedef struct { t_bnet_header h; bn_int password_hash1[5]; /* hash of lowercase password w/o null */ /* player name */ } PACKED_ATTR() t_client_createacctreq1; /******************************************************/ /******************************************************/ /* FF 2A 18 00 01 00 00 00 .*...... 13 00 00 00 78 52 82 02 00 00 00 00 00 00 00 00 ................ ---120 82 130 2--- FF 2A 08 00 01 00 00 00 .*...... */ #define SERVER_CREATEACCTREPLY1 0x2aff typedef struct { t_bnet_header h; bn_int result; } PACKED_ATTR() t_server_createacctreply1; #define SERVER_CREATEACCTREPLY1_RESULT_OK 0x00000001 #define SERVER_CREATEACCTREPLY1_RESULT_NO 0x00000000 /******************************************************/ /******************************************************/ /* FF 2B 20 00 01 00 00 00 .+ ..... 00 00 00 00 4D 00 00 00 0E 01 00 00 20 00 00 00 ....M....... ... CE 01 00 00 DD 07 00 00 ........ FF 2B 20 00 01 00 00 00 00 00 00 00 06 00 00 .+ ............ 00 72 01 00 00 40 00 00 00 A9 07 00 00 FF 07 00 .r...@.......... 00 . from Starcraft 1.05 FF 2B 20 00 01 00 00 00 00 00 00 00 06 00 00 00 .+ ............. 7C 01 00 00 20 00 00 00 00 02 00 00 FF 07 00 00 |... ........... */ #define CLIENT_UNKNOWN_2B 0x2bff /* FIXME: what is this? */ typedef struct { t_bnet_header h; bn_int unknown1; /* 01 00 00 00 */ /* 01 00 00 00 */ bn_int unknown2; /* 00 00 00 00 */ /* 00 00 00 00 */ bn_int unknown3; /* 4D 00 00 00 */ /* 06 00 00 00 */ bn_int unknown4; /* 0E 01 00 00 */ /* 72 01 00 00 */ bn_int unknown5; /* 20 00 00 00 */ /* 40 00 00 00 */ bn_int unknown6; /* CE 01 00 00 */ /* A9 07 00 00 */ bn_int unknown7; /* DD 07 00 00 */ /* FF 07 00 00 */ } PACKED_ATTR() t_client_unknown_2b; #define CLIENT_UNKNOWN_2B_UNKNOWN1 0x00000001 #define CLIENT_UNKNOWN_2B_UNKNOWN2 0x00000000 #define CLIENT_UNKNOWN_2B_UNKNOWN3 0x0000004d #define CLIENT_UNKNOWN_2B_UNKNOWN4 0x0000010e #define CLIENT_UNKNOWN_2B_UNKNOWN5 0x00000020 #define CLIENT_UNKNOWN_2B_UNKNOWN6 0x000001ce #define CLIENT_UNKNOWN_2B_UNKNOWN7 0x000007dd /******************************************************/ /******************************************************/ /* later replaced by progident2 and the authreq packets FF 06 14 00 36 38 58 49 ....68XI 50 58 45 53 BB 00 00 00 00 00 00 00 PXES........ sent by 1.05 Starcraft FF 06 14 00 36 38 58 49 52 41 54 53 BD 00 00 00 ....68XIRATS.... 00 00 00 00 .... Diablo II 1.03 FF 06 14 00 36 38 58 49 56 44 32 44 03 00 ....68XIVD2D.. 00 00 00 00 00 00 ...... */ #define CLIENT_PROGIDENT 0x06ff typedef struct { t_bnet_header h; bn_int archtag; bn_int clienttag; /* see tag.h */ bn_int versionid; /* FIXME: how does the versionid work? */ bn_int unknown1; /* FIXME: always zero? spawn flag? */ } PACKED_ATTR() t_client_progident; /******************************************************/ /******************************************************/ /* These formulas are for authenticating the client version. FF 06 5A 00 00 86 BA E3 ..Z..... 09 28 BC 01 49 58 38 36 76 65 72 32 2E 6D 70 71 .(..IX86ver2.mpq 00 41 3D 32 30 31 39 34 39 38 38 39 39 20 42 3D .A=2019498899 B= 33 34 32 33 32 39 32 33 39 34 20 43 3D 31 37 31 3423292394 C=171 39 30 31 31 32 32 32 20 34 20 41 3D 41 5E 53 20 9011222 4 A=A^S 42 3D 42 2D 43 20 43 3D 43 5E 41 20 41 3D 41 5E B=B-C C=C^A A=A^ 42 00 B. FF 06 59 00 00 C1 12 EC 09 28 BC 01 49 58 38 36 ..Y......(..IX86 76 65 72 35 2E 6D 70 71 00 41 3D 31 38 37 35 35 ver5.mpq.A=18755 39 31 33 34 31 20 42 3D 32 34 39 31 30 39 39 38 91341 B=24910998 30 39 20 43 3D 36 33 34 38 35 36 36 30 34 20 34 09 C=634856604 4 20 41 3D 41 2D 53 20 42 3D 42 5E 43 20 43 3D 43 A=A-S B=B^C C=C 2B 41 20 41 3D 41 5E 42 00 +A A=A^B. FF 06 5A 00 00 C1 12 EC 09 28 BC 01 49 58 38 36 ..Z......(..IX86 76 65 72 35 2E 6D 70 71 00 41 3D 31 37 31 32 39 ver5.mpq.A=17129 34 38 34 32 36 20 42 3D 33 36 30 30 30 33 30 36 48426 B=36000306 30 37 20 43 3D 33 33 39 30 34 31 37 39 35 39 20 07 C=3390417959 34 20 41 3D 41 2D 53 20 42 3D 42 5E 43 20 43 3D 4 A=A-S B=B^C C= 43 2D 41 20 41 3D 41 2D 42 00 C-A A=A-B. FF 06 5A 00 00 3A 7F E8 09 28 BC 01 49 58 38 36 ..Z..:...(..IX86 76 65 72 34 2E 6D 70 71 00 41 3D 31 31 38 36 39 ver4.mpq.A=11869 35 38 31 34 31 20 42 3D 31 33 37 37 34 34 31 34 58141 B=13774414 35 37 20 43 3D 31 37 37 32 37 38 37 37 30 35 20 57 C=1772787705 34 20 41 3D 41 5E 53 20 42 3D 42 5E 43 20 43 3D 4 A=A^S B=B^C C= 43 2B 41 20 41 3D 41 5E 42 00 C+A A=A^B. FF 06 5A 00 00 56 CD F6 09 28 BC 01 49 58 38 36 ..Z..V...(..IX86 76 65 72 37 2E 6D 70 71 00 41 3D 31 30 32 36 30 ver7.mpq.A=10260 34 34 33 35 34 20 42 3D 34 31 33 32 36 33 30 37 44354 B=41326307 31 31 20 43 3D 32 33 30 32 34 31 31 33 32 38 20 11 C=2302411328 34 20 41 3D 41 5E 53 20 42 3D 42 5E 43 20 43 3D 4 A=A^S B=B^C C= 43 5E 41 20 41 3D 41 2B 42 00 C^A A=A+B. */ #define SERVER_AUTHREQ1 0x06ff typedef struct { t_bnet_header h; bn_long timestamp; /* FIXME: file modification time? */ /* versioncheck filename */ /* equation */ } PACKED_ATTR() t_server_authreq1; /******************************************************/ /******************************************************/ /* First seen in Diablo II (and LoD) 1.09 FF 50 65 00 00 00 00 00 36 1A 6C 45 76 BC 00 00 .Pe.....6.lEv... 00 48 A6 EF 09 28 BC 01 49 58 38 36 76 65 72 36 .H...(..IX86ver6 2E 6D 70 71 00 41 3D 33 38 34 35 35 38 31 36 33 .mpq.A=384558163 34 20 42 3D 38 38 30 38 32 33 35 38 30 20 43 3D 4 B=880823580 C= 31 33 36 33 39 33 37 31 30 33 20 34 20 41 3D 41 1363937103 4 A=A 2D 53 20 42 3D 42 2D 43 20 43 3D 43 2D 41 20 41 -S B=B-C C=C-A A 3D 41 2D 42 00 =A-B. FF 50 65 00 00 00 00 00 .Pe..... 30 4B C1 33 10 EB 09 00 00 A5 C4 DD 09 28 BC 01 0K.3.........(.. 49 58 38 36 76 65 72 30 2E 6D 70 71 00 41 3D 31 IX86ver0.mpq.A=1 34 33 32 36 36 32 34 37 38 20 42 3D 36 35 32 32 432662478 B=6522 37 38 36 32 35 20 43 3D 31 37 36 31 35 31 35 38 78625 C=17615158 36 39 20 34 20 41 3D 41 5E 53 20 42 3D 42 2B 43 69 4 A=A^S B=B+C 20 43 3D 43 2B 41 20 41 3D 41 5E 42 00 C=C+A A=A^B. */ #define SERVER_AUTHREQ_109 0x50ff typedef struct { t_bnet_header h; bn_int logontype; /* 00 00 00 00 always zero */ bn_int sessionkey; bn_int sessionnum; bn_long timestamp; /* versioncheck filename */ /* equation */ } PACKED_ATTR() t_server_authreq_109; #define SERVER_AUTHREQ_109_LOGONTYPE 0x0000000 #define SERVER_AUTHREQ_109_LOGONTYPE_W3 0x00000002 #define SERVER_AUTHREQ_109_LOGONTYPE_W3XP 0x00000002 /******************************************************/ /* ADDED BY UNDYING SOULZZ 4/3/02 */ #define VERSIONTAG_WARCRAFT3_113 "WAR3_113" /******************************************************/ /* FF 07 40 00 36 38 58 49 52 41 54 53 BD 00 00 00 ..@.68XIRATS.... 00 05 00 01 1E 88 D7 08 73 74 61 72 63 72 61 66 ........starcraf 74 2E 65 78 65 20 30 33 2F 30 38 2F 39 39 20 32 t.exe 03/08/99 2 32 3A 34 31 3A 35 30 20 31 30 34 32 34 33 32 00 2:41:50 1042432. sent by the 1.05 Starcraft FF 07 40 00 36 38 58 49 52 41 54 53 BD 00 00 00 ..@.68XIRATS.... 00 05 00 01 AE AC DE 87 73 74 61 72 63 72 61 66 ........starcraf 74 2E 65 78 65 20 30 33 2F 30 38 2F 39 39 20 32 t.exe 03/08/99 2 32 3A 34 31 3A 35 30 20 31 30 34 32 34 33 32 00 2:41:50 1042432. sent by the 1.08alpha Brood War (Starcraft game) in response to A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B with IX86ver1.mpq FF 07 40 00 36 38 58 49 52 41 54 53 C3 00 00 00 ..@.68XIRATS.... 01 08 00 01 A1 52 CE FE 73 74 61 72 63 72 61 66 .....R..starcraf 74 2E 65 78 65 20 31 32 2F 32 38 2F 30 30 20 31 t.exe 12/28/00 1 31 3A 32 38 3A 35 32 20 31 30 38 32 33 36 38 00 1:28:52 1082368. sent by the 1.07 Diablo FF 07 3C 00 36 38 58 49 4C 54 52 44 26 00 00 00 ..<.68XILTRD&... 01 06 05 62 8C 56 E6 21 64 69 61 62 6C 6F 2E 65 ...b.V.!diablo.e 78 65 20 30 39 2F 31 37 2F 39 38 20 31 38 3A 30 xe 09/17/98 18:0 30 3A 34 30 20 37 36 30 33 32 30 00 0:40 760320. FF 07 45 00 36 38 58 49 4E 42 32 57 4B 00 00 00 ..E.68XINB2WK... 99 00 00 02 3D 51 C4 AA 57 61 72 63 72 61 66 74 ....=Q..Warcraft 20 49 49 20 42 4E 45 2E 65 78 65 20 31 30 2F 31 II BNE.exe 10/1 35 2F 39 39 20 30 30 3A 33 37 3A 35 34 20 37 30 5/99 00:37:54 70 34 35 31 32 00 4512. sent by the 1.03 Diablo II FF 07 3A 00 36 38 58 49 ..:.68XI 56 44 32 44 03 00 00 00 00 03 00 01 47 3E 26 73 VD2D........G>&s 47 61 6D 65 2E 65 78 65 20 30 38 2F 30 35 2F 30 Game.exe 08/05/0 30 20 30 31 3A 34 32 3A 32 38 20 32 39 34 39 31 0 01:42:28 29491 32 00 2. */ #define CLIENT_AUTHREQ1 0x07ff typedef struct { t_bnet_header h; bn_int archtag; bn_int clienttag; bn_int versionid; bn_int gameversion; bn_int checksum; /* executable info */ } PACKED_ATTR() t_client_authreq1; /******************************************************/ /******************************************************/ /* FF 07 0A 00 02 00 00 00 ........ 00 00 .. FF 07 0A 00 02 00 00 00 00 00 .......... */ #define SERVER_AUTHREPLY1 0x07ff typedef struct { t_bnet_header h; bn_int message; /* filename */ /* unknown */ } PACKED_ATTR() t_server_authreply1; #define SERVER_AUTHREPLY1_MESSAGE_BADVERSION 0x00000000 #define SERVER_AUTHREPLY1_MESSAGE_UPDATE 0x00000001 /* initiate auto-update */ #define SERVER_AUTHREPLY1_MESSAGE_OK 0x00000002 /******************************************************/ /******************************************************/ /* First seen in Diablo II (and LoD) 1.09 FF 51 09 00 00 00 00 00 00 .Q....... */ #define SERVER_AUTHREPLY_109 0x51ff typedef struct { t_bnet_header h; bn_int message; /* message string? */ } PACKED_ATTR() t_server_authreply_109; #define SERVER_AUTHREPLY_109_MESSAGE_OK 0x00000000 #define SERVER_AUTHREPLY_109_MESSAGE_UPDATE 0x00000100 #define SERVER_AUTHREPLY_109_MESSAGE_BADVERSION 0x00000101 /* we should check the first 10 values or so to see what they mean */ /******************************************************/ /******************************************************/ /* First seen in Diablo II (and LoD) 1.09 FF 51 67 00 C9 88 DA 42 00 09 00 01 46 97 62 9A .Qg....B....F.b. 01 00 00 00 00 00 00 00 10 00 00 00 06 00 00 00 ................ A5 E7 39 00 00 00 00 00 ED CD 4F F7 6A 7A 4F 96 ..9.......O.jzO. 85 7A 2D A2 7F 1F B1 D6 81 B3 8D 50 47 61 6D 65 .z-........PGame 2E 65 78 65 20 30 38 2F 31 36 2F 30 31 20 32 33 .exe 08/16/01 23 3A 30 34 3A 34 30 20 34 32 34 30 36 37 00 74 73 :04:40 424067.ts 69 6E 67 68 75 61 00 inghua. */ #define CLIENT_AUTHREQ_109 0x51ff typedef struct { t_bnet_header h; bn_int ticks; bn_int gameversion; bn_int checksum; bn_int cdkey_number; /* count of cdkeys, d2 = 1, lod = 2 */ bn_int spawn; /* set if using spawn copy */ /* cdkey info(s) */ /* executable info */ /* cdkey owner */ } PACKED_ATTR() t_client_authreq_109; /* values are the same as in CLIENT_AUTHREQ1 */ typedef struct { bn_int len; bn_int type; bn_int checksum; bn_int u1; bn_int hash[5]; } PACKED_ATTR() t_cdkey_info; /******************************************************/ /******************************************************/ /* Batle.net used to send requests for registry and email info. Thanks to bnetanon, I have a dump of these old packets. */ /* FF 18 41 00 00 00 00 00 01 00 00 80 53 6F 66 74 ..A.........Soft 77 61 72 65 5C 4D 69 63 72 6F 73 6F 66 74 5C 4D ware\Microsoft\M 53 20 53 65 74 75 70 20 28 41 43 4D 45 29 5C 55 S Setup (ACME)\U 73 65 72 20 49 6E 66 6F 00 44 65 66 4E 61 6D 65 ser Info.DefName 00 . FF 18 48 00 00 00 00 00 01 00 00 80 53 6F 66 74 ..H.........Soft 77 61 72 65 5C 4D 69 63 72 6F 73 6F 66 74 5C 4D ware\Microsoft\M 65 64 69 61 50 6C 61 79 65 72 5C 43 6F 6E 74 72 ediaPlayer\Contr 6F 6C 5C 50 6C 61 79 42 61 72 00 43 6C 72 42 61 ol\PlayBar.ClrBa 63 6B 43 6F 6C 6F 72 00 ckColor. */ #define SERVER_REGSNOOPREQ 0x18ff typedef struct { t_bnet_header h; bn_int unknown1; /* 00 00 00 00 */ /* sequence match like in other packets? */ bn_int hkey; /* registry key */ /* value name */ } PACKED_ATTR() t_server_regsnoopreq; #define SERVER_REGSNOOPREQ_UNKNOWN1 0x00000000 #define SERVER_REGSNOOPREQ_HKEY_CLASSES_ROOT 0x80000000 #define SERVER_REGSNOOPREQ_HKEY_CURRENT_USER 0x80000001 #define SERVER_REGSNOOPREQ_HKEY_LOCAL_MACHINE 0x80000002 #define SERVER_REGSNOOPREQ_HKEY_USERS 0x80000003 #define SERVER_REGSNOOPREQ_HKEY_PERFORMANCE_DATA 0x80000004 #define SERVER_REGSNOOPREQ_HKEY_CURRENT_CONFIG 0x80000005 #define SERVER_REGSNOOPREQ_HKEY_DYN_DATA 0x80000006 #define SERVER_REGSNOOPREQ_HKEY_PERFORMANCE_TEXT 0x80000050 #define SERVER_REGSNOOPREQ_HKEY_PERFORMANCE_NLSTEXT 0x80000060 #define SERVER_REGSNOOPREQ_REGKEY "Software\\Microsoft\\MS Setup (ACME)\\User Info" #define SERVER_REGSNOOPREQ_REGVALNAME "DefName" /******************************************************/ /******************************************************/ /* If the key exists, the client send this back */ /* FF 18 0C 00 00 00 00 00 42 6F 62 00 ........Bob. FF 18 0C 00 00 00 00 00 A0 9C A0 00 ............ */ #define CLIENT_REGSNOOPREPLY 0x18ff typedef struct { t_bnet_header h; bn_int unknown1; /* 00 00 00 00 */ /* same as request? */ /* registry value (string, dword, or binary */ } PACKED_ATTR() t_client_regsnoopreply; /******************************************************/ /******************************************************/ /* FF 07 0A 00 02 00 00 00 00 00 .......... */ #define CLIENT_ICONREQ 0x2dff typedef struct { t_bnet_header h; } PACKED_ATTR() t_client_iconreq; /******************************************************/ /******************************************************/ /* FF 2D 16 00 76 34 1F 8F .-..v4.. C0 D6 BD 01 69 63 6F 6E 73 2E 62 6E 69 00 ....icons.bni. FF 2D 16 00 00 77 D0 01 C7 B1 BE 01 69 63 6F 6E .-...w......icon 73 2E 62 6E 69 00 s.bni. */ #define SERVER_ICONREPLY 0x2dff typedef struct { t_bnet_header h; bn_long timestamp; /* file modification time? */ /* filename */ } PACKED_ATTR() t_server_iconreply; /******************************************************/ /******************************************************/ #define CLIENT_LADDERSEARCHREQ 0x2fff typedef struct { t_bnet_header h; bn_int clienttag; bn_int id; /* (AKA ladder type) 1==standard, 3==ironman */ bn_int type; /* (AKA ladder sort) */ /* player name */ } PACKED_ATTR() t_client_laddersearchreq; #define CLIENT_LADDERSEARCHREQ_ID_STANDARD 0x00000001 #define CLIENT_LADDERSEARCHREQ_ID_IRONMAN 0x00000003 #define CLIENT_LADDERSEARCHREQ_TYPE_HIGHESTRATED 0x00000000 #define CLIENT_LADDERSEARCHREQ_TYPE_MOSTWINS 0x00000002 #define CLIENT_LADDERSEARCHREQ_TYPE_MOSTGAMES 0x00000003 /******************************************************/ /******************************************************/ #define SERVER_LADDERSEARCHREPLY 0x2fff typedef struct /* FIXME: how does client know how many names? do we send separate replies for each name in the request? */ { t_bnet_header h; bn_int rank; /* 0 means 1st, etc */ } PACKED_ATTR() t_server_laddersearchreply; #define SERVER_LADDERSEARCHREPLY_RANK_NONE 0xffffffff /******************************************************/ /******************************************************/ /* FF 30 1C 00 00 00 00 00 .0...... 32 37 34 34 37 37 32 39 31 34 38 32 38 00 63 6C 2744772914828.cl 6F 75 64 00 oud. */ #define CLIENT_CDKEY 0x30ff typedef struct { t_bnet_header h; bn_int spawn; /* FIXME: not sure if this is correct, but cdkey2 does it this way */ /* cd key */ /* owner name */ /* Was this always here? */ } PACKED_ATTR() t_client_cdkey; #define CLIENT_CDKEY_UNKNOWN1 0x00000000 /******************************************************/ /******************************************************/ /* FF 30 0E 00 01 00 00 00 .0...... 63 6C 6F 75 64 00 cloud. */ #define SERVER_CDKEYREPLY 0x30ff typedef struct { t_bnet_header h; bn_int message; /* owner name */ } PACKED_ATTR() t_server_cdkeyreply; #define SERVER_CDKEYREPLY_MESSAGE_OK 0x00000001 #define SERVER_CDKEYREPLY_MESSAGE_BAD 0x00000002 #define SERVER_CDKEYREPLY_MESSAGE_WRONGAPP 0x00000003 #define SERVER_CDKEYREPLY_MESSAGE_ERROR 0x00000004 /* disabled */ #define SERVER_CDKEYREPLY_MESSAGE_INUSE 0x00000005 /* (any other value seems to correspond to ok) */ /******************************************************/ /******************************************************/ /* FF 36 34 00 00 00 00 00 0D 00 00 00 01 00 00 00 .64............. B5 AE 23 00 50 E5 D5 C0 DB 55 1E 38 0A F5 58 B9 ..#.P....U.8..X. 47 64 C6 C2 9F BB FF B8 81 E7 EB EC 1B 13 C6 38 Gd.............8 52 6F 62 00 Rob. FF 36 34 00 00 00 00 00 0D 00 00 00 01 00 00 00 .64............. 7F D7 00 00 90 64 77 2F D7 5B 42 38 1F A1 A2 6F .....dw/.[B8...o E8 FA BE F8 B6 0B BA 0F CA 64 3A 17 14 56 83 AB .........d:..V.. 42 6F 62 00 Bob. FF 36 35 00 00 00 00 00 10 00 00 00 04 00 00 00 .65............. 0D 43 03 00 7A 11 07 ED 7C 9E 1E 38 E5 87 8B 3B .C..z...|..8...; 9C 19 91 D9 0D 10 FC C1 C0 86 8C 8D DA A4 45 0B ..............E. XX XX XX XX 00 XXXX. FF 36 34 00 00 00 00 00 10 00 00 00 04 00 00 00 .64............. 70 F9 02 00 58 F9 B6 E6 38 49 5C 38 38 9C 31 E4 p...X...8I\88.1. 1D 3D 40 05 66 AD 4C C8 1D 12 8E 49 9E 60 1A CB .=@.f.L....I.`.. 42 6F 62 00 Bob. */ #define CLIENT_CDKEY2 0x36ff typedef struct { t_bnet_header h; bn_int spawn; bn_int keylen; /* without terminating NUL */ bn_int productid; bn_int keyvalue1; bn_int sessionkey; bn_int ticks; bn_int key_hash[5]; /* owner name */ } PACKED_ATTR() t_client_cdkey2; #define CLIENT_CDKEY2_SPAWN_TRUE 0x00000001 #define CLIENT_CDKEY2_SPAWN_FALSE 0x00000000 /******************************************************/ /******************************************************/ /* From Diablo II 1.08? FF 42 43 00 AB 4C A4 3B .BC..L.; 01 00 00 00 00 00 00 00 10 00 00 00 06 00 00 00 ................ XX 60 12 00 00 00 00 00 5D 82 82 C4 F4 8F D0 91 X`......]....... E1 5B AB 95 D9 EE EF 18 44 3E F1 C9 XX XX XX XX .[......D>..XXXX XX XX XX XX XX XX XX XX XX XX 00 XXXXXXXXXX. FF 42 44 00 17 78 42 77 01 00 00 00 00 00 00 00 .BD..xBw........ 10 00 00 00 06 00 00 00 XX F3 10 00 00 00 00 00 ........X....... A8 29 8B C4 41 BD 33 AB 74 4C 1F 1E 5C XX CA 83 .)..A.3.tL..\X.. 7F E5 36 14 XX XX XX XX XX XX XX XX XX XX XX XX ..6.XXXXXXXXXXXX XX XX XX 00 XXX. FF 42 44 00 C6 25 A1 3B 01 00 00 00 00 00 00 00 .BD..%.;........ 10 00 00 00 06 00 00 00 XX F3 10 00 00 00 00 00 ........X....... C4 3F FB 05 94 0C AC D4 3B 63 B1 90 E4 XX 53 B9 .?......;c...XS. 70 C3 6F 2E XX XX XX XX XX XX XX XX XX XX XX XX p.o.XXXXXXXXXXXX XX XX XX 00 XXX. */ #define CLIENT_CDKEY3 0x42ff typedef struct { t_bnet_header h; bn_int unknown1; /* FIXME: some kind of salt? */ bn_int unknown2; /* 01 00 00 00 */ bn_int unknown3; /* 00 00 00 00 */ bn_int unknown4; /* 10 00 00 00 */ bn_int unknown5; /* 06 00 00 00 */ bn_int unknown6; /* FIXME: value1? */ bn_int unknown7; /* 00 00 00 00 */ bn_int key_hash[5]; /* owner name */ } PACKED_ATTR() t_client_cdkey3; #define CLIENT_CDKEY3_UNKNOWN1 0xffffffff #define CLIENT_CDKEY3_UNKNOWN2 0x00000001 #define CLIENT_CDKEY3_UNKNOWN3 0x00000000 #define CLIENT_CDKEY3_UNKNOWN4 0x00000010 #define CLIENT_CDKEY3_UNKNOWN5 0x00000006 #define CLIENT_CDKEY3_UNKNOWN6 0x00123456 #define CLIENT_CDKEY3_UNKNOWN7 0x00000000 /******************************************************/ /******************************************************/ /* FF 42 09 00 00 00 00 00 .B...... 00 FF 42 09 00 00 00 00 00 00 .B....... */ #define SERVER_CDKEYREPLY3 0x42ff typedef struct { t_bnet_header h; bn_int message; /* owner name */ /* FIXME: or error message, or ... */ } PACKED_ATTR() t_server_cdkeyreply3; #define SERVER_CDKEYREPLY3_MESSAGE_OK 0x00000000 /******************************************************/ /******************************************************/ /* FF 34 0D 00 00 00 00 00 00 00 00 00 00 .4........... */ #define CLIENT_REALMLISTREQ 0x34ff typedef struct { t_bnet_header h; bn_int unknown1; bn_int unknown2; } PACKED_ATTR() t_client_realmlistreq; /******************************************************/ /******************************************************/ /* 0000: FF 40 04 00 .@.. */ #define CLIENT_REALMLISTREQ_110 0x40ff typedef struct { t_bnet_header h; } PACKED_ATTR() t_client_realmlistreq_110; /******************************************************/ /******************************************************/ /* FF 34 5E 00 00 00 00 00 01 00 00 00 00 00 00 C0 .4^............. 00 00 00 00 00 00 00 00 00 00 00 00 10 82 01 00 ................ FF FF FF FF 00 00 00 00 42 65 74 61 57 65 73 74 ........BetaWest 00 50 6C 65 61 73 65 20 73 65 6C 65 63 74 20 74 .Please select t 68 69 73 20 61 73 20 79 6F 75 72 20 72 65 61 6C his as your real 6D 20 64 75 72 69 6E 67 20 62 65 74 61 00 m during beta. ff 34 5e 00 00 00 00 00 01 00 00 00 00 00 00 c0 .4^............. 00 00 00 00 00 00 00 00 00 00 00 00 bc 95 01 00 ................ ff ff ff ff 00 00 00 00 42 65 74 61 57 65 73 74 ........BetaWest 00 50 6c 65 61 73 65 20 73 65 6c 65 63 74 20 74 .Please select t 68 69 73 20 61 73 20 79 6f 75 72 20 72 65 61 6c his as your real 6d 20 64 75 72 69 6e 67 20 62 65 74 61 00 m during beta. ff 34 5e 00 00 00 00 00 01 00 00 00 00 00 00 c0 .4^............. 00 00 00 00 00 00 00 00 00 00 00 00 c8 99 01 00 ................ ff ff ff ff 00 00 00 00 42 65 74 61 57 65 73 74 ........BetaWest 00 50 6c 65 61 73 65 20 73 65 6c 65 63 74 20 74 .Please select t 68 69 73 20 61 73 20 79 6f 75 72 20 72 65 61 6c his as your real 6d 20 64 75 72 69 6e 67 20 62 65 74 61 00 m during beta. from bnetd-0.3.23pre18 to Diablo II 1.03 FF 34 4B 00 00 00 00 00 01 00 00 00 00 00 .4K........... 00 C0 00 00 00 00 00 00 00 00 00 00 00 00 10 82 ................ 01 00 FF FF FF FF 00 00 00 00 51 61 72 61 74 68 ..........Qarath 52 65 61 6C 6D 00 54 48 45 20 43 68 6F 69 63 65 Realm.THE Choice 20 46 6F 72 20 4E 6F 77 28 74 6D 29 00 For Now(tm). */ #define SERVER_REALMLISTREPLY 0x34ff /* realm list reply? */ typedef struct { t_bnet_header h; bn_int unknown1; bn_int count; /* realm entries */ } PACKED_ATTR() t_server_realmlistreply; #define SERVER_REALMLISTREPLY_UNKNOWN1 0x00000000 typedef struct { bn_int unknown3; bn_int unknown4; bn_int unknown5; bn_int unknown6; bn_int unknown7; /* this one is always different... 00 01 XX XX.. what is it? */ bn_int unknown8; bn_int unknown9; /* realm name */ /* realm description */ } PACKED_ATTR() t_server_realmlistreply_data; #define SERVER_REALMLISTREPLY_DATA_UNKNOWN3 0xc0000000 #define SERVER_REALMLISTREPLY_DATA_UNKNOWN4 0x00000000 #define SERVER_REALMLISTREPLY_DATA_UNKNOWN5 0x00000000 #define SERVER_REALMLISTREPLY_DATA_UNKNOWN6 0x00000000 #define SERVER_REALMLISTREPLY_DATA_UNKNOWN7 0x00018210 /* 98832 or 1;33296 */ #define SERVER_REALMLISTREPLY_DATA_UNKNOWN8 0xffffffff #define SERVER_REALMLISTREPLY_DATA_UNKNOWN9 0x00000000 /******************************************************/ /******************************************************/ /* # 44 packet from server: type=0x40ff(unknown) length=40 class=bnet 0000: FF 40 28 00 00 00 00 00 01 00 00 00 01 00 00 00 .@(............. 0010: 45 75 72 6F 70 65 00 52 65 61 6C 6D 20 66 6F 72 Europe.Realm for 0020: 20 45 75 72 6F 70 65 00 Europe. */ #define SERVER_REALMLISTREPLY_110 0x40ff typedef struct { t_bnet_header h; bn_int unknown1; bn_int count; /* realm entries */ } PACKED_ATTR() t_server_realmlistreply_110; #define SERVER_REALMLISTREPLY_110_UNKNOWN1 0x00000000 typedef struct { bn_int unknown1; /* realm name */ /* realm description */ } PACKED_ATTR() t_server_realmlistreply_110_data; #define SERVER_REALMLISTREPLY_110_DATA_UNKNOWN1 0x00000001 #define CLIENT_PROFILEREQ 0x35ff typedef struct /* join realm request */ { t_bnet_header h; bn_int count; /* player name */ } PACKED_ATTR() t_client_profilereq; #define SERVER_PROFILEREPLY 0x35ff typedef struct /* realm join reply? */ { t_bnet_header h; bn_int count; /* same as in req */ bn_byte fail; /* != 0 if a problem occured */ /* profile-description */ /* profile-location */ /* bn_int clanTAG */ } PACKED_ATTR() t_server_profilereply; #define CLIENT_UNKNOWN_37 0x37ff typedef struct /* character list request, character list upload? */ { t_bnet_header h; bn_int opencount; /* Number of OPEN characters on user's machine! */ /* Always zero for "closed" connections. */ /* unknown2 */ /* subsequent blocks of t_d2char_info or something */ /* similar, so server could read this list and */ /* include in the 0x37ff reply as a choice (this */ /* makes sense cuz the server does NOT store open */ /* character details - this also explains why */ /* unknown1 is always 0 in the beta, and the 0x00 */ /* of unknown2 acts as a EOF when client read the */ /* t_d2char_info structures */ } PACKED_ATTR() t_client_unknown_37; /******************************************************/ /******************************************************/ /* FF 37 01 01 00 00 00 00 08 00 00 00 04 00 00 00 .7.............. 42 65 74 61 57 65 73 74 2C 4D 6F 4E 6B 00 87 80 BetaWest,MoNk... 06 01 01 01 01 50 FF FF 02 02 FF FF FF FF FF FF .....P.......... 02 49 50 50 50 50 FF FF FF 50 50 FF FF FF FF FF .IPPPP...PP..... FF 14 88 82 80 80 FF FF FF 00 42 65 74 61 57 65 ..........BetaWe 73 74 2C 4D 6F 4E 6B 2D 65 00 83 80 05 02 02 01 st,MoNk-e....... 01 2B FF 1B 02 02 FF FF FF FF FF FF 03 FF FF FF .+.............. FF FF FF FF A8 FF FF FF FF FF FF FF FF 10 80 82 ................ 80 80 FF FF FF 00 42 65 74 61 57 65 73 74 2C 4D ......BetaWest,M 6F 4E 6B 2D 65 65 00 83 80 06 01 01 01 01 FF 4C oNk-ee.........L FF 02 02 FF FF FF FF FF FF 01 FF 48 48 48 48 FF ...........HHHH. A6 FF 48 48 FF FF FF FF FF FF 0F 80 80 80 80 FF ..HH............ FF FF 00 42 65 74 61 57 65 73 74 2C 4D 6F 4E 6B ...BetaWest,MoNk 2D 74 77 6F 00 87 80 01 01 01 01 01 FF FF FF 01 -two............ 01 FF FF FF FF FF FF 02 FF FF FF FF FF FF FF FF ................ FF FF FF FF FF FF FF FF 01 84 80 FF FF FF 80 80 ................ 00 . ^-- 1: (BetaWest) MoNk 2: (BetaWest) MoNk-e 3: (BetaWest) MoNk-ee 4: (BetaWest) MoNk-two ff 37 4e 00 00 00 00 00 08 00 00 00 01 00 00 00 .7N............. 42 65 74 61 57 65 73 74 2c 4c 69 66 65 6c 69 6b BetaWest,Lifelik 65 00 87 80 01 01 01 01 01 ff ff ff 01 01 ff ff e............... ff ff ff ff 03 ff ff ff ff ff ff ff ff ff ff ff ................ ff ff ff ff ff 01 80 80 ff ff ff 80 80 00 .............. ff 37 4e 00 00 00 00 00 08 00 00 00 01 00 00 00 .7N............. 42 65 74 61 57 65 73 74 2c 51 6c 65 78 54 45 53 BetaWest,QlexTES 54 00 83 80 ff ff ff ff ff 30 ff 1b ff ff ff ff T........0...... ff ff ff ff 04 ff ff ff ff ff ff ff ff ff ff ff ................ ff ff ff ff ff 01 80 80 80 80 ff ff ff 00 .............. from bnetd-0.3.23pre18 to Diablo II 1.03 "Char1 {BNE}" [lvl 20, amaz] "Char2 {BNE}" [lvl 21, sorc] "Char3 {BNE}" [lvl 22, necro] FF 37 D9 00 00 00 00 00 08 00 00 00 03 00 Gv.7............ 00 00 51 61 72 61 74 68 52 65 61 6C 6D 2C 43 68 ..QarathRealm,Ch 61 72 31 00 87 80 01 01 01 01 01 01 01 01 01 01 ar1............. 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................ 01 01 01 01 01 01 01 14 85 86 01 FF FF FF FF 42 ...............B 4E 45 54 44 00 51 61 72 61 74 68 52 65 61 6C 6d NETD.QarathRealm 2C 43 68 61 72 32 00 87 80 01 01 01 01 01 01 01 ,Char2.......... 01 01 01 01 01 01 01 01 01 02 01 01 01 01 01 01 ................ 01 01 01 01 01 01 01 01 01 01 15 85 86 01 FF FF ................ FF FF 42 4E 45 54 44 00 51 61 72 61 74 68 52 65 ..BNETD.QarathRe 61 6C 6D 2C 43 68 61 72 33 00 87 80 01 01 01 01 alm,Char3....... 01 01 01 01 01 01 01 01 01 01 01 01 03 01 01 01 ................ 01 01 01 01 01 01 01 01 01 01 01 01 01 16 85 86 ................ 01 FF FF FF FF 42 4E 45 54 44 00 .....BNETD. */ #define SERVER_UNKNOWN_37 0x37ff typedef struct /* character list reply? */ { t_bnet_header h; bn_int unknown1; bn_int unknown2; /* _bucky_: max chars allowed? */ bn_int count; /* # of chars, same number of */ /* t_char_info to follow in */ /* packet */ /* d2char_info blocks */ } PACKED_ATTR() t_server_unknown_37; #define SERVER_UNKNOWN_37_UNKNOWN1 0x00000000 #define SERVER_UNKNOWN_37_UNKNOWN2 0x00000008 /* The ONLY 0x00 that should appear should be the terminating NUL for */ /* the character name string and the guild tag string, they're used as */ /* delimiters to separate character name and the character structure */ /* If you got any other NUL's in here the next character's info will */ /* be royally fucked up - using 0x01 or 0xff for unknowns seem to work */ /* well */ typedef struct { /* "RealmName,CharacterName" - for closed characters */ /* - OR - */ /* "CharacterName" - for open characters */ /* - strlen(CharacterName) must be <= 15 - */ bn_byte unknownb1; /* 0x83, 0x87? */ bn_byte unknownb2; /* 0x80...? */ bn_byte helmgfx; bn_byte bodygfx; bn_byte leggfx; bn_byte lhandweapon; bn_byte lhandgfx; bn_byte rhandweapon; /* Partial weapon code list: 0x2f: 1H Axe 0x30: 1H Sword 0x50: 2H Staff 0x51: Another 2H Staff 0x52: Another 2H Staff 0x53: Another 2H Staff 0x54: 2H Axe 0x55: Scythe 0x56: empty? 0x57: Another 2H Axe 0x58: Halberd? 0x59: empty? 0x5a: Another 2H Axe 0x5b: Another Halberd 0x5c: empty? 0x5d: 1H club? 0x5e: empty? 0x5f: empty? */ bn_byte rhandgfx; bn_byte unknownb3; bn_byte unknownb4; bn_byte unknownb5; bn_byte unknownb6; bn_byte unknownb7; bn_byte unknownb8; bn_byte unknownb9; bn_byte unknownb10; bn_byte unknownb11; bn_byte class; /* 0x01=Amazon, 0x02=Sor, 0x03=Nec, 0x04=Pal, 0x05=Bar */ bn_int unknown1; bn_int unknown2; bn_int unknown3; bn_int unknown4; bn_byte level; /* yes, byte, not short/int/long */ bn_byte status; /* 0x01-03 = Norm & alive */ /* 0x04-07 = HC & alive */ /* 0x08-0b = Norm & "dead"? */ /* 0x0c+ = HC & dead, chat only */ /* Add 0x80 to get same effect */ bn_byte title; /* 0x01=none 0x02=Sir/Dame? 0x03=Sir/Dame? 0x04=Lord? 0x05=Lord? 0x06=Baron? 0x07=Baron? */ /* Same codes for HC chars */ /* Add 0x80 to get same effect */ bn_byte unknownb13; bn_byte emblembgc; /* Guild emblem background colour */ bn_byte emblemfgc; /* Guild emblem foreground colour */ bn_byte emblemnum; /* Guild emblem type number */ /* emblem number corresponds to D2DATA.MPQ/data/global/ui/Emblems/iconXXa.dc6 */ /* where XX = emblem number - 1 (ie, 0x0A corresponds to icon09a.dc6) use */ /* for dummy values seem safe... 0x01 won't work, you'll get an emblem... */ bn_byte unknownb14; /* Guild Tag */ /* must not be longer than 3 chars */ } PACKED_ATTR() t_d2char_info; #define D2CHAR_INFO_UNKNOWNB1 0x83 #define D2CHAR_INFO_UNKNOWNB2 0x80 #define D2CHAR_INFO_FILLER 0xff /* non-zero padding */ #define D2CHAR_INFO_CLASS_AMAZON 0x01 #define D2CHAR_INFO_CLASS_SORCERESS 0x02 #define D2CHAR_INFO_CLASS_NECROMANCER 0x03 #define D2CHAR_INFO_CLASS_PALADIN 0x04 #define D2CHAR_INFO_CLASS_BARBARIAN 0x05 #define D2CHAR_INFO_CLASS_DRUID 0x06 #define D2CHAR_INFO_CLASS_ASSASSIN 0x07 /******************************************************/ /******************************************************/ /* D2 packet... not sent very often and the client doesn't * seem to expect an answer */ /* FIXME: what the hell does this one do? */ /* FF 39 13 00 42 65 74 61 57 65 73 74 2C 62 75 73 .9..BetaWest,bus 74 61 00 ta. this one was sent after a closed character was deleted on the auth server... maybe a notifier for the gateway server? FF 39 17 00 42 6F 62 73 57 6F 72 6C 64 2C 63 68 .9..BobsWorld,ch 61 72 6E 61 6D 65 00 arname. */ #define CLIENT_UNKNOWN_39 0x39ff typedef struct { t_bnet_header h; /* character name */ /* what about open chars? */ } PACKED_ATTR() t_client_unknown_39; /******************************************************/ /******************************************************/ /* FF 3A 2E 00 58 4C F2 00 19 C2 08 00 D7 33 37 D3 .:..XL.......37. 42 8C 92 37 C2 26 08 A9 3E 92 05 28 A1 5A 18 B9 B..7.&..>..(.Z.. 6D 61 73 74 6F 64 6F 6E 74 66 69 6C 6D 00 mastodontfilm. FF 3A 28 00 2B 73 1C 01 88 91 F2 0D AF 22 43 25 .:(.+s......."C% BF E4 2D 45 42 37 04 DB AF 95 66 71 16 85 67 60 ..-EB7....fq..g` 51 6C 65 78 53 5A 47 00 QlexSZG. */ #define CLIENT_LOGINREQ2 0x3aff typedef struct { t_bnet_header h; bn_int ticks; /* is it really? */ bn_int sessionkey; bn_int password_hash2[5]; /* player name */ } PACKED_ATTR() t_client_loginreq2; /******************************************************/ /******************************************************/ /* # 21 packet from client: type=0x46ff(unknown) length=8 class=bnet 0000: FF 46 08 00 00 00 00 00 .F...... */ #define CLIENT_MOTD_W3 0x46ff typedef struct { t_bnet_header h; bn_int last_news_time; /* date of the last news item the client has */ } PACKED_ATTR() t_client_motd_w3; /******************************************************/ /******************************************************/ /* # 22 packet from server: type=0x46ff(unknown) length=225 class=bnet 0000: FF 46 E1 00 01 16 3A 6C 3C FF FF FF FF 00 00 00 .F....:l<....... 0010: 00 00 00 00 00 57 65 6C 63 6F 6D 65 20 74 6F 20 .....Welcome to 0020: 42 61 74 74 6C 65 2E 6E 65 74 21 0A 54 68 69 73 Battle.net!.This 0030: 20 73 65 72 76 65 72 20 69 73 20 68 6F 73 74 65 server is hoste 0040: 64 20 62 79 20 41 54 26 54 2E 0A 54 68 65 72 65 d by AT&T..There 0050: 20 61 72 65 20 63 75 72 72 65 6E 74 6C 79 20 36 are currently 6 0060: 32 38 20 75 73 65 72 73 20 70 6C 61 79 69 6E 67 28 users playing 0070: 20 31 35 39 20 67 61 6D 65 73 20 6F 66 20 57 61 159 games of Wa 0080: 72 63 72 61 66 74 20 49 49 49 2C 20 61 6E 64 20 rcraft III, and 0090: 31 37 37 33 34 36 20 75 73 65 72 73 20 70 6C 61 177346 users pla 00A0: 79 69 6E 67 20 37 37 38 33 37 20 67 61 6D 65 73 ying 77837 games 00B0: 20 6F 6E 20 42 61 74 74 6C 65 2E 6E 65 74 2E 0A on Battle.net.. 00C0: 4C 61 73 74 20 6C 6F 67 6F 6E 3A 20 54 68 75 20 Last logon: Thu 00D0: 46 65 62 20 31 34 20 20 35 3A 32 38 20 50 4D 0A Feb 14 5:28 PM. 00E0: 00 . # Match 4, 2002 # 92 packet from server: type=0x46ff(unknown) length=859 class=bnet 0000: FF 46 5B 03 01 B4 B2 82 3C 20 B6 83 3C 20 B6 83 .F[.....< ..< .. 0010: 3C 20 B6 83 3C 57 65 20 68 61 76 65 20 62 65 65 < .. ws-2-11.1038: P 190:262(72) ack 272 win 65264 ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** FF 53 48 00 00 00 00 00 .SH..... 4B A8 FF 5D 1E 5D 2D 50 D1 2B B2 95 74 AD 5F 4E K..].]-P.+..t._N 88 A4 88 48 18 27 89 50 F1 AA 1B D5 D7 B6 47 BC ...H.'.P......G. 30 8B 2A 54 AA 99 23 96 75 8A 5E 67 35 8E 5B 22 0.*T..#.u.^g5.[" 2C 0E 68 2E C2 95 E9 D7 A1 82 F1 2C 1E 2B 28 36 ,.h........,.+(6 */ #define SERVER_LOGINREPLY_W3 0x53ff typedef struct { t_bnet_header h; bn_int message; /* seems to be response to client-challenge */ bn_int unknown[16]; } PACKED_ATTR() t_server_loginreply_w3; #define SERVER_LOGINREPLY_W3_MESSAGE_SUCCESS 0x00000000 #define SERVER_LOGINREPLY_W3_MESSAGE_ALREADY 0x00000001 /* Account already logged on */ #define SERVER_LOGINREPLY_W3_MESSAGE_BADACCT 0x00000001 /* Accoutn does not exist */ /******************************************************/ /******************************************************/ /* single player crack based: # 34 packet from server: type=0x54ff(unknown) length=40 class=bnet 0000: FF 54 28 00 00 00 00 00 00 00 00 00 00 00 00 00 .T(............. 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0020: 00 00 00 00 00 00 00 00 ........ * Password Checksum ? * -- client -- 0x54ff - 2 bytes size - 2 bytes (0x0018) unknown1 - 20 bytes -- server -- 0x54ff - 2 bytes size - 2 bytes msgid - 4 bytes { 0x00000000 accept 0x00000002 password incorrect } unknown1 - 20 bytes Packet #13 0x0000 FF 54 1C 00 00 00 00 00-3A D5 B9 B1 2B D9 B5 D9 ÿT......:Õ¹?Ùµ? 0x0010 87 3B 2B 3D 28 57 C0 2E-02 93 5F 8B ?+=(W?.“_? */ #define CLIENT_LOGONPROOFREQ 0x54ff typedef struct { t_bnet_header h; bn_int password_hash1[5]; } PACKED_ATTR() t_client_logonproofreq; #define SERVER_LOGONPROOFREPLY 0x54ff typedef struct { t_bnet_header h; bn_int response; bn_int unknown1; bn_short port0; bn_int unknown2; bn_short port1; bn_int unknown3; bn_int unknown4; } PACKED_ATTR() t_server_logonproofreply; #define SERVER_LOGONPROOFREPLY_RESPONSE_OK 0x00000000 /*#define SERVER_LOGONPROOFREPLY_RESPONSE_BADPASS 0x00000001 */ #define SERVER_LOGONPROOFREPLY_RESPONSE_BADPASS 0x00000002 /* from the battle net dump... */ #define SERVER_LOGONPROOFREPLY_RESPONSE_EMAIL 0x0000000E #define SERVER_LOGONPROOFREPLY_UNKNOWN1 0x02825278 #define SERVER_LOGONPROOFREPLY_UNKNOWN2 0x00000000 #define SERVER_LOGONPROOFREPLY_UNKNOWN3 0x02825278 #define SERVER_LOGONPROOFREPLY_UNKNOWN4 0x00000000 /******************************************************/ /******************************************************/ /* # 13 packet from client: type=0x52ff(unknown) length=83 class=bnet 0000: FF 52 53 00 2B 63 B9 05 CA F3 E1 BA 58 5C ED 65 .RS.+c......X\.e 0010: BE 8F 0E 89 A9 B8 C7 FE 75 2C 44 10 AE 19 B5 14 ........u,D..... 0020: E8 CA E9 C7 37 50 7D 0F 9A 89 00 FF 2F 10 BB EE ....7P}...../... 0030: A8 0C 81 64 AD AF DC C7 3F 58 F1 20 A1 05 E2 38 ...d....?X. ...8 0040: 18 87 85 5B 74 68 65 61 63 63 6F 75 6E 74 6E 61 ...[theaccountna 0050: 6D 65 00 me. */ #define CLIENT_CREATEACCOUNT_W3 0x52ff typedef struct { t_bnet_header h; bn_byte unknown[64]; /* player name */ } PACKED_ATTR() t_client_createaccount_w3; /******************************************************/ /******************************************************/ /******************************************************/ /* # 20 packet from client: type=0x45ff(unknown) length=6 class=bnet 0000: FF 45 06 00 E0 17 .E.... */ #define CLIENT_CHANGEGAMEPORT 0x45ff typedef struct { t_bnet_header h; bn_short port; } PACKED_ATTR() t_client_changegameport; /******************************************************/ /* RECV-> 0000 FF 52 08 00 00 00 00 00 .R...... */ #define SERVER_CREATEACCOUNT_W3 0x52ff typedef struct { t_bnet_header h; bn_int result; } PACKED_ATTR() t_server_createaccount_w3; #define SERVER_CREATEACCOUNT_W3_RESULT_OK 0x00000000 #define SERVER_CREATEACCOUNT_W3_RESULT_EXIST 0x00000004 #define SERVER_CREATEACCOUNT_W3_RESULT_EMPTY 0x00000007 #define SERVER_CREATEACCOUNT_W3_RESULT_INVALID 0x00000008 #define SERVER_CREATEACCOUNT_W3_RESULT_BANNED 0x00000009 #define SERVER_CREATEACCOUNT_W3_RESULT_SHORT 0x0000000A #define SERVER_CREATEACCOUNT_W3_RESULT_PUNCTUATION 0x0000000B #define SERVER_CREATEACCOUNT_W3_RESULT_PUNCTUATION2 0x0000000C /******************************************************/ /******************************************************/ /* FF 3A 08 00 00 00 00 00 .:...... */ #define SERVER_LOGINREPLY2 0x3aff typedef struct { t_bnet_header h; bn_int message; } PACKED_ATTR() t_server_loginreply2; #define SERVER_LOGINREPLY2_MESSAGE_SUCCESS 0x00000000 #define SERVER_LOGINREPLY2_MESSAGE_NONEXIST 0x00000001 /* Account does not exists */ #define SERVER_LOGINREPLY2_MESSAGE_BADPASS 0x00000002 /* Bad password */ #define SERVER_LOGINREPLY2_MESSAGE_LOCKED 0x00000006 /* Account is locked */ /******************************************************/ /******************************************************/ /* Diablo II 1.03 */ /* sent when registering new player with open Battle.net */ /* and when logging in with closed Battle.net */ /* (closed) b.net login: enter name/password -> 3dff packet (open) b.net login: enter name/password -> "login" packet (bad account) <-- CORRECT "Create new account" -> TOS grab -> Enter password -> 3dff packet */ /* FF 3D 20 00 B8 C0 A1 2F 56 B1 47 65 CF 55 09 62 .= ..../V.Ge.U.b 8E 21 3C 59 57 BC E8 EA 45 6C 66 6C 6F 72 64 00 .!= 1.10: * "%s %u %u %u %u %u %u %u %u %u %s" * client tag (RATS, PXES, RHSS) * rating * number (ladder rank) * stars (normal wins) * spawned (1 of spawned, 0 otherwise) * unknown4 (always zero?) * highest ladder rating * unknown6 (always zero?) * unknown7 (always zero?) * icon tag (usually client tag) * * for DRTL: * "%s %u %u %u %u %u %u %u %u %u" * client tag (LTRD) * level * class (0==warrior, 1==rogue, 2==sorcerer) * dots (times killed diablo) * strength * magic * dexterity * vitality * gold * unknown2 (always zero?) * * for D2DV: * "%s%s,%s," * client tag (VD2D) * realm * character name * 43 unknown bytes */ #define PLAYERINFO_DRTL_CLASS_WARRIOR 0 #define PLAYERINFO_DRTL_CLASS_ROGUE 1 #define PLAYERINFO_DRTL_CLASS_SORCERER 2 /******************************************************/ /******************************************************/ #define CLIENT_PROGIDENT2 0x0bff typedef struct { t_bnet_header h; bn_int clienttag; } PACKED_ATTR() t_client_progident2; /******************************************************/ /******************************************************/ #define CLIENT_JOINCHANNEL 0x0cff typedef struct { t_bnet_header h; bn_int channelflag; } PACKED_ATTR() t_client_joinchannel; #define CLIENT_JOINCHANNEL_NORMAL 0x00000000 #define CLIENT_JOINCHANNEL_GENERIC 0x00000001 #define CLIENT_JOINCHANNEL_CREATE 0x00000002 /******************************************************/ /******************************************************/ #define SERVER_CHANNELLIST 0x0bff typedef struct { t_bnet_header h; /* channel names */ } PACKED_ATTR() t_server_channellist; /******************************************************/ /******************************************************/ /* We don't use this for now. It makes the client put the list of IPs/hostnames into the registry. FF 04 8F 00 00 00 00 00 32 30 39 2E 36 37 2E 31 ........209.67.1 33 36 2E 31 37 34 3B 32 30 37 2E 36 39 2E 31 39 36.174;207.69.19 34 2E 32 31 30 3B 32 30 37 2E 36 39 2E 31 39 34 4.210;207.69.194 2E 31 38 39 3B 32 31 36 2E 33 32 2E 37 33 2E 31 .189;216.32.73.1 37 34 3B 32 30 39 2E 36 37 2E 31 33 36 2E 31 37 74;209.67.136.17 31 3B 32 30 36 2E 37 39 2E 32 35 34 2E 31 39 32 1;206.79.254.192 3B 32 30 37 2E 31 33 38 2E 33 34 2E 33 3B 32 30 ;207.138.34.3;20 39 2E 36 37 2E 31 33 36 2E 31 37 32 3B 65 78 6F 9.67.136.172;exo 64 75 73 2E 62 61 74 74 6C 65 2E 6E 65 74 00 dus.battle.net. */ #define SERVER_SERVERLIST 0x04ff typedef struct { t_bnet_header h; bn_int unknown1; /* 00 00 00 00 */ /* list */ } PACKED_ATTR() t_server_serverlist; #define SERVER_SERVERLIST_UNKNOWN1 0x00000000 /******************************************************/ /******************************************************/ /* FF 0F 30 00 01 00 00 00 00 00 00 00 00 00 00 00 ..0............. 00 00 00 00 00 00 00 00 00 00 00 00 52 6F 73 73 ............Ross 00 52 41 54 53 20 30 20 30 20 30 20 30 20 30 00 .RATS 0 0 0 0 0. FF 0F 38 00 07 00 00 00 21 00 00 00 64 00 00 00 ..8.....!...d... 00 00 00 00 D8 94 F6 07 B3 2C 6E 02 4D 6F 4E 6B .........,n.MoNk 32 6B 00 44 69 61 62 6C 6F 20 49 49 20 42 65 74 2k.Diablo II Bet 61 57 65 73 74 2D 31 00 aWest-1. MT_ADD: 0x0000: ff 0a 53 00 4d 6f 4e 6b 32 6b 00 56 44 32 44 42 ..S.MoNk2k.VD2DB 0x0010: 65 74 61 57 65 73 74 2c 4d 6f 4e 6b 2d 65 65 2c etaWest,MoNk-ee, 0x0020: 83 80 06 01 01 01 01 ff 4c ff 02 02 ff ff ff ff ........L....... 0x0030: ff ff 01 ff 48 48 48 48 ff a6 ff 48 48 ff ff ff ....HHHH...HH... 0x0040: ff ff ff 10 80 80 80 80 ff ff ff 00 4d 6f 4e 6b ............MoNk 0x0050: 32 6b 00 ff 0f 38 00 07 00 00 00 21 00 00 00 6d 2k...8.....!...m 0x0060: 00 00 00 00 00 00 00 d8 94 f6 08 a4 46 6e 02 4d ............Fn.M 0x0070: 6f 4e 6b 32 6b 00 44 69 61 62 6c 6f 20 49 49 20 oNk2k.Diablo II 0x0080: 42 65 74 61 57 65 73 74 2d 31 00 ff 0f 62 00 01 BetaWest-1...b.. 0x0090: 00 00 00 00 00 00 00 28 00 00 00 00 00 00 00 d8 .......(........ 0x00a0: 94 f6 07 69 fb 6d 02 4e 6f 72 62 62 6f 00 56 44 ...i.m.Norbbo.VD 0x00b0: 32 44 42 65 74 61 57 65 73 74 2c 44 6f 6f 73 68 2DBetaWest,Doosh 0x00c0: 2c 87 80 05 02 01 01 01 2b ff 1b 02 02 ff ff ff ,.......+....... 0x00d0: ff ff ff 03 ff ff ff ff ff ff ff ff ff ff ff ff ................ 0x00e0: ff ff ff ff 0a 80 80 80 80 ff ff ff 00 ff 0f 65 ...............e 0x00f0: 00 01 00 00 00 00 00 00 00 32 00 00 00 00 00 00 .........2...... 0x0100: 00 d8 94 f6 07 23 00 6e 02 6e 6a 67 6f 61 6c 69 .....#.n.njgoali 0x0110: 65 00 56 44 32 44 42 65 74 61 57 65 73 74 2c 73 e.VD2DBetaWest,s 0x0120: 68 65 69 6b 61 2c 83 80 05 02 01 02 02 ff 4c ff heika,........L. 0x0130: 02 02 ff ff ff ff ff ff 02 ff ff ff ff ff ff ff ................ 0x0140: ff ff ff ff ff ff ff ff ff 09 80 80 80 80 ff ff ................ 0x0150: ff 00 ff 0f 67 00 01 00 00 00 00 00 00 00 1f 00 ....g........... 0x0160: 00 00 00 00 00 00 d8 94 f6 09 eb 24 6e 02 72 6f ...........$n.ro 0x0170: 62 6d 6d 73 64 00 56 44 32 44 42 65 74 61 57 65 bmmsd.VD2DBetaWe 0x0180: 73 74 2c 56 61 6e 63 6f 75 76 65 72 2c 83 80 05 st,Vancouver,... 0x0190: 02 02 01 01 30 ff 1b 02 02 ff ff ff ff ff ff 04 ....0........... 0x01a0: 4f ff ff ff ff ff ff a9 ff ff ff ff ff ff ff ff O............... 0x01b0: 09 80 80 80 80 ff ff ff 00 ff 0f 62 00 01 00 00 ...........b.... 0x01c0: 00 00 00 00 00 6e 00 00 00 00 00 00 00 ce 4f fe .....n........O. 0x01d0: c0 f9 02 15 01 4c 79 63 74 68 69 73 00 56 44 32 .....Lycthis.VD2 0x01e0: 44 42 65 74 61 57 65 73 74 2c 45 6c 6c 65 2c 83 DBetaWest,Elle,. 0x01f0: 80 04 02 01 01 01 ff 4d ff 02 02 ff ff ff ff ff .......M........ 0x0200: ff 01 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 0x0210: ff ff 06 80 80 80 80 ff ff ff 00 ff 0f 6b 00 01 .............k.. 0x0220: 00 00 00 00 00 00 00 19 01 00 00 00 00 00 00 ce ................ 0x0230: 4f fe c1 e2 1b 9c 00 52 6f 62 4d 69 74 63 68 65 O......RobMitche 0x0240: 6c 6c 00 56 44 32 44 42 65 74 61 57 65 73 74 2c ll.VD2DBetaWest, 0x0250: 53 6f 6f 6e 65 72 64 65 64 2c 83 80 06 02 02 01 Soonerded,...... 0x0260: 01 46 46 ff 02 02 ff ff ff ff ff ff 05 ff ff ff .FF............. 0x0270: ff ff ff 29 ff ff ff ff ff ff ff ff ff 11 80 82 ...)............ 0x0280: 80 80 ff ff ff 00 ff 0f 66 00 01 00 00 00 00 00 ........f....... 0x0290: 00 00 bc 00 00 00 00 00 00 00 d8 94 f6 09 8f 3f ...............? 0x02a0: 6e 02 4d 61 72 6c 6f 63 6b 31 00 56 44 32 44 42 n.Marlock1.VD2DB 0x02b0: 65 74 61 57 65 73 74 2c 6d 61 72 6c 6f 63 6b 2c etaWest,marlock, 0x02c0: 83 80 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 0x02d0: ff ff 05 ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 0x02e0: ff ff ff 01 80 80 80 80 ff ff ff 00 ff 0f 63 00 ..............c. 0x02f0: 01 00 00 00 00 00 00 00 c8 00 00 00 00 00 00 00 ................ 0x0300: d1 43 88 aa bd ce 3c 00 42 2d 57 61 74 74 7a 00 .C....<.B-Wattz. From bnetd-0.4.23pre18 to Diablo II 1.03 FF 0F 69 00 09 00 00 00 00 00 00 00 12 00 I@..i... ........ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 45 6C ........ ......El 66 6C 6F 72 64 00 56 44 32 44 51 61 72 61 74 68 flord.VD 2DQarath 52 65 61 6C 6D 2C 46 61 6B 65 43 68 61 72 2C 83 Realm,Fa keChar,. 80 FF FF FF FF FF 2F FF FF FF FF FF FF FF FF FF ....../. ........ FF 03 FF FF FF FF FF FF FF FF FF FF FF FF FF FF ........ ........ FF FF 07 80 80 80 80 FF FF FF 00 ........ ... */ #define SERVER_MESSAGE 0x0fff typedef struct { t_bnet_header h; bn_int type; bn_int flags; /* player flags (or channel flags for MT_CHANNEL) */ bn_int latency; bn_int player_ip; /* always zero? */ bn_int account_num; /* player's IP (big endian), no longer used, always 0D F0 AD BA */ bn_int reg_auth; /* server ip and/or reg auth? CD key and/or account number? */ /* player name */ /* text */ } PACKED_ATTR() t_server_message; #define SERVER_MESSAGE_PLAYER_IP_DUMMY 0x00000000 /* nok */ #define SERVER_MESSAGE_REG_AUTH 0xBAADF00D /* 0D F0 AD BA */ /* #define SERVER_MESSAGE_REG_AUTH 0x07f694d8 */ #define SERVER_MESSAGE_ACCOUNT_NUM 0x0df0adba /* For MT_ADD, MT_JOIN, the text portion looks like: * * for STAR, SEXP, SSHR: * "%4c %u %u %u %u %u" * client tag (RATS, PXES, RHSS) * rating * number (ladder rank) * stars (normal wins) * unknown3 (always zero?) * unknown4 (always zero?) * * for DRTL: * "%4c %u %u %u %u %u %u %u %u %u" * client tag (LTRD) FIXME: RHSD? * level * class (0==warrior, 1==rogue, 2==sorcerer) * dots (times killed diablo) * strength * magic * dexterity * vitality * gold * unknown2 (always zero?) * * for CHAT: * FIXME: ??? "%4c" * client tag (TAHC) * * FIXME: Warcraft II? * * for D2DV: * open: * "%4c" * client tag (VD2D) * closed: * "%4c%s,%s,%s" * client tag (VD2D) * realm name * character name * character info */ #define SERVER_MESSAGE_TYPE_ADDUSER 0x00000001 /* ADD,USER,SHOWUSER */ #define SERVER_MESSAGE_TYPE_JOIN 0x00000002 #define SERVER_MESSAGE_TYPE_PART 0x00000003 /* LEAVE */ #define SERVER_MESSAGE_TYPE_WHISPER 0x00000004 #define SERVER_MESSAGE_TYPE_TALK 0x00000005 /* MESSAGE */ #define SERVER_MESSAGE_TYPE_BROADCAST 0x00000006 #define SERVER_MESSAGE_TYPE_CHANNEL 0x00000007 /* JOINING */ /* unused? 0x00000008 */ #define SERVER_MESSAGE_TYPE_USERFLAGS 0x00000009 #define SERVER_MESSAGE_TYPE_WHISPERACK 0x0000000a /* WHISPERSENT */ /* unused? 0x0000000b */ /* unused? 0x0000000c */ #define SERVER_MESSAGE_TYPE_CHANNELFULL 0x0000000d #define SERVER_MESSAGE_TYPE_CHANNELDOESNOTEXIST 0x0000000e #define SERVER_MESSAGE_TYPE_CHANNELRESTRICTED 0x0000000f /* unused? 0x00000010 */ /* unused? 0x00000011 */ #define SERVER_MESSAGE_TYPE_INFO 0x00000012 #define SERVER_MESSAGE_TYPE_ERROR 0x00000013 /* unused? 0x00000014 */ /* unused? 0x00000015 */ /* unused? 0x00000016 */ #define SERVER_MESSAGE_TYPE_EMOTE 0x00000017 /****** Player Flags ******/ /* flag bits for above struct */ /* ADDED BY UNDYING SOULZZ 4/7/02 */ #define W3_ICON_SET 0x00000000 #define MAX_STR_RACELEN 20 #define MAX_STR_ACCTPASSLEN 10 #define W3_RACE_RANDOM 32 #define W3_RACE_HUMANS 1 #define W3_RACE_ORCS 2 #define W3_RACE_UNDEAD 8 #define W3_RACE_NIGHTELVES 4 #define W3_RACE_DEMONS 16 #define W3_ICON_RANDOM 0 /* - Although when client presses random in PG and it sends "32" its "0" for icon */ #define W3_ICON_HUMANS 1 #define W3_ICON_ORCS 2 #define W3_ICON_UNDEAD 3 /* - Although when client presses undead in PG and it sends "8" its "3" for icon */ #define W3_ICON_NIGHTELVES 4 #define W3_ICON_DEMONS 5 /* Icon setup 3RAW then */ /* Races: 1 = human, 2 = orc, 8 = undead, 4 = nightelf 32 = random */ /* Misc icons are 6-9 * - There might be some icons not defined*/ /* If you find them let us know pse, forums.cheatlist.com in War3 Hacking/Development */ /*Human Icons*/ #define W3_ICON_HUMAN_FOOTMAN "3RAW 1 1 11" #define W3_ICON_HUMAN_KNIGHT "3RAW 1 1 100" #define W3_ICON_HUMAN_ARCHMAGE "3RAW 1 1 250" #define W3_ICON_HUMAN_HERO "3RAW 1 1 1000" /*Orc Icons*/ #define W3_ICON_ORC_PEON "3RAW 1 2 00" /* default icon , unless u change it in code*/ #define W3_ICON_ORC_GRUNT "3RAW 1 2 10" #define W3_ICON_ORC_TAUREN "3RAW 1 2 100" #define W3_ICON_ORC_FARSEER "3RAW 1 2 250" #define W3_ICON_ORC_HERO "3RAW 1 2 1000" /*Undead Icons*/ #define W3_ICON_UNDEAD_GHOUL "3RAW 1 3 10" #define W3_ICON_UNDEAD_ABOM "3RAW 1 3 100" #define W3_ICON_UNDEAD_LICH "3RAW 1 3 250" #define W3_ICON_UNDEAD_HERO "3RAW 1 3 1000" /*Night Elf Icons*/ #define W3_ICON_ELF_ARCHER "3RAW 1 4 10" #define W3_ICON_ELF_DRUIDCLAW "3RAW 1 4 100" #define W3_ICON_ELF_PRIESMOON "3RAW 1 4 250" #define W3_ICON_ELF_HERO "3RAW 1 4 1000" /*Random Icons , like NPC's, Creeps*/ #define W3_ICON_RANDOM_GREENDRAGON "3RAW 1 9 10" #define W3_ICON_RANDOM_BLACKDRAGON "3RAW 1 9 100" #define W3_ICON_RANDOM_REDDRAGON "3RAW 1 9 250" #define W3_ICON_RANDOM_BLUEDRAGON "3RAW 1 9 1000" /* End of Undying Edits */ /* Blizzard Entertainment employee */ #define MF_BLIZZARD 0x00000001 /* blue Blizzard logo */ /* Channel operator */ #define MF_GAVEL 0x00000002 /* gavel */ /* Speaker in moderated channel */ #define MF_VOICE 0x00000004 /* megaphone */ /* System operator */ #define MF_BNET 0x00000008 /* (old: blue Blizzard, new: green b.net) or red BNETD logo */ /* Chat bot or other user without UDP support */ #define MF_PLUG 0x00000010 /* tiny plug to right of icon, no UDP */ /* Squelched/Ignored user */ #define MF_X 0x00000020 /* big red X */ /* Special guest of Blizzard Entertainment */ #define MF_SHADES 0x00000040 /* sunglasses */ /* unused 0x00000080 */ /* Use BEL character in error codes. Some bots use it as a flag. Battle.net */ /* stopped supporting it recently. */ #define MF_BEEP 0x00000100 /* no change in icon */ /* Registered Professional Gamers League player */ #define MF_PGLPLAY 0x00000200 /* PGL player logo */ /* Registered Professional Gamers League official */ #define MF_PGLOFFL 0x00000400 /* PGL official logo */ /* Registered KBK player */ #define MF_KBKPLAY 0x00000800 /* KBK player logo */ /* Official KBK Referee */ #define MF_KBKREF 0x00001000 /* KBK referee logo */ /* FIXME: this number may be wrong */ /* unused... FIXME: how many bits work? 16 or 32? */ /****** Channel Flags ******/ /* flag bits for MT_CHANNEL message */ #define CF_PUBLIC 0x00000001 /* public channel */ #define CF_MODERATED 0x00000002 /* moderated channel */ #define CF_RESTRICTED 0x00000004 /* ? restricted channel ? */ #define CF_THEVOID 0x00000008 /* "The Void" */ #define CF_SYSTEM 0x00000020 /* system channel */ #define CF_OFFICIAL 0x00001000 /* official channel */ /* * Examples: * 0x00001003 Blizzard Tech Support * 0x00001001 Open Tech Support * 0x00000021 Diablo II USA-1 or War2BNE USA-1 * 0x0000000D warez * 0x00000009 The Void * 0x00000001 War2 Ladder Challenges or Diablo II PvP * 0x00000000 clan randomchannel * 0x00000000 randomchannel */ /******************************************************/ /******************************************************/ #define CLIENT_MESSAGE 0x0eff typedef struct { t_bnet_header h; /* text */ } PACKED_ATTR() t_client_message; /******************************************************/ /******************************************************/ /* FF 09 17 00 03 00 00 00 FF FF 00 00 00 00 00 00 ................ 19 00 00 00 00 00 00 ....... FF 09 24 00 00 00 00 00 00 00 00 00 00 00 00 00 ..$............. 01 00 00 00 4C 61 64 64 65 72 20 31 20 6F 6E 20 ....Ladder 1 on 31 00 00 00 1... */ #define CLIENT_GAMELISTREQ 0x09ff typedef struct { t_bnet_header h; bn_short gametype; bn_short unknown1; bn_int unknown2; bn_int unknown3; bn_int maxgames; /* game name */ } PACKED_ATTR() t_client_gamelistreq; #define CLIENT_GAMELISTREQ_ALL 0x0000 #define CLIENT_GAMELISTREQ_MELEE 0x0002 #define CLIENT_GAMELISTREQ_FFA 0x0003 #define CLIENT_GAMELISTREQ_ONEONONE 0x0004 #define CLIENT_GAMELISTREQ_CTF 0x0005 #define CLIENT_GAMELISTREQ_GREED 0x0006 #define CLIENT_GAMELISTREQ_SLAUGHTER 0x0007 #define CLIENT_GAMELISTREQ_SDEATH 0x0008 #define CLIENT_GAMELISTREQ_LADDER 0x0009 #define CLIENT_GAMELISTREQ_IRONMAN 0x0010 #define CLIENT_GAMELISTREQ_MAPSET 0x000a #define CLIENT_GAMELISTREQ_TEAMMELEE 0x000b #define CLIENT_GAMELISTREQ_TEAMFFA 0x000c #define CLIENT_GAMELISTREQ_TEAMCTF 0x000d #define CLIENT_GAMELISTREQ_PGL 0x000e #define CLIENT_GAMELISTREQ_TOPVBOT 0x000f #define CLIENT_GAMELISTREQ_DIABLO 0x0409 /* FIXME: this should be the langid */ #define CLIENT_GAMELISTREQ_LOADED 0x0a00 /* FIXME: Diablo reports differently than it is listed in GAMELIST */ #define CLIENT_GAMETYPE_DIABLO_0 0x00000000 /* Level 1 Char */ #define CLIENT_GAMETYPE_DIABLO_1 0x00000001 /* Level 2 Char */ #define CLIENT_GAMETYPE_DIABLO_2 0x00000002 /* Level ? Char */ #define CLIENT_GAMETYPE_DIABLO_3 0x00000003 /* Level 4 Char */ #define CLIENT_GAMETYPE_DIABLO_4 0x00000004 /* Level ? Char */ #define CLIENT_GAMETYPE_DIABLO_5 0x00000005 /* Level ? Char */ #define CLIENT_GAMETYPE_DIABLO_6 0x00000006 /* Level ? Char */ #define CLIENT_GAMETYPE_DIABLO_7 0x00000007 /* Level ? Char */ #define CLIENT_GAMETYPE_DIABLO_8 0x00000008 /* Level 20-24 Char */ #define CLIENT_GAMETYPE_DIABLO_9 0x00000009 /* Level 25-? Char */ #define CLIENT_GAMETYPE_DIABLO_a 0x0000000a /* Level ? Char */ #define CLIENT_GAMETYPE_DIABLO_b 0x0000000b /* Level ? Char */ #define CLIENT_GAMETYPE_DIABLO_c 0x0000000c /* Level ? Char */ #define CLIENT_GAMETYPE_DIABLO_d 0x0000000d /* Level ? Char */ /* list might continue - what is maximum diablo level ? */ /* FIXME: Not sure how Diablo II does things yet */ #define CLIENT_GAMETYPE_DIABLO2_CLOSE 0x00000000 /* close game */ #define CLIENT_GAMETYPE_DIABLO2_OPEN_NORMAL 0X00000008 /* open, normal difficulty */ #define CLIENT_GAMETYPE_DIABLO2_OPEN_NIGHTMARE 0X00000009 /* open, nightmare difficulty */ #define CLIENT_GAMETYPE_DIABLO2_OPEN_HELL 0X0000000a /* open, hell difficulty */ /******************************************************/ /******************************************************/ /* FF 09 35 00 01 00 00 00 00 00 00 00 03 00 01 00 ..5............. 00 00 00 00 02 00 17 E0 80 7B 4F 0D 00 00 00 00 .........{O..... 00 00 00 00 04 00 00 00 64 00 00 00 4D 79 47 61 ........d...MyGa 6D 65 00 00 00 me... FF 09 5B 00 01 00 00 00 00 00 00 00 03 00 01 00 ..[............. 02 00 17 E0 80 7B 4F 0D 00 00 00 00 00 00 00 00 .....{O......... 04 00 00 00 2B 00 00 00 47 61 6D 65 00 50 61 73 ....+...Game.Pas 73 00 2C 33 34 2C 31 32 2C 35 2C 31 2C 33 2C 31 s.,34,12,5,1,3,1 2C 63 63 63 33 36 34 30 36 2C 2C 42 6F 62 0D 43 ,ccc36406,,Bob.C 68 61 6C 6C 65 6E 67 65 72 0D 00 hallenger.. FF 09 D4 03 0A 00 00 00 0C 00 00 00 09 04 00 00 ................ 02 00 17 E0 CD E8 B5 E1 00 00 00 00 00 00 00 00 ................ 00 00 00 00 3C 00 00 00 4A 65 73 73 65 27 73 20 ....<...Jesse's 57 6F 72 6C 64 00 00 32 0D 4C 69 7A 7A 69 65 2E World..2.Lizzie. 42 6F 72 64 65 6E 0D 4C 54 52 44 20 34 30 20 31 Borden.LTRD 40 1 20 33 20 31 32 31 20 31 32 36 20 33 30 36 20 31 3 121 126 306 1 33 36 20 35 34 37 30 32 20 30 00 ... FF 09 70 00 01 00 00 00 0F 00 04 00 09 04 00 00 ..p............. 02 00 17 E0 C6 0B 13 3C 00 00 00 00 00 00 00 00 .......<........ 04 00 00 00 C5 00 00 00 4C 61 64 64 65 72 20 31 ........Ladder 1 20 6F 6E 20 31 00 00 2C 2C 2C 36 2C 32 2C 66 2C on 1..,,,6,2,f, 34 2C 66 63 63 35 38 65 34 61 2C 37 32 30 30 2C 4,fcc58e4a,7200, 49 63 65 36 39 62 75 72 67 0D 46 6F 72 65 73 74 Ice69burg.Forest 20 54 72 61 69 6C 20 42 4E 45 2E 70 75 64 0D 00 Trail BNE.pud.. # war3 # 66 packet from server: type=0x09ff(SERVER_GAMELISTREPLY) length=131 class=bnet 0000: FF 09 83 00 01 00 00 00 01 00 00 00 09 04 00 00 ................ 0010: 02 00 17 E0 18 CF BF 9B 00 00 00 00 00 00 00 00 ................ 0020: 10 00 00 00 0F 00 00 00 33 20 6F 6E 20 33 20 64 ........3 on 3 d 0030: 61 72 6B 20 66 6F 72 65 73 74 00 00 35 31 30 30 ark forest..5100 0040: 30 30 30 30 30 01 03 01 01 81 01 81 01 73 27 25 00000........s'% 0050: 15 29 4D 61 71 53 73 5D 63 65 75 61 5D A9 29 37 .)MaqSs]ceua].)7 0060: 29 45 61 73 6B 69 21 47 6F 73 65 73 75 DD 2F 77 )Easki!Gosesu./w 0070: 33 6D 01 4B 61 D7 69 73 69 69 6F 5B 53 07 4B 5D 3m.Ka.isiio[S.K] 0080: 01 01 00 ... [23:32] <@nok-> 0000: FF 09 E9 01 04 00 00 00 01 00 00 00 09 04 00 00 ................ [23:32] <@nok-> 0010: 02 00 17 E0 40 69 1B 07 00 00 00 00 00 00 00 00 ....@i.......... 0000: FF 09 7A 01 03 00 00 00 01 00 00 00 09 04 00 00 ..z............. 0010: 02 00 17 E0 18 2C 7E 7B 00 00 00 00 00 00 00 00 .....,~{........ 0020: 10 00 00 00 09 00 00 00 34 20 6F 6E 20 34 20 4D ........4 on 4 M 0030: 69 73 74 00 00 37 31 30 30 30 30 30 30 30 01 03 ist..710000000.. 0040: 01 01 89 01 89 01 75 4D 7B 27 A1 4D 61 71 53 73 ......uM{'.MaqSs 0050: 5D 63 65 75 61 5D B9 29 39 29 47 6F 6D 65 17 6D ]ceua].)9)Gome.m 0060: 73 21 69 6F 21 75 75 69 65 21 4D 69 73 75 1D 2F s!io!uuie!Misu./ 0070: 77 33 6D 01 51 73 BB 69 6F 63 65 2D 4D 75 17 63 w3m.Qs.ioce-Mu.c 0080: 69 67 65 73 01 01 00 01 00 00 00 09 04 00 00 02 iges............ */ #define SERVER_GAMELISTREPLY 0x09ff typedef struct { t_bnet_header h; bn_int gamecount; bn_int sstatus; /* when reply with error to specific game */ /* games */ } PACKED_ATTR() t_server_gamelistreply; #define SERVER_GAMELISTREPLY_GAME_SSTATUS_NOTFOUND 0x0 /* but also any other value diff from the ones bellow */ #define SERVER_GAMELISTREPLY_GAME_SSTATUS_PASS 0x2 /* password incorrect */ #define SERVER_GAMELISTREPLY_GAME_SSTATUS_FULL 0x3 /* game full */ #define SERVER_GAMELISTREPLY_GAME_SSTATUS_STARTED 0x4 /* game started */ #define SERVER_GAMELISTREPLY_GAME_SSTATUS_NOSPAWNCDKEY 0x5 /* trying to use a spawn install join invalid cdkey creator game */ #define SERVER_GAMELISTREPLY_GAME_SSTATUS_LOADED 0x0a00 /* Loaded game */ typedef struct { /* if yak doesn't like this... then the client doesn't also =) (bbf) bn_int unknown7; */ bn_short gametype; bn_short unknown1; /* langid under Diablo... */ bn_short unknown3; /* bn_int deleted; */ /* they changed the structure at one point */ bn_short port; /* big endian byte order... at least they are consistent! */ bn_int game_ip; /* big endian byte order */ bn_int unknown4; bn_int unknown5; /* FIXME: got to figure out where latency is */ bn_int status; bn_int unknown6; /* game name */ /* clear password */ /* info */ } PACKED_ATTR() t_server_gamelistreply_game; #define SERVER_GAMELISTREPLY_GAME_UNKNOWN7 0x00000000 //0x00000409 // 0x0000000c #define SERVER_GAMELISTREPLY_GAME_UNKNOWN1 0x0001 //0x0000 //0x0001 // 0x0000 #define SERVER_GAMELISTREPLY_GAME_UNKNOWN3 0x0002 #define SERVER_GAMELISTREPLY_GAME_UNKNOWN4 0x00000000 #define SERVER_GAMELISTREPLY_GAME_UNKNOWN5 0x00000000 #define SERVER_GAMELISTREPLY_GAME_STATUS_OPEN 0x00000004 #define SERVER_GAMELISTREPLY_GAME_STATUS_FULL 0x00000006 #define SERVER_GAMELISTREPLY_GAME_STATUS_STARTED 0x0000000e #define SERVER_GAMELISTREPLY_GAME_STATUS_DONE 0x0000000c #define SERVER_GAMELISTREPLY_GAME_UNKNOWN6 0x0000002b /* latency? */ #define SERVER_GAMELISTREPLY_TYPE_DIABLO2_OPEN 0x0704 /* open game */ /******************************************************/ /******************************************************/ #define CLIENT_STARTGAME1 0x08ff /* original starcraft or shareware (1.01) */ typedef struct { t_bnet_header h; bn_int status; bn_int unknown3; bn_short gametype; bn_short unknown1; bn_int unknown4; bn_int unknown5; /* game name */ /* game password */ /* game info */ } PACKED_ATTR() t_client_startgame1; /* I have also seen 1,5,7,f */ #define CLIENT_STARTGAME1_STATUSMASK 0x0000000f #define CLIENT_STARTGAME1_STATUS_OPEN 0x00000004 #define CLIENT_STARTGAME1_STATUS_FULL 0x00000006 #define CLIENT_STARTGAME1_STATUS_STARTED 0x0000000e #define CLIENT_STARTGAME1_STATUS_DONE 0x0000000c /******************************************************/ /******************************************************/ /* FF 1B 14 00 02 00 17 E0 80 7B 3F 54 00 00 00 00 .........{?T.... 00 00 00 00 .... */ #define CLIENT_UNKNOWN_1B 0x1bff typedef struct { t_bnet_header h; bn_short unknown1; /* FIXME: This "2" is the same as in the game listings. What do they mean? */ bn_short port; /* big endian byte order */ bn_int ip; /* big endian byte order */ bn_int unknown2; bn_int unknown3; } PACKED_ATTR() t_client_unknown_1b; #define CLIENT_UNKNOWN_1B_UNKNOWN1 0x0002 #define CLIENT_UNKNOWN_1B_UNKNOWN2 0x00000000 #define CLIENT_UNKNOWN_1B_UNKNOWN3 0x00000000 /******************************************************/ /******************************************************/ /* FF 1A 4C 00 01 00 00 00 00 00 00 00 00 00 00 00 ..L............. 0F 00 00 00 00 00 00 00 E0 17 00 00 61 6E 73 00 ............ans. 65 6C 6D 6F 00 30 0D 77 61 72 72 69 6F 72 0D 4C elmo.0.warrior.L 54 52 44 20 31 20 30 20 30 20 33 30 20 31 30 20 TRD 1 0 0 30 10 32 30 20 32 35 20 31 30 30 20 30 00 20 25 100 0. */ #define CLIENT_STARTGAME3 0x1aff /* Starcraft 1.03, Diablo 1.07 */ typedef struct { t_bnet_header h; bn_int status; bn_int unknown3; bn_short gametype; bn_short unknown1; bn_int unknown6; bn_int unknown4; /* port # under Diablo */ bn_int unknown5; /* game name */ /* game password */ /* game info */ } PACKED_ATTR() t_client_startgame3; #define CLIENT_STARTGAME3_STATUSMASK 0x0000000f #define CLIENT_STARTGAME3_STATUS_OPEN1 0x00000001 /* used by Diablo */ #define CLIENT_STARTGAME3_STATUS_OPEN 0x00000004 #define CLIENT_STARTGAME3_STATUS_FULL 0x00000006 #define CLIENT_STARTGAME3_STATUS_STARTED 0x0000000e #define CLIENT_STARTGAME3_STATUS_DONE 0x0000000c /******************************************************/ /******************************************************/ /* FF 1C 49 00 00 00 00 00 00 00 00 00 03 00 01 00 ..I............. 00 00 00 00 00 00 00 00 74 65 61 6D 6D 65 6C 65 ........teammele 65 00 00 2C 2C 2C 2C 31 2C 33 2C 31 2C 33 65 33 e..,,,,1,3,1,3e3 37 61 38 34 63 2C 37 2C 61 6E 73 65 6C 6D 6F 0D 7a84c,7,anselmo. 4F 63 74 6F 70 75 73 0D 00 Octopus.. Brood War 1.04 ladder, disconnect==loss FF 1C 45 00 10 00 00 00 00 00 00 00 09 00 02 00 ..E............. 00 00 00 00 01 00 00 00 54 45 53 54 00 00 2C 34 ........TEST..,4 34 2C 31 34 2C 2C 32 2C 39 2C 32 2C 33 65 33 37 4,14,,2,9,2,3e37 61 38 34 63 2C 33 2C 52 6F 73 73 0D 41 73 68 72 a84c,3,Ross.Ashr 69 67 6F 0D 00 igo.. Brood War 1.04 ladder, disconnect==disconnect FF 1C 45 00 00 00 00 00 00 00 00 00 09 00 01 00 ..E............. 00 00 00 00 01 00 00 00 54 45 53 54 00 00 2C 34 ........TEST..,4 34 2C 31 34 2C 2C 32 2C 39 2C 31 2C 33 65 33 37 4,14,,2,9,1,3e37 61 38 34 63 2C 33 2C 52 6F 73 73 0D 41 73 68 72 a84c,3,Ross.Ashr 69 67 6F 0D 00 igo.. Brood War 1.04 greed, minerals==10000 FF 1C 4C 00 00 00 00 00 00 00 00 00 06 00 04 00 ..L............. 00 00 00 00 00 00 00 00 74 65 73 74 31 30 30 30 ........test1000 30 00 00 2C 33 34 2C 31 32 2C 2C 31 2C 36 2C 34 0..,34,12,,1,6,4 2C 33 65 33 37 61 38 34 63 2C 2C 52 6F 73 73 0D ,3e37a84c,,Ross. 43 68 61 6C 6C 65 6E 67 65 72 0D 00 Challenger.. FF 1C 4F 00 ..O. 00 00 00 00 00 00 00 00 02 00 01 00 1F 00 00 00 ................ 00 00 00 00 74 65 73 74 00 00 2C 34 34 2C 31 34 ....test..,44,14 2C 35 2C 32 2C 32 2C 31 2C 32 31 30 34 62 62 33 ,5,2,2,1,2104bb3 36 2C 34 2C 48 6F 6D 65 72 0D 54 68 65 20 4C 6F 6,4,Homer.The.Lo 73 74 20 54 65 6D 70 6C 65 0D 00 st.Temple.. Diablo II 1.03 (level diff 0) FF 1C 20 00 00 00 00 00 00 00 00 00 00 00 .. ... ........ 00 00 00 00 00 00 00 00 00 00 54 65 73 74 00 00 ........ ..Test.. 31 00 1. */ #define CLIENT_STARTGAME4 0x1cff /* Brood War or newer Starcraft (1.04, 1.05) */ typedef struct { t_bnet_header h; bn_short status; /* 0x0001 - private war3 game */ bn_short flag; bn_int unknown2; /* 00 00 00 00 */ bn_short gametype; bn_short option; /* 01 00 */ bn_int unknown4; /* 00 00 00 00 */ bn_int unknown5; /* 00 00 00 00 */ /* game name */ /* game password */ /* game info */ } PACKED_ATTR() t_client_startgame4; #define CLIENT_STARTGAME4_UNKNOWN2 0x00000000 #define CLIENT_STARTGAME4_STATUSMASK_16 0x000000ff #define CLIENT_STARTGAME4_STATUSMASK_INIT_VALID 0x00000093 #define CLIENT_STARTGAME4_STATUSMASK_OPEN_VALID 0x0000009f #define CLIENT_STARTGAME4_STATUS_INIT 0x00000000 #define CLIENT_STARTGAME4_STATUS_PRIVATE 0x00000001 #define CLIENT_STARTGAME4_STATUS_FULL 0x00000002 #define CLIENT_STARTGAME4_STATUS_OPEN 0x00000004 #define CLIENT_STARTGAME4_STATUS_START 0x00000008 #define CLIENT_STARTGAME4_STATUS_DISC_IS_LOSS 0x00000010 #define CLIENT_STARTGAME4_STATUS_REPLAY 0x00000080 #define CLIENT_STARTGAME4_OPTION_MELEE_NORMAL 0x0001 #define CLIENT_STARTGAME4_OPTION_FFA_NORMAL 0x0001 #define CLIENT_STARTGAME4_OPTION_ONEONONE_NORMAL 0x0001 #define CLIENT_STARTGAME4_OPTION_CTF_NORMAL 0x0001 #define CLIENT_STARTGAME4_OPTION_GREED_10000 0x0004 #define CLIENT_STARTGAME4_OPTION_GREED_7500 0x0003 #define CLIENT_STARTGAME4_OPTION_GREED_5000 0x0002 #define CLIENT_STARTGAME4_OPTION_GREED_2500 0x0001 #define CLIENT_STARTGAME4_OPTION_SLAUGHTER_60 0x0004 #define CLIENT_STARTGAME4_OPTION_SLAUGHTER_45 0x0003 #define CLIENT_STARTGAME4_OPTION_SLAUGHTER_30 0x0002 #define CLIENT_STARTGAME4_OPTION_SLAUGHTER_15 0x0001 #define CLIENT_STARTGAME4_OPTION_SDEATH_NORMAL 0x0001 #define CLIENT_STARTGAME4_OPTION_LADDER_COUNTASLOSS 0x0002 #define CLIENT_STARTGAME4_OPTION_LADDER_NOPENALTY 0x0001 #define CLIENT_STARTGAME4_OPTION_IRONMAN_ 0x000 /* FIXME */ #define CLIENT_STARTGAME4_OPTION_MAPSET_NORMAL 0x0001 #define CLIENT_STARTGAME4_OPTION_TEAMMELEE_4 0x0003 #define CLIENT_STARTGAME4_OPTION_TEAMMELEE_3 0x0002 #define CLIENT_STARTGAME4_OPTION_TEAMMELEE_2 0x0001 #define CLIENT_STARTGAME4_OPTION_TEAMFFA_4 0x0003 #define CLIENT_STARTGAME4_OPTION_TEAMFFA_3 0x0002 #define CLIENT_STARTGAME4_OPTION_TEAMFFA_2 0x0001 #define CLIENT_STARTGAME4_OPTION_TEAMCTF_4 0x0003 #define CLIENT_STARTGAME4_OPTION_TEAMCTF_3 0x0002 #define CLIENT_STARTGAME4_OPTION_TEAMCTF_2 0x0001 #define CLIENT_STARTGAME4_OPTION_PGL_ 0x000 /* FIXME */ #define CLIENT_STARTGAME4_OPTION_TOPVBOT_1 0x0001 /* 1 vs all [ 1x1, 1x2, 1x3 ...] */ #define CLIENT_STARTGAME4_OPTION_TOPVBOT_2 0x0002 /* f.e. for (8) The Hunters.scm 1 vs all */ #define CLIENT_STARTGAME4_OPTION_TOPVBOT_3 0x0003 /* means 1x7 */ #define CLIENT_STARTGAME4_OPTION_TOPVBOT_4 0x0004 /* 4 vs all */ #define CLIENT_STARTGAME4_OPTION_TOPVBOT_5 0x0005 #define CLIENT_STARTGAME4_OPTION_TOPVBOT_6 0x0006 #define CLIENT_STARTGAME4_OPTION_TOPVBOT_7 0x0007 #define CLIENT_STARTGAME4_UNKNOWN4 0x00000000 #define CLIENT_STARTGAME4_UNKNOWN5 0x00000000 #define CLIENT_STARTGAME4_OPTION_NONE 0x000 /* FIXME */ #define CLIENT_STARTGAME4_FLAG_PRIVATE 0x0001 #define CLIENT_STARTGAME4_FLAG_PRIVATE_PASSWORD "password" #define CLIENT_MAPTYPE_SELFMADE 0 #define CLIENT_MAPTYPE_BLIZZARD 1 #define CLIENT_MAPTYPE_LADDER 2 #define CLIENT_MAPTYPE_PGL 3 #define CLIENT_MAPTYPE_KBK 4 #define CLIENT_MAPTYPE_CompUSA 5 /* CLIENT_GAMESPEED_FAST is NULL for "fast" games, I convert it into 4 */ #define CLIENT_GAMESPEED_SLOWEST 0 #define CLIENT_GAMESPEED_SLOWER 1 #define CLIENT_GAMESPEED_SLOW 2 #define CLIENT_GAMESPEED_NORMAL 3 #define CLIENT_GAMESPEED_FAST 4 #define CLIENT_GAMESPEED_FASTER 5 #define CLIENT_GAMESPEED_FASTEST 6 /* The tileset is NULL for BADLANDS, I'm using zero here */ #define CLIENT_TILESET_BADLANDS 0 #define CLIENT_TILESET_SPACE 1 #define CLIENT_TILESET_INSTALLATION 2 #define CLIENT_TILESET_ASHWORLD 3 #define CLIENT_TILESET_JUNGLE 4 #define CLIENT_TILESET_DESERT 5 #define CLIENT_TILESET_ICE 6 #define CLIENT_TILESET_TWILIGHT 7 /* Diablo II Difficulty */ #define CLIENT_DIFFICULTY_NORMAL 1 #define CLIENT_DIFFICULTY_NIGHTMARE 2 #define CLIENT_DIFFICULTY_HELL 3 /* assumed */ #define CLIENT_DIFFICULTY_HARDCORE_NORMAL 4 #define CLIENT_DIFFICULTY_HARDCORE_NIGHTMARE 5 /* assumed */ #define CLIENT_DIFFICULTY_HARDCORE_HELL 6 /* assumed */ /******************************************************/ /******************************************************/ #define SERVER_STARTGAME1_ACK 0x08ff typedef struct { t_bnet_header h; bn_int reply; } PACKED_ATTR() t_server_startgame1_ack; #define SERVER_STARTGAME1_ACK_NO 0x00000000 #define SERVER_STARTGAME1_ACK_OK 0x00000001 /******************************************************/ /******************************************************/ #define SERVER_STARTGAME3_ACK 0x1aff typedef struct { t_bnet_header h; bn_int reply; } PACKED_ATTR() t_server_startgame3_ack; #define SERVER_STARTGAME3_ACK_NO 0x00000000 #define SERVER_STARTGAME3_ACK_OK 0x00000001 /******************************************************/ /******************************************************/ #define SERVER_STARTGAME4_ACK 0x1cff typedef struct { t_bnet_header h; bn_int reply; } PACKED_ATTR() t_server_startgame4_ack; #define SERVER_STARTGAME4_ACK_NO 0x00000001 #define SERVER_STARTGAME4_ACK_OK 0x00000000 /******************************************************/ /******************************************************/ #define CLIENT_CLOSEGAME 0x02ff #define CLIENT_CLOSEGAME2 0x1fff typedef struct { t_bnet_header h; } PACKED_ATTR() t_client_closegame; /******************************************************/ /******************************************************/ #define CLIENT_LEAVECHANNEL 0x10ff typedef struct { t_bnet_header h; } PACKED_ATTR() t_client_leavechannel; /******************************************************/ /* packets 0x60ff - 0x64ff moved to anongame_protocal.h [Omega] */ /******************************************************/ /* FF 32 2A 00 1A 29 25 72 77 C3 3C 25 6B 4D 7A A4 .2*..)%rw.<%kMz. 3B 92 38 D5 01 F4 A5 6B 28 32 29 43 68 61 6C 6C ;.8....k(2)Chall 65 6E 67 65 72 2E 73 63 6D 00 enger.scm. FF 32 2C 00 21 F8 16 2D 99 D9 BC A4 A6 5C BA 60 .2,.!..-.....\.` 71 DE 6D 64 6F BC A5 03 28 34 29 44 69 72 65 20 q.mdo...(4)Dire 53 74 72 61 69 74 73 2E 73 63 6D 00 Straits.scm. */ #define CLIENT_MAPAUTHREQ1 0x32ff typedef struct { t_bnet_header h; bn_int file_checksum[5]; /* mapfile */ } PACKED_ATTR() t_client_mapauthreq1; /******************************************************/ /******************************************************/ /* FF 32 08 00 01 00 00 00 .2...... */ #define SERVER_MAPAUTHREPLY1 0x32ff typedef struct { t_bnet_header h; bn_int response; } PACKED_ATTR() t_server_mapauthreply1; #define SERVER_MAPAUTHREPLY1_NO 0x00000000 #define SERVER_MAPAUTHREPLY1_OK 0x00000001 #define SERVER_MAPAUTHREPLY1_LADDER_OK 0x00000002 /******************************************************/ /******************************************************/ /* From BW1.08alpha: FF 3C 31 00 7A 20 01 00 3B B7 C6 27 0D 61 C3 79 .<1.z ..;..'.a.y 79 BE 24 5E 9C 07 05 7D 0B 6A A0 78 28 35 29 4A y.$^...}.j.x(5)J 65 77 65 6C 65 64 20 52 69 76 65 72 2E 73 63 6D eweled River.scm 00 . */ #define CLIENT_MAPAUTHREQ2 0x3cff typedef struct { t_bnet_header h; bn_int unknown; bn_int file_hash[5]; /* mapfile */ } PACKED_ATTR() t_client_mapauthreq2; /******************************************************/ /******************************************************/ /* assuming it looks like the REPLY1 packet.... */ #define SERVER_MAPAUTHREPLY2 0x3cff typedef struct { t_bnet_header h; bn_int response; } PACKED_ATTR() t_server_mapauthreply2; #define SERVER_MAPAUTHREPLY2_NO 0x00000000 /* FIXME: these values are guesses */ #define SERVER_MAPAUTHREPLY2_OK 0x00000001 #define SERVER_MAPAUTHREPLY2_LADDER_OK 0x00000002 /******************************************************/ /******************************************************/ /* FF 15 14 00 36 38 58 49 52 41 54 53 00 00 00 00 ....68XIRATS.... AF 14 55 36 ..U6 */ #define CLIENT_ADREQ 0x15ff typedef struct { t_bnet_header h; bn_int archtag; bn_int clienttag; bn_int prev_adid; /* zero if first request */ bn_int ticks; /* Unix-style time in seconds */ } PACKED_ATTR() t_client_adreq; /******************************************************/ /******************************************************/ /* Sent in response to a CLIENT_ADREQ to tell the client which banner to display next FF 15 3A 00 72 00 00 00 2E 70 63 78 50 15 7A 1C ..:.r....pcxP.z. CE 0F BD 01 61 64 30 30 30 30 37 32 2E 70 63 78 ....ad000072.pcx 00 68 74 74 70 3A 2F 2F 77 77 77 2E 62 6C 69 7A .http://www.bliz 7A 61 72 64 2E 63 6F 6D 2F 00 zard.com/. FF 15 3C 00 C3 00 00 00 2E 73 6D 6B 00 9B 36 A6 ..<......smk..6. 8F 5B BE 01 61 64 30 30 30 30 63 33 2E 73 6D 6B .[..ad0000c3.smk 00 68 74 74 70 3A 2F 2F 77 77 77 2E 66 61 74 68 .http://www.fath 65 72 68 6F 6F 64 2E 6F 72 67 2F 00 erhood.org/. FF 15 36 00 2B 51 02 00 ..6.+Q.. 2E 70 63 78 00 00 00 00 58 01 B2 00 61 64 30 32 .pcx....X...ad02 35 31 32 62 2E 70 63 78 00 68 74 74 70 3A 2F 2F 512b.pcx.http:// 77 77 77 2E 66 73 67 73 2E 63 6F 6D 2F 00 www.fsgs.com/. */ #define SERVER_ADREPLY 0x15ff typedef struct { t_bnet_header h; bn_int adid; bn_int extensiontag; /* unlike other tags, this one is "forward" */ bn_long timestamp; /* file modification time? */ /* filename */ /* link URL */ } PACKED_ATTR() t_server_adreply; /******************************************************/ /******************************************************/ #define CLIENT_ADACK 0x21ff /* Sent after client has displayed the banner 0000: FF 21 36 00 36 38 58 49 52 41 54 53 72 00 00 00 .!6.68XIRATSr... 0010: 61 64 30 30 30 30 37 32 2E 70 63 78 00 68 74 74 ad000072.pcx.htt 0020: 70 3A 2F 2F 77 77 77 2E 62 6C 69 7A 7A 61 72 64 p://www.blizzard 0030: 2E 63 6F 6D 2F 00 .com/. 0000: FF 21 38 00 36 38 58 49 4C 54 52 44 C3 00 00 00 .!8.68XILTRD.... 0010: 61 64 30 30 30 30 63 33 2E 73 6D 6B 00 68 74 74 ad0000c3.smk.htt 0020: 70 3A 2F 2F 77 77 77 2E 66 61 74 68 65 72 68 6F p://www.fatherho 0030: 6F 64 2E 6F 72 67 2F 00 od.org/. */ typedef struct { t_bnet_header h; bn_int archtag; bn_int clienttag; bn_int adid; /* adfile */ /* adlink */ } PACKED_ATTR() t_client_adack; /******************************************************/ /******************************************************/ /* Sent if the user clicks on the adbanner */ #define CLIENT_ADCLICK 0x16ff typedef struct { t_bnet_header h; bn_int adid; bn_int unknown1; } PACKED_ATTR() t_client_adclick; /******************************************************/ /******************************************************/ /* first seen in Diablo II? */ /* FF 41 08 00 01 00 00 00 .A...... */ #define CLIENT_ADCLICK2 0x41ff typedef struct { t_bnet_header h; bn_int adid; } PACKED_ATTR() t_client_adclick2; /******************************************************/ /******************************************************/ /* first seen in Diablo II? */ /* FF 41 2C 00 0B 20 00 00 68 74 .qT....A,.. ..ht 74 70 3A 2F 2F 77 77 77 2E 62 6C 69 7A 7A 61 72 tp://www.blizzar 64 2E 63 6F 6D 2F 64 69 61 62 6C 6F 32 65 78 70 d.com/diablo2exp 2F 00 /. */ #define SERVER_ADCLICKREPLY2 0x41ff typedef struct { t_bnet_header h; bn_int adid; /* link URL */ } PACKED_ATTR() t_server_adclickreply2; /******************************************************/ /******************************************************/ /* seen in SC107a */ #define CLIENT_UNKNOWN_17 0x17ff typedef struct { t_bnet_header h; /* FIXME: what is in here... is there a cooresponding server packet? */ } PACKED_ATTR() t_client_unknown_17; /******************************************************/ /******************************************************/ /* seen in SC107a */ #define CLIENT_UNKNOWN_24 0x24ff typedef struct { t_bnet_header h; /* FIXME: what is in here... is there a cooresponding server packet? */ } PACKED_ATTR() t_client_unknown_24; /******************************************************/ /******************************************************/ /* FF 2E 18 00 4E 42 32 57 01 00 00 00 00 00 00 00 ....NB2W........ 00 00 00 00 0A 00 00 00 ........ */ #define CLIENT_LADDERREQ 0x2eff typedef struct { t_bnet_header h; bn_int clienttag; bn_int id; /* (AKA ladder type) 1==standard, 3==ironman */ bn_int type; /* (AKA ladder sort) */ bn_int startplace; /* start listing on this entries */ bn_int count; /* how many entries to list */ } PACKED_ATTR() t_client_ladderreq; #define CLIENT_LADDERREQ_ID_STANDARD 0x00000001 #define CLIENT_LADDERREQ_ID_IRONMAN 0x00000003 #define CLIENT_LADDERREQ_TYPE_HIGHESTRATED 0x00000000 #define CLIENT_LADDERREQ_TYPE_MOSTWINS 0x00000002 #define CLIENT_LADDERREQ_TYPE_MOSTGAMES 0x00000003 /******************************************************/ /******************************************************/ /* Sent in repsonse to CLIENT_LADDERREQ FF 2E AB 03 52 41 54 53 01 00 00 00 00 00 00 00 ....RATS........ 00 00 00 00 0A 00 00 00 27 00 00 00 01 00 00 00 ........'....... 01 00 00 00 74 06 00 00 00 00 00 00 27 00 00 00 ....t.......'... 01 00 00 00 01 00 00 00 74 06 00 00 00 00 00 00 ........t....... 00 00 00 00 00 00 00 00 FF FF FF FF 74 06 00 00 ............t... 00 00 00 00 00 00 00 00 12 27 4E FF 2D DD BE 01 .........'N.-... 12 27 4E FF 2D DD BE 01 6E 65 6D 62 69 3A 29 6B .'N.-...nembi:)k 69 6C 6C 65 72 00 1D 00 00 00 03 00 00 00 00 00 iller........... 00 00 67 06 00 00 00 00 00 00 1D 00 00 00 03 00 ..g............. 00 00 00 00 00 00 67 06 00 00 00 00 00 00 01 00 ......g......... 00 00 00 00 00 00 FF FF FF FF 67 06 00 00 01 00 ..........g..... 00 00 00 00 00 00 D8 5B 9E D0 32 DD BE 01 D8 5B .......[..2....[ 9E D0 32 DD BE 01 53 4B 45 4C 54 4F 4E 00 1F 00 ..2...SKELTON... 00 00 03 00 00 00 00 00 00 00 EF 05 00 00 00 00 ................ 00 00 1F 00 00 00 03 00 00 00 00 00 00 00 EF 05 ................ 00 00 00 00 00 00 02 00 00 00 00 00 00 00 FF FF ................ FF FF EF 05 00 00 02 00 00 00 00 00 00 00 62 26 ..............b& 55 0C 51 DC BE 01 62 26 55 0C 51 DC BE 01 7A 69 U.Q...b&U.Q...zi 7A 69 62 65 5E 2E 7E 00 19 00 00 00 02 00 00 00 zibe^.~......... 00 00 00 00 FC 05 00 00 00 00 00 00 18 00 00 00 ................ 02 00 00 00 00 00 00 00 EE 05 00 00 00 00 00 00 ................ 03 00 00 00 00 00 00 00 FF FF FF FF FC 05 00 00 ................ 03 00 00 00 00 00 00 00 A0 25 4F 31 90 DE BE 01 .........%O1.... 8C F1 7F 9F 66 DD BE 01 59 4F 4F 4A 49 4E 27 53 ....f...YOOJIN'S 00 1D 00 00 00 02 00 00 00 00 00 00 00 EC 05 00 ................ 00 00 00 00 00 1D 00 00 00 02 00 00 00 00 00 00 ................ 00 EC 05 00 00 00 00 00 00 04 00 00 00 00 00 00 ................ 00 FF FF FF FF EC 05 00 00 03 00 00 00 00 00 00 ................ 00 F4 58 78 82 2F D7 BE 01 F4 58 78 82 2F D7 BE ..Xx./....Xx./.. 01 3D 7B 5F 7C 5F 7D 3D 00 1A 00 00 00 00 00 00 .={_|_}=........ 00 00 00 00 00 E2 05 00 00 00 00 00 00 1A 00 00 ................ 00 00 00 00 00 00 00 00 00 E2 05 00 00 00 00 00 ................ 00 05 00 00 00 00 00 00 00 FF FF FF FF E2 05 00 ................ 00 05 00 00 00 00 00 00 00 F2 DC 0D 1F 6C DD BE .............l.. 01 F2 DC 0D 1F 6C DD BE 01 5B 53 50 41 43 45 5D .....l...[SPACE] 2D 31 2D 54 2E 53 2E 4A 00 15 00 00 00 02 00 00 -1-T.S.J........ 00 01 00 00 00 E0 05 00 00 00 00 00 00 15 00 00 ................ 00 02 00 00 00 01 00 00 00 E0 05 00 00 00 00 00 ................ 00 06 00 00 00 00 00 00 00 FF FF FF FF E0 05 00 ................ 00 06 00 00 00 00 00 00 00 7A C9 F6 6E 0B DE BE .........z..n... 01 7A C9 F6 6E 0B DE BE 01 5B 46 65 77 5D 2D 44 .z..n....[Few]-D 2E 73 00 23 00 00 00 00 00 00 00 00 00 00 00 DF .s.#............ 05 00 00 00 00 00 00 23 00 00 00 00 00 00 00 00 .......#........ 00 00 00 DF 05 00 00 00 00 00 00 07 00 00 00 00 ................ 00 00 00 FF FF FF FF E2 05 00 00 04 00 00 00 00 ................ 00 00 00 6E D9 DC 3A E2 DA BE 01 6E D9 DC 3A E2 ...n..:....n..:. DA BE 01 5B 4C 2E 73 5D 2D 43 6F 6F 6C 00 1F 00 ...[L.s]-Cool... 00 00 07 00 00 00 02 00 00 00 DD 05 00 00 00 00 ................ 00 00 1F 00 00 00 07 00 00 00 02 00 00 00 DD 05 ................ 00 00 00 00 00 00 08 00 00 00 00 00 00 00 FF FF ................ FF FF 07 06 00 00 02 00 00 00 00 00 00 00 B6 CE ................ B1 D8 7A D8 BE 01 B6 CE B1 D8 7A D8 BE 01 52 6F ..z.......z...Ro 60 4C 65 58 7E 50 72 4F 27 5A 65 4E 00 18 00 00 `LeX~PrO'ZeN.... 00 04 00 00 00 00 00 00 00 DD 05 00 00 00 00 00 ................ 00 18 00 00 00 04 00 00 00 00 00 00 00 DD 05 00 ................ 00 00 00 00 00 09 00 00 00 00 00 00 00 FF FF FF ................ FF DD 05 00 00 04 00 00 00 00 00 00 00 50 76 4C .............PvL F7 AD D7 BE 01 50 76 4C F7 AD D7 BE 01 48 61 6E .....PvL.....Han 5F 65 53 54 68 65 72 2E 27 27 00 _eSTher.''. */ #define SERVER_LADDERREPLY 0x2eff typedef struct { t_bnet_header h; bn_int clienttag; bn_int id; /* (AKA ladder type) 1==standard, 3==ironman */ bn_int type; /* (AKA ladder sort) */ bn_int startplace; /* start listing on this entries */ bn_int count; /* how many entries to list */ /* ladder entry */ /* player name */ } PACKED_ATTR() t_server_ladderreply; #define CLIENT_LADDERREPLY_ID_STANDARD 0x00000001 #define CLIENT_LADDERREPLY_ID_IRONMAN 0x00000003 typedef struct { bn_int wins; bn_int loss; bn_int disconnect; bn_int rating; bn_int rank; } PACKED_ATTR() t_ladder_data; typedef struct { t_ladder_data current; t_ladder_data active; bn_int ttest[6]; /* 00 00 00 00 00 00 00 00 FF FF FF FF 74 06 00 00 00 00 00 00 00 00 00 00 */ bn_long lastgame_current; /* timestamp */ bn_long lastgame_active; /* timestamp */ } PACKED_ATTR() t_ladder_entry; /******************************************************/ /******************************************************/ /* FF 25 08 00 EA 7F DB 02 .%...... */ #define CLIENT_ECHOREPLY 0x25ff typedef struct { t_bnet_header h; bn_int ticks; } PACKED_ATTR() t_client_echoreply; /******************************************************/ /******************************************************/ #define SERVER_ECHOREQ 0x25ff typedef struct { t_bnet_header h; bn_int ticks; } PACKED_ATTR() t_server_echoreq; /******************************************************/ /******************************************************/ /* What I'm calling the ping happens every 90 seconds during gameplay. I'm not exactly sure what it is, but it didn't hurt that we didn't respond up to now... I went ahead and coded a response in. This packet is sent at other times as well, even before login. This is probably a keepalive packet and the UDP is sent to make sure the UDP entry on the NAT gateway remains valid. Prolix calls these null packets and says they are sent every 60 seconds. This seems to be associated with a UDP packet 7 from the client: 7: cli class=bnet[0x01] type=CLIENT_PINGREQ[0x00ff] length=4 0000: FF 00 04 00 .... 5: clt prot=udp[0x07] from=128.123.62.23:6112 to=128.123.62.23:6112 length=8 0000: 07 00 00 00 2E 95 9D 00 ........ 7: srv class=bnet[0x01] type=SERVER_PINGREPLY[0x00ff] length=4 0000: FF 00 04 00 .... FF 00 04 00 .... */ #define CLIENT_PINGREQ 0x00ff typedef struct { t_bnet_header h; } PACKED_ATTR() t_client_pingreq; /******************************************************/ /******************************************************/ /* FF 00 04 00 .... */ #define SERVER_PINGREPLY 0x00ff typedef struct { t_bnet_header h; } PACKED_ATTR() t_server_pingreply; /******************************************************/ /******************************************************/ /* FF 2C 3D 02 00 00 00 00 08 00 00 00 03 00 00 00 .,=............. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 52 6F 73 73 ............Ross 5F 43 4D 00 00 00 00 00 00 00 00 4F 6E 20 6D 61 _CM........On ma 70 20 22 43 68 61 6C 6C 65 6E 67 65 72 22 3A 0A p "Challenger":. 00 52 6F 73 73 5F 43 4D 20 77 61 73 20 50 72 6F .Ross_CM was Pro 74 6F 73 73 20 61 6E 64 20 70 6C 61 79 65 64 20 toss and played 66 6F 72 20 33 31 20 6D 69 6E 75 74 65 73 0A 0A for 31 minutes.. 20 20 4F 76 65 72 61 6C 6C 20 53 63 6F 72 65 20 Overall Score 32 38 31 30 35 0A 20 20 20 20 20 20 20 20 20 31 28105. 1 31 37 30 30 20 66 6F 72 20 55 6E 69 74 73 0A 20 1700 for Units. 20 20 20 20 20 20 20 20 20 31 34 37 35 20 66 6F 1475 fo 72 20 53 74 72 75 63 74 75 72 65 73 0A 20 20 20 r Structures. 20 20 20 20 20 20 31 34 39 33 30 20 66 6F 72 20 14930 for 52 65 73 6F 75 72 63 65 73 0A 0A 20 20 55 6E 69 Resources.. Uni 74 73 20 53 63 6F 72 65 20 31 31 37 30 30 0A 20 ts Score 11700. 20 20 20 20 20 20 20 20 20 20 20 37 30 20 55 6E 70 Pn */ #define CLIENT_GAME_REPORT 0x2cff typedef struct { t_bnet_header h; bn_int unknown1; /* 0x00000000 */ bn_int count; /* (number of player slots (will be 8 for now) */ /* results... */ /* names... */ /* report header */ /* report body */ } PACKED_ATTR() t_client_game_report; typedef struct { bn_int result; } PACKED_ATTR() t_client_game_report_result; #define CLIENT_GAME_REPORT_RESULT_PLAYING 0x00000000 #define CLIENT_GAME_REPORT_RESULT_WIN 0x00000001 #define CLIENT_GAME_REPORT_RESULT_LOSS 0x00000002 #define CLIENT_GAME_REPORT_RESULT_DRAW 0x00000003 #define CLIENT_GAME_REPORT_RESULT_DISCONNECT 0x00000004 #define CLIENT_GAME_REPORT_RESULT_OBSERVER 0x00000005 /******************************************************/ /******************************************************/ /* War Craft II BNE (original): FF 22 1B 00 4E 42 32 57 4B 00 00 00 4C 61 64 64 ."..NB2WK...Ladd 65 72 20 31 20 6F 6E 20 31 00 00 er 1 on 1.. */ #define CLIENT_JOIN_GAME 0x22ff typedef struct { t_bnet_header h; bn_int clienttag; bn_int versiontag; /* game name */ /* game password */ } PACKED_ATTR() t_client_join_game; /******************************************************/ /******************************************************/ /* FF 27 84 00 01 00 00 00 04 00 00 00 52 6F 73 73 .'..........Ross 5F 43 4D 00 70 72 6F 66 69 6C 65 5C 73 65 78 00 _CM.profile\sex. 70 72 6F 66 69 6C 65 5C 61 67 65 00 70 72 6F 66 profile\age.prof 69 6C 65 5C 6C 6F 63 61 74 69 6F 6E 00 70 72 6F ile\location.pro 66 69 6C 65 5C 64 65 73 63 72 69 70 74 69 6F 6E file\description 00 61 73 64 66 00 61 73 66 00 61 73 64 66 00 61 .asdf.asf.asdf.a 73 64 66 61 73 64 66 61 73 64 66 61 73 64 66 0D sdfasdfasdfasdf. 0A 61 73 64 0D 0A 66 61 73 64 0D 0A 66 61 73 64 .asd..fasd..fasd 66 0D 0A 00 f... */ #define CLIENT_STATSUPDATE 0x27ff typedef struct { t_bnet_header h; bn_int name_count; bn_int key_count; /* names... */ /* values... */ } PACKED_ATTR() t_client_statsupdate; /******************************************************/ /******************************************************/ #define CLIENT_REALMJOINREQ_109 0x3eff typedef struct { t_bnet_header h; bn_int seqno; bn_int seqnohash[5]; /* Realm Name */ } PACKED_ATTR() t_client_realmjoinreq_109; /******************************************************/ /******************************************************/ #define SERVER_REALMJOINREPLY_109 0x3eff typedef struct { t_bnet_header h; bn_int seqno; bn_int u1; bn_int bncs_addr1; bn_int sessionnum; bn_int addr; bn_short port; bn_short u3; bn_int sessionkey; /* zero */ bn_int u5; bn_int u6; bn_int clienttag; bn_int versionid; bn_int bncs_addr2; bn_int u7; /* zero */ bn_int secret_hash[5]; /* account name */ } PACKED_ATTR() t_server_realmjoinreply_109; /******************************************************/ #define CLIENT_SEARCH_LAN_GAMES 0x2ff7 typedef struct { t_bnet_header h; bn_byte game_tag[4]; /* 3WAR */ bn_int unknown1; bn_int unknown2; } PACKED_ATTR() t_client_search_lan_games; #define CLIENT_CHANGECLIENT 0x5cff typedef struct { t_bnet_header h; bn_int clienttag; } t_client_changeclient; #define CLIENT_SETEMAILREPLY 0x59ff typedef struct { t_bnet_header h; /* email address */ } PACKED_ATTR() t_client_setemailreply; #define SERVER_SETEMAILREQ 0x59ff /* send this packet to client before login ok packet will cause client to enter input email screen */ typedef struct { t_bnet_header h; } PACKED_ATTR() t_server_setemailreq; #define CLIENT_GETPASSWORDREQ 0x5aff typedef struct { t_bnet_header h; /* account name */ /* email address */ } PACKED_ATTR() t_client_getpasswordreq; #define CLIENT_CHANGEEMAILREQ 0x5bff typedef struct { t_bnet_header h; /* account name */ /* old email address */ /* new email address */ } PACKED_ATTR() t_client_changeemailreq; #define CLIENT_MOTDREQ 0x46ff typedef struct { t_bnet_header h; bn_int last_news_time; /* date of the last news item the client has */ } PACKED_ATTR() t_client_motdreq; /* this packet is sent right after cdkey and version auth reply success and crashdump exist 0x0000: ff 5d 14 00 01 01 00 27 00 0a 01 05 00 00 c0 00 .].....'........ 0x0010: 00 00 00 00 .... */ #define CLIENT_CRASHDUMP 0x5dff typedef struct { t_bnet_header h; /* crashdump file data */ /* contains data like client version, exception code, code address */ } PACKED_ATTR() t_client_crashdump; #define CLIENT_CLANINFOREQ 0x82ff typedef struct { t_bnet_header h; bn_int count; bn_int clantag; /* player name */ } PACKED_ATTR() t_client_claninforeq; #define SERVER_CLANINFOREPLY 0x82ff typedef struct { t_bnet_header h; bn_int count; bn_byte fail; /* string - clan name */ /* bn_byte - clan rank */ /* bn_int - join time */ } PACKED_ATTR() t_server_claninforeply; #define CLIENT_ARRANGEDTEAM_ACCEPT_INVITE 0xfdff typedef struct { t_bnet_header h; } PACKED_ATTR() t_client_arrangedteam_accept_invite; /* clan handling */ #define SERVER_W3XP_CLAN_MEMBER_CHIEFTAIN 0x04 #define SERVER_W3XP_CLAN_MEMBER_SHAMAN 0x03 #define SERVER_W3XP_CLAN_MEMBER_GRUNT 0x02 #define SERVER_W3XP_CLAN_MEMBER_PEON 0x01 #define SERVER_W3XP_CLAN_MEMBER_NEW 0x00 #define SERVER_W3XP_CLAN_MEMBER_OFFLINE 0x00 #define SERVER_W3XP_CLAN_MEMBER_ONLINE 0x01 #define SERVER_W3XP_CLAN_MEMBER_CHANNEL 0x02 #define SERVER_W3XP_CLAN_MEMBER_GAME 0x03 #define SERVER_W3XP_CLAN_MEMBER_PRIVATE_GAME 0x04 /*Paquet #267 0x0000 FF 75 0A 00 00 00 42 54-54 04 ÿu....BTT. */ /* 300: recv class=bnet[0x02] type=unknown[0x70ff] length=12 0000: FF 70 0C 00 01 00 00 00 00 64 73 66 .p.......dsf 300: send class=bnet[0x02] type=unknown[0x70ff] length=56 0000: FF 70 38 00 01 00 00 00 00 09 44 4A 50 32 00 44 .p8.......DJP2.D 0010: 4A 50 33 00 44 4A 50 34 00 44 4A 50 35 00 44 4A JP3.DJP4.DJP5.DJ 0020: 50 36 00 44 4A 50 37 00 44 4A 50 38 00 44 4A 50 P6.DJP7.DJP8.DJP 0030: 39 00 44 4A 50 31 30 00 9.DJP10. 300: recv class=bnet[0x02] type=CLIENT_FRIENDINFOREQ[0x66ff] length=5 0000: FF 66 05 00 01 .f... 300: send class=bnet[0x02] type=unknown[0x66ff] length=12 0000: FF 66 0C 00 01 00 00 00 00 00 00 00 .f.......... 300: recv class=bnet[0x02] type=unknown[0x71ff] length=64 0000: FF 71 40 00 01 00 00 00 74 65 73 74 00 00 64 73 .q@.....test..ds 0010: 66 09 44 4A 50 32 00 44 4A 50 33 00 44 4A 50 34 f.DJP2.DJP3.DJP4 0020: 00 44 4A 50 35 00 44 4A 50 36 00 44 4A 50 37 00 .DJP5.DJP6.DJP7. 0030: 44 4A 50 38 00 44 4A 50 39 00 44 4A 50 31 30 00 DJP8.DJP9.DJP10. 300: send class=bnet[0x02] type=unknown[0x71ff] length=10 0000: FF 71 0A 00 01 00 00 00 00 00 .q........ 300: send class=bnet[0x02] type=unknown[0x75ff] length=12 0000: FF 75 0C 00 00 00 00 00 64 73 66 00 .u......dsf. 300: recv class=bnet[0x02] type=CLIENT_FRIENDINFOREQ[0x66ff] length=5 0000: FF 66 05 00 02 .f... 300: send class=bnet[0x02] type=unknown[0x66ff] length=12 0000: FF 66 0C 00 02 00 00 00 00 00 00 00 .f.......... */ #define CLIENT_W3XP_CLAN_CREATEREQ 0x70ff typedef struct{ t_bnet_header h; bn_int count; bn_int clantag; } PACKED_ATTR() t_client_w3xp_clan_createreq; #define SERVER_W3XP_CLAN_CREATEREPLY 0x70ff typedef struct{ t_bnet_header h; bn_int count; bn_byte check_result; bn_byte friend_count; /* player name in chan or mutual char player_name[sizeof (friend_name)]; */ } PACKED_ATTR() t_server_w3xp_clan_createreply; #define SERVER_W3XP_CLAN_CREATEREPLY_CHECK_OK 0x00 #define SERVER_W3XP_CLAN_CREATEREPLY_CHECK_ALLREADY_IN_USE 0x01 #define SERVER_W3XP_CLAN_CREATEREPLY_CHECK_TIME_LIMIT 0x02 #define SERVER_W3XP_CLAN_CREATEREPLY_CHECK_EXCEPTION 0x04 #define SERVER_W3XP_CLAN_CREATEREPLY_CHECK_INVALID_CLAN_TAG 0x0a /* 3852: recv class=bnet[0x02] type=unknown[0x71ff] length=70 0000: FF 71 46 00 01 00 00 00 53 75 62 57 61 72 5A 6F .qF.....SubWarZo 0010: 6E 65 00 00 5A 57 53 09 44 4A 50 32 00 44 4A 50 ne..ZWS.DJP2.DJP 0020: 33 00 44 4A 50 34 00 44 4A 50 35 00 44 4A 50 36 3.DJP4.DJP5.DJP6 0030: 00 44 4A 50 37 00 44 4A 50 38 00 44 4A 50 31 30 .DJP7.DJP8.DJP10 0040: 00 44 4A 50 39 00 .DJP9. */ #define CLIENT_W3XP_CLAN_CREATEINVITEREQ 0x71ff typedef struct{ t_bnet_header h; bn_int count; /* Clan Name (\0 terminated string) bn_int clantag; bn_byte friend_count; //Number of friend selected Name of friend (\0 terminated string) */ } PACKED_ATTR() t_client_w3xp_clan_createinvitereq; /*3756: send class=bnet[0x02] type=unknown[0x71ff] length=14 0000: FF 71 0E 00 02 00 00 00 05 44 4A 50 32 00 .q.......DJP2. <- Unable to receive invitation ( PG search, already in a clan, etc... )*/ /*3756: Paquet #266 0x0000 FF 71 0A 00 05 00 00 00-00 00 ÿq........ <- Clan invitation = Sucessfully done */ #define SERVER_W3XP_CLAN_CREATEINVITEREPLY 0x71ff typedef struct{ t_bnet_header h; bn_int count; bn_byte status; /* 0x05 = Cannot contact(not in channel screen) or already in clan | 0x04 = Decline | 0x00 = OK :) Name of failed member(\0 terminated string) */ } PACKED_ATTR() t_server_w3xp_clan_createinvitereply; #define SERVER_W3XP_CLAN_CREATEINVITEREQ 0x72ff typedef struct{ t_bnet_header h; bn_int count; bn_int clantag; /* Clan Name (\0 terminated string) Clan Creator (\0 terminated string) bn_byte friend_count; //Number of friend selected Name of friend (\0 terminated string) */ } PACKED_ATTR() t_server_w3xp_clan_createinvitereq; #define CLIENT_W3XP_CLAN_CREATEINVITEREPLY 0x72ff typedef struct{ t_bnet_header h; bn_int count; bn_int clantag; /* Clan Creator (\0 terminated string) bn_byte reply */ /* 0x04--decline 0x05--Cannot contact(not in channel screen) or already in clan 0x06--accept*/ } PACKED_ATTR() t_client_w3xp_clan_createinvitereply; /* 3876: recv class=bnet[0x02] type=unknown[0x73ff] length=8 0000: FF 73 08 00 01 00 00 00 .s...... */ #define CLIENT_W3XP_CLAN_DISBANDREQ 0x73ff typedef struct{ t_bnet_header h; bn_int count; } PACKED_ATTR() t_client_w3xp_clan_disbandreq; #define SERVER_W3XP_CLAN_DISBANDREPLY 0x73ff typedef struct{ t_bnet_header h; bn_int count; bn_byte result; /* 0-- Success 1-- Exception raised 2-- Clan exists less than 1 week, cannot remove */ } PACKED_ATTR() t_server_w3xp_clan_disbandreply; #define SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_OK 0x0 #define SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_EXCEPTION 0x1 #define SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_NOT_AUTHORIZED 0x07 #define SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_FAILED 0x2 #define CLIENT_W3XP_CLAN_MEMBERNEWCHIEFREQ 0x74ff typedef struct{ t_bnet_header h; bn_int count; /*Player_Name deleted(\0 terminated) */ } PACKED_ATTR() t_client_w3xp_clan_membernewchiefreq; #define SERVER_W3XP_CLAN_MEMBERNEWCHIEFREPLY 0x74ff typedef struct{ t_bnet_header h; bn_int count; bn_byte result; /* 0-successful 1-failed */ } PACKED_ATTR() t_server_w3xp_clan_membernewchiefreply; #define SERVER_W3XP_CLAN_MEMBERNEWCHIEFREPLY_SUCCESS 0x00 #define SERVER_W3XP_CLAN_MEMBERNEWCHIEFREPLY_FAILED 0x01 #define SERVER_W3XP_CLAN_CLANACK 0x75ff typedef struct{ t_bnet_header h; bn_byte unknow1; /* 0x00 */ bn_int clantag; bn_byte status; /* member status */ } PACKED_ATTR() t_server_w3xp_clan_clanack; #define SERVER_W3XP_CLANQUITNOTIFY 0x76ff typedef struct{ t_bnet_header h; bn_byte status; } PACKED_ATTR() t_server_w3xp_clanquitnotify; #define SERVER_W3XP_CLANQUITNOTIFY_STATUS_REMOVED_FROM_CLAN 0x01 /* 3876: recv class=bnet[0x02] type=unknown[0x77ff] length=13 0000: FF 77 0D 00 01 00 00 00 44 4A 50 31 00 .w......DJP1. */ #define CLIENT_W3XP_CLAN_INVITEREQ 0x77ff typedef struct{ t_bnet_header h; bn_int count; /*Player_Name invited */ } PACKED_ATTR() t_client_w3xp_clan_invitereq; #define SERVER_W3XP_CLAN_INVITEREPLY 0x77ff typedef struct{ t_bnet_header h; bn_int count; bn_byte result; /* 0x04--decline 0x05--Cannot contact(not in channel screen) or already in clan */ } PACKED_ATTR() t_server_w3xp_clan_invitereply; #define CLIENT_W3XP_CLANMEMBER_REMOVE_REQ 0x78ff typedef struct{ t_bnet_header h; bn_int count; /*Player_Name deleted(\0 terminated) */ } PACKED_ATTR() t_client_w3xp_clanmember_remove_req; #define SERVER_W3XP_CLANMEMBER_REMOVE_REPLY 0x78ff typedef struct{ t_bnet_header h; bn_int count; bn_byte result; /* 0-successful 1-failed */ } PACKED_ATTR() t_server_w3xp_clanmember_remove_reply; #define SERVER_W3XP_CLANMEMBER_REMOVE_SUCCESS 0x00 #define SERVER_W3XP_CLANMEMBER_REMOVE_FAILED 0x01 #define SERVER_W3XP_CLAN_INVITEREQ 0x79ff typedef struct{ t_bnet_header h; bn_int count; bn_int clantag; /*Clan_Name (\0 terminated) Player_Name invited (\0 terminated) */ } PACKED_ATTR() t_server_w3xp_clan_invitereq; #define CLIENT_W3XP_CLAN_INVITEREPLY 0x79ff typedef struct{ t_bnet_header h; bn_int count; bn_int clantag; /*Player_Name invited (\0 terminated) bn_byte reply *//* 0x04--decline 0x05--Cannot contact(not in channel screen) or already in clan 0x06--accept 0x07--no privilege to invite 0x08--cannot invite(??any difference from cannot contact?) 0x09--clan full*/ } PACKED_ATTR() t_client_w3xp_clan_invitereply; #define W3XP_CLAN_INVITEREPLY_SUCCESS 0x00 #define W3XP_CLAN_INVITEREPLY_DECLINE 0x04 #define W3XP_CLAN_INVITEREPLY_FAILED 0x05 #define W3XP_CLAN_INVITEREPLY_ACCEPT 0x06 #define W3XP_CLAN_INVITEREPLY_NOPRIVILEGE 0x07 #define W3XP_CLAN_INVITEREPLY_CANNOT 0x08 #define W3XP_CLAN_INVITEREPLY_CLANFULL 0x09 #define CLIENT_W3XP_CLANMEMBER_RANKUPDATE_REQ 0x7aff typedef struct{ t_bnet_header h; bn_int count; /*Player_Name invited(\0 terminated) Player_Status(bn_byte: 1~4) */ } PACKED_ATTR() t_client_w3xp_clanmember_rankupdate_req; #define SERVER_W3XP_CLANMEMBER_RANKUPDATE_REPLY 0x7aff typedef struct{ t_bnet_header h; bn_int count; bn_byte result; /* 0-successful 1-failed */ } PACKED_ATTR() t_server_w3xp_clanmember_rankupdate_reply; #define SERVER_W3XP_CLANMEMBER_RANKUPDATE_SUCCESS 0x00 #define SERVER_W3XP_CLANMEMBER_RANKUPDATE_FAILED 0x01 #define CLIENT_W3XP_CLAN_MOTDCHG 0x7bff typedef struct{ t_bnet_header h; bn_int unknow1; /* Motd en string ^^ */ } PACKED_ATTR() t_client_w3xp_clan_motdchg; #define SERVER_W3XP_CLAN_MOTDREPLY_UNKNOW1 0x00000000 #define SERVER_W3XP_CLAN_MOTDREPLY 0x7cff typedef struct{ t_bnet_header h; bn_int count; bn_int unknow1; /* 0x00000000 */ /* MOTD */ } PACKED_ATTR() t_server_w3xp_clan_motdreply; #define CLIENT_W3XP_CLAN_MOTDREQ 0x7cff typedef struct{ t_bnet_header h; bn_int count; } PACKED_ATTR() t_client_w3xp_clan_motdreq; /* Paquet #52 0x0000 FF 7D 10 01 01 00 00 00-13 4D 79 73 74 69 2E 53 ÿ}.......Mysti.S 0x0010 77 5A 00 04 01 00 73 61-75 72 6F 6E 2E 73 77 7A wZ....sauron.swz 0x0020 00 03 00 00 73 69 6D 6F-6E 2E 53 77 5A 00 03 00 ....simon.SwZ... 0x0030 00 4E 65 6F 2D 56 61 67-72 61 6E 74 2E 73 77 7A .Neo-Vagrant.swz 0x0040 00 02 00 00 77 4D 7A 00-02 00 00 6B 61 74 6E 6F ....wMz....katno 0x0050 6D 61 64 2E 53 77 5A 00-02 00 00 47 7A 62 65 75 mad.SwZ....Gzbeu 0x0060 68 2E 53 77 5A 00 02 00-00 53 69 6C 76 65 72 2E h.SwZ....Silver. 0x0070 53 77 5A 00 02 00 00 4D-61 67 67 65 75 73 00 02 SwZ....Maggeus.. 0x0080 00 00 4F 6E 69 2D 4D 75-73 68 61 2E 53 77 5A 00 ..Oni-Musha.SwZ. 0x0090 02 00 00 4D 61 67 67 65-75 53 2E 53 77 5A 00 02 ...MaggeuS.SwZ.. 0x00A0 00 00 53 69 72 65 5F 4C-6F 75 70 00 02 00 00 6B ..Sire_Loup....k 0x00B0 69 6C 6C 69 62 6F 79 00-03 00 00 52 65 64 2E 44 illiboy....Red.D 0x00C0 72 61 4B 65 00 02 00 00-53 69 72 65 2E 53 77 5A raKe....Sire.SwZ 0x00D0 00 03 00 00 73 74 72 61-69 67 68 74 5F 63 6F 75 ....straight_cou 0x00E0 67 61 72 00 02 00 00 52-65 64 44 72 61 6B 65 2E gar....RedDrake. 0x00F0 53 77 5A 00 02 00 00 54-72 6F 6C 6C 6F 00 02 00 SwZ....Trollo... 0x0100 00 53 69 6C 76 65 72 62-65 61 72 64 00 00 00 00 .Silverbeard.... */ #define SERVER_W3XP_CLANMEMBERLIST_REPLY 0x7dff typedef struct{ t_bnet_header h; bn_int count; bn_byte member_count; /* player repeat start * Name of player(\0 terminated string) * bn_byte CHIEFTAIN = 0x04 * SHAMANS = 0x03 * GRUNT = 0x02 * PEON = 0x01 * NEW_MEMBER = 0x00 <- can't be promoted/devoted * bn_byte online status * unknown(always \0) * repeat end */ } PACKED_ATTR() t_server_w3xp_clanmemberlist_reply; /* Paquet #51 0x0000 FF 7D 08 00 01 00 00 00- ÿ}...... */ #define CLIENT_W3XP_CLANMEMBERLIST_REQ 0x7dff typedef struct{ t_bnet_header h; bn_int count; } PACKED_ATTR() t_client_w3xp_clanmemberlist_req; #define SERVER_W3XP_CLANMEMBER_REMOVED_NOTIFY 0x7eff typedef struct{ t_bnet_header h; /* Player_Name deleted(\0 terminated) */ } PACKED_ATTR() t_server_w3xp_clanmember_removed_notify; #define SERVER_W3XP_CLANMEMBERUPDATE 0x7fff typedef struct{ t_bnet_header h; /* Player_Name invited(\0 terminated) * Player_Status(bn_byte: 1~4) * Player_Online(bn_short: 0x0/0x1) */ } PACKED_ATTR() t_server_w3xp_clanmemberupdate; #endif pvpgn-1.8.5/src/common/packet.h0000644000175000017500000004535711151345317015357 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysng@ucsd.edu) * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_PACKET_TYPES #define INCLUDED_PACKET_TYPES #ifdef JUST_NEED_TYPES # include "common/field_sizes.h" # include "common/init_protocol.h" # include "common/bnet_protocol.h" # include "common/anongame_protocol.h" # include "common/file_protocol.h" # include "common/bot_protocol.h" # include "common/udp_protocol.h" # include "common/d2game_protocol.h" # include "d2cs/d2cs_protocol.h" # include "d2cs/d2cs_d2gs_protocol.h" # include "d2cs/d2cs_bnetd_protocol.h" #else # define JUST_NEED_TYPES # include "common/field_sizes.h" # include "common/init_protocol.h" # include "common/bnet_protocol.h" # include "common/anongame_protocol.h" # include "common/file_protocol.h" # include "common/bot_protocol.h" # include "common/udp_protocol.h" # include "common/d2game_protocol.h" # include "d2cs/d2cs_protocol.h" # include "d2cs/d2cs_d2gs_protocol.h" # include "d2cs/d2cs_bnetd_protocol.h" # undef JUST_NEED_TYPES #endif typedef enum { packet_class_none, packet_class_init, packet_class_bnet, packet_class_file, packet_class_raw, packet_class_udp, packet_class_d2game, packet_class_d2gs, packet_class_d2cs, packet_class_d2cs_bnetd, packet_class_w3route } t_packet_class; typedef enum { packet_dir_from_client, packet_dir_from_server } t_packet_dir; /* These aren't really packets so much as records in a TCP stream. They are variable- * length structures which make up the Battle.net protocol. It is just easier to call * them "packets". */ typedef struct { unsigned int ref; /* reference count */ t_packet_class class; unsigned int flags; /* user-defined flags (used to mark UDP in bnproxy) */ unsigned int len; /* raw packets have no header, so we use this */ /* next part looks just like it would on the network (no padding, byte for byte) */ union { char data[MAX_PACKET_SIZE]; t_bnet_generic bnet; t_file_generic file; t_udp_generic udp; t_d2game_generic d2game; t_w3route_generic w3route; t_client_initconn client_initconn; t_server_authreply1 server_authreply1; t_server_authreq1 server_authreq1; t_client_authreq1 client_authreq1; t_server_authreply_109 server_authreply_109; t_server_authreq_109 server_authreq_109; t_client_authreq_109 client_authreq_109; t_client_cdkey client_cdkey; t_server_cdkeyreply server_cdkeyreply; t_client_statsreq client_statsreq; t_server_statsreply server_statsreply; t_client_loginreq1 client_loginreq1; t_server_loginreply1 server_loginreply1; t_client_progident client_progident; t_client_progident2 client_progident2; t_client_joinchannel client_joinchannel; t_server_channellist server_channellist; t_server_serverlist server_serverlist; t_server_message server_message; t_client_message client_message; t_client_gamelistreq client_gamelistreq; t_server_gamelistreply server_gamelistreply; t_client_udpok client_udpok; t_client_unknown_1b client_unknown_1b; t_client_startgame1 client_startgame1; t_server_startgame1_ack server_startgame1_ack; t_client_startgame3 client_startgame3; t_server_startgame3_ack server_startgame3_ack; t_client_startgame4 client_startgame4; t_server_startgame4_ack server_startgame4_ack; t_client_leavechannel client_leavechannel; t_client_closegame client_closegame; t_client_mapauthreq1 client_mapauthreq1; t_server_mapauthreply1 server_mapauthreply1; t_client_mapauthreq2 client_mapauthreq2; t_server_mapauthreply2 server_mapauthreply2; t_client_ladderreq client_ladderreq; t_server_ladderreply server_ladderreply; t_client_laddersearchreq client_laddersearchreq; t_server_laddersearchreply server_laddersearchreply; t_client_adreq client_adreq; t_server_adreply server_adreply; t_client_adack client_adack; t_client_adclick client_adclick; t_client_adclick2 client_adclick2; t_server_adclickreply2 server_adclickreply2; t_client_game_report client_gamerep; t_server_sessionkey1 server_sessionkey1; t_server_sessionkey2 server_sessionkey2; t_client_createacctreq1 client_createacctreq1; t_server_createacctreply1 server_createacctreply1; t_client_changepassreq client_changepassreq; t_server_changepassack server_changepassack; t_client_iconreq client_iconreq; t_server_iconreply server_iconreply; t_client_fileinforeq client_fileinforeq; t_server_fileinforeply server_fileinforeply; t_client_statsupdate client_statsupdate; t_client_countryinfo1 client_countryinfo1; t_client_countryinfo_109 client_countryinfo_109; t_client_unknown_2b client_unknown_2b; t_client_compinfo1 client_compinfo1; t_client_compinfo2 client_compinfo2; t_server_compreply server_compreply; t_server_echoreq server_echoreq; t_client_echoreply client_echoreply; t_client_playerinforeq client_playerinforeq; t_server_playerinforeply server_playerinforeply; t_client_pingreq client_pingreq; t_server_pingreply server_pingreply; t_client_cdkey2 client_cdkey2; t_server_cdkeyreply2 server_cdkeyreply2; t_client_cdkey3 client_cdkey3; t_server_cdkeyreply3 server_cdkeyreply3; t_server_regsnoopreq server_regsnoopreq; t_client_regsnoopreply client_regsnoopreply; t_client_realmlistreq client_realmlistreq; t_client_realmlistreq_110 client_realmlistreq_110; t_server_realmlistreply server_realmlistreply; t_server_realmlistreply_110 server_realmlistreply_110; t_client_profilereq client_profilereq; t_server_profilereply server_profilereply; t_client_realmjoinreq_109 client_realmjoinreq_109; t_server_realmjoinreply_109 server_realmjoinreply_109; t_client_unknown_37 client_unknown_37; t_server_unknown_37 server_unknown_37; t_client_unknown_39 client_unknown_39; t_client_loginreq2 client_loginreq2; t_server_loginreply2 server_loginreply2; t_client_loginreq_w3 client_loginreq_w3; t_server_loginreply_w3 server_loginreply_w3; t_client_createacctreq2 client_createacctreq2; t_server_createacctreply2 server_createacctreply2; t_client_changegameport client_changegameport; t_client_file_req client_file_req; t_server_file_reply server_file_reply; t_server_file_unknown1 server_file_unknown1; t_client_file_req2 client_file_req2; t_client_file_req3 client_file_req3; t_server_udptest server_udptest; t_client_udpping client_udpping; t_client_sessionaddr1 client_sessionaddr1; t_client_sessionaddr2 client_sessionaddr2; t_client_motd_w3 client_motd_w3; t_server_motd_w3 server_motd_w3; t_client_logonproofreq client_logonproofreq; t_server_logonproofreply server_logonproofreply; t_client_createaccount_w3 client_createaccount_w3; t_server_createaccount_w3 server_createaccount_w3; t_client_findanongame client_findanongame; t_client_findanongame_at client_findanongame_at; t_client_findanongame_at_inv client_findanongame_at_inv; t_server_findanongame_playgame_cancel server_findanongame_playgame_cancel; t_server_anongame_found server_anongame_found; t_d2cs_bnetd_generic d2cs_bnetd; t_bnetd_d2cs_authreq bnetd_d2cs_authreq; t_d2cs_bnetd_authreply d2cs_bnetd_authreply; t_bnetd_d2cs_authreply bnetd_d2cs_authreply; t_d2cs_bnetd_accountloginreq d2cs_bnetd_accountloginreq; t_bnetd_d2cs_accountloginreply bnetd_d2cs_accountloginreply; t_d2cs_bnetd_charloginreq d2cs_bnetd_charloginreq; t_bnetd_d2cs_charloginreply bnetd_d2cs_charloginreply; t_bnetd_d2cs_gameinforeq bnetd_d2cs_gameinforeq; t_d2cs_bnetd_gameinforeply d2cs_bnetd_gameinforeply; t_d2cs_d2gs_generic d2cs_d2gs; t_d2cs_d2gs_authreq d2cs_d2gs_authreq; t_d2gs_d2cs_authreply d2gs_d2cs_authreply; t_d2cs_d2gs_authreply d2cs_d2gs_authreply; t_d2cs_d2gs_setinitinfo d2cs_d2gs_setinitinfo; t_d2cs_d2gs_setgsinfo d2cs_d2gs_setgsinfo; t_d2gs_d2cs_setgsinfo d2gs_d2cs_setgsinfo; t_d2cs_d2gs_creategamereq d2cs_d2gs_creategamereq; t_d2gs_d2cs_creategamereply d2gs_d2cs_creategamereply; t_d2cs_d2gs_joingamereq d2cs_d2gs_joingamereq; t_d2gs_d2cs_joingamereply d2gs_d2cs_joingamereply; t_d2gs_d2cs_updategameinfo d2gs_d2cs_updategameinfo; t_d2gs_d2cs_closegame d2gs_d2cs_closegame; t_d2cs_d2gs_echoreq d2cs_d2gs_echoreq; t_d2gs_d2cs_echoreply d2gs_d2cs_echoreply; t_d2cs_d2gs_control d2cs_d2gs_control; t_d2cs_d2gs_setconffile d2cs_d2gs_setconffile; t_d2cs_client_generic d2cs_client; t_client_d2cs_loginreq client_d2cs_loginreq; t_d2cs_client_loginreply d2cs_client_loginreply; t_client_d2cs_createcharreq client_d2cs_createcharreq; t_d2cs_client_createcharreply d2cs_client_createcharreply; t_client_d2cs_creategamereq client_d2cs_creategamereq; t_d2cs_client_creategamereply d2cs_client_creategamereply; t_client_d2cs_joingamereq client_d2cs_joingamereq; t_d2cs_client_joingamereply d2cs_client_joingamereply; t_client_d2cs_gamelistreq client_d2cs_gamelistreq; t_d2cs_client_gamelistreply d2cs_client_gamelistreply; t_client_d2cs_gameinforeq client_d2cs_gameinforeq; t_d2cs_client_gameinforeply d2cs_client_gameinforeply; t_client_d2cs_charloginreq client_d2cs_charloginreq; t_d2cs_client_charloginreply d2cs_client_charloginreply; t_client_d2cs_deletecharreq client_d2cs_deletecharreq; t_d2cs_client_deletecharreply d2cs_client_deletecharreply; t_client_d2cs_ladderreq client_d2cs_ladderreq; t_d2cs_client_ladderreply d2cs_client_ladderreply; t_client_d2cs_motdreq client_d2cs_motdreq; t_d2cs_client_motdreply d2cs_client_motdreply; t_client_d2cs_cancelcreategame client_d2cs_cancelcreategame; t_d2cs_client_creategamewait d2cs_client_creategamewait; t_client_d2cs_charladderreq client_d2cs_charladderreq; t_client_d2cs_charlistreq client_d2cs_charlistreq; t_d2cs_client_charlistreply d2cs_client_charlistreply; t_client_d2cs_charlistreq_110 client_d2cs_charlistreq_110; t_d2cs_client_charlistreply_110 d2cs_client_charlistreply_110; t_client_d2cs_convertcharreq client_d2cs_convertcharreq; t_d2cs_client_convertcharreply d2cs_client_convertcharreply; t_client_friendslistreq client_friendslistreq; t_server_friendslistreply server_friendslistreply; t_client_friendinforeq client_friendinforeq; t_server_friendinforeply server_friendinforeply; t_server_friendadd_ack server_friendadd_ack; t_server_frienddel_ack server_frienddel_ack; t_server_friendmove_ack server_friendmove_ack; t_client_arrangedteam_friendscreen client_arrangedteam_friendscreen; t_server_arrangedteam_friendscreen server_arrangedteam_friendscreen; t_client_arrangedteam_invite_friend client_arrangedteam_invite_friend; t_server_arrangedteam_invite_friend_ack server_arrangedteam_invite_friend_ack; t_server_arrangedteam_send_invite server_arrangedteam_send_invite; t_client_arrangedteam_accept_invite client_arrangedteam_accept_invite; t_client_arrangedteam_accept_decline_invite client_arrangedteam_accept_decline_invite; t_server_arrangedteam_member_decline server_arrangedteam_member_decline; t_client_findanongame_profile client_findanongame_profile; t_server_findanongame_profile2 server_findanongame_profile2; t_client_w3route_req client_w3route_req; t_server_w3route_ack server_w3route_ack; t_server_w3route_playerinfo server_w3route_playerinfo; t_server_w3route_levelinfo server_w3route_levelinfo; t_server_w3route_startgame1 server_w3route_startgame1; t_server_w3route_startgame2 server_w3route_startgame2; t_client_w3route_loadingdone client_w3route_loadingdone; t_server_w3route_loadingack server_w3route_loadingack; t_client_w3route_connected client_w3route_connected; t_server_w3route_echoreq server_w3route_echoreq; t_client_w3route_abort client_w3route_abort; t_server_w3route_ready server_w3route_host; t_client_w3route_gameresult client_w3route_gameresult; t_client_findanongame_inforeq client_findanongame_inforeq; t_server_findanongame_inforeply server_findanongame_inforeply; t_client_w3xp_clan_invitereq client_w3xp_clan_invitereq; t_server_w3xp_clan_invitereply server_w3xp_clan_invitereply; t_server_w3xp_clan_invitereq server_w3xp_clan_invitereq; t_client_w3xp_clan_invitereply client_w3xp_clan_invitereply; t_client_w3xp_clan_disbandreq client_w3xp_clan_disbandreq; t_server_w3xp_clan_disbandreply server_w3xp_clan_disbandreply; t_client_w3xp_clan_motdchg client_w3xp_clan_motdchg; t_client_w3xp_clan_motdreq client_w3xp_clan_motdreq; t_server_w3xp_clan_motdreply server_w3xp_clan_motdreply; t_client_w3xp_clanmemberlist_req client_w3xp_clanmemberlist_req; t_server_w3xp_clanmemberlist_reply server_w3xp_clanmemberlist_reply; t_client_w3xp_clan_createreq client_w3xp_clan_createreq; t_server_w3xp_clan_createreply server_w3xp_clan_createreply; t_client_w3xp_clan_createinvitereq client_w3xp_clan_createinvitereq; t_server_w3xp_clan_createinvitereply server_w3xp_clan_createinvitereply; t_server_w3xp_clan_createinvitereq server_w3xp_clan_createinvitereq; t_client_w3xp_clan_createinvitereply client_w3xp_clan_createinvitereply; t_server_w3xp_clan_clanack server_w3xp_clan_clanack; t_server_w3xp_clanmemberupdate server_w3xp_clanmemberupdate; t_client_w3xp_clanmember_rankupdate_req client_w3xp_clanmember_rankupdate_req; t_server_w3xp_clanmember_rankupdate_reply server_w3xp_clanmember_rankupdate_reply; t_client_w3xp_clanmember_remove_req client_w3xp_clanmember_remove_req; t_server_w3xp_clanmember_remove_reply server_w3xp_clanmember_remove_reply; t_client_w3xp_clan_membernewchiefreq client_w3xp_clan_membernewchiefreq; t_server_w3xp_clan_membernewchiefreply server_w3xp_clan_membernewchiefreply; t_server_w3xp_clanquitnotify server_w3xp_clanquitnotify; t_server_w3xp_clanmember_removed_notify server_w3xp_clanmember_removed_notify; t_server_findanongame_iconreply server_findanongame_iconreply; t_client_changeclient client_changeclient; t_client_anongame client_anongame; t_server_anongame_search_reply server_anongame_search_reply; t_client_anongame_tournament_request client_anongame_tournament_request; t_server_anongame_tournament_reply server_anongame_tournament_reply; t_client_setemailreply client_setemailreq; t_server_setemailreq server_setemailreply; t_client_getpasswordreq client_getpasswordreq; t_client_changeemailreq client_changeemailreq; t_client_crashdump client_crashdump; t_client_claninforeq client_claninforeq; t_server_claninforeply server_claninforeply; t_client_findanongame_profile_clan client_findanongame_profile_clan; t_server_findanongame_profile_clan server_findanongame_profile_clan; } u; } t_packet; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_PACKET_PROTOS #define INCLUDED_PACKET_PROTOS #include "common/lstr.h" extern t_packet * packet_create(t_packet_class class) ; extern void packet_destroy(t_packet const * packet); extern t_packet * packet_add_ref(t_packet * packet); extern void packet_del_ref(t_packet * packet); extern t_packet_class packet_get_class(t_packet const * packet); extern char const * packet_get_class_str(t_packet const * packet); extern int packet_set_class(t_packet * packet, t_packet_class class); extern unsigned int packet_get_type(t_packet const * packet); extern char const * packet_get_type_str(t_packet const * packet, t_packet_dir dir); extern int packet_set_type(t_packet * packet, unsigned int type); extern unsigned int packet_get_size(t_packet const * packet); extern int packet_set_size(t_packet * packet, unsigned int size); extern unsigned int packet_get_header_size(t_packet const * packet); extern unsigned int packet_get_flags(t_packet const * packet); extern int packet_set_flags(t_packet * packet, unsigned int flags); extern int packet_append_string(t_packet * packet, char const * str); extern int packet_append_ntstring(t_packet * packet, char const * str); extern int packet_append_lstr(t_packet * packet, t_lstr *lstr); extern int packet_append_data(t_packet * packet, void const * data, unsigned int len); extern void const * packet_get_raw_data_const(t_packet const * packet, unsigned int offset); extern void * packet_get_raw_data(t_packet * packet, unsigned int offset); extern void * packet_get_raw_data_build(t_packet * packet, unsigned int offset); extern char const * packet_get_str_const(t_packet const * packet, unsigned int offset, unsigned int maxlen); extern void const * packet_get_data_const(t_packet const * packet, unsigned int offset, unsigned int len); extern t_packet * packet_duplicate(t_packet const * src); #endif #endif pvpgn-1.8.5/src/common/queue.c0000644000175000017500000001313111151345317015210 0ustar aaronaaron/* * Copyright (C) 1998,1999,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define QUEUE_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif # ifdef HAVE_MEMORY_H # include # endif #endif #include "common/packet.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/queue.h" #include "common/setup_after.h" #define QUEUE_QUANTUM 10 /* allocate ring buffer slots for 10 packets at once */ extern t_packet * queue_pull_packet(t_queue * * queue) { t_queue * temp; t_packet * packet; // eventlog(eventlog_level_debug, __FUNCTION__, "entered: queue %p", queue); if (!queue) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL queue pointer"); return NULL; } temp = *queue; if (!temp || !temp->ulen) return NULL; // eventlog(eventlog_level_debug, __FUNCTION__, "getting element from tail (%d/%d head/tail %d/%d)", temp->alen, temp->ulen, temp->head, temp->tail); /* getting entry from tail and updating queue */ packet = temp->ring[temp->tail]; temp->tail = (temp->tail + 1) % temp->alen; temp->ulen--; // eventlog(eventlog_level_debug, __FUNCTION__, "read %p element from tail (%d/%d head/tail %d/%d)", packet, temp->alen, temp->ulen, temp->head, temp->tail); if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"NULL packet in queue"); return NULL; } return packet; } extern t_packet * queue_peek_packet(t_queue const * const * queue) { t_packet * packet; // eventlog(eventlog_level_debug, __FUNCTION__, "entered: queue %p", queue); if (!queue) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL queue pointer"); return NULL; } if (!*queue || !(*queue)->ulen) return NULL; packet = (*queue)->ring[(*queue)->tail]; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"NULL packet in queue"); return NULL; } return packet; } extern void queue_push_packet(t_queue * * queue, t_packet * packet) { t_queue * temp; void *ptr; // eventlog(eventlog_level_debug, __FUNCTION__, "entered: queue %p packet %p", queue, packet); if (!queue) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL queue pointer"); return; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return; } temp = *queue; if (!temp) { // eventlog(eventlog_level_debug, __FUNCTION__, "queue is NULL , initilizing"); temp = xmalloc(sizeof(t_queue)); temp->alen = temp->ulen = 0; temp->ring = NULL; temp->head = temp->tail = 0; *queue = temp; } if (temp->ulen == temp->alen) { /* ring queue is full, need to allocate some memory */ /* FIXME: find a solution if (temp->alen) eventlog(eventlog_level_error, __FUNCTION__, "queue is full (resizing) (oldsize: %u)", temp->alen); */ ptr = xrealloc(temp->ring, sizeof(t_packet *) * (temp->alen + QUEUE_QUANTUM)); temp->ring = (t_packet **)ptr; temp->alen += QUEUE_QUANTUM; // eventlog(eventlog_level_debug, __FUNCTION__, "queue new size %d/%d head/tail %d/%d", temp->alen, temp->ulen, temp->head, temp->tail); if (temp->head) { unsigned moved; moved = (QUEUE_QUANTUM <= temp->head) ? QUEUE_QUANTUM : temp->head; memmove(temp->ring + temp->ulen, temp->ring, sizeof(t_packet *) * moved); if (temp->head > QUEUE_QUANTUM) { memmove(temp->ring, temp->ring + moved, sizeof(t_packet *) * (temp->head - moved)); temp->head -= moved; } else if (temp->head < QUEUE_QUANTUM) temp->head = temp->ulen + moved; else temp->head = 0; } else temp->head = temp->ulen; } temp->ring[temp->head] = packet_add_ref(packet); temp->head = (temp->head + 1) % temp->alen; temp->ulen++; // eventlog(eventlog_level_debug, __FUNCTION__, "packet added (%d/%d head/tail %d/%d)", temp->alen, temp->ulen, temp->head, temp->tail); } extern int queue_get_length(t_queue const * const * queue) { // eventlog(eventlog_level_debug, __FUNCTION__, "entered: queue %p", queue); if (!queue) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL queue pointer"); return 0; } if (*queue == NULL) return 0; return (*queue)->ulen; } extern void queue_clear(t_queue * * queue) { t_packet * temp; // eventlog(eventlog_level_debug, __FUNCTION__, "entered: queue %p", queue); if (!queue) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL queue pointer"); return; } if (*queue) { while ((temp = queue_pull_packet(queue))) packet_del_ref(temp); if ((*queue)->ring) xfree((void*)((*queue)->ring)); xfree((void*)(*queue)); } } pvpgn-1.8.5/src/common/list.h0000644000175000017500000000670011151345317015050 0ustar aaronaaron/* * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_LIST_TYPES #define INCLUDED_LIST_TYPES typedef struct elem #ifdef LIST_INTERNAL_ACCESS { void * data; struct elem * prev; struct elem * next; } #endif t_elem; typedef struct list #ifdef LIST_INTERNAL_ACCESS { unsigned int len; t_elem * head; t_elem * tail; } #endif t_list; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_LIST_PROTOS #define INCLUDED_LIST_PROTOS extern t_list * list_create(void) ; extern int list_destroy(t_list * list); extern unsigned int list_get_length(t_list const * list); extern int list_prepend_data(t_list * list, void * data); extern int list_append_data(t_list * list, void * data); extern t_elem * list_get_elem_by_data(t_list const * list, void const * data); extern t_elem const * list_get_elem_by_data_const(t_list const * list, void const * data); /* note changed API for those commands: due to direct removal of elements from list, you need to take special care during list traversal. a pointer to the traversal variable needs to be passed to the list_remove functions, so they can properly modify it to point to the "previous" element (the one before the element to be deleted) so the next elem_get_next call will address the "next" element (the one after the element to be deleted) */ extern int list_remove_data(t_list * list, void const * data, t_elem ** elem); /* delete matching item */ extern int list_remove_elem(t_list * list, t_elem ** elem); extern void * list_get_data_by_pos(t_list const * list, unsigned int pos); #ifdef LIST_DEBUG extern t_elem * list_get_first_real(t_list const * list, char const * fn, unsigned int ln); # define list_get_first(L) list_get_first_real(L,__FILE__,__LINE__) #else extern t_elem * list_get_first(t_list const * list); #endif #ifdef LIST_DEBUG extern t_elem const * list_get_first_const_real(t_list const * list, char const * fn, unsigned int ln); # define list_get_first_const(L) list_get_first_const_real(L,__FILE__,__LINE__) #else extern t_elem const * list_get_first_const(t_list const * list); #endif extern void * elem_get_data(t_elem const * elem); extern int elem_set_data(t_elem * elem, void * data); #define elem_get_next(list,elem) elem_get_next_real(list,elem,__FILE__,__LINE__) extern t_elem * elem_get_next_real(t_list const * list, t_elem const * elem,char const * fn, unsigned int ln); extern t_elem const * elem_get_next_const(t_list const * list, t_elem const * elem); #define LIST_TRAVERSE(list,curr) for (curr=(list)?list_get_first(list):(NULL); curr; curr=elem_get_next(list,curr)) #define LIST_TRAVERSE_CONST(list,curr) for (curr=(list)?list_get_first_const(list):(NULL); curr; curr=elem_get_next_const(list,curr)) #endif #endif pvpgn-1.8.5/src/common/util.h0000644000175000017500000000432611151345317015054 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_UTIL_PROTOS #define INCLUDED_UTIL_PROTOS #define JUST_NEED_TYPES #include #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #undef JUST_NEED_TYPES extern int strstart(char const * full, char const * part) ; extern char * file_get_line(FILE * fp) ; extern char * strreverse(char * str); extern int str_to_uint(char const * str, unsigned int * num); extern int str_to_ushort(char const * str, unsigned short * num); extern int str_print_term(FILE * fp, char const * str, unsigned int len, int allow_nl); extern int str_get_bool(char const * str) ; extern char const * seconds_to_timestr(unsigned int totsecs); /* FIXME: can this be marked pure? */ extern int clockstr_to_seconds(char const * clockstr, unsigned int * totsecs); extern char * escape_fs_chars(char const * in, unsigned int len) ; extern char * escape_chars(char const * in, unsigned int len) ; extern char * unescape_chars(char const * in) ; extern void str_to_hex(char * target, char * data, int datalen); extern int hex_to_str(char const * source, char * data, int datalen); extern char * buildpath(char const *root, const char *suffix); extern char *str_skip_space(char *str); extern char *str_skip_word(char *str); extern int timestr_to_time(char const * timestr, time_t* ptime); extern void strlower(char* str); #endif #endif pvpgn-1.8.5/src/common/d2char_checksum.h0000644000175000017500000000174511151345317017126 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_D2CHAR_CHECKSUM_H #define INCLUDED_D2CHAR_CHECKSUM_H #define D2CHARSAVE_CHECKSUM_OFFSET 0x0C extern int d2charsave_checksum(unsigned char const * data, unsigned int len, unsigned int offset); #endif pvpgn-1.8.5/src/common/d2char_checksum.c0000644000175000017500000000225711151345317017120 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "common/setup_after.h" extern int d2charsave_checksum(unsigned char const * data, unsigned int len,unsigned int offset) { int checksum; unsigned int i; unsigned int ch; if (!data) return 0; checksum=0; for (i=0; i=offset && iO.....Ma 0020: 70 73 5C 46 72 6F 7A 65 6E 54 68 72 6F 6E 65 5C ps\FrozenThrone\ 0030: 28 34 29 46 6C 6F 6F 64 70 6C 61 69 6E 73 31 76 (4)Floodplains1v 0040: 31 2E 77 33 78 00 FF FF FF FF 31 44 4C 46 02 00 1.w3x.....1DLF.. 0050: 00 00 02 02 .... PG 2v2 # 28332 packet from server: type=0x44ff(unknown) length=83 class=bnet 0000: FF 44 53 00 01 02 00 00 00 00 00 00 00 D3 E9 00 .DS............. 0010: DC E0 17 2E 67 00 00 9A 7D 56 0F 06 00 01 4D 61 ....g...}V....Ma 0020: 70 73 5C 46 72 6F 7A 65 6E 54 68 72 6F 6E 65 5C ps\FrozenThrone\ 0030: 28 36 29 53 63 6F 72 63 68 65 64 42 61 73 69 6E (6)ScorchedBasin 0040: 2E 77 33 78 00 FF FF FF FF 4D 41 45 54 04 02 00 .w3x.....MAET... 0050: 00 02 02 ... PG 4v4 # 28827 packet from server: type=0x44ff(unknown) length=82 class=bnet 0000: FF 44 52 00 01 02 00 00 00 00 00 00 00 3F F1 53 .DR..........?.S 0010: DA E0 17 77 D6 00 00 92 D4 B8 56 06 00 03 4D 61 ...w......V...Ma 0020: 70 73 5C 46 72 6F 7A 65 6E 54 68 72 6F 6E 65 5C ps\FrozenThrone\ 0030: 28 38 29 42 61 74 74 6C 65 67 72 6F 75 6E 64 2E (8)Battleground. 0040: 77 33 78 00 FF FF FF FF 4D 41 45 54 08 02 00 00 w3x.....MAET.... 0050: 02 02 .. PG 3v3 # 357 packet from server: type=0x44ff(unknown) length=84 class=bnet 0000: FF 44 54 00 01 01 00 00 00 00 00 00 00 3F F1 53 .DT..........?.S 0010: CE E0 17 10 22 01 00 29 0F 62 A0 06 00 02 4D 61 ...."..).b....Ma 0020: 70 73 5C 46 72 6F 7A 65 6E 54 68 72 6F 6E 65 5C ps\FrozenThrone\ 0030: 28 36 29 42 6C 6F 6F 64 73 74 6F 6E 65 4D 65 73 (6)BloodstoneMes 0040: 61 2E 77 33 78 00 FF FF FF FF 4D 41 45 54 06 02 a.w3x.....MAET.. 0050: 00 00 02 02 .... PG 4v4 # 620 packet from server: type=0x44ff(unknown) length=79 class=bnet 0000: FF 44 4F 00 01 02 00 00 00 00 00 00 00 3F F1 53 .DO..........?.S 0010: DA E0 17 94 22 01 00 4C 29 5F 62 06 00 03 4D 61 ...."..L)_b...Ma 0020: 70 73 5C 46 72 6F 7A 65 6E 54 68 72 6F 6E 65 5C ps\FrozenThrone\ 0030: 28 38 29 53 61 6E 63 74 75 61 72 79 2E 77 33 78 (8)Sanctuary.w3x 0040: 00 FF FF FF FF 4D 41 45 54 08 02 00 00 02 02 .....MAET...... PG sffa # 810 packet from server: type=0x44ff(unknown) length=82 class=bnet 0000: FF 44 52 00 01 03 00 00 00 00 00 00 00 3F F1 53 .DR..........?.S 0010: C9 E0 17 3E 22 01 00 93 44 ED 22 06 00 04 4D 61 ...>"...D."...Ma 0020: 70 73 5C 46 72 6F 7A 65 6E 54 68 72 6F 6E 65 5C ps\FrozenThrone\ 0030: 28 38 29 42 61 74 74 6C 65 67 72 6F 75 6E 64 2E (8)Battleground. 0040: 77 33 78 00 FF FF FF FF 20 41 46 46 05 00 00 00 w3x..... AFF.... 0050: 02 02 .. =-=-=-=-==-=-=-=-= AT 2v2 # 74077 packet from server: type=0x44ff(unknown) length=87 class=bnet 0000: FF 44 57 00 01 09 00 00 00 00 00 00 00 3F F1 53 .DW..........?.S 0010: D3 E0 17 D8 D1 00 00 B4 2B 57 C6 06[01 00]4D 61 ........+W....Ma 0020: 70 73 5C 46 72 6F 7A 65 6E 54 68 72 6F 6E 65 5C ps\FrozenThrone\ 0030: 28 36 29 53 74 72 61 6E 67 6C 65 74 68 6F 72 6E (6)Stranglethorn 0040: 56 61 6C 65 2E 77 33 78 00 FF FF FF FF 32 53 56 Vale.w3x.....2SV 0050: 32 04 02 00 00 02 02 2...... AT 2v2 # 83549 packet from server: type=0x44ff(unknown) length=79 class=bnet 0000: FF 44 4F 00 01 0A 00 00 00 00 00 00 00 3F F1 53 .DO..........?.S 0010: CF E0 17 BB D1 00 00 01 CB E4 BA 06[01 00]4D 61 ..............Ma 0020: 70 73 5C 46 72 6F 7A 65 6E 54 68 72 6F 6E 65 5C ps\FrozenThrone\ 0030: 28 36 29 47 6E 6F 6C 6C 57 6F 6F 64 2E 77 33 78 (6)GnollWood.w3x 0040: 00 FF FF FF FF 32 53 56 32 04 02 00 00 02 02 .....2SV2...... */ #define SERVER_ANONGAME_FOUND 0x44ff typedef struct { t_bnet_header h; bn_byte option; /* 1: anongame found */ bn_int count; bn_int unknown1; /* 00 00 00 00 */ bn_int ip; bn_short port; bn_byte unknown2; bn_byte unknown3; bn_short unknown4; /* usually 00 00 , seen 01 00 */ bn_int id; /* random val for identifying client */ bn_byte unknown5; /* 0x06 */ bn_byte type; /* 0 = PG , 1 = AT , 2 = TY - from TYPE */ bn_byte gametype; /* for PG - 0 = 1v1 , 1 = 2v2 , 2 = 3v3 , 3 = 4v4 , 4 = sffa * for AT - 0 = 2v2 , 2 = 3v3 , 3 = 4v3 * for TY - set to 0 * from TYPE */ /* char * mapname */ /* t_saf_pt2 * pt2 */ } PACKED_ATTR() t_server_anongame_found; /* MISC PACKET APPEND DATA's */ typedef struct { bn_int unknown1; /* 0xFFFFFFFF */ bn_int anongame_string; /* ie. SOLO, TEAM, 2VS2, etc. */ bn_byte totalplayers; bn_byte totalteams; /* 1v1 & sffa = 0, rest 2 */ bn_short unknown2; /* 0x0000 */ bn_byte visibility; /* 0x01 = dark - 0x02 = default */ bn_byte unknown3; /* 0x02 */ } PACKED_ATTR() t_saf_pt2; /***********************************************************************************/ /* option 02 - info request */ #define CLIENT_FINDANONGAME_INFOREQ 0x44ff typedef struct { t_bnet_header h; bn_byte option; /* type of request: * 0x02 for matchmaking infos */ bn_int count; /* 0x00000001 increments each request of same type */ bn_byte noitems; } PACKED_ATTR() t_client_findanongame_inforeq; #define SERVER_FINDANONGAME_INFOREPLY 0x44ff typedef struct { t_bnet_header h; bn_byte option; /* as received from client */ bn_int count; /* as received from client */ bn_byte noitems; /* not very sure about it */ /* data */ /* for type 0x02 : if is : URL\0 : contains 3 NULL terminated urls/strings MAP\0 : contains 7 (seen so far) maps names TYPE : unknown 38 bytes probably meaning anongame types DESC : */ } PACKED_ATTR() t_server_findanongame_inforeply; /***********************************************************************************/ /* option 03 - playgame cancel */ #define SERVER_FINDANONGAME_PLAYGAME_CANCEL 0x44ff typedef struct { t_bnet_header h; /* header */ bn_byte cancel; /* Cancel byte always 03 */ bn_int count; } PACKED_ATTR() t_server_findanongame_playgame_cancel; /* option 04 - profile request */ typedef struct { t_bnet_header h; bn_byte option; bn_int count; /* USERNAME TO LOOKUP * CLIENT TAG */ } PACKED_ATTR() t_client_findanongame_profile; #define SERVER_FINDANONGAME_PROFILE 0x44ff /* typedef struct { t_bnet_header h; //header bn_byte option; // in this case it will be 0x04 (for profile) bn_int count; // count that goes up each time user clicks on someones profile // REST OF PROFILE STATS - THIS WILL BE SET IN HANDLE_BNET.C after // SERVER LOOKS UP THE USER ACCOUNT } PACKED_ATTR() t_server_findanongame_profile; */ typedef struct { t_bnet_header h; bn_byte option; bn_int count; bn_int icon; bn_byte rescount; /* REST OF PROFILE STATS - THIS WILL BE SET IN HANDLE_BNET.C after * SERVER LOOKS UP THE USER ACCOUNT */ } PACKED_ATTR() t_server_findanongame_profile2; /***********************************************************************************/ /* option 07 - tournament request */ #define CLIENT_FINDANONGAME_TOURNAMENT_REQUEST 0x44ff typedef struct { t_bnet_header h; bn_byte option; /* 07 */ bn_int count; /* 01 00 00 00 */ } PACKED_ATTR() t_client_anongame_tournament_request; #define SERVER_FINDANONGAME_TOURNAMENT_REPLY 0x44ff typedef struct { t_bnet_header h; bn_byte option; /* 07 */ bn_int count; /* 00 00 00 01 reply with same number */ bn_byte type; /* type - 01 = notice - time = prelim round begins * 02 = signups - time = signups end * 03 = signups over - time = prelim round ends * 04 = prelim over - time = finals round 1 begins */ bn_byte unknown; /* 00 */ bn_short unknown4; /* random ? might be part of time/date ? */ bn_int timestamp; bn_byte unknown5; /* 01 effects time/date */ bn_short countdown; /* countdown until next timestamp (seconds) */ bn_short unknown2; /* 00 00 */ bn_byte wins; /* during prelim */ bn_byte losses; /* during prelim */ bn_byte ties; /* during prelim */ bn_byte unknown3; /* 00 = notice. 08 = signups thru prelim over (02-04) */ bn_byte selection; /* matches anongame_TY_section of DESC */ bn_byte descnum; /* matches desc_count of DESC */ bn_byte nulltag; /* 00 */ } PACKED_ATTR() t_server_anongame_tournament_reply; /***********************************************************************************/ /* option 08 - clan profile request */ typedef struct { t_bnet_header h; bn_byte option; bn_int count; bn_int clantag; bn_int clienttag; } PACKED_ATTR() t_client_findanongame_profile_clan; #define SERVER_FINDANONGAME_PROFILE_CLAN 0x44ff typedef struct { t_bnet_header h; bn_byte option; bn_int count; bn_byte rescount; /* REST OF PROFILE STATS - THIS WILL BE SET IN HANDLE_BNET.C after * SERVER LOOKS UP THE USER ACCOUNT */ } PACKED_ATTR() t_server_findanongame_profile_clan; /***********************************************************************************/ /* option 9 - icon request */ #define SERVER_FINDANONGAME_ICONREPLY 0x44ff typedef struct{ t_bnet_header h; bn_byte option; /* as received from client */ bn_int count; /* as received from client */ bn_int curricon; /* current icon code */ bn_byte table_width; /* the icon table width */ bn_byte table_size; /* the icon table total size */ /* table data */ } PACKED_ATTR() t_server_findanongame_iconreply; /***********************************************************************************/ #define SERVER_ANONGAME_SOLO_STR 0x534F4C4F /* "SOLO" */ #define SERVER_ANONGAME_TEAM_STR 0x5445414D /* "TEAM" */ #define SERVER_ANONGAME_SFFA_STR 0x46464120 /* "FFA " */ #define SERVER_ANONGAME_AT2v2_STR 0x32565332 /* "2VS2" */ #define SERVER_ANONGAME_AT3v3_STR 0x33565333 /* "3VS3" */ #define SERVER_ANONGAME_AT4v4_STR 0x34565334 /* "4VS4" */ #define SERVER_ANONGAME_TY_STR 0X54592020 /* "TY " FIXME-TY: WHAT TO PUT HERE */ #define CLIENT_FINDANONGAME_INFOTAG_URL 0x55524c /* URL\0 */ #define CLIENT_FINDANONGAME_INFOTAG_MAP 0x4d4150 /* MAP\0 */ #define CLIENT_FINDANONGAME_INFOTAG_TYPE 0x54595045 /* TYPE */ #define CLIENT_FINDANONGAME_INFOTAG_DESC 0x44455343 /* DESC */ #define CLIENT_FINDANONGAME_INFOTAG_LADR 0x4c414452 /* LADR */ #define CLIENT_FINDANONGAME_INFOTAG_SOLO 0x534f4c4f /* SOLO */ #define CLIENT_FINDANONGAME_INFOTAG_TEAM 0x5445414d /* TEAM */ #define CLIENT_FINDANONGAME_INFOTAG_FFA 0x46464120 /* FFA\20 */ #define ANONGAME_TYPE_1V1 0 #define ANONGAME_TYPE_2V2 1 #define ANONGAME_TYPE_3V3 2 #define ANONGAME_TYPE_4V4 3 #define ANONGAME_TYPE_SMALL_FFA 4 #define ANONGAME_TYPE_AT_2V2 5 #define ANONGAME_TYPE_TEAM_FFA 6 #define ANONGAME_TYPE_AT_3V3 7 #define ANONGAME_TYPE_AT_4V4 8 /* Added by Omega */ #define ANONGAME_TYPE_TY 9 #define ANONGAME_TYPE_5V5 10 #define ANONGAME_TYPE_6V6 11 #define ANONGAME_TYPE_2V2V2 12 #define ANONGAME_TYPE_3V3V3 13 #define ANONGAME_TYPE_4V4V4 14 #define ANONGAME_TYPE_2V2V2V2 15 #define ANONGAME_TYPE_3V3V3V3 16 #define ANONGAME_TYPE_AT_2V2V2 17 #define ANONGAME_TYPES 18 #define SERVER_FINDANONGAME_PROFILE_UNKNOWN2 0x6E736865 /* Sheep */ /***********************************************************************************/ /***********************************************************************************/ /* This is a blank packet - includes just type and size */ #define CLIENT_ARRANGEDTEAM_FRIENDSCREEN 0x60ff typedef struct { t_bnet_header h; } PACKED_ATTR() t_client_arrangedteam_friendscreen; /***********************************************************************************/ #define SERVER_ARRANGEDTEAM_FRIENDSCREEN 0x60ff typedef struct { t_bnet_header h; bn_byte f_count; /* usernames get appended here */ } PACKED_ATTR() t_server_arrangedteam_friendscreen; #define SERVER_ARRANGED_TEAM_ADDNAME 0x01 /***********************************************************************************/ /* 0000: FF 61 1C 00 01 00 00 00 C9 7B A0 02 01 00 00 00 .........{...... 0010: 01 74 72 65 6E 64 65 63 69 64 65 00 .trendecide. */ #define CLIENT_ARRANGEDTEAM_INVITE_FRIEND 0x61ff typedef struct { t_bnet_header h; bn_int count; bn_int id; bn_int unknown1; /* 01 00 00 00 */ bn_byte numfriends; /* next is a byte, that is the number of friends to invite */ /* usernames get appended here */ } PACKED_ATTR() t_client_arrangedteam_invite_friend; /***********************************************************************************/ #define SERVER_ARRANGEDTEAM_INVITE_FRIEND_ACK 0x61ff typedef struct { t_bnet_header h; bn_int count; bn_int id; /* client id */ bn_int timestamp; bn_byte teamsize; /* numfriends + 1 */ bn_int info[5]; } PACKED_ATTR() t_server_arrangedteam_invite_friend_ack; /***********************************************************************************/ #define SERVER_ARRANGEDTEAM_SEND_INVITE 0x63ff typedef struct { t_bnet_header h; bn_int count; bn_int id; /* client id of inviter */ bn_int inviterip; /* IP address of the person who invited them into the game */ bn_short port; /* Port of the person who invited them into the game */ bn_byte numfriends; /* Number of friends that got invited to the game */ /* username of the inviter */ /* usernames of the others who got invited */ } PACKED_ATTR() t_server_arrangedteam_send_invite; /***********************************************************************************/ #define CLIENT_ARRANGEDTEAM_ACCEPT_DECLINE_INVITE 0x63ff typedef struct { t_bnet_header h; bn_int count; bn_int id; bn_int option; /* accept or decline */ /* username of the inviter */ } PACKED_ATTR() t_client_arrangedteam_accept_decline_invite; #define CLIENT_ARRANGEDTEAM_ACCEPT 0x00000003 #define CLIENT_ARRANGEDTEAM_DECLINE 0x00000002 /***********************************************************************************/ #define SERVER_ARRANGEDTEAM_MEMBER_DECLINE 0x62ff typedef struct { t_bnet_header h; bn_int count; bn_int action; /* number assigned to player? playernum? */ /* username of the person who declined invitation */ } PACKED_ATTR() t_server_arrangedteam_member_decline; #define SERVER_ARRANGEDTEAM_ACCEPT 0x00000003 #define SERVER_ARRANGEDTEAM_DECLINE 0x00000002 /***********************************************************************************/ /* not used ?? [Omega] */ /* 0000: FF 64 1C 00 02 00 00 00 00 00 00 00 01 00 00 00 .d.............. 0010: 00 00 00 00 03 00 00 00 00 00 00 00 ............ */ /* THIS NEEDS FINISHED */ /* #define SERVER_ARRANGEDTEAM_TEAM_STATS 0x64ff typedef struct { t_bnet_header h; } */ /***********************************************************************************/ /***********************************************************************************/ /* # 144 packet from client: type=0x65ff(unknown) length=4 class=bnet 0000: FF 65 04 00 .e.. */ #define CLIENT_FRIENDSLISTREQ 0x65ff typedef struct { t_bnet_header h; } PACKED_ATTR() t_client_friendslistreq; /* # 158 packet from server: type=0x65ff(unknown) length=16 class=bnet 0000: FF 65 10 00 01 66 6F 6F 00 00 00 00 00 00 00 00 .e.. .foo. ....... */ #define SERVER_FRIENDSLISTREPLY 0x65ff typedef struct { t_bnet_header h; bn_byte friendcount; /* 1 byte status, 0-terminated name, 6 bytes unknown, ... */ } PACKED_ATTR() t_server_friendslistreply; typedef struct { bn_byte status; bn_byte location; bn_int clienttag; } PACKED_ATTR() t_server_friendslistreply_status; /* # 124 packet from client: type=0x66ff(unknown) length=5 class=bnet 0000: FF 66 05 00 00 .f... */ /* FF 66-05 00 00 40 - AT */ #define CLIENT_FRIENDINFOREQ 0x66ff typedef struct { t_bnet_header h; bn_byte friendnum; } PACKED_ATTR() t_client_friendinforeq; /* # 126 packet from server: type=0x66ff(unknown) length=12 class=bnet 0000: FF 66 0C 00 00 00 00 00 00 00 00 00 .f.......... Arranged Team sends this to each inviter FF 66-1A 00 00 01 03 33 52 41 ..g....f.....3RA 0x0040 57 41 72 72 61 6E 67 65-64 20 54 65 61 6D 73 00 WArranged Teams. and this to the inviter FF 66-18 00 00 01 02 33 52 41 ..i....f.....3RA 0x0040 57 57 61 72 63 72 61 66-74 20 49 49 49 00 WWarcraft III. */ #define SERVER_FRIENDINFOREPLY 0x66ff typedef struct { t_bnet_header h; bn_byte friendnum; bn_byte type; bn_byte status; bn_int clienttag; /* game name */ } PACKED_ATTR() t_server_friendinforeply; #define FRIEND_TYPE_NON_MUTUAL 0x00 #define FRIEND_TYPE_MUTUAL 0x01 #define FRIEND_TYPE_DND 0x02 #define FRIEND_TYPE_AWAY 0x04 /******************************************************/ /* # 126 packet from server: type=0x67ff(unknown) length=15 class=bnet 0000: FF 67 0F 00 66 6F 6F 00 00 00 00 00 00 00 00 .g..foo........ */ #define SERVER_FRIENDADD_ACK 0x67ff typedef struct { t_bnet_header h; /* friend name, status */ } PACKED_ATTR() t_server_friendadd_ack; /******************************************************/ /* # 114 packet from server: type=0x68ff(unknown) length=5 class=bnet 0000: FF 68 05 00 01 .h... */ #define SERVER_FRIENDDEL_ACK 0x68ff typedef struct { t_bnet_header h; bn_byte friendnum; } PACKED_ATTR() t_server_frienddel_ack; /******************************************************/ #define SERVER_FRIENDMOVE_ACK 0x69ff typedef struct { t_bnet_header h; bn_byte pos1; bn_byte pos2; } PACKED_ATTR() t_server_friendmove_ack; #define FRIENDSTATUS_OFFLINE 0x00 #define FRIENDSTATUS_ONLINE 0x01 #define FRIENDSTATUS_CHAT 0x02 #define FRIENDSTATUS_PUBLIC_GAME 0x03 #define FRIENDSTATUS_PRIVATE_GAME 0x05 #endif pvpgn-1.8.5/src/common/introtate.h0000644000175000017500000000463611151345317016114 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_INTROTATE_PROTOS #define INCLUDED_INTROTATE_PROTOS /* * ROTL(x,n,w) rotates "w" bit wide value "x" by "n" bits to the left * * The expression passed in as x must have a type at least as wide as w. * The type should probably be unsigned for this to be guaranteed to work * properly. If n or w is signed and larger than x remember that the * promotion rules would promote x to be of the same (signed) type. * * Unfortunately C doesn't have rotate operations and they can be difficult * to implement when handling rotates by zero, negative numbers, or numbers * greater or equal to the bit width of the number. This is because ANSI/ISO * C makes weak guarantees about the left and right shift operators. We * would like to not depend on word size, endianness, or how negative * integers are represented. Unfortunately only some of those goals may be * achieved. As for optimization, a really good compiler might be able to * recognize what we are doing and turn it into a single machine instruction. */ /* valid for 00 */ /*#define ROTL(x,n,w) (((x)<<(n)) | ((x)>>((w)-(n))))*/ /* valid for 0<=n0 */ /*#define ROTL(x,n,w) (((x)<<(n)) | ((x)>>(((-(n))&(w-1)))))*/ /* valid for 0<=n and w>0 , depends on 2's complement */ #define ROTL(x,n,w) (((x)<<((n)&(w-1))) | ((x)>>(((-(n))&(w-1))))) /* valid for 0<=n and w>0 , uses three mods and an ugly conditional */ /* FIXME: and also a bug because it doesn't work on PPC */ /*#define ROTL(x,n,w) (((n)%(w)) ? (((x)<<((n)%(w))) | ((x)>>((w)-((n)%(w))))) : (x))*/ #define ROTL32(x,n) ROTL(x,n,32) #define ROTL16(x,n) ROTL(x,n,16) #endif #endif pvpgn-1.8.5/src/common/bnettime.c0000644000175000017500000001467311151345317015707 0ustar aaronaaron/* * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define BNETTIME_INTERNAL_ACCESS #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include #include "compat/strerror.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/gettimeofday.h" #ifdef HAVE_SYS_TYPES_H # include #endif #include "common/eventlog.h" #include "common/bn_type.h" #include "common/bnettime.h" #include "common/setup_after.h" /* * By comparing the hex numbers from packet dumps with the times displayed * on the login screen, bnettime seems to be in units of 10E-7 seconds. It * is stored in a 64bit value, and represented as two distinct numbers when * it is used as a string in the protocol. * * examples (client in GMT timezone): * 11/04/99 05:16 0x01 "29304451 3046165090" * 01/03/99 11:19 0x01 "29243146 3825346784" * 08/02/99 21:28 0x01 "29285677 4283311890" * 12/12/99 01:55 0x01 "29312068 151587081" * * The top number seems to be in units of about 7 minutes because the bottom * number rolls over every 2^32 10E-7 seconds, which is: * (2^32)*.0000001 * 429.4967296 // seconds * 429/60 * 7.15827882666666666666 // minutes * * The epoch was determined using a binary search looking for Jan 1, 1970 * (GMT) to be displayed after setting the last game time to a pair of * numbers. It was determined through all 64 bits by looking for the exact * number where adding one pushes it over to 00:01. It was determined to be: * "27111902 3577643008" * * It appears that this is the same format as is used in MS-DOS to store file * times. The format is a 64 bit number telling how many 100 nanosecond * intervals since Jan 1, 1601. * * If I was clever I should be able to do this without floating point math. * I don't feel like being clever though :) (Refer to the function * DOSFS_UnixTimeToFileTime() in dosfs.c in the WINE source code for an * example that I wish I had seen before writing this). * * Update... from looking at the WINE sources VAP has determined that these * are actually in MS-Windows FileTime format. * * "In the WINE listing, you can see that * FileTime = (UnixTime * 10 000 000) + 116 444 736 000 000 000 + remainder * These dates are represented from 1 Jan 1601." */ #define SEC_PER_USEC .0000001 #define UNIX_EPOCH 11644473600. /* seconds the Unix epoch is from the bnettime epoch */ #define SEC_PER_UPPER 429.4967296 /* (2^32)*10E-7 */ #define SEC_PER_LOWER .0000001 #define UPPER_PER_SEC .00232830643653869628 /* 10E7/(2^32) */ #define LOWER_PER_SEC 10000000. extern t_bnettime secs_to_bnettime(double secs) { t_bnettime temp; temp.u = (unsigned int)(secs*UPPER_PER_SEC); temp.l = (unsigned int)(secs*LOWER_PER_SEC); return temp; } extern double bnettime_to_secs(t_bnettime bntime) { return ((double)bntime.u)*SEC_PER_UPPER+ ((double)bntime.l)*SEC_PER_LOWER; } extern t_bnettime time_to_bnettime(time_t stdtime, unsigned int usec) { return secs_to_bnettime((double)stdtime+(double)usec*SEC_PER_USEC+UNIX_EPOCH); } extern time_t bnettime_to_time(t_bnettime bntime) { return (time_t)(bnettime_to_secs(bntime)-UNIX_EPOCH); } /* return current time as bnettime */ extern t_bnettime bnettime(void) { struct timeval tv; if (gettimeofday(&tv,NULL)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not get time (gettimeofday: %s)",pstrerror(errno)); return time_to_bnettime(time(NULL),0); } return time_to_bnettime((time_t)tv.tv_sec,tv.tv_usec); } /* FIXME: the string functions here should probably go in account_wrap */ extern char const * bnettime_get_str(t_bnettime bntime) { static char temp[1024]; sprintf(temp,"%u %u",bntime.u,bntime.l); return temp; } extern int bnettime_set_str(t_bnettime * bntime, char const * timestr) { if (!bntime) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL bntime"); return -1; } if (!timestr) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL timestr"); return -1; } if (sscanf(timestr,"%u %u",&bntime->u,&bntime->l)!=2) return -1; return 0; } extern void bnettime_to_bn_long(t_bnettime in, bn_long * out) { if (!out) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL out"); return; } bn_long_set_a_b(out,in.u,in.l); } extern void bn_long_to_bnettime(bn_long in, t_bnettime * out) { if (!out) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL out"); return; } out->u = bn_long_get_a(in); out->l = bn_long_get_b(in); } extern int local_tzbias(void) /* in minutes */ { #ifdef HAVE_MKTIME time_t now; time_t test; time_t testloc; struct tm * temp; now = time(NULL); if (!(temp = gmtime(&now))) return 0; if ((test = mktime(temp))==(time_t)(-1)) return 0; if (!(temp = localtime(&now))) return 0; if ((testloc = mktime(temp))==(time_t)(-1)) return 0; if (testloc>test) /* time_t is probably unsigned... */ return -(int)(testloc-test)/60; return (int)(test-testloc)/60; #else return 0; /* can't determine current offset */ #endif } extern t_bnettime bnettime_add_tzbias(t_bnettime bntime, int tzbias) { return secs_to_bnettime(bnettime_to_secs(bntime)-(double)tzbias*60.0); } pvpgn-1.8.5/src/common/fdwatch_kqueue.c0000644000175000017500000002170611151345317017072 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * *BSD kqueue(2) based backend * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_EVENT_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include "fdwatch.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/setup_after.h" #ifdef HAVE_KQUEUE static int sr; static int kq; static struct kevent *kqchanges = NULL; /* changes to make to kqueue */ static struct kevent *kqevents = NULL; /* events to investigate */ /* r/w indices from idx to the kqchanges index where the change is stored */ static int *_rridx, *_wridx; static unsigned nochanges; static int fdw_kqueue_init(int nfds); static int fdw_kqueue_close(void); static int fdw_kqueue_add_fd(int idx, t_fdwatch_type rw); static int fdw_kqueue_del_fd(int idx); static int fdw_kqueue_watch(long timeout_msecs); static void fdw_kqueue_handle(void); t_fdw_backend fdw_kqueue = { fdw_kqueue_init, fdw_kqueue_close, fdw_kqueue_add_fd, fdw_kqueue_del_fd, fdw_kqueue_watch, fdw_kqueue_handle }; static int fdw_kqueue_init(int nfds) { int i; if ((kq = kqueue()) == -1) return -1; kqevents = (struct kevent *) xmalloc(sizeof(struct kevent) * nfds); kqchanges = (struct kevent *) xmalloc(sizeof(struct kevent) * nfds * 2); _rridx = (int *) xmalloc(sizeof(int) * nfds); _wridx = (int *) xmalloc(sizeof(int) * nfds); memset(kqchanges, 0, sizeof(struct kevent) * nfds); for (i = 0; i < nfds; i++) { _rridx[i] = -1; _wridx[i] = -1; } sr = 0; nochanges = 0; eventlog(eventlog_level_info, __FUNCTION__, "fdwatch kqueue() based layer initialized (max %d sockets)", nfds); return 0; } static int fdw_kqueue_close(void) { if (_rridx) { xfree((void *) _rridx); _rridx = NULL; } if (_wridx) { xfree((void *) _wridx); _wridx = NULL; } if (kqchanges) { xfree((void *) kqchanges); kqchanges = NULL; } if (kqevents) { xfree((void *) kqevents); kqevents = NULL; } sr = 0; nochanges = 0; return 0; } static int fdw_kqueue_add_fd(int idx, t_fdwatch_type rw) { static int ridx; t_fdwatch_fd *cfd; /* eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); */ cfd = fdw_fds + idx; /* adding read event filter */ if (!(fdw_rw(cfd) & fdwatch_type_read) && rw & fdwatch_type_read) { if (_rridx[idx] >= 0 && _rridx[idx] < nochanges && kqchanges[_rridx[idx]].ident == fdw_fd(cfd)) { ridx = _rridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (read) fd on %d", ridx); */ } else { ridx = nochanges++; _rridx[idx] = ridx; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (read) fd on %d", ridx); */ } EV_SET(kqchanges + ridx, fdw_fd(cfd), EVFILT_READ, EV_ADD, 0, 0, (void*)idx); } else if (fdw_rw(cfd) & fdwatch_type_read && !( rw & fdwatch_type_read)) { if (_rridx[idx] >= 0 && _rridx[idx] < nochanges && kqchanges[_rridx[idx]].ident == fdw_fd(cfd)) { ridx = _rridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (read) fd on %d", ridx); */ } else { ridx = nochanges++; _rridx[idx] = ridx; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (read) fd on %d", ridx); */ } EV_SET(kqchanges + ridx, fdw_fd(cfd), EVFILT_READ, EV_DELETE, 0, 0, (void*)idx); } /* adding write event filter */ if (!(fdw_rw(cfd) & fdwatch_type_write) && rw & fdwatch_type_write) { if (_wridx[idx] >= 0 && _wridx[idx] < nochanges && kqchanges[_wridx[idx]].ident == fdw_fd(cfd)) { ridx = _wridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (write) fd on %d", ridx); */ } else { ridx = nochanges++; _wridx[idx] = ridx; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (write) fd on %d", ridx); */ } EV_SET(kqchanges + ridx, fdw_fd(cfd), EVFILT_WRITE, EV_ADD, 0, 0, (void*)idx); } else if (fdw_rw(cfd) & fdwatch_type_write && !(rw & fdwatch_type_write)) { if (_wridx[idx] >= 0 && _wridx[idx] < nochanges && kqchanges[_wridx[idx]].ident == fdw_fd(cfd)) { ridx = _wridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (write) fd on %d", ridx); */ } else { ridx = nochanges++; _wridx[idx] = ridx; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (write) fd on %d", ridx); */ } EV_SET(kqchanges + ridx, fdw_fd(cfd), EVFILT_WRITE, EV_DELETE, 0, 0, (void*)idx); } return 0; } static int fdw_kqueue_del_fd(int idx) { t_fdwatch_fd *cfd; /* eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd); */ if (sr > 0) eventlog(eventlog_level_error, __FUNCTION__, "BUG: called while still handling sockets"); cfd = fdw_fds + idx; /* the last event changes about this fd has not yet been sent to kernel */ if (fdw_rw(cfd) & fdwatch_type_read && nochanges && _rridx[idx] >= 0 && _rridx[idx] < nochanges && kqchanges[_rridx[idx]].ident == fdw_fd(cfd)) { nochanges--; if (_rridx[idx] < nochanges) { int oidx; oidx = (int)(kqchanges[nochanges].udata); if (kqchanges[nochanges].filter == EVFILT_READ && _rridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ _rridx[oidx] = _rridx[idx]; memcpy(kqchanges + _rridx[idx], kqchanges + nochanges, sizeof(struct kevent)); } if (kqchanges[nochanges].filter == EVFILT_WRITE && _wridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ _wridx[oidx] = _rridx[idx]; memcpy(kqchanges + _rridx[idx], kqchanges + nochanges, sizeof(struct kevent)); } } _rridx[idx] = -1; } if (fdw_rw(cfd) & fdwatch_type_write && nochanges && _wridx[idx] >= 0 && _wridx[idx] < nochanges && kqchanges[_wridx[idx]].ident == fdw_fd(cfd)) { nochanges--; if (_wridx[idx] < nochanges) { int oidx; oidx = (int)(kqchanges[nochanges].udata); if (kqchanges[nochanges].filter == EVFILT_READ && _rridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ _rridx[oidx] = _wridx[idx]; memcpy(kqchanges + _wridx[idx], kqchanges + nochanges, sizeof(struct kevent)); } if (kqchanges[nochanges].filter == EVFILT_WRITE && _wridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ _wridx[oidx] = _wridx[idx]; memcpy(kqchanges + _wridx[idx], kqchanges + nochanges, sizeof(struct kevent)); } } _wridx[idx] = -1; } /* here we presume the calling code does close() on the socket and if so * it is automatically removed from any kernel kqueues */ return 0; } static int fdw_kqueue_watch(long timeout_msec) { static struct timespec ts; ts.tv_sec = timeout_msec / 1000L; ts.tv_nsec = (timeout_msec % 1000L) * 1000000L; sr = kevent(kq, nochanges > 0 ? kqchanges : NULL, nochanges, kqevents, fdw_maxcons, &ts); nochanges = 0; return sr; } static void fdw_kqueue_handle(void) { register unsigned i; t_fdwatch_fd *cfd; /* eventlog(eventlog_level_trace, __FUNCTION__, "called"); */ for (i = 0; i < sr; i++) { /* eventlog(eventlog_level_trace, __FUNCTION__, "checking %d ident: %d read: %d write: %d", i, kqevents[i].ident, kqevents[i].filter & EVFILT_READ, kqevents[i].filter & EVFILT_WRITE); */ cfd = fdw_fds + (int)kqevents[i].udata; if (fdw_rw(cfd) & fdwatch_type_read && kqevents[i].filter == EVFILT_READ) if (fdw_hnd(cfd) (fdw_data(cfd), fdwatch_type_read) == -2) continue; if (fdw_rw(cfd) & fdwatch_type_write && kqevents[i].filter == EVFILT_WRITE) fdw_hnd(cfd) (fdw_data(cfd), fdwatch_type_write); } sr = 0; } #endif /* HAVE_KQUEUE */ pvpgn-1.8.5/src/common/bnethashconv.h0000644000175000017500000000216611151345317016561 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_BNETHASHCONV_PROTOS #define INCLUDED_BNETHASHCONV_PROTOS #define JUST_NEED_TYPES #include "common/bn_type.h" #include "common/bnethash.h" #undef JUST_NEED_TYPES extern void bnhash_to_hash(bn_int const * bnhash, t_hash * hash); extern void hash_to_bnhash(t_hash const * hash, bn_int * bnhash); #endif #endif pvpgn-1.8.5/src/common/packet.c0000644000175000017500000011231611151345317015340 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 1999,2000,2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_MEMORY_H # include #endif #include "compat/memcpy.h" #include "common/eventlog.h" #include "common/bn_type.h" #include "common/field_sizes.h" #include "common/xalloc.h" #include "common/lstr.h" #include "common/packet.h" #include "common/setup_after.h" extern t_packet * packet_create(t_packet_class class) { t_packet * temp; if (class!=packet_class_init && class!=packet_class_bnet && class!=packet_class_file && class!=packet_class_udp && class!=packet_class_raw && class!=packet_class_d2game && class!=packet_class_d2cs && class!=packet_class_d2gs && class!=packet_class_d2cs_bnetd && class!=packet_class_w3route) { eventlog(eventlog_level_error,__FUNCTION__,"invalid packet class %d",(int)class); return NULL; } temp = xmalloc(sizeof(t_packet)); temp->ref = 1; temp->class = class; temp->flags = 0; packet_set_size(temp,0); return temp; } extern void packet_destroy(t_packet const * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return; } xfree((void *)packet); /* avoid warning */ } extern t_packet * packet_add_ref(t_packet * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return NULL; } packet->ref++; return packet; } extern void packet_del_ref(t_packet * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return; } if (packet->ref<2) /* if would go to zero */ packet_destroy(packet); else packet->ref--; } extern t_packet_class packet_get_class(t_packet const * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return packet_class_none; } switch (packet->class) { case packet_class_init: return packet_class_init; case packet_class_bnet: return packet_class_bnet; case packet_class_file: return packet_class_file; case packet_class_udp: return packet_class_udp; case packet_class_raw: return packet_class_raw; case packet_class_d2game: return packet_class_d2game; case packet_class_d2cs: return packet_class_d2cs; case packet_class_d2gs: return packet_class_d2gs; case packet_class_d2cs_bnetd: return packet_class_d2cs_bnetd; case packet_class_w3route: return packet_class_w3route; case packet_class_none: return packet_class_none; default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->class); return packet_class_none; } } extern char const * packet_get_class_str(t_packet const * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return "unknown"; } switch (packet->class) { case packet_class_init: return "init"; case packet_class_bnet: return "bnet"; case packet_class_file: return "file"; case packet_class_udp: return "udp"; case packet_class_raw: return "raw"; case packet_class_d2game: return "d2game"; case packet_class_d2gs: return "d2gs"; case packet_class_d2cs_bnetd: return "d2cs_bnetd"; case packet_class_d2cs: return "d2cs"; case packet_class_w3route: return "w3route"; case packet_class_none: return "none"; default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->class); return "unknown"; } } extern int packet_set_class(t_packet * packet, t_packet_class class) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (packet->class!=packet_class_raw) { eventlog(eventlog_level_error,__FUNCTION__,"got non-raw packet"); return -1; } if (class!=packet_class_init && class!=packet_class_bnet && class!=packet_class_file && class!=packet_class_udp && class!=packet_class_raw && class!=packet_class_d2game && class!=packet_class_d2cs && class!=packet_class_d2gs && class!=packet_class_d2cs_bnetd && class!=packet_class_w3route) { eventlog(eventlog_level_error,__FUNCTION__,"invalid packet class %d",(int)class); return -1; } packet->class = class; return 0; } extern unsigned int packet_get_type(t_packet const * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return 0; } switch (packet->class) { case packet_class_init: return CLIENT_INITCONN; /* all init packets are of this type */ case packet_class_bnet: if (packet_get_size(packet)u.bnet.h.type); case packet_class_file: if (packet_get_size(packet)u.file.h.type); case packet_class_udp: if (packet_get_size(packet)u.udp.h.type); case packet_class_raw: return 0; /* raw packets don't have a type, but don't warn because the packet dump tries anyway */ case packet_class_d2game: if (packet_get_size(packet)u.d2game.h.type); case packet_class_d2gs: if (packet_get_size(packet)u.d2cs_d2gs.h.type); case packet_class_d2cs_bnetd: if (packet_get_size(packet)u.d2cs_d2gs.h.type); case packet_class_d2cs: if (packet_get_size(packet)u.d2cs_client.h.type); case packet_class_w3route: if (packet_get_size(packet)u.w3route.h.type); default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->class); return 0; } } extern char const * packet_get_type_str(t_packet const * packet, t_packet_dir dir) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return "unknown"; } switch (dir) { case packet_dir_from_client: switch (packet->class) { case packet_class_init: return "CLIENT_INITCONN"; case packet_class_bnet: if (packet_get_size(packet)u.bnet.h.type)) { case CLIENT_COMPINFO1: return "CLIENT_COMPINFO1"; case CLIENT_COMPINFO2: return "CLIENT_COMPINFO2"; case CLIENT_COUNTRYINFO1: return "CLIENT_COUNTRYINFO1"; case CLIENT_COUNTRYINFO_109: return "CLIENT_COUNTRYINFO_109"; case CLIENT_CREATEACCTREQ1: return "CLIENT_CREATEACCTREQ1"; case CLIENT_UNKNOWN_2B: return "CLIENT_UNKNOWN_2B"; case CLIENT_PROGIDENT: return "CLIENT_PROGIDENT"; case CLIENT_AUTHREQ1: return "CLIENT_AUTHREQ1"; case CLIENT_AUTHREQ_109: return "CLIENT_AUTHREQ_109"; case CLIENT_REGSNOOPREPLY: return "CLIENT_REGSNOOPREPLY"; case CLIENT_ICONREQ: return "CLIENT_ICONREQ"; case CLIENT_LADDERSEARCHREQ: return "CLIENT_LADDERSEARCHREQ"; case CLIENT_CDKEY: return "CLIENT_CDKEY"; case CLIENT_CDKEY2: return "CLIENT_CDKEY2"; case CLIENT_CDKEY3: return "CLIENT_CDKEY3"; case CLIENT_REALMLISTREQ: return "CLIENT_REALMLISTREQ"; case CLIENT_REALMLISTREQ_110: return "CLIENT_REALMLISTREQ_110"; case CLIENT_PROFILEREQ: return "CLIENT_PROFILEREQ"; case CLIENT_UNKNOWN_37: return "CLIENT_UNKNOWN_37"; case CLIENT_UNKNOWN_39: return "CLIENT_UNKNOWN_39"; case CLIENT_LOGINREQ2: return "CLIENT_LOGINREQ2"; case CLIENT_MOTD_W3: return "CLIENT_MOTD_W3"; case CLIENT_LOGINREQ_W3: return "CLIENT_LOGINREQ_W3"; case CLIENT_LOGONPROOFREQ: return "CLIENT_LOGONPROOFREQ"; case CLIENT_CREATEACCOUNT_W3: return "CLIENT_CREATEACCOUNT_W3"; case CLIENT_CHANGEGAMEPORT: return "CLIENT_CHANGEGAMEPORT"; case CLIENT_CREATEACCTREQ2: return "CLIENT_CREATEACCTREQ2"; case CLIENT_UDPOK: return "CLIENT_UDPOK"; case CLIENT_FILEINFOREQ: return "CLIENT_FILEINFOREQ"; case CLIENT_STATSREQ: return "CLIENT_STATSREQ"; case CLIENT_LOGINREQ1: return "CLIENT_LOGINREQ1"; case CLIENT_CHANGEPASSREQ: return "CLIENT_CHANGEPASSREQ"; case CLIENT_PLAYERINFOREQ: return "CLIENT_PLAYERINFOREQ"; case CLIENT_PROGIDENT2: return "CLIENT_PROGIDENT2"; case CLIENT_JOINCHANNEL: return "CLIENT_JOINCHANNEL"; case CLIENT_MESSAGE: return "CLIENT_MESSAGE"; case CLIENT_GAMELISTREQ: return "CLIENT_GAMELISTREQ"; case CLIENT_STARTGAME1: return "CLIENT_STARTGAME1"; case CLIENT_UNKNOWN_1B: return "CLIENT_UNKNOWN_1B"; case CLIENT_STARTGAME3: return "CLIENT_STARTGAME3"; case CLIENT_STARTGAME4: return "CLIENT_STARTGAME4"; case CLIENT_CLOSEGAME: return "CLIENT_CLOSEGAME"; case CLIENT_CLOSEGAME2: return "CLIENT_CLOSEGAME2"; case CLIENT_LEAVECHANNEL: return "CLIENT_LEAVECHANNEL"; case CLIENT_MAPAUTHREQ1: return "CLIENT_MAPAUTHREQ1"; case CLIENT_MAPAUTHREQ2: return "CLIENT_MAPAUTHREQ2"; case CLIENT_ADREQ: return "CLIENT_ADREQ"; case CLIENT_ADACK: return "CLIENT_ADACK"; case CLIENT_ADCLICK: return "CLIENT_ADCLICK"; case CLIENT_ADCLICK2: return "CLIENT_ADCLICK2"; case CLIENT_UNKNOWN_17: return "CLIENT_UNKNOWN_17"; case CLIENT_UNKNOWN_24: return "CLIENT_UNKNOWN_24"; case CLIENT_LADDERREQ: return "CLIENT_LADDERREQ"; case CLIENT_ECHOREPLY: return "CLIENT_ECHOREPLY"; case CLIENT_PINGREQ: return "CLIENT_PINGREQ"; case CLIENT_GAME_REPORT: return "CLIENT_GAME_REPORT"; case CLIENT_JOIN_GAME: return "CLIENT_JOIN_GAME"; case CLIENT_STATSUPDATE: return "CLIENT_STATSUPDATE"; case CLIENT_REALMJOINREQ_109: return "CLIENT_REALMJOINREQ_109"; case CLIENT_CHANGECLIENT: return "CLIENT_CHANGECLIENT"; case CLIENT_SETEMAILREPLY: return "CLIENT_SETEMAILREPLY"; case CLIENT_GETPASSWORDREQ: return "CLIENT_GETPASSWORDREQ"; case CLIENT_CHANGEEMAILREQ: return "CLIENT_CHANGEEMAILREQ"; case CLIENT_CRASHDUMP: return "CLIENT_CRASHDUMP"; case CLIENT_FINDANONGAME: return "CLIENT_FINDANONGAME"; case CLIENT_ARRANGEDTEAM_FRIENDSCREEN: return "CLIENT_ARRANGEDTEAM_FRIENDSCREEN"; case CLIENT_ARRANGEDTEAM_INVITE_FRIEND: return "CLIENT_ARRANGEDTEAM_INVITE_FRIEND"; case CLIENT_ARRANGEDTEAM_ACCEPT_DECLINE_INVITE: return "CLIENT_ARRANGEDTEAM_ACCEPT_DECLINE_INVITE"; case CLIENT_FRIENDSLISTREQ: return "CLIENT_FRIENDSLISTREQ"; case CLIENT_FRIENDINFOREQ: return "CLIENT_FRIENDINFOREQ"; case CLIENT_CLANINFOREQ: return "CLIENT_CLANINFOREQ"; } return "unknown"; case packet_class_file: if (packet_get_size(packet)u.file.h.type)) { case CLIENT_FILE_REQ: return "CLIENT_FILE_REQ"; } return "unknown"; case packet_class_udp: if (packet_get_size(packet)u.udp.h.type)) { case SERVER_UDPTEST: /* we get these if we send stuff to ourself */ return "SERVER_UDPTEST"; case CLIENT_UDPPING: return "CLIENT_UDPPING"; case CLIENT_SESSIONADDR1: return "CLIENT_SESSIONADDR1"; case CLIENT_SESSIONADDR2: return "CLIENT_SESSIONADDR2"; } return "unknown"; case packet_class_raw: return "CLIENT_RAW"; case packet_class_d2game: if (packet_get_size(packet)u.d2game.h.type)) { default: return "CLIENT_D2GAME"; } return "unknown"; case packet_class_d2cs: return "D2CS"; case packet_class_d2gs: return "D2GS"; case packet_class_d2cs_bnetd: return "D2CS_BNETD"; case packet_class_w3route: if (packet_get_size(packet)u.bnet.h.type)) { case CLIENT_W3ROUTE_REQ: return "CLIENT_W3ROUTE_REQ"; case CLIENT_W3ROUTE_LOADINGDONE: return "CLIENT_W3ROUTE_LOADINGDONE"; case CLIENT_W3ROUTE_ABORT: return "CLIENT_W3ROUTE_ABORT"; case CLIENT_W3ROUTE_CONNECTED: return "CLIENT_W3ROUTE_CONNECTED"; case CLIENT_W3ROUTE_ECHOREPLY: return "CLIENT_W3ROUTE_ECHOREPLY"; case CLIENT_W3ROUTE_GAMERESULT: return "CLIENT_W3ROUTE_GAMERESULT"; case CLIENT_W3ROUTE_GAMERESULT_W3XP: return "CLIENT_W3ROUTE_GAMERESULT_W3XP"; } return "unknown"; case packet_class_none: return "unknown"; } eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->class); return "unknown"; case packet_dir_from_server: switch (packet->class) { case packet_class_init: return "unknown"; case packet_class_bnet: if (packet_get_size(packet)u.bnet.h.type)) { case SERVER_COMPREPLY: return "SERVER_COMPREPLY"; case SERVER_SESSIONKEY1: return "SERVER_SESSIONKEY1"; case SERVER_SESSIONKEY2: return "SERVER_SESSIONKEY2"; case SERVER_CREATEACCTREPLY1: return "SERVER_CREATEACCTREPLY1"; case SERVER_AUTHREQ1: return "SERVER_AUTHREQ1"; case SERVER_AUTHREQ_109: return "SERVER_AUTHREQ_109"; case SERVER_AUTHREPLY1: return "SERVER_AUTHREPLY1"; case SERVER_AUTHREPLY_109: return "SERVER_AUTHREPLY_109"; case SERVER_REGSNOOPREQ: return "SERVER_REGSNOOPREQ"; case SERVER_ICONREPLY: return "SERVER_ICONREPLY"; case SERVER_LADDERSEARCHREPLY: return "SERVER_LADDERSEARCHREPLY"; case SERVER_CDKEYREPLY: return "SERVER_CDKEYREPLY"; case SERVER_CDKEYREPLY2: return "SERVER_CDKEYREPLY2"; case SERVER_CDKEYREPLY3: return "SERVER_CDKEYREPLY3"; case SERVER_REALMLISTREPLY: return "SERVER_REALMLISTREPLY"; case SERVER_REALMLISTREPLY_110: return "SERVER_REALMLISTREPLY_110"; case SERVER_PROFILEREPLY: return "SERVER_PROFILEREPLY"; case SERVER_UNKNOWN_37: return "SERVER_UNKNOWN_37"; case SERVER_MOTD_W3: return "SERVER_MOTD_W3"; case SERVER_LOGINREPLY_W3: return "SERVER_LOGINREPLY_W3"; case SERVER_LOGONPROOFREPLY: return "SERVER_LOGONPROOFREPLY"; case SERVER_CREATEACCOUNT_W3: return "SERVER_CREATEACCTREPLY2"; case SERVER_LOGINREPLY2: return "SERVER_LOGINREPLY2"; case SERVER_CREATEACCTREPLY2: return "SERVER_CREATEACCOUNT_W3"; case SERVER_FILEINFOREPLY: return "SERVER_FILEINFOREPLY"; case SERVER_STATSREPLY: return "SERVER_STATSREPLY"; case SERVER_LOGINREPLY1: return "SERVER_LOGINREPLY1"; case SERVER_CHANGEPASSACK: return "SERVER_CHANGEPASSACK"; case SERVER_PLAYERINFOREPLY: return "SERVER_PLAYERINFOREPLY"; case SERVER_CHANNELLIST: return "SERVER_CHANNELLIST"; case SERVER_SERVERLIST: return "SERVER_SERVERLIST"; case SERVER_MESSAGE: return "SERVER_MESSAGE"; case SERVER_GAMELISTREPLY: return "SERVER_GAMELISTREPLY"; case SERVER_STARTGAME1_ACK: return "SERVER_STARTGAME1_ACK"; case SERVER_STARTGAME3_ACK: return "SERVER_STARTGAME3_ACK"; case SERVER_STARTGAME4_ACK: return "SERVER_STARTGAME4_ACK"; case SERVER_MAPAUTHREPLY1: return "SERVER_MAPAUTHREPLY1"; case SERVER_MAPAUTHREPLY2: return "SERVER_MAPAUTHREPLY2"; case SERVER_ADREPLY: return "SERVER_ADREPLY"; case SERVER_ADCLICKREPLY2: return "SERVER_ADCLICKREPLY2"; case SERVER_LADDERREPLY: return "SERVER_LADDERREPLY"; case SERVER_ECHOREQ: return "SERVER_ECHOREQ"; case SERVER_PINGREPLY: return "SERVER_PINGREPLY"; case SERVER_REALMJOINREPLY_109: return "SERVER_REALMJOINREPLY_109"; case SERVER_SETEMAILREQ: return "SERVER_SETEMAILREQ"; case SERVER_FINDANONGAME: return "SERVER_FINDANONGAME"; case SERVER_ARRANGEDTEAM_FRIENDSCREEN: return "SERVER_ARRANGEDTEAM_FRIENDSCREEN"; case SERVER_ARRANGEDTEAM_INVITE_FRIEND_ACK: return "SERVER_ARRANGEDTEAM_INVITE_FRIEND_ACK"; case SERVER_ARRANGEDTEAM_SEND_INVITE: return "SERVER_ARRANGEDTEAM_SEND_INVITE"; case SERVER_ARRANGEDTEAM_MEMBER_DECLINE: return "SERVER_ARRANGEDTEAM_MEMBER_DECLINE"; case SERVER_FRIENDSLISTREPLY: return "SERVER_FRIENDSLISTREPLY"; case SERVER_FRIENDINFOREPLY: return "SERVER_FRIENDINFOREPLY"; case SERVER_FRIENDADD_ACK: return "SERVER_FRIENDADD_ACK"; case SERVER_FRIENDDEL_ACK: return "SERVER_FRIENDDEL_ACK"; case SERVER_FRIENDMOVE_ACK: return "SERVER_FRIENDMOVE_ACK"; case SERVER_CLANINFOREPLY: return "SERVER_CLANINFO_REPLY"; } return "unknown"; case packet_class_file: if (packet_get_size(packet)u.file.h.type)) { case SERVER_FILE_REPLY: return "SERVER_FILE_REPLY"; } return "unknown"; case packet_class_udp: if (packet_get_size(packet)u.udp.h.type)) { case SERVER_UDPTEST: return "SERVER_UDPTEST"; } return "unknown"; case packet_class_raw: return "SERVER_RAW"; case packet_class_d2game: if (packet_get_size(packet)u.d2game.h.type)) { default: return "SERVER_D2GAME"; } return "unknown"; case packet_class_d2cs: return "D2CS"; case packet_class_d2gs: return "D2GS"; case packet_class_d2cs_bnetd: return "D2CS_BNETD"; case packet_class_w3route: if (packet_get_size(packet)u.bnet.h.type)) { case SERVER_W3ROUTE_READY: return "SERVER_W3ROUTE_READY"; case SERVER_W3ROUTE_LOADINGACK: return "SERVER_W3ROUTE_LOADINGACK"; case SERVER_W3ROUTE_ECHOREQ: return "SERVER_W3ROUTE_ECHOREQ"; case SERVER_W3ROUTE_ACK: return "SERVER_W3ROUTE_ACK"; case SERVER_W3ROUTE_PLAYERINFO: return "SERVER_W3ROUTE_PLAYERINFO"; case SERVER_W3ROUTE_LEVELINFO: return "SERVER_W3ROUTE_LEVELINFO"; case SERVER_W3ROUTE_STARTGAME1: return "SERVER_W3ROUTE_STARTGAME1"; case SERVER_W3ROUTE_STARTGAME2: return "SERVER_W3ROUTE_STARTGAME2"; } return "unknown"; case packet_class_none: return "unknown"; } eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->class); return "unknown"; } eventlog(eventlog_level_error,__FUNCTION__,"got unknown direction %d",(int)dir); return "unknown"; } extern int packet_set_type(t_packet * packet, unsigned int type) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } switch (packet->class) { case packet_class_init: if (type!=CLIENT_INITCONN) { eventlog(eventlog_level_error,__FUNCTION__,"init packet type 0x%08x is not valid",type); return -1; } return 0; case packet_class_bnet: if (packet_get_size(packet)MAX_NORMAL_TYPE) { eventlog(eventlog_level_error,__FUNCTION__,"bnet packet type 0x%08x is too large",type); return -1; } bn_short_set(&packet->u.bnet.h.type,(unsigned short)type); return 0; case packet_class_file: if (packet_get_size(packet)MAX_FILE_TYPE) { eventlog(eventlog_level_error,__FUNCTION__,"file packet type 0x%08x is too large",type); return -1; } bn_short_set(&packet->u.file.h.type,(unsigned short)type); return 0; case packet_class_udp: if (packet_get_size(packet)u.udp.h.type,type); return 0; case packet_class_d2game: if (packet_get_size(packet)u.d2game.h.type,type); return 0; case packet_class_d2gs: if (packet_get_size(packet)u.d2cs_d2gs.h.type,type); return 0; case packet_class_d2cs_bnetd: if (packet_get_size(packet)u.d2cs_bnetd.h.type,type); return 0; case packet_class_d2cs: if (packet_get_size(packet)u.d2cs_client.h.type,type); return 0; case packet_class_w3route: if (packet_get_size(packet)u.w3route.h.type,(unsigned short)type); return 0; case packet_class_raw: eventlog(eventlog_level_error,__FUNCTION__,"can not set packet type for raw packet"); return 0; default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->class); return -1; } } /* size of the _complete_ packet, not the amount currently received or sent */ extern unsigned int packet_get_size(t_packet const * packet) { unsigned int size; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return 0; } switch (packet->class) { case packet_class_init: size = sizeof(t_client_initconn); break; case packet_class_bnet: size = (unsigned int)bn_short_get(packet->u.bnet.h.size); break; case packet_class_file: size = (unsigned int)bn_short_get(packet->u.file.h.size); break; case packet_class_udp: size = packet->len; break; case packet_class_raw: size = packet->len; break; case packet_class_d2game: size = packet->len; /* FIXME: does header not contain the size? */ break; case packet_class_d2gs: size = (unsigned int)bn_short_get(packet->u.d2cs_d2gs.h.size); break; case packet_class_d2cs_bnetd: size = (unsigned int)bn_short_get(packet->u.d2cs_bnetd.h.size); break; case packet_class_d2cs: size = (unsigned int)bn_short_get(packet->u.d2cs_client.h.size); break; case packet_class_w3route: size = (unsigned int)bn_short_get(packet->u.w3route.h.size); break; default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->class); return 0; } if (size>MAX_PACKET_SIZE) { eventlog(eventlog_level_error,__FUNCTION__,"packet has bad size %u",size); return 0; } return size; } extern int packet_set_size(t_packet * packet, unsigned int size) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (size>MAX_PACKET_SIZE) { eventlog(eventlog_level_error,__FUNCTION__,"got bad size %u",size); return -1; } switch (packet->class) { case packet_class_init: if (size!=0 && size!=sizeof(t_client_initconn)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid size %u for init packet",size); return -1; } packet->len = size; return 0; case packet_class_bnet: if (size!=0 && sizeu.bnet.h.size,size); return 0; case packet_class_file: if (size!=0 && sizeu.file.h.size,size); return 0; case packet_class_udp: if (size!=0 && sizelen = size; return 0; case packet_class_raw: packet->len = size; return 0; case packet_class_d2game: packet->len = size; /* FIXME: does header not contain the size? */ return 0; case packet_class_d2cs: bn_short_set(&packet->u.d2cs_client.h.size,size); return 0; case packet_class_d2gs: bn_short_set(&packet->u.d2cs_d2gs.h.size,size); return 0; case packet_class_d2cs_bnetd: bn_short_set(&packet->u.d2cs_bnetd.h.size,size); return 0; case packet_class_w3route: if (size!=0 && sizeu.w3route.h.size,size); return 0; default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->class); return -1; } } extern unsigned int packet_get_header_size(t_packet const * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return MAX_PACKET_SIZE; } switch (packet_get_class(packet)) { case packet_class_init: return 0; case packet_class_bnet: return sizeof(t_bnet_header); case packet_class_file: return sizeof(t_file_header); case packet_class_udp: return sizeof(t_udp_header); case packet_class_raw: return 0; case packet_class_d2game: return 0; /* FIXME: is there no game packet header? */ case packet_class_d2cs: return sizeof(t_d2cs_client_header); case packet_class_d2gs: return sizeof(t_d2cs_d2gs_header); case packet_class_d2cs_bnetd: return sizeof(t_d2cs_bnetd_header); case packet_class_w3route: return sizeof(t_w3route_header); default: eventlog(eventlog_level_error,__FUNCTION__,"packet has bad class %d",(int)packet_get_class(packet)); return MAX_PACKET_SIZE; } } extern unsigned int packet_get_flags(t_packet const * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return 0; } return packet->flags; } extern int packet_set_flags(t_packet * packet, unsigned int flags) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } packet->flags = flags; return 0; } extern int packet_append_string(t_packet * packet, char const * str) { unsigned int len; unsigned short addlen; unsigned short size; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (!str) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL string"); return -1; } len = strlen(str)+1; size = packet_get_size(packet); if (size>=MAX_PACKET_SIZE) return -1; if (MAX_PACKET_SIZE-(unsigned int)size>len) addlen = len; else addlen = MAX_PACKET_SIZE-size; if (addlen<1) return -1; memcpy(packet->u.data+size,str,addlen-1); packet->u.data[size+addlen-1] = '\0'; packet_set_size(packet,size+addlen); return (int)addlen; } extern int packet_append_ntstring(t_packet * packet, char const * str) { unsigned int len; unsigned short addlen; unsigned short size; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (!str) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL string"); return -1; } len = strlen(str); size = packet_get_size(packet); if (size>=MAX_PACKET_SIZE) return -1; if (MAX_PACKET_SIZE-(unsigned int)size>len) addlen = len; else addlen = MAX_PACKET_SIZE-size; if (addlen<1) return -1; memcpy(packet->u.data+size,str,addlen); packet_set_size(packet,size+addlen); return (int)addlen; } extern int packet_append_lstr(t_packet * packet, t_lstr *lstr) { unsigned short addlen; unsigned short size; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (!lstr || !lstr_get_str(lstr)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL string"); return -1; } size = packet_get_size(packet); if (size>=MAX_PACKET_SIZE) return -1; if (MAX_PACKET_SIZE-(unsigned int)size>lstr_get_len(lstr)) addlen = lstr_get_len(lstr); else addlen = MAX_PACKET_SIZE-size; if (addlen<1) return -1; memcpy(packet->u.data+size,lstr_get_str(lstr),addlen-1); packet->u.data[size+addlen-1] = '\0'; packet_set_size(packet,size+addlen); return (int)addlen; } extern int packet_append_data(t_packet * packet, void const * data, unsigned int len) { unsigned short addlen; unsigned short size; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (!data) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL data"); return -1; } size = packet_get_size(packet); if (size>=MAX_PACKET_SIZE) return -1; if (MAX_PACKET_SIZE-(unsigned int)size>len) addlen = len; else addlen = MAX_PACKET_SIZE-size; if (addlen<1) return -1; memcpy(packet->u.data+size,data,addlen); packet_set_size(packet,size+addlen); return (int)addlen; } extern void const * packet_get_raw_data_const(t_packet const * packet, unsigned int offset) { unsigned int size; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return NULL; } size = (unsigned int)packet_get_size(packet); if (offset>=size || offset>=MAX_PACKET_SIZE) { eventlog(eventlog_level_error,__FUNCTION__,"got bad offset %u for packet size %u",offset,size); return NULL; } return packet->u.data+offset; } extern void * packet_get_raw_data(t_packet * packet, unsigned int offset) { unsigned int size; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return NULL; } size = (unsigned int)packet_get_size(packet); if (offset>=size || offset>=MAX_PACKET_SIZE) { eventlog(eventlog_level_error,__FUNCTION__,"got bad offset %u for packet size %u",offset,size); return NULL; } return packet->u.data+offset; } extern void * packet_get_raw_data_build(t_packet * packet, unsigned int offset) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return NULL; } if (offset>=MAX_PACKET_SIZE) { eventlog(eventlog_level_error,__FUNCTION__,"got bad offset %u for packet",offset); return NULL; } return packet->u.data+offset; } /* maxlen includes room for NUL char */ extern char const * packet_get_str_const(t_packet const * packet, unsigned int offset, unsigned int maxlen) { unsigned int size; unsigned int pos; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return NULL; } size = (unsigned int)packet_get_size(packet); if (offset>=size) { eventlog(eventlog_level_error,__FUNCTION__,"got bad offset %u for packet size %u",offset,size); return NULL; } for (pos=offset; packet->u.data[pos]!='\0'; pos++) if (pos>=size || pos-offset>=maxlen) return NULL; if (pos>=size || pos-offset>=maxlen) /* NUL must be inside too */ return NULL; return packet->u.data+offset; } extern void const * packet_get_data_const(t_packet const * packet, unsigned int offset, unsigned int len) { unsigned int size; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return NULL; } if (len<1) { eventlog(eventlog_level_error,__FUNCTION__,"got zero length"); return NULL; } size = (unsigned int)packet_get_size(packet); if (offset+len>size) { eventlog(eventlog_level_error,__FUNCTION__,"got bad offset %u and length %u for packet size %u",offset,len,size); return NULL; } return packet->u.data+offset; } extern t_packet * packet_duplicate(t_packet const * src) { t_packet * p; if (!(p = packet_create(packet_get_class(src)))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return NULL; } packet_append_data(p,src->u.data,packet_get_size(src)); packet_set_flags(p,packet_get_flags(src)); return p; } pvpgn-1.8.5/src/common/eventlog.c0000644000175000017500000002162611151345317015717 0ustar aaronaaron/* * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #include #include "compat/strerror.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/strcasecmp.h" #include "compat/vargs.h" #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/strftime.h" #ifdef HAVE_UNISTD_H # include #endif #include "common/eventlog.h" #include "common/hexdump.h" #include "common/setup_after.h" #ifdef WIN32_GUI # include "win32/winmain.h" #endif static FILE * eventstrm=NULL; static t_eventlog_level currlevel=eventlog_level_debug| eventlog_level_info| eventlog_level_warn| eventlog_level_error| eventlog_level_fatal; /* FIXME: maybe this should be default for win32 */ static int eventlog_debugmode=0; extern void eventlog_set_debugmode(int debugmode) { eventlog_debugmode = debugmode; } extern void eventlog_set(FILE * fp) { eventstrm = fp; } extern FILE * eventlog_get(void) { return eventstrm; } extern int eventlog_close(void) { fclose(eventstrm); return 0; } extern int eventlog_open(char const * filename) { FILE * temp; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return -1; } if (!(temp = fopen(filename,"a"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for appending (fopen: %s)",filename,pstrerror(errno)); return -1; } if (eventstrm && eventstrm!=stderr) /* close old one */ if (fclose(eventstrm)<0) { eventstrm = temp; eventlog(eventlog_level_error,__FUNCTION__,"could not close previous logfile after writing (fclose: %s)",pstrerror(errno)); return 0; } eventstrm = temp; return 0; } extern void eventlog_clear_level(void) { currlevel = eventlog_level_none; } extern int eventlog_add_level(char const * levelname) { if (!levelname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL levelname"); return -1; } if (strcasecmp(levelname,"trace")==0) { currlevel |= eventlog_level_trace; return 0; } if (strcasecmp(levelname,"debug")==0) { currlevel |= eventlog_level_debug; return 0; } if (strcasecmp(levelname,"info")==0) { currlevel |= eventlog_level_info; return 0; } if (strcasecmp(levelname,"warn")==0) { currlevel |= eventlog_level_warn; return 0; } if (strcasecmp(levelname,"error")==0) { currlevel |= eventlog_level_error; return 0; } if (strcasecmp(levelname,"fatal")==0) { currlevel |= eventlog_level_fatal; return 0; } eventlog(eventlog_level_error,__FUNCTION__,"got bad levelname \"%s\"",levelname); return -1; } extern int eventlog_del_level(char const * levelname) { if (!levelname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL levelname"); return -1; } if (strcasecmp(levelname,"trace")==0) { currlevel &= ~eventlog_level_trace; return 0; } if (strcasecmp(levelname,"debug")==0) { currlevel &= ~eventlog_level_debug; return 0; } if (strcasecmp(levelname,"info")==0) { currlevel &= ~eventlog_level_info; return 0; } if (strcasecmp(levelname,"warn")==0) { currlevel &= ~eventlog_level_warn; return 0; } if (strcasecmp(levelname,"error")==0) { currlevel &= ~eventlog_level_error; return 0; } if (strcasecmp(levelname,"fatal")==0) { currlevel &= ~eventlog_level_fatal; return 0; } eventlog(eventlog_level_error,__FUNCTION__,"got bad levelname \"%s\"",levelname); return -1; } extern char const * eventlog_get_levelname_str(t_eventlog_level level) { switch (level) { case eventlog_level_trace: return "trace"; case eventlog_level_debug: return "debug"; case eventlog_level_info: return "info "; case eventlog_level_warn: return "warn "; case eventlog_level_error: return "error"; case eventlog_level_fatal: return "fatal"; default: return "unknown"; } } extern void eventlog_hexdump_data(void const * data, unsigned int len) { unsigned int i; char dst[100]; unsigned char * datac; if (!data) { eventlog(eventlog_level_error, __FUNCTION__, "got NULL data"); return; } for (i = 0, datac = (char*)data; i < len; i += 16, datac += 16) { hexdump_string(datac, (len - i < 16) ? (len - i) : 16, dst, i); fprintf(eventstrm,"%s\n",dst); #ifdef WIN32_GUI gui_lprintf(eventlog_level_info,"%s\n",dst); #endif if (eventlog_debugmode) { printf("%s\n",dst); } } if (eventlog_debugmode) fflush(stdout); fflush(eventstrm); } extern void eventlog(t_eventlog_level level, char const * module, char const * fmt, ...) { va_list args; char time_string[EVENT_TIME_MAXLEN]; struct tm * tmnow; time_t now; if (!(level&currlevel)) return; if (!eventstrm) return; /* get the time before parsing args */ time(&now); if (!(tmnow = localtime(&now))) strcpy(time_string,"?"); else strftime(time_string,EVENT_TIME_MAXLEN,EVENT_TIME_FORMAT,tmnow); if (!module) { fprintf(eventstrm,"%s [error] eventlog: got NULL module\n",time_string); #ifdef WIN32_GUI gui_lprintf(eventlog_level_error,"%s [error] eventlog: got NULL module\n",time_string); #endif fflush(eventstrm); return; } if (!fmt) { fprintf(eventstrm,"%s [error] eventlog: got NULL fmt\n",time_string); #ifdef WIN32_GUI gui_lprintf(eventlog_level_error,"%s [error] eventlog: got NULL fmt\n",time_string); #endif fflush(eventstrm); return; } fprintf(eventstrm,"%s [%s] %s: ",time_string,eventlog_get_levelname_str(level),module); #ifdef WIN32_GUI gui_lprintf(level,"%s [%s] %s: ",time_string,eventlog_get_levelname_str(level),module); #endif VA_START(args,fmt); #ifdef HAVE_VPRINTF vfprintf(eventstrm,fmt,args); #ifdef WIN32_GUI gui_lvprintf(level,fmt,args); #endif #else # if HAVE__DOPRNT _doprnt(fmt,args,eventstrm); # else fprintf(eventstrm,"sorry, vfprintf() and _doprnt() are not available on this system"); # endif #endif va_end(args); fprintf(eventstrm,"\n"); #ifdef WIN32_GUI gui_lprintf(level,"\n"); #endif if (eventlog_debugmode) { printf("%s [%s] %s: ",time_string,eventlog_get_levelname_str(level),module); va_start(args,fmt); #ifdef HAVE_VPRINTF vprintf(fmt,args); #else # if HAVE__DOPRNT _doprnt(fmt,args,stdout); # else printf("sorry, vfprintf() and _doprnt() are not available on this system"); # endif #endif va_end(args); printf("\n"); fflush(stdout); } fflush(eventstrm); } extern void eventlog_step(char const * filename, t_eventlog_level level, char const * module, char const * fmt, ...) { va_list args; char time_string[EVENT_TIME_MAXLEN]; struct tm * tmnow; time_t now; FILE * fp; if (!(level&currlevel)) return; if (!eventstrm) return; if (!(fp = fopen(filename, "a"))) return; /* get the time before parsing args */ time(&now); if (!(tmnow = localtime(&now))) strcpy(time_string,"?"); else strftime(time_string,EVENT_TIME_MAXLEN,EVENT_TIME_FORMAT,tmnow); if (!module) { fprintf(fp,"%s [error] eventlog_step: got NULL module\n",time_string); fclose(fp); return; } if (!fmt) { fprintf(fp,"%s [error] eventlog_step: got NULL fmt\n",time_string); fclose(fp); return; } fprintf(fp,"%s [%s] %s: ",time_string,eventlog_get_levelname_str(level),module); va_start(args,fmt); #ifdef HAVE_VPRINTF vfprintf(fp,fmt,args); #else # if HAVE__DOPRNT _doprnt(fmt,args,fp); # else fprintf(fp,"sorry, vfprintf() and _doprnt() are not available on this system"); # endif #endif va_end(args); fprintf(fp,"\n"); fclose(fp); } pvpgn-1.8.5/src/common/eventlog.h0000644000175000017500000000767711151345317015736 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_EVENTLOG_TYPES #define INCLUDED_EVENTLOG_TYPES typedef enum { eventlog_level_none = 0, eventlog_level_trace= 1, eventlog_level_debug= 2, eventlog_level_info = 4, eventlog_level_warn = 8, eventlog_level_error=16, eventlog_level_fatal=32 } t_eventlog_level; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_EVENTLOG_PROTOS #define INCLUDED_EVENTLOG_PROTOS #define JUST_NEED_TYPES #include #undef JUST_NEED_TYPES extern void eventlog_set_debugmode(int debugmode); extern void eventlog_set(FILE * fp); extern FILE * eventlog_get(void); extern int eventlog_open(char const * filename); extern int eventlog_close(void); extern void eventlog_clear_level(void); extern int eventlog_add_level(char const * levelname); extern int eventlog_del_level(char const * levelname); extern char const * eventlog_get_levelname_str(t_eventlog_level level); extern void eventlog_hexdump_data(void const * data, unsigned int len); extern void eventlog(t_eventlog_level level, char const * module, char const * fmt, ...); extern void eventlog_step(char const * filename, t_eventlog_level level, char const * module, char const * fmt, ...); #define FATAL0(fmt) eventlog(eventlog_level_fatal,__FUNCTION__,fmt) #define FATAL1(fmt,arg1) eventlog(eventlog_level_fatal,__FUNCTION__,fmt,arg1) #define FATAL2(fmt,arg1,arg2) eventlog(eventlog_level_fatal,__FUNCTION__,fmt,arg1,arg2) #define FATAL3(fmt,arg1,arg2,arg3) eventlog(eventlog_level_fatal,__FUNCTION__,fmt,arg1,arg2,arg3) #define ERROR0(fmt) eventlog(eventlog_level_error,__FUNCTION__,fmt) #define ERROR1(fmt,arg1) eventlog(eventlog_level_error,__FUNCTION__,fmt,arg1) #define ERROR2(fmt,arg1,arg2) eventlog(eventlog_level_error,__FUNCTION__,fmt,arg1,arg2) #define ERROR3(fmt,arg1,arg2,arg3) eventlog(eventlog_level_error,__FUNCTION__,fmt,arg1,arg2,arg3) #define WARN0(fmt) eventlog(eventlog_level_warn,__FUNCTION__,fmt) #define WARN1(fmt,arg1) eventlog(eventlog_level_warn,__FUNCTION__,fmt,arg1) #define WARN2(fmt,arg1,arg2) eventlog(eventlog_level_warn,__FUNCTION__,fmt,arg1,arg2) #define WARN3(fmt,arg1,arg2,arg3) eventlog(eventlog_level_warn,__FUNCTION__,fmt,arg1,arg2,arg3) #define INFO0(fmt) eventlog(eventlog_level_info,__FUNCTION__,fmt) #define INFO1(fmt,arg1) eventlog(eventlog_level_info,__FUNCTION__,fmt,arg1) #define INFO2(fmt,arg1,arg2) eventlog(eventlog_level_info,__FUNCTION__,fmt,arg1,arg2) #define INFO3(fmt,arg1,arg2,arg3) eventlog(eventlog_level_info,__FUNCTION__,fmt,arg1,arg2,arg3) #define DEBUG0(fmt) eventlog(eventlog_level_debug,__FUNCTION__,fmt) #define DEBUG1(fmt,arg1) eventlog(eventlog_level_debug,__FUNCTION__,fmt,arg1) #define DEBUG2(fmt,arg1,arg2) eventlog(eventlog_level_debug,__FUNCTION__,fmt,arg1,arg2) #define DEBUG3(fmt,arg1,arg2,arg3) eventlog(eventlog_level_debug,__FUNCTION__,fmt,arg1,arg2,arg3) #define TRACE0(fmt) eventlog(eventlog_level_trace,__FUNCTION__,fmt) #define TRACE1(fmt,arg1) eventlog(eventlog_level_trace,__FUNCTION__,fmt,arg1) #define TRACE2(fmt,arg1,arg2) eventlog(eventlog_level_trace,__FUNCTION__,fmt,arg1,arg2) #define TRACE3(fmt,arg1,arg2,arg3) eventlog(eventlog_level_trace,__FUNCTION__,fmt,arg1,arg2,arg3) #endif #endif pvpgn-1.8.5/src/common/bn_type.h0000644000175000017500000000624411151345317015540 0ustar aaronaaron/* * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_BN_TYPE_TYPES #define INCLUDED_BN_TYPE_TYPES #ifdef JUST_NEED_TYPES # include "compat/uint.h" #else # define JUST_NEED_TYPES # include "compat/uint.h" # undef JUST_NEED_TYPES #endif typedef t_uint8 bn_basic; typedef bn_basic bn_byte[1]; typedef bn_basic bn_short[2]; typedef bn_basic bn_int[4]; typedef bn_basic bn_long[8]; #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_BN_TYPE_PROTOS #define INCLUDED_BN_TYPE_PROTOS #define JUST_NEED_TYPES # include "compat/uint.h" #undef JUST_NEED_TYPES extern int bn_byte_tag_get(bn_byte const * src, char * dst, unsigned int len); extern int bn_short_tag_get(bn_short const * src, char * dst, unsigned int len); extern int bn_int_tag_get(bn_int const * src, char * dst, unsigned int len); extern int bn_long_tag_get(bn_long const * src, char * dst, unsigned int len); extern int bn_byte_tag_set(bn_byte * dst, char const * tag); extern int bn_short_tag_set(bn_short * dst, char const * tag); extern int bn_int_tag_set(bn_int * dst, char const * tag); extern int bn_long_tag_set(bn_long * dst, char const * tag); extern t_uint8 bn_byte_get(bn_byte const src) ; extern t_uint16 bn_short_get(bn_short const src) ; extern t_uint16 bn_short_nget(bn_short const src) ; extern t_uint32 bn_int_get(bn_int const src) ; extern t_uint32 bn_int_nget(bn_int const src) ; #ifdef HAVE_T_UINT64 extern t_uint64 bn_long_get(bn_long const src) ; #endif extern t_uint32 bn_long_get_a(bn_long const src) ; extern t_uint32 bn_long_get_b(bn_long const src) ; extern int bn_byte_set(bn_byte * dst, t_uint8 src); extern int bn_short_set(bn_short * dst, t_uint16 src); extern int bn_short_nset(bn_short * dst, t_uint16 src); extern int bn_int_set(bn_int * dst, t_uint32 src); extern int bn_int_nset(bn_int * dst, t_uint32 src); #ifdef HAVE_T_UINT64 extern int bn_long_set(bn_long * dst, t_uint64 src); extern int bn_long_nset(bn_long * dst, t_uint64 src); #endif extern int bn_long_set_a_b(bn_long * dst, t_uint32 srca, t_uint32 srcb); extern int bn_long_nset_a_b(bn_long * dst, t_uint32 srca, t_uint32 srcb); extern int bn_raw_set(void * dst, void const * src, unsigned int len); extern int bn_byte_tag_eq(bn_byte const src, char const * tag) ; extern int bn_short_tag_eq(bn_short const src, char const * tag) ; extern int bn_int_tag_eq(bn_int const src, char const * tag) ; extern int bn_long_tag_eq(bn_long const src, char const * tag) ; extern int uint32_to_int(t_uint32 num); #endif #endif pvpgn-1.8.5/src/common/util.c0000644000175000017500000003703311151345317015050 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "compat/strtoul.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include "compat/strcasecmp.h" #include "compat/strncasecmp.h" #include "common/xalloc.h" #include #include "common/util.h" #include "common/setup_after.h" extern int strstart(char const * full, char const * part) { size_t strlen_part; int compare_result; if (!full || !part) return 1; strlen_part = strlen(part); compare_result = strncasecmp(full,part,strlen_part); /* If there is more than the command, make sure it is separated */ if (compare_result!=0) return compare_result; else if (full[strlen_part]!=' ' && full[strlen_part]!='\0') return 1; else return compare_result; } #define DEF_LEN 64 #define INC_LEN 16 extern char * file_get_line(FILE * fp) { static char * line = NULL; static unsigned int len = 0; unsigned int pos = 0; int prev_char,curr_char; // use file_get_line with NULL argument to clear the buffer if (!(fp)) { len = 0; if ((line)) xfree((void *)line); line = NULL; return NULL; } if (!(line)) { line = xmalloc(DEF_LEN); len = DEF_LEN; } prev_char = '\0'; while ((curr_char = fgetc(fp))!=EOF) { if (((char)curr_char)=='\r') continue; /* make DOS line endings look Unix-like */ if (((char)curr_char)=='\n') { if (pos<1 || ((char)prev_char)!='\\') break; pos--; /* throw away the backslash */ prev_char = '\0'; continue; } prev_char = curr_char; line[pos++] = (char)curr_char; if ((pos+1)>=len) { len += INC_LEN; line = xrealloc(line,len); } } if (curr_char==EOF && pos<1) /* not even an empty line */ { return NULL; } line[pos] = '\0'; return line; } extern char * strreverse(char * str) { unsigned int len; char temp; char *start, *end; if (!str) return NULL; len = strlen(str); for (start=str,end=str+len-1;start='\000' && str[i]<'\040')) && (!allow_nl || (str[i]!='\r' && str[i]!='\n'))) fprintf(fp,"^%c",str[i]+64); else fputc((int)str[i],fp); return 0; } extern int str_get_bool(char const * str) { if (!str) return -1; if (strcasecmp(str,"true")==0 || strcasecmp(str,"yes")==0 || strcasecmp(str,"on")==0 || strcmp(str,"1")==0) return 1; if (strcasecmp(str,"false")==0 || strcasecmp(str,"no")==0 || strcasecmp(str,"off")==0 || strcmp(str,"0")==0) return 0; return -1; } extern char const * seconds_to_timestr(unsigned int totsecs) { static char temp[256]; int days; int hours; int minutes; int seconds; days = totsecs/(24*60*60); hours = totsecs/(60*60) - days*24; minutes = totsecs/60 - days*24*60 - hours*60; seconds = totsecs - days*24*60*60 - hours*60*60 - minutes*60; if (days>0) sprintf(temp,"%d day%s %d hour%s %d minute%s %d second%s", days,days==1 ? "" : "s", hours,hours==1 ? "" : "s", minutes,minutes==1 ? "" : "s", seconds,seconds==1 ? "" : "s"); else if (hours>0) sprintf(temp,"%d hour%s %d minute%s %d second%s", hours,hours==1 ? "" : "s", minutes,minutes==1 ? "" : "s", seconds,seconds==1 ? "" : "s"); else if (minutes>0) sprintf(temp,"%d minute%s %d second%s", minutes,minutes==1 ? "" : "s", seconds,seconds==1 ? "" : "s"); else sprintf(temp,"%d second%s.", seconds,seconds==1 ? "" : "s"); return temp; } extern int clockstr_to_seconds(char const * clockstr, unsigned int * totsecs) { unsigned int i,j; unsigned int temp; if (!clockstr) return -1; if (!totsecs) return -1; for (i=j=temp=0; j= len*3+1 then the buffer was overflowed */ out[outpos] = '\0'; return out; } extern char * escape_chars(char const * in, unsigned int len) { char * out; unsigned int inpos; unsigned int outpos; if (!in) return NULL; out = xmalloc(len*4+1); /* if all turn into \xxx */ for (inpos=0,outpos=0; inpos= len*4+1 then the buffer was overflowed */ out[outpos] = '\0'; return out; } extern char * unescape_chars(char const * in) { char * out; unsigned int inpos; unsigned int outpos; unsigned int inlen; if (!in) return NULL; inlen = strlen(in); out = xmalloc(inlen+1); for (inpos=0,outpos=0; inpos255) /* bad escape (including \000), leave it as-is */ { out[outpos++] = '\\'; strcpy(&out[outpos],temp); outpos += strlen(temp); } else out[outpos++] = (unsigned char)num; } } } out[outpos] = '\0'; return out; } extern void str_to_hex(char * target, char * data, int datalen) { unsigned char c; int i; for (i = 0; i < datalen; i++) { c = (data[i]) & 0xff; sprintf(target + i*3, "%02X ", c); target[i*3+3] = '\0'; /* fprintf(stderr, "str_to_hex %d | '%02x' '%s'\n", i, c, target); */ } } extern int hex_to_str(char const * source, char * data, int datalen) { /* * TODO: We really need a more robust function here, * for now, I'll just use this hack for a quick evaluation */ char byte; char c; int i; for (i = 0; i < datalen; i++) { byte = 0; /* fprintf(stderr, "hex_to_str %d | '%02x'", i, byte); */ c = source [i*3 + 0]; byte += 16 * ( c > '9' ? (c - 'A' + 10) : (c - '0')); /* fprintf(stderr, " | '%c' '%02x'", c, byte); */ c = source [i*3 + 1]; byte += 1 * ( c > '9' ? (c - 'A' + 10) : (c - '0')); /* fprintf(stderr, " | '%c' '%02x'", c, byte); */ /* fprintf(stderr, "\n"); */ data[i] = byte; } /* fprintf(stderr, "finished, returning %d from '%s'\n", i, source); */ return i; } extern char * buildpath(char const *root, const char *suffix) { char *result; result = (char*) xmalloc(strlen(root) + 1 + strlen(suffix) + 1); strcpy(result,root); strcat(result,"/"); strcat(result,suffix); return result; } extern char * str_skip_space(char *str) { for(;*str == ' ' || *str == '\t';str++); return str; } extern char * str_skip_word(char *str) { for(;*str != ' ' && *str != '\t' && *str;str++); return str; } /* convert a time string to time_t time string format is: yyyy/mm/dd or yyyy-mm-dd or yyyy.mm.dd hh:mm:ss */ extern int timestr_to_time(char const * timestr, time_t* ptime) { char const * p; char ch; struct tm when; int day_s, time_s, last; if (!timestr) return -1; if (!timestr[0]) { *ptime = 0; return 0; } p = timestr; day_s = time_s = 0; last = 0; memset(&when, 0, sizeof(when)); when.tm_mday = 1; when.tm_isdst = -1; while (1) { ch = *timestr; timestr++; switch (ch) { case '/': case '-': case '.': if (day_s == 0) { when.tm_year = atoi(p) - 1900; } else if (day_s == 1) { when.tm_mon = atoi(p) - 1; } else if (day_s == 2) { when.tm_mday = atoi(p); } time_s = 0; day_s++; p = timestr; last = 1; break; case ':': if (time_s == 0) { when.tm_hour = atoi(p); } else if (time_s == 1) { when.tm_min = atoi(p); } else if (time_s == 2) { when.tm_sec = atoi(p); } day_s = 0; time_s++; p = timestr; last = 2; break; case ' ': case '\t': case '\x0': if (last == 1) { if (day_s == 0) { when.tm_year = atoi(p) - 1900; } else if (day_s == 1) { when.tm_mon = atoi(p) - 1; } else if (day_s == 2) { when.tm_mday = atoi(p); } } else if (last == 2) { if (time_s == 0) { when.tm_hour = atoi(p); } else if (time_s == 1) { when.tm_min = atoi(p); } else if (time_s == 2) { when.tm_sec = atoi(p); } } time_s = day_s = 0; p = timestr; last = 0; break; default: break; } if (!ch) break; } *ptime = mktime(&when); return 0; } extern void strlower(char* str) { for(;*str;str++) *str = tolower(*str); } pvpgn-1.8.5/src/common/cdbhash.h0000644000175000017500000000207711151345317015474 0ustar aaronaaron/* * Copyright (C) 2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __CDBHASH_H_INCLUDED__ #define __CDBHASH_H_INCLUDED__ typedef unsigned int t_cdbhash; static inline t_cdbhash cdb_hash(const void* data, size_t len) { t_cdbhash h; const char* p = (const char*)data; for (h = 5381; len > 0; --len, ++p) { h += h << 5; h ^= *p; } return h; } #endif /* __CDBHASH_H_INCLUDED__ */ pvpgn-1.8.5/src/common/file_protocol.h0000644000175000017500000001141411151345317016733 0ustar aaronaaron/* * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_FILE_PROTOCOL_TYPES #define INCLUDED_FILE_PROTOCOL_TYPES #ifdef JUST_NEED_TYPES # include "common/bn_type.h" #else # define JUST_NEED_TYPES # include "common/bn_type.h" # undef JUST_NEED_TYPES #endif /******************************************************/ typedef struct { bn_short size; bn_short type; } PACKED_ATTR() t_file_header; /******************************************************/ /******************************************************/ typedef struct { t_file_header h; } PACKED_ATTR() t_file_generic; /******************************************************/ /******************************************************/ /* CLIENT FILE MPQ REQ 2D 00 00 01 36 38 58 49 -...68XI 50 58 45 53 00 00 00 00 00 00 00 00 00 00 00 00 PXES............ 00 2C 58 E1 09 28 BC 01 49 58 38 36 76 65 72 31 .,X..(..IX86ver1 2E 6D 70 71 00 .mpq. CLIENT FILE TOS REQ 28 00 00 01 36 38 58 49 (...68XI 50 58 45 53 00 00 00 00 00 00 00 00 00 00 00 00 PXES............ 30 C3 89 86 09 4F BD 01 74 6F 73 2E 74 78 74 00 0....O..tos.txt. CLIENT FILE AD REQ 2D 00 00 01 36 38 58 49 -...68XI 50 58 45 53 2B 51 02 00 2E 70 63 78 00 00 00 00 PXES+Q...pcx.... 00 00 00 00 58 01 B2 00 61 64 30 32 35 31 32 62 ....X...ad02512b 2E 70 63 78 00 .pcx. */ #define CLIENT_FILE_REQ 0x0100 typedef struct { t_file_header h; bn_int archtag; bn_int clienttag; bn_int adid; bn_int extensiontag; /* unlike other tags, this one is "forward" */ bn_int startoffset; /* is this actually used in the original clients? */ bn_long timestamp; /* filename */ } PACKED_ATTR() t_client_file_req; /******************************************************/ /* the next 2 file requests appeared on w3 first. first it sends filereq2 then server replies with some rnadom int then client sends filereq3 (which is a raw packet with no valuable header) then filename then server replies with normal file_reply and sends the contents 12: recv class=file[0x03] type=unknown[0x0200] length=20 0000: 14 00 00 02 36 38 58 49 33 52 41 57 00 00 00 00 ....68XI3RAW.... 0010: 00 00 00 00 .... */ #define CLIENT_FILE_REQ2 0x0200 typedef struct { t_file_header h; bn_int archtag; bn_int clienttag; bn_long unknown1; } PACKED_ATTR() t_client_file_req2; #define CLIENT_FILE_REQ3 0x0000 typedef struct { bn_int unknown1; bn_long timestamp; bn_long unknown2; bn_long unknown3; bn_long unknown4; bn_long unknown5; bn_long unknown6; /* filename */ } PACKED_ATTR() t_client_file_req3; /******************************************************/ /* SERVER FILE MPQ REPLY 25 00 00 00 33 1B 00 00 %...3... 00 00 00 00 00 00 00 00 00 2C 58 E1 09 28 BC 01 .........,X..(.. 49 58 38 36 76 65 72 31 2E 6D 70 71 00 IX86ver1.mpq. SERVER FILE TOS REPLY 20 00 00 00 E4 00 00 00 P."..... ....... 00 00 00 00 00 00 00 00 30 C3 89 86 09 4F BD 01 ........0....O.. 74 6F 73 2E 74 78 74 00 tos.txt. SERVER FILE AD REPLY 25 00 00 00 30 2E 00 00 %...0... 2B 51 02 00 2E 70 63 78 00 00 00 00 58 01 B2 00 +Q...pcx....X... 61 64 30 32 35 31 32 62 2E 70 63 78 00 ad02512b.pcx. */ #define SERVER_FILE_REPLY 0x0000 typedef struct { t_file_header h; bn_int filelen; bn_int adid; bn_int extensiontag; /* unlike other tags, this one is "forward" */ bn_long timestamp; /* filename */ } PACKED_ATTR() t_server_file_reply; /******************************************************/ #define SERVER_FILE_UNKNOWN1 0xdeadbeef typedef struct { bn_int unknown; } PACKED_ATTR() t_server_file_unknown1; #endif pvpgn-1.8.5/src/common/bnethashconv.c0000644000175000017500000000330211151345317016545 0ustar aaronaaron/* * Copyright (C) 1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include "common/bnethash.h" #include "common/bn_type.h" #include "common/eventlog.h" #include "common/bnethashconv.h" #include "common/setup_after.h" extern void bnhash_to_hash(bn_int const * bnhash, t_hash * hash) { unsigned int i; if (!bnhash) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL bnhash"); return; } if (!hash) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash"); return; } for (i=0; i<5; i++) (*hash)[i] = bn_int_get(bnhash[i]); } extern void hash_to_bnhash(t_hash const * hash, bn_int * bnhash) { unsigned int i; if (!bnhash) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL bnhash"); return; } if (!hash) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash"); return; } for (i=0; i<5; i++) bn_int_set(&bnhash[i],(*hash)[i]); } pvpgn-1.8.5/src/common/fdwatch_select.h0000644000175000017500000000206011151345317017047 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * select() based backend * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __INCLUDED_FDWATCH_SELECT__ #define __INCLUDED_FDWATCH_SELECT__ extern t_fdw_backend fdw_select; #endif /* __INCLUDED_FDWATCH_SELECT__ */ pvpgn-1.8.5/src/common/setup_after.h0000644000175000017500000000167411151345317016423 0ustar aaronaaron/* * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_SETUP_BEFORE_H # error "This file must be included after all other header files" #endif #ifndef INCLUDED_SETUP_AFTER_H #define INCLUDED_SETUP_AFTER_H #endif pvpgn-1.8.5/src/common/asnprintf.c0000644000175000017500000002136711151345317016102 0ustar aaronaaron/* * Copyright (C) 2005 Olaf Freyer (aaron@cs.tu-berlin.de) * * Based upon lib/vsnprintf.c from the linux kernel sources * * Copyright (C) 1991, 1992 Linus Torvalds * vsprintf.c -- Lars Wirzenius & Linus Torvalds. * * * Wirzenius wrote this portably, Torvalds fucked it up :-) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #include #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "compat/uint.h" #include "asnprintf.h" #include "common/setup_after.h" static int skip_atoi(const char **s) { int i=0; while (isdigit(**s)) i = i*10 + *((*s)++) - '0'; return i; } t_uint32 do_div(t_uint64 *n, t_uint32 base) { t_uint32 remainder = *n % base; *n = *n / base; return remainder; } static char * number(char * buf, char * end, t_uint64 num, int base, int size, int precision, int type) { char c,sign,tmp[66]; const char *digits; static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int i; digits = (type & LARGE) ? large_digits : small_digits; if (type & LEFT) type &= ~ZEROPAD; if (base < 2 || base > 36) return NULL; c = (type & ZEROPAD) ? '0' : ' '; sign = 0; if (type & SIGN) { if ((t_int64) num < 0) { sign = '-'; num = - (t_int64) num; size--; } else if (type & PLUS) { sign = '+'; size--; } else if (type & SPACE) { sign = ' '; size--; } } if (type & SPECIAL) { if (base == 16) size -= 2; else if (base == 8) size--; } i = 0; if (num == 0) tmp[i++]='0'; else while (num != 0) tmp[i++] = digits[do_div(&num,base)]; if (i > precision) precision = i; size -= precision; if (!(type&(ZEROPAD+LEFT))) { while(size-->0) { if (buf <= end) *buf = ' '; ++buf; } } if (sign) { if (buf <= end) *buf = sign; ++buf; } if (type & SPECIAL) { if (base==8) { if (buf <= end) *buf = '0'; ++buf; } else if (base==16) { if (buf <= end) *buf = '0'; ++buf; if (buf <= end) *buf = digits[33]; ++buf; } } if (!(type & LEFT)) { while (size-- > 0) { if (buf <= end) *buf = c; ++buf; } } while (i < precision--) { if (buf <= end) *buf = '0'; ++buf; } while (i-- > 0) { if (buf <= end) *buf = tmp[i]; ++buf; } while (size-- > 0) { if (buf <= end) *buf = ' '; ++buf; } return buf; } int vasnprintf(char *buf, size_t size, t_fmtentry *entries, unsigned entlen, const char *fmt, va_list args) { int len; t_uint64 num; int i, base; char *str, *end, c; const char *s; int flags; /* flags to number() */ int field_width; /* width of output field */ int precision; /* min. # of digits for integers; max number of chars for from string */ int qualifier; /* 'h', 'l', or 'L' for integer fields */ /* 'z' support added 23/7/1999 S.H. */ /* 'z' changed to 'Z' --davidm 1/25/99 */ unsigned fmtno = 0; /* Reject out-of-range values early */ if ((int) size < 0) return 0; str = buf; end = buf + size - 1; /* if (end < buf - 1) { end = ((void *) -1); size = end - buf + 1; } */ for (; *fmt; ++fmt) { t_fmtentry* const fmtent = entries + fmtno; if (*fmt != '%') continue; if (fmtno >= entlen) return -1; fmtent->trans = str; fmtent->fmt = fmt; fmtno++; /* process flags */ flags = 0; repeat: ++fmt; /* this also skips first '%' */ switch (*fmt) { case '-': flags |= LEFT; goto repeat; case '+': flags |= PLUS; goto repeat; case ' ': flags |= SPACE; goto repeat; case '#': flags |= SPECIAL; goto repeat; case '0': flags |= ZEROPAD; goto repeat; } /* get field width */ field_width = -1; if (isdigit(*fmt)) field_width = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ field_width = va_arg(args, int); if (field_width < 0) { field_width = -field_width; flags |= LEFT; } } /* get the precision */ precision = -1; if (*fmt == '.') { ++fmt; if (isdigit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ precision = va_arg(args, int); } if (precision < 0) precision = 0; } /* get the conversion qualifier */ qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z' || *fmt == 'z') { qualifier = *fmt; ++fmt; if (qualifier == 'l' && *fmt == 'l') { qualifier = 'L'; ++fmt; } } /* default base */ base = 10; switch (*fmt) { case 'c': if (!(flags & LEFT)) { while (--field_width > 0) { if (str > end) return -1; *str = ' '; ++str; } } c = (unsigned char) va_arg(args, int); if (str > end) return -1; *str = c; ++str; while (--field_width > 0) { if (str > end) return -1; *str = ' '; ++str; } fmtent->fmtlen = fmt - fmtent->fmt + 1; fmtent->translen = str - fmtent->trans; continue; case 's': s = va_arg(args, char *); if (!s) s = ""; len = strlen(s); if (len>precision) len=precision; if (!(flags & LEFT)) { while (len < field_width--) { if (str > end) return -1; *str = ' '; ++str; } } for (i = 0; i < len; ++i) { if (str > end) return -1; *str = *s; ++str; ++s; } while (len < field_width--) { if (str > end) return -1; *str = ' '; ++str; } fmtent->fmtlen = fmt - fmtent->fmt + 1; fmtent->translen = str - fmtent->trans; continue; case 'p': if (field_width == -1) { field_width = 2*sizeof(void *); flags |= ZEROPAD; } str = number(str, end, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); if (str > end) return -1; fmtent->fmtlen = fmt - fmtent->fmt + 1; fmtent->translen = str - fmtent->trans; continue; case 'n': /* FIXME: * What does C99 say about the overflow case here? */ if (qualifier == 'l') { long * ip = va_arg(args, long *); *ip = (str - buf); } else if (qualifier == 'Z' || qualifier == 'z') { size_t * ip = va_arg(args, size_t *); *ip = (str - buf); } else { int * ip = va_arg(args, int *); *ip = (str - buf); } fmtent->fmtlen = fmt - fmtent->fmt + 1; fmtent->translen = str - fmtent->trans; continue; case '%': if (str > end) return -1; *str = '%'; ++str; fmtent->fmtlen = fmt - fmtent->fmt + 1; fmtent->translen = str - fmtent->trans; continue; /* integer number formats - set up the flags and "break" */ case 'o': base = 8; break; case 'X': flags |= LARGE; case 'x': base = 16; break; case 'd': case 'i': flags |= SIGN; case 'u': break; default: if (str > end) return -1; *str = '%'; ++str; if (*fmt) { if (str > end) return -1; *str = *fmt; ++str; } else { --fmt; } fmtent->fmtlen = fmt - fmtent->fmt + 1; fmtent->translen = str - fmtent->trans; continue; } if (qualifier == 'L') num = va_arg(args, long long); else if (qualifier == 'l') { num = va_arg(args, unsigned long); if (flags & SIGN) num = (signed long) num; } else if (qualifier == 'Z' || qualifier == 'z') { num = va_arg(args, size_t); } else if (qualifier == 'h') { num = (unsigned short) va_arg(args, int); if (flags & SIGN) num = (signed short) num; } else { num = va_arg(args, unsigned int); if (flags & SIGN) num = (signed int) num; } str = number(str, end, num, base, field_width, precision, flags); if (str > end) return -1; fmtent->fmtlen = fmt - fmtent->fmt + 1; fmtent->translen = str - fmtent->trans; } if (str <= end) *str = '\0'; /* the trailing null byte doesn't count towards the total * ++str; */ return str - buf; } int asnprintf(char * buf, size_t size, t_fmtentry *entries, unsigned entlen, const char *fmt, ...) { va_list args; int i; VA_START(args, fmt); i=vasnprintf(buf,size,entries,entlen,fmt,args); va_end(args); return i; } pvpgn-1.8.5/src/common/network.c0000644000175000017500000001341311151345317015560 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common/setup_before.h" #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include #include "compat/strerror.h" #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include "compat/socket.h" #include "compat/recv.h" #include "compat/send.h" #ifdef HAVE_NETINET_IN_H # include #endif #include "compat/netinet_in.h" #include "compat/psock.h" #include "common/packet.h" #include "common/eventlog.h" #include "common/field_sizes.h" #include "common/network.h" #include "common/setup_after.h" extern int net_recv(int sock, void *buff, int len) { int res; res = psock_recv(sock, buff, len, 0); if (res > 0) return res; if (!res) return -1; /* connection closed */ if ( #ifdef PSOCK_EINTR psock_errno()==PSOCK_EINTR || #endif #ifdef PSOCK_EAGAIN psock_errno()==PSOCK_EAGAIN || #endif #ifdef PSOCK_EWOULDBLOCK psock_errno()==PSOCK_EWOULDBLOCK || #endif #ifdef PSOCK_ENOMEM psock_errno()==PSOCK_ENOMEM || #endif 0) /* try later */ return 0; if ( #ifdef PSOCK_ENOTCONN psock_errno()==PSOCK_ENOTCONN || #endif #ifdef PSOCK_ECONNRESET psock_errno()==PSOCK_ECONNRESET || #endif 0) { /* eventlog(eventlog_level_debug,__FUNCTION__,"[%d] remote host closed connection (psock_recv: %s)",sock,pstrerror(psock_errno())); */ return -1; /* common error: close connection, but no message */ } eventlog(eventlog_level_debug,__FUNCTION__,"[%d] receive error (closing connection) (psock_recv: %s)",sock,pstrerror(psock_errno())); return -1; } extern int net_recv_packet(int sock, t_packet * packet, unsigned int * currsize) { int addlen; unsigned int header_size; void * temp; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet (closing connection)",sock); return -1; } if (!currsize) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL currsize (closing connection)",sock); return -1; } if ((header_size = packet_get_header_size(packet))>=MAX_PACKET_SIZE) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not determine header size (closing connection)",sock); return -1; } if (!(temp = packet_get_raw_data_build(packet,*currsize))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not obtain raw data pointer at offset %u (closing connection)",sock,*currsize); return -1; } if (*currsize=total_size) { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] more data requested for already complete packet (total_size=%u currsize=%u) (closing connection)",sock,total_size,*currsize); return -1; } addlen = net_recv(sock, temp, total_size-*currsize); } if (addlen<=0) return addlen; *currsize += addlen; if (*currsize>=header_size && *currsize==packet_get_size(packet)) return 1; return 0; } extern int net_send(int sock, const void *buff, int len) { int res; res = psock_send(sock, buff, len, 0); if (res > 0) return res; if (!res) return -1; if ( #ifdef PSOCK_EINTR psock_errno()==PSOCK_EINTR || #endif #ifdef PSOCK_EAGAIN psock_errno()==PSOCK_EAGAIN || #endif #ifdef PSOCK_EWOULDBLOCK psock_errno()==PSOCK_EWOULDBLOCK || #endif #ifdef PSOCK_ENOBUFS psock_errno()==PSOCK_ENOBUFS || #endif #ifdef PSOCK_ENOMEM psock_errno()==PSOCK_ENOMEM || #endif 0) return 0; /* try again later */ if ( #ifdef PSOCK_EPIPE psock_errno()!=PSOCK_EPIPE && #endif #ifdef PSOCK_ECONNRESET psock_errno()!=PSOCK_ECONNRESET && #endif 1) eventlog(eventlog_level_debug,__FUNCTION__,"[%d] could not send data (closing connection) (psock_send: %s)",sock,pstrerror(psock_errno())); return -1; } extern int net_send_packet(int sock, t_packet const * packet, unsigned int * currsize) { unsigned int size; int addlen; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet (closing connection)",sock); return -1; } if (!currsize) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL currsize (closing connection)",sock); return -1; } if ((size = packet_get_size(packet))<1) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] packet to send is empty (skipping it)",sock); *currsize = 0; return 1; } addlen = net_send(sock,packet_get_raw_data_const(packet,*currsize),size-*currsize); if (addlen <= 0) return addlen; *currsize += addlen; /* sent all data in this packet? */ if (size==*currsize) { *currsize = 0; return 1; } return 0; } pvpgn-1.8.5/src/common/network.h0000644000175000017500000000244111151345317015564 0ustar aaronaaron/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_NETWORK_PROTOS #define INCLUDED_NETWORK_PROTOS #define JUST_NEED_TYPES #include "common/packet.h" #undef JUST_NEED_TYPES extern int net_recv(int sock, void *buff, int len); extern int net_send(int sock, const void *buff, int len); extern int net_recv_packet(int sock, t_packet * packet, unsigned int * currsize); extern int net_send_packet(int sock, t_packet const * packet, unsigned int * currsize); #endif #endif pvpgn-1.8.5/src/common/fdwatch_kqueue.h0000644000175000017500000000206511151345317017074 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * *BSD kqueue() based backend * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __INCLUDED_FDWATCH_KQUEUE__ #define __INCLUDED_FDWATCH_KQUEUE__ extern t_fdw_backend fdw_kqueue; #endif /* __INCLUDED_FDWATCH_KQUEUE__ */ pvpgn-1.8.5/src/common/xalloc.h0000644000175000017500000000410011151345317015347 0ustar aaronaaron/* * Copyright (C) 2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_XALLOC_TYPES /* out of memory callback function */ typedef int (*t_oom_cb)(void); #define INCLUDED_XALLOC_TYPES #endif /* INCLUDED_XALLOC_TYPES */ #ifndef INCLUDED_XALLOC_PROTOS #define INCLUDED_XALLOC_PROTOS #ifdef HAVE_STDDEF_H # include #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifndef XALLOC_SKIP #define xmalloc(size) xmalloc_real(size,__FILE__,__LINE__) void *xmalloc_real(size_t size, const char *fn, unsigned ln); #define xcalloc(no,size) xcalloc_real(no,size,__FILE__,__LINE__) void *xcalloc_real(size_t nmemb, size_t size, const char *fn, unsigned ln); #define xrealloc(ptr,size) xrealloc_real(ptr,size,__FILE__,__LINE__) void *xrealloc_real(void *ptr, size_t size, const char *fn, unsigned ln); #define xstrdup(str) xstrdup_real(str,__FILE__,__LINE__) char *xstrdup_real(const char *str, const char *fn, unsigned ln); #define xfree(ptr) xfree_real(ptr,__FILE__,__LINE__) void xfree_real(void *ptr, const char *fn, unsigned ln); void xalloc_setcb(t_oom_cb cb); #else /* XALLOC_SKIP */ #define xmalloc(size) malloc(size) #define xcalloc(no,size) calloc(no,size) #define xrealloc(ptr,size) realloc(ptr,size) #define xstrdup(str) strdup(str) #define xfree(ptr) free(ptr) #define xalloc_setcb(cb) #endif #endif /* INCLUDED_XALLOC_PROTOS */ pvpgn-1.8.5/src/common/xstring.h0000644000175000017500000000237511151345317015577 0ustar aaronaaron/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_XSTRING_H #define INCLUDED_XSTRING_H extern char * strtolower(char * str); extern char * hexstrdup(unsigned char const * src); extern unsigned int hexstrtoraw(unsigned char const * src, char * data, unsigned int datalen); extern unsigned char xtoi(unsigned char ch); extern char * * strtoargv(char const * str, unsigned int * count); extern char * arraytostr(char * * array, char const * delim, int count); extern char * str_strip_affix(char * str, char const * affix); #endif pvpgn-1.8.5/src/common/conf.h0000644000175000017500000000400511151345317015016 0ustar aaronaaron/* * Copyright (C) 2004,2005 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __CONF_H_TYPES__ #define __CONF_H_TYPES__ /* a conf entry object with a set and a get method */ typedef struct { const char *name; int (*set)(const char *valstr); /* called with NULL for cleanup */ const char * (*get)(void); int (*setdef)(void); } t_conf_entry; #endif /* __CONF_H_TYPES__ */ #ifndef __CONF_H_PROTOS__ #define __CONF_H_PROTOS__ #include #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif /* helpfull utility functions for common conf types like bool, int and str */ extern int conf_set_bool(unsigned *pbool, const char *valstr, unsigned def); extern int conf_set_int(unsigned *pint, const char *valstr, unsigned def); extern int conf_set_str(const char **pstr, const char *valstr, const char *def); extern int conf_set_timestr(time_t* ptime, const char *valstr, time_t def); extern const char* conf_get_int(unsigned ival); extern const char* conf_get_bool(unsigned ival); /* loading/unloading functions */ extern int conf_load_file(FILE *fd, t_conf_entry *conftab); extern int conf_load_cmdline(int argc, char **argv, t_conf_entry *conftab); extern void conf_unload(t_conf_entry *conftab); #endif /* __CONF_H_PROTOS__ */ pvpgn-1.8.5/src/common/irc_protocol.h0000644000175000017500000004762311151345317016604 0ustar aaronaaron/* * Copyright (C) 2001 Marco Ziech (mmz@gmx.net) * Copyright (C) 2005 Bryan Biedenkapp (gatekeep@gmail.com) * Copyright (C) 2008 Pelish (pelish@gmail.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_IRC_PROTOCOL_TYPES #define INCLUDED_IRC_PROTOCOL_TYPES #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_INIT_PROTOCOL_PROTOS #define INCLUDED_INIT_PROTOCOL_PROTOS /* IRC Defines */ #define WOL_NICKNAME_LEN 9 #define CHANNEL_PREFIX "(ov)@+" #define CHANNEL_TYPE "#" /* Reply Defines */ /* The following defines were taken from include/numeric.h * of the undernet-ircd distribution. * See http://www.undernet.org/ */ /** reply's */ #define RPL_WELCOME 1 #define RPL_YOURHOST 2 #define RPL_CREATED 3 #define RPL_MYINFO 4 #define RPL_ISUPPORT 5 /* Undernet/Dalnet extension */ /* RPL_BOUNCE IRCnet extension */ /* RPL_MAP 6 unreal */ /* RPL_MAPEND 7 unreal */ #define RPL_SNOMASK 8 /* Undernet extension */ #define RPL_STATMEMTOT 9 /* Undernet extension */ #define RPL_STATMEM 10 /* Undernet extension */ /* RPL_YOURCOOKIE 14 IRCnet extension */ #define RPL_MAP 15 /* Undernet extension */ #define RPL_MAPMORE 16 /* Undernet extension */ #define RPL_MAPEND 17 /* Undernet extension */ /* RPL_YOURID 42 IRCnet extension */ /* RPL_ATTEMPTINGJUNC 50 aircd extension */ /* RPL_ATTEMPTINGREROUTE 51 aircd extension */ /* * Numberic replies from server commands. * These are currently in the range 200-399. */ #define RPL_TRACELINK 200 #define RPL_TRACECONNECTING 201 #define RPL_TRACEHANDSHAKE 202 #define RPL_TRACEUNKNOWN 203 #define RPL_TRACEOPERATOR 204 #define RPL_TRACEUSER 205 #define RPL_TRACESERVER 206 #define RPL_TRACENEWTYPE 208 #define RPL_TRACECLASS 209 /* RPL_STATS 210 aircd extension, used instead of having multiple stats numerics */ /* RPL_TRACERECONNECT 210 IRCnet extension */ #define RPL_STATSLINKINFO 211 #define RPL_STATSCOMMANDS 212 #define RPL_STATSCLINE 213 /* RPL_STATSOLDNLINE 214 unreal */ #define RPL_STATSNLINE 214 /* unused */ #define RPL_STATSILINE 215 #define RPL_STATSKLINE 216 #define RPL_STATSPLINE 217 /* Undernet extenstion */ /* RPL_STATSQLINE 217 Various */ #define RPL_STATSYLINE 218 #define RPL_ENDOFSTATS 219 /* See also RPL_STATSDLINE */ /* RPL_STATSPLINE 220 Hybrid - Because 217 was for old Q: lines. */ /* RPL_STATSBLINE 220 Numerics List: Dalnet,unreal */ #define RPL_UMODEIS 221 /* RPL_SQLINE_NICK 222 Numerics List: Dalnet */ /* RPL_STATSELINE 223 dalnet */ /* RPL_STATSGLINE 223 unreal */ /* RPL_STATSFLINE 224 Hybrid extension,Dalnet */ /* RPL_STATSTLINE 224 unreal */ /* RPL_STATSDLINE 225 Hybrid extension */ /* RPL_STATSZLINE 225 Dalnet RPL_STATSELINE 225 unreal RPL_STATSCOUNT 226 Dalnet RPL_STATSNLINE 226 unreal RPL_STATSGLINE 227 Dalnet RPL_STATSVLINE 227 unreal */ #define RPL_SERVICEINFO 231 /* unused */ #define RPL_ENDOFSERVICES 232 /* unused */ /* RPL_RULES 232 unreal */ #define RPL_SERVICE 233 /* unused */ #define RPL_SERVLIST 234 /* unused */ #define RPL_SERVLISTEND 235 /* unused */ #define RPL_STATSENGINE 237 /* Undernet engine name */ #define RPL_STATSFLINE 238 /* Undernet feature lines */ /* RPL_STATSIAUTH 239 IRCnet extension */ /* RPL_STATSVLINE 240 IRCnet extension */ /* RPL_STATSXLINE 240 austnet */ #define RPL_STATSLLINE 241 #define RPL_STATSUPTIME 242 #define RPL_STATSOLINE 243 #define RPL_STATSHLINE 244 /* RPL_STATSSLINE 245 Reserved / Dalnet / IRCnet / EFnet */ /* RPL_STATSSPING 246 Numerics List: IRCnet */ #define RPL_STATSTLINE 246 /* Undernet extension */ /* RPL_STATSULINE 246 Dalnet */ #define RPL_STATSGLINE 247 /* Undernet extension */ /* RPL_STATSXLINE 247 hybrid extension,PTlink,unreal */ /* RPL_STATSBLINE 247 Numerics List: IRCnet */ #define RPL_STATSULINE 248 /* Undernet extension */ /* RPL_STATSDEFINE 248 Numerics List: IRCnet */ #define RPL_STATSDEBUG 249 /* Extension to RFC1459 */ #define RPL_STATSCONN 250 /* Undernet extension */ /* RPL_STATSDLINE 250 Numerics List: IRCnet */ #define RPL_LUSERCLIENT 251 #define RPL_LUSEROP 252 #define RPL_LUSERUNKNOWN 253 #define RPL_LUSERCHANNELS 254 #define RPL_LUSERME 255 #define RPL_ADMINME 256 #define RPL_ADMINLOC1 257 #define RPL_ADMINLOC2 258 #define RPL_ADMINEMAIL 259 #define RPL_TRACELOG 261 /* unused */ #define RPL_TRACEPING 262 /* Extension to RFC1459, unused */ /* RPL_TRACEEND 262 efnet(?) Numerics List: IRCnet */ /* RPL_LOAD_THROTTLED 263 efnet/hybrid */ /* RPL_TRYAGAIN 263 Numerics List: IRCnet */ /* RPL_LOAD2HI 263 Dalnet */ /* RPL_CURRENT_LOCAL 265 aircd/efnet/hybrid/dalnet*/ /* RPL_CURRENT_GLOBAL 266 aircd/efnet/hybrid/dalnet */ /* RPL_START_NETSTAT 267 aircd */ /* RPL_NETSTAT 268 aircd */ /* RPL_END_NETSTAT 269 aircd */ #define RPL_PRIVS 270 /* Undernet extension - privs */ #define RPL_SILELIST 271 /* Undernet extension */ #define RPL_ENDOFSILELIST 272 /* Undernet extension */ /* RPL_NOTIFY 273 aircd */ /* RPL_END_NOTIFY 274 aircd */ /* RPL_STATSDELTA 274 IRCnet extension */ #define RPL_STATSDLINE 275 /* Undernet extension */ #define RPL_GLIST 280 /* Undernet extension */ #define RPL_ENDOFGLIST 281 /* Undernet extension */ #define RPL_JUPELIST 282 /* Undernet extension - jupe -Kev */ #define RPL_ENDOFJUPELIST 283 /* Undernet extension - jupe -Kev */ #define RPL_FEATURE 284 /* Undernet extension - features */ /* RPL_CHANINFO_HANDLE 285 aircd */ /* RPL_CHANINFO_USERS 286 aircd */ /* RPL_CHANINFO_CHOPS 287 aircd */ /* RPL_CHANINFO_VOICES 288 aircd */ /* RPL_CHANINFO_AWAY 289 aircd */ /* RPL_CHANINFO_OPERS 290 aircd */ /* RPL_HELPHDR 290 Numeric List: Dalnet */ /* RPL_CHANINFO_BANNED 291 aircd */ /* RPL_HELPOP 291 Numeric List: Dalnet */ /* RPL_CHANINFO_BANS 292 aircd */ /* RPL_HELPTLR 292 Numeric List: Dalnet */ /* RPL_CHANINFO_INVITE 293 aircd */ /* RPL_HELPHLP 293 Numeric List: Dalnet */ /* RPL_CHANINFO_INVITES 294 aircd */ /* RPL_HELPFWD 294 Numeric List: Dalnet */ /* RPL_CHANINFO_KICK 295 aircd */ /* RPL_HELPIGN 295 Numeric List: Dalnet */ /* RPL_CHANINFO_KICKS 296 aircd */ /* RPL_END_CHANINFO 299 aircd */ #define RPL_NONE 300 /* unused */ #define RPL_AWAY 301 #define RPL_USERHOST 302 #define RPL_ISON 303 #define RPL_TEXT 304 /* unused */ #define RPL_UNAWAY 305 #define RPL_NOWAWAY 306 #define RPL_USERIP 307 /* Undernet extension */ /* NotAway, aircd */ /* RPL_WHOISREGNICK 307 Numeric List: Dalnet */ /* RPL_SUSERHOST 307 austnet */ /* RPL_NOTIFYACTION 308 aircd */ /* RPL_WHOISADMIN 308 Numeric List: Dalnet */ /* RPL_RULESSTART 308 unreal */ /* RPL_NICKTRACE 309 aircd */ /* RPL_WHOISSADMIN 309 Numeric List: Dalnet */ /* RPL_ENDOFRULES 309 unreal */ /* RPL_WHOISHELPER 309 austnet */ /* RPL_WHOISSVCMSG 310 Dalnet */ /* RPL_WHOISHELPOP 310 unreal */ /* RPL_WHOISSERVICE 310 austnet */ #define RPL_WHOISUSER 311 /* See also RPL_ENDOFWHOIS */ #define RPL_WHOISSERVER 312 #define RPL_WHOISOPERATOR 313 #define RPL_WHOWASUSER 314 /* See also RPL_ENDOFWHOWAS */ #define RPL_ENDOFWHO 315 /* See RPL_WHOREPLY/RPL_WHOSPCRPL */ /* RPL_WHOISCHANOP 316 removed from RFC1459 */ #define RPL_WHOISIDLE 317 #define RPL_ENDOFWHOIS 318 /* See RPL_WHOISUSER/RPL_WHOISSERVER/ RPL_WHOISOPERATOR/RPL_WHOISIDLE */ #define RPL_WHOISCHANNELS 319 /* RPL_WHOIS_HIDDEN 320 Anothernet +h, ick! */ /* RPL_WHOISSPECIAL 320 unreal */ #define RPL_LISTSTART 321 #define RPL_LIST 322 #define RPL_LISTEND 323 #define RPL_CHANNELMODEIS 324 /* RPL_CHANNELPASSIS 325 IRCnet extension */ /* RPL_UNIQOPIS 325 IRCnet extension */ /* RPL_NOCHANPASS 326 IRCnet extension */ /* RPL_CHPASSUNKNOWN 327 IRCnet extension */ /* RPL_CHANNEL_URL 328 dalnet, anothernet */ #define RPL_CREATIONTIME 329 /* RPL_WHOWAS_TIME 330 ? */ #define RPL_NOTOPIC 331 #define RPL_TOPIC 332 #define RPL_TOPICWHOTIME 333 /* Undernet extension */ #define RPL_LISTUSAGE 334 /* Undernet extension */ /* RPL_COMMANDSYNTAX 334 Dalnet */ /* RPL_LISTSYNTAX 334 unreal */ /* RPL_CHANPASSOK 338 IRCnet extension (?)*/ /* RPL_WHOISACTUALLY 338 dalnet */ /* RPL_BADCHANPASS 339 IRCnet extension (?)*/ #define RPL_INVITING 341 /* RPL_SUMMONING 342 removed from RFC1459 */ #define RPL_INVITELIST 346 /* IRCnet, Undernet extension */ #define RPL_ENDOFINVITELIST 347 /* IRCnet, Undernet extension */ /* RPL_EXCEPTLIST 348 IRCnet extension */ /* RPL_ENDOFEXCEPTLIST 349 IRCnet extension */ #define RPL_VERSION 351 #define RPL_WHOREPLY 352 /* See also RPL_ENDOFWHO */ #define RPL_NAMREPLY 353 /* See also RPL_ENDOFNAMES */ #define RPL_WHOSPCRPL 354 /* Undernet extension, See also RPL_ENDOFWHO */ #define RPL_KILLDONE 361 /* not used */ #define RPL_CLOSING 362 #define RPL_CLOSEEND 363 #define RPL_LINKS 364 #define RPL_ENDOFLINKS 365 #define RPL_ENDOFNAMES 366 /* See RPL_NAMREPLY */ #define RPL_BANLIST 367 #define RPL_ENDOFBANLIST 368 #define RPL_ENDOFWHOWAS 369 #define RPL_INFO 371 #define RPL_MOTD 372 #define RPL_INFOSTART 373 /* not used */ #define RPL_ENDOFINFO 374 #define RPL_MOTDSTART 375 #define RPL_ENDOFMOTD 376 /* RPL_KICKEXPIRED 377 aircd */ /* RPL_SPAM 377 austnet */ /* RPL_BANEXPIRED 378 aircd */ /* RPL_KICKLINKED 379 aircd */ /* RPL_BANLINKED 380 aircd */ #define RPL_YOUREOPER 381 #define RPL_REHASHING 382 /* RPL_YOURSERVICE 383 Numeric List: various */ #define RPL_MYPORTIS 384 /* not used */ #define RPL_NOTOPERANYMORE 385 /* Extension to RFC1459, not used */ /* RPL_QLIST 386 unreal */ /* RPL_ENDOFQLIST 387 unreal */ /* RPL_ALIST 388 unreal */ /* RPL_ENDOFALIST 389 unreal */ #define RPL_TIME 391 /* RPL_START_USERS 392 Dalnet/EFnet/IRCnet */ /* RPL_USERS 393 Dalnet/EFnet/IRCnet */ /* RPL_END_USERS 394 Dalnet/EFnet/IRCnet */ /* RPL_NOUSERS 395 Dalnet/EFnet/IRCnet */ /* * Numberic replies from server commands. * These are currently in the range 600-699. */ /* RPL_LOGON 600 dalnet,unreal RPL_LOGOFF 601 dalnet,unreal RPL_WATCHOFF 602 dalnet,unreal RPL_WATCHSTAT 603 dalnet,unreal RPL_NOWON 604 dalnet,unreal RPL_NOWOFF 605 dalnet,unreal RPL_WATCHLIST 606 dalnet,unreal RPL_ENDOFWATCHLIST 607 dalnet,unreal RPL_MAPMORE 610 unreal RPL_MAPMORE 615 PTlink RPL_DCCSTATUS 617 dalnet RPL_DCCLIST 618 dalnet RPL_ENDOFDCCLIST 619 dalnet RPL_DCCINFO 620 dalnet RPL_DUMPING 640 unreal RPL_DUMPRPL 641 unreal RPL_EODUMP 642 unreal */ /** * Westwood Online Extensions */ #define RPL_GAME_CHANNEL 326 #define RPL_CHANNEL 327 #define RPL_GET_CODEPAGE 328 #define RPL_SET_CODEPAGE 329 #define RPL_GET_LOCALE 309 #define RPL_SET_LOCALE 310 #define RPL_BATTLECLAN 358 #define RPL_BAD_LOGIN 378 #define RPL_VERCHK_NONREQ 379 /* for WOL */ #define RPL_FIND_USER_EX 398 #define RPL_UPDATE_RECORD 602 #define RPL_IRCSERV 605 #define RPL_ENDSERVLIST 607 #define RPL_GAMERESSERV 608 #define RPL_LADDERSERV 609 #define RPL_LOBCOUNT 610 #define ERR_IDNOEXIST 439 #define ERR_GAMECHANCLOSED 478 /** error's */ /* * Errors are in the range from 400-599 currently and are grouped by what * commands they come from. */ #define ERR_FIRSTERROR 400 /* unused */ #define ERR_NOSUCHNICK 401 #define ERR_NOSUCHSERVER 402 #define ERR_NOSUCHCHANNEL 403 #define ERR_CANNOTSENDTOCHAN 404 #define ERR_TOOMANYCHANNELS 405 #define ERR_WASNOSUCHNICK 406 #define ERR_TOOMANYTARGETS 407 /* ERR_NOSUCHSERVICE 408 IRCnet */ /* ERR_NOCOLORSONCHAN 408 Dalnet */ #define ERR_NOORIGIN 409 #define ERR_NORECIPIENT 411 #define ERR_NOTEXTTOSEND 412 #define ERR_NOTOPLEVEL 413 #define ERR_WILDTOPLEVEL 414 /* ERR_BADMASK 415 IRCnet extension */ #define ERR_QUERYTOOLONG 416 /* Undernet extension */ /* ERR_TOOMANYMATCHES 416 IRCnet extension */ /* ERR_LENGTHTRUNCATED 419 aircd */ #define ERR_UNKNOWNCOMMAND 421 #define ERR_NOMOTD 422 #define ERR_NOADMININFO 423 /* ERR_FILEERROR 424 removed from RFC1459 */ /* ERR_TOOMANYAWAY 429 Dalnet */ #define ERR_NONICKNAMEGIVEN 431 #define ERR_ERRONEUSNICKNAME 432 #define ERR_NICKNAMEINUSE 433 /* ERR_SERVICENAMEINUSE 434 ? */ /* ERR_NORULES 434 unreal */ /* ERR_SERVICECONFUSED 435 ? */ /* ERR_BANONCHAN 435 dalnet */ #define ERR_NICKCOLLISION 436 #define ERR_BANNICKCHANGE 437 /* Undernet extension */ /* ERR_UNAVAILRESOURCE 437 IRCnet extension */ #define ERR_NICKTOOFAST 438 /* Undernet extension */ /* ERR_DEAD 438 IRCnet reserved for later use */ #define ERR_TARGETTOOFAST 439 /* Undernet extension */ /* ERR_SERVICESDOWN 440 Dalnet,unreal */ #define ERR_USERNOTINCHANNEL 441 #define ERR_NOTONCHANNEL 442 #define ERR_USERONCHANNEL 443 /* ERR_NOLOGIN 444 removed from RFC1459 */ /* ERR_SUMMONDISABLED 445 removed from RFC1459 */ /* ERR_USERSDISABLED 446 removed from RFC1459 */ /* ERR_NONICKCHANGE 447 unreal */ #define ERR_NOTREGISTERED 451 /* ERR_IDCOLLISION 452 IRCnet extension ? */ /* ERR_NICKLOST 453 IRCnet extension ? */ /* ERR_HOSTILENAME 455 unreal */ /* ERR_NOHIDING 459 unreal */ /* ERR_NOTFORHALFOPS 460 unreal */ #define ERR_NEEDMOREPARAMS 461 #define ERR_ALREADYREGISTRED 462 #define ERR_NOPERMFORHOST 463 #define ERR_PASSWDMISMATCH 464 #define ERR_YOUREBANNEDCREEP 465 #define ERR_YOUWILLBEBANNED 466 #define ERR_KEYSET 467 /* Undernet extension */ #define ERR_INVALIDUSERNAME 468 /* Undernet extension */ /* ERR_ONLYSERVERSCANCHANGE 468 Dalnet,unreal */ /* ERR_LINKSET 469 unreal */ /* ERR_LINKCHANNEL 470 unreal */ /* ERR_KICKEDFROMCHAN 470 aircd */ #define ERR_CHANNELISFULL 471 #define ERR_UNKNOWNMODE 472 #define ERR_INVITEONLYCHAN 473 #define ERR_BANNEDFROMCHAN 474 #define ERR_BADCHANNELKEY 475 #define ERR_BADCHANMASK 476 /* Undernet extension */ /* ERR_NEEDREGGEDNICK 477 DalNet Extention */ #define ERR_BANLISTFULL 478 /* Undernet extension */ /* ERR_LINKFAIL 479 unreal */ #define ERR_BADCHANNAME 479 /* EFNet extension */ /* 479 Undernet extension badchan */ /* ERR_CANNOTKNOCK 480 unreal */ /* ERR_NOULINE 480 austnet */ #define ERR_NOPRIVILEGES 481 #define ERR_CHANOPRIVSNEEDED 482 #define ERR_CANTKILLSERVER 483 #define ERR_ISCHANSERVICE 484 /* Undernet extension */ /* ERR_DESYNC 484 Dalnet,PTlink */ /* ERR_ATTACKDENY 484 unreal */ #define ERR_RESTRICTED 484 /* IRCnet extension */ /* ERR_UNIQOPRIVSNEEDED 485 IRCnet extension */ /* ERR_KILLDENY 485 unreal */ /* ERR_CANTKICKADMIN 485 PTlink */ /* ERR_HTMDISABLED 486 unreal */ /* ERR_CHANTOORECENT 487 IRCnet extension (?) */ /* ERR_TSLESSCHAN 488 IRCnet extension (?) */ #define ERR_VOICENEEDED 489 /* Undernet extension */ #define ERR_NOOPERHOST 491 /* ERR_NOSERVICEHOST 492 IRCnet extension */ #define ERR_NOFEATURE 493 /* Undernet extension - features */ #define ERR_BADFEATVALUE 494 /* Undernet extension - features */ #define ERR_BADLOGTYPE 495 /* Undernet extension - features */ #define ERR_BADLOGSYS 496 /* Undernet extension - features */ #define ERR_BADLOGVALUE 497 /* Undernet extension - features */ #define ERR_ISOPERLCHAN 498 /* Undernet extension */ #define ERR_UMODEUNKNOWNFLAG 501 #define ERR_USERSDONTMATCH 502 /* ERR_GHOSTEDCLIENT 503 efnet */ /* ERR_VWORLDWARN 503 austnet */ #define ERR_SILELISTFULL 511 /* Undernet extension */ /* ERR_NOTIFYFULL 512 aircd */ /* ERR_TOOMANYWATCH 512 Numeric List: Dalnet */ #define ERR_NOSUCHGLINE 512 /* Undernet extension */ #define ERR_BADPING 513 /* Undernet extension */ /* ERR_NEEDPONG 512 Numeric List: Dalnet */ #define ERR_NOSUCHJUPE 514 /* Undernet extension - jupe -Kev */ /* ERR_TOOMANYDCC 514 dalnet */ #define ERR_BADEXPIRE 515 /* Undernet extension - jupe -Kev */ #define ERR_DONTCHEAT 516 /* Undernet extension */ #define ERR_DISABLED 517 /* Undernet extension -Kev */ /* ERR_NOINVITE 518 unreal */ #define ERR_LONGMASK 518 /* Undernet extension -Kev */ /* ERR_ADMONLY 519 unreal */ #define ERR_TOOMANYUSERS 519 /* Undernet extension -Kev */ /* ERR_OPERONLY 520 unreal */ #define ERR_MASKTOOWIDE 520 /* Undernet extension -Kev */ /* ERR_WHOTRUNC 520 austnet */ #define ERR_LASTERROR 521 /* ERR_LISTSYNTAX 521 dalnet ERR_WHOSYNTAX 522 dalnet ERR_WHOLIMEXCEED 523 dalnet */ #endif #endif pvpgn-1.8.5/src/common/hashtable.c0000644000175000017500000003262211151345317016025 0ustar aaronaaron/* * Copyright (C) 2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define HASHTABLE_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #include "common/eventlog.h" #include "common/hashtable.h" #include "common/xalloc.h" #include "common/setup_after.h" static int nodata; /* if data points to this, then the entry was actually deleted */ static t_entry * hashtable_entry_export(t_internentry * entry, t_hashtable const * hashtable, unsigned int row); static t_entry * hashtable_entry_export(t_internentry * entry, t_hashtable const * hashtable, unsigned int row) { t_entry * temp; if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL entry"); return NULL; } if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return NULL; } if (row>=hashtable->num_rows) { eventlog(eventlog_level_error,__FUNCTION__,"got bad row %u (max %u)",row,hashtable->num_rows-1); return NULL; } temp = xmalloc(sizeof(t_entry)); temp->row = row; temp->real = entry; temp->hashtable = hashtable; return temp; } extern t_hashtable * hashtable_create(unsigned int num_rows) { t_hashtable * new; unsigned int i; if (num_rows<1) { eventlog(eventlog_level_error,__FUNCTION__,"num_rows must be at least 1"); return NULL; } new = xmalloc(sizeof(t_hashtable)); new->rows = xmalloc(sizeof(t_internentry *)*num_rows); new->num_rows = num_rows; new->len = 0; for (i=0; irows[i] = NULL; return new; } extern int hashtable_destroy(t_hashtable * hashtable) { unsigned int i; if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return -1; } hashtable_purge(hashtable); for (i=0; inum_rows; i++) if (hashtable->rows[i]) eventlog(eventlog_level_error,__FUNCTION__,"got non-empty hashtable"); xfree(hashtable->rows); xfree(hashtable); return 0; } extern int hashtable_purge(t_hashtable * hashtable) { unsigned int row; t_internentry * curr; t_internentry * head; t_internentry * next; t_internentry * * change; if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return -1; } #ifdef HASHTABLE_DEBUG hashtable_check(hashtable); #endif for (row=0; rownum_rows; row++) { head = NULL; change = NULL; for (curr=hashtable->rows[row]; curr; curr=next) { next = curr->next; if (curr->data==&nodata) { if (change) *change = next; xfree(curr); } else { if (!head) head = curr; change = &curr->next; } } hashtable->rows[row] = head; } return 0; } extern int hashtable_check(t_hashtable const * hashtable) { unsigned int emptycnt; unsigned int validcnt; unsigned int row; unsigned int temp; t_internentry const * tail; t_internentry const * curr; if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return -1; } if (hashtable->num_rows<1) { eventlog(eventlog_level_error,__FUNCTION__,"num_rows=%u",hashtable->num_rows); return -1; } if (!hashtable->rows) { eventlog(eventlog_level_error,__FUNCTION__,"hashtable->rows is NULL"); return -1; } emptycnt=validcnt = 0; for (row=0; rownum_rows; row++) { tail = NULL; for (curr=hashtable->rows[row]; curr; curr=curr->next) { if (tail) { if (curr==tail) /* tail is currently the previous node */ { eventlog(eventlog_level_error,__FUNCTION__,"row %u is circular (curr==prev==%p)",row,curr); return -1; } if (curr->next==tail) { eventlog(eventlog_level_error,__FUNCTION__,"row %u is circular (curr->next==prev==%p)",row,curr); return -1; } for (temp=0; tempnum_rows; temp++) if (curr==hashtable->rows[temp]) { eventlog(eventlog_level_error,__FUNCTION__,"row %u is circular (curr==rows[%u]==%p)",row,temp,curr); return -1; } } if (curr->data==&nodata) emptycnt++; else validcnt++; tail = curr; } } if (emptycnt>10 && emptycnt>validcnt+5) /* arbitrary heuristic to detect missing list_purge() cal ls */ eventlog(eventlog_level_warn,__FUNCTION__,"emptycnt=%u but validcnt=%u",emptycnt,validcnt); if (hashtable->len!=validcnt) { eventlog(eventlog_level_error,__FUNCTION__,"hashtable->len=%u but validcnt=%u",hashtable->len,validcnt); return -1; } return 0; } extern unsigned int hashtable_get_length(t_hashtable const * hashtable) { if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return 0; } return hashtable->len; } extern int hashtable_insert_data(t_hashtable * hashtable, void * data, unsigned int hash) { unsigned int row; t_internentry * entry; if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return -1; } entry = xmalloc(sizeof(t_internentry)); entry->data = data; row = hash%hashtable->num_rows; entry->next = hashtable->rows[row]; hashtable->rows[row] = entry; hashtable->len++; return 0; } extern t_entry * hashtable_get_entry_by_data(t_hashtable const * hashtable, void const * data, unsigned int hash) { unsigned int row; t_internentry * curr; if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return NULL; } row = hash%hashtable->num_rows; for (curr=hashtable->rows[row]; curr; curr=curr->next) if (curr->data==data) return hashtable_entry_export(curr,hashtable,row); return NULL; } extern t_entry const * hashtable_get_entry_by_data_const(t_hashtable const * hashtable, void const * data, unsigned int hash) { unsigned int row; t_internentry * curr; if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return NULL; } row = hash%hashtable->num_rows; for (curr=hashtable->rows[row]; curr; curr=curr->next) if (curr->data==data) return hashtable_entry_export(curr,hashtable,row); return NULL; } extern int hashtable_remove_entry(t_hashtable * hashtable, t_entry * entry) { if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return -1; } if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL entry"); return -1; } if (!entry->real) { eventlog(eventlog_level_error,__FUNCTION__,"entry has NULL real pointer"); return -1; } if (entry->real->data==&nodata) { eventlog(eventlog_level_error,__FUNCTION__,"got deleted entry"); return -1; } entry->real->data = &nodata; hashtable->len--; return 0; } extern int hashtable_remove_data(t_hashtable * hashtable, void const * data, unsigned int hash) { t_entry * entry; int retval; if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return -1; } if (!(entry = hashtable_get_entry_by_data(hashtable,data,hash))) return -1; retval = hashtable_remove_entry(hashtable,entry); hashtable_entry_release(entry); return retval; } extern void * entry_get_data(t_entry const * entry) { if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL entry"); return NULL; } if (!entry->real) { eventlog(eventlog_level_error,__FUNCTION__,"entry has NULL real pointer"); return NULL; } if (entry->real->data==&nodata) { eventlog(eventlog_level_error,__FUNCTION__,"got deleted entry"); return NULL; } return entry->real->data; } extern void * hashtable_get_data_by_pos(t_hashtable const * hashtable, unsigned int pos) { t_internentry const * curr; unsigned int row; unsigned int len; if (!hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); return NULL; } len = 0; row = 0; curr = NULL; for (;;) { if (!curr) { if (row>=hashtable->num_rows) break; curr = hashtable->rows[row++]; continue; } if (curr->data!=&nodata && len++==pos) return curr->data; curr = curr->next; } eventlog(eventlog_level_error,__FUNCTION__,"requested position %u but len=%u",pos,len); return NULL; } #ifdef HASHTABLE_DEBUG extern t_entry * hashtable_get_first_real(t_hashtable const * hashtable, char const * fn, unsigned int ln) #else extern t_entry * hashtable_get_first(t_hashtable const * hashtable) #endif { unsigned int row; t_internentry * curr; if (!hashtable) { #ifdef HASHTABLE_DEBUG eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable from %s:%u",fn,ln); #else eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); #endif return NULL; } for (row=0; rownum_rows; row++) for (curr=hashtable->rows[row]; curr; curr=curr->next) if (curr->data!=&nodata) return hashtable_entry_export(curr,hashtable,row); return NULL; } extern t_entry * entry_get_next(t_entry * entry) { t_hashtable const * hashtable; unsigned int row; t_internentry * curr; if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL entry"); return NULL; } hashtable = entry->hashtable; for (curr=entry->real->next; curr; curr=curr->next) if (curr->data!=&nodata) { entry->real = curr; return entry; } for (row=entry->row+1; rownum_rows; row++) for (curr=hashtable->rows[row]; curr; curr=curr->next) if (curr->data!=&nodata) { entry->real = curr; entry->row = row; return entry; } hashtable_entry_release(entry); return NULL; } #ifdef HASHTABLE_DEBUG extern t_entry * hashtable_get_first_matching_real(t_hashtable const * hashtable, unsigned int hash, char const * fn, unsigned int ln) #else extern t_entry * hashtable_get_first_matching(t_hashtable const * hashtable, unsigned int hash) #endif { unsigned int row; t_internentry * curr; if (!hashtable) { #ifdef HASHTABLE_DEBUG eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable from %s:%u",fn,ln); #else eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashtable"); #endif return NULL; } row = hash%hashtable->num_rows; for (curr=hashtable->rows[row]; curr; curr=curr->next) if (curr->data!=&nodata) return hashtable_entry_export(curr,hashtable,row); return NULL; } extern t_entry * entry_get_next_matching(t_entry * entry) { t_internentry * curr; if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL entry"); return NULL; } for (curr=entry->real->next; curr; curr=curr->next) if (curr->data!=&nodata) { entry->real = curr; return entry; } hashtable_entry_release(entry); return NULL; } extern int hashtable_entry_release(t_entry * entry) { if (!entry) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL entry"); return -1; } if (!entry->hashtable) { eventlog(eventlog_level_error,__FUNCTION__,"got entry with NULL hashtable"); return -1; } if (!entry->real) { eventlog(eventlog_level_error,__FUNCTION__,"got entry with NULL real pointer"); return -1; } if (entry->row>=entry->hashtable->num_rows) { eventlog(eventlog_level_error,__FUNCTION__,"entry has bad row %u (max %u)",entry->row,entry->hashtable->num_rows-1); return -1; } #ifdef HASHTABLE_DEBUG hashtable_check(entry->hashtable); #endif xfree(entry); return 0; } extern int hashtable_stats(t_hashtable * hashtable) { unsigned int row; t_internentry * curr; unsigned int rcount, max, min; if (!hashtable) { eventlog(eventlog_level_error, __FUNCTION__,"got NULL hashtable"); return -1; } #ifdef HASHTABLE_DEBUG hashtable_check(hashtable); #endif max = 0; min = hashtable->len; for (row=0; rownum_rows; row++) { rcount = 0; for (curr=hashtable->rows[row]; curr; curr=curr->next) if (curr->data!=&nodata) rcount++; if (rcount > max) max = rcount; if (rcount < min) min = rcount; } eventlog(eventlog_level_info, __FUNCTION__, "hashsize: %u min: %u max: %u avg: %.2f diff: %.2f%c", hashtable->num_rows, min, max, (float)(min + max)/2, (float)(max - min)/max*100, '%'); return 0; } pvpgn-1.8.5/src/common/fdwatch_select.c0000644000175000017500000001156411151345317017053 0ustar aaronaaron/* * Abstraction API/layer for the various ways PvPGN can inspect sockets state * 2003 (C) * * Code is based on the ideas found in thttpd project. * * select() based backend * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define FDWATCH_BACKEND #include "common/setup_before.h" #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif /* According to earlier standards */ #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_UNISTD_H # include #endif /* According to POSIX 1003.1-2001 */ #ifdef HAVE_SYS_SELECT_H # include #endif #include "compat/psock.h" #include "fdwatch.h" #include "common/eventlog.h" #include "common/xalloc.h" #include "common/elist.h" #include "common/setup_after.h" #ifdef HAVE_SELECT static int sr; static int smaxfd; static t_psock_fd_set *rfds = NULL, *wfds = NULL, /* working sets (updated often) */ *trfds = NULL, *twfds = NULL; /* templates (updated rare) */ static int fdw_select_init(int nfds); static int fdw_select_close(void); static int fdw_select_add_fd(int idx, t_fdwatch_type rw); static int fdw_select_del_fd(int idx); static int fdw_select_watch(long timeout_msecs); static void fdw_select_handle(void); t_fdw_backend fdw_select = { fdw_select_init, fdw_select_close, fdw_select_add_fd, fdw_select_del_fd, fdw_select_watch, fdw_select_handle }; static int fdw_select_init(int nfds) { if (nfds > FD_SETSIZE) return -1; /* this should not happen */ rfds = xmalloc(sizeof(t_psock_fd_set)); wfds = xmalloc(sizeof(t_psock_fd_set)); trfds = xmalloc(sizeof(t_psock_fd_set)); twfds = xmalloc(sizeof(t_psock_fd_set)); PSOCK_FD_ZERO(trfds); PSOCK_FD_ZERO(twfds); smaxfd = sr = 0; eventlog(eventlog_level_info, __FUNCTION__, "fdwatch select() based layer initialized (max %d sockets)", nfds); return 0; } static int fdw_select_close(void) { if (rfds) { xfree((void *)rfds); rfds = NULL; } if (wfds) { xfree((void *)wfds); wfds = NULL; } if (trfds) { xfree((void *)trfds); trfds = NULL; } if (twfds) { xfree((void *)twfds); twfds = NULL; } smaxfd = sr = 0; return 0; } static int fdw_select_add_fd(int idx, t_fdwatch_type rw) { int fd; // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); fd = fdw_fd(fdw_fds + idx); /* select() interface is limited by FD_SETSIZE max socket value */ if (fd >= FD_SETSIZE) return -1; if (rw & fdwatch_type_read) PSOCK_FD_SET(fd, trfds); else PSOCK_FD_CLR(fd, trfds); if (rw & fdwatch_type_write) PSOCK_FD_SET(fd, twfds); else PSOCK_FD_CLR(fd, twfds); if (smaxfd < fd) smaxfd = fd; return 0; } static int fdw_select_del_fd(int idx) { int fd; fd = fdw_fd(fdw_fds + idx); // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd); if (sr > 0) eventlog(eventlog_level_error, __FUNCTION__, "BUG: called while still handling sockets"); PSOCK_FD_CLR(fd, trfds); PSOCK_FD_CLR(fd, twfds); return 0; } static int fdw_select_watch(long timeout_msec) { static struct timeval tv; tv.tv_sec = timeout_msec / 1000; tv.tv_usec = timeout_msec % 1000; /* set the working sets based on the templates */ memcpy(rfds, trfds, sizeof(t_psock_fd_set)); memcpy(wfds, twfds, sizeof(t_psock_fd_set)); return (sr = psock_select(smaxfd + 1, rfds, wfds, NULL, &tv)); } static int fdw_select_cb(t_fdwatch_fd *cfd, void *data) { // eventlog(eventlog_level_trace, __FUNCTION__, "idx: %d fd: %d", idx, fdw_fd->fd); if (fdw_rw(cfd) & fdwatch_type_read && PSOCK_FD_ISSET(fdw_fd(cfd), rfds) && fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_read) == -2) return 0; if (fdw_rw(cfd) & fdwatch_type_write && PSOCK_FD_ISSET(fdw_fd(cfd), wfds)) fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_write); return 0; } static void fdw_select_handle(void) { // eventlog(eventlog_level_trace, __FUNCTION__, "called nofds: %d", fdw_nofds); fdwatch_traverse(fdw_select_cb,NULL); sr = 0; } #endif /* HAVE_SELECT */ pvpgn-1.8.5/src/common/init_protocol.h0000644000175000017500000000371611151345317016765 0ustar aaronaaron/* * Copyright (C) 1998,1999 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCLUDED_INIT_PROTOCOL_TYPES #define INCLUDED_INIT_PROTOCOL_TYPES #ifdef JUST_NEED_TYPES # include "common/bn_type.h" #else # define JUST_NEED_TYPES # include "common/bn_type.h" # undef JUST_NEED_TYPES #endif /* There is no header for this packet class and there is only * one packet type. */ /* * There is a single byte sent upon initial connections that * reports the connection type. */ /******************************************************/ #define CLIENT_INITCONN 0x1 typedef struct { bn_byte class; } PACKED_ATTR() t_client_initconn; /******************************************************/ #endif /*****/ #ifndef JUST_NEED_TYPES #ifndef INCLUDED_INIT_PROTOCOL_PROTOS #define INCLUDED_INIT_PROTOCOL_PROTOS #define CLIENT_INITCONN_CLASS_BNET 0x01 /* standard bnet protocol */ #define CLIENT_INITCONN_CLASS_FILE 0x02 #define CLIENT_INITCONN_CLASS_BOT 0x03 #define CLIENT_INITCONN_CLASS_ENC 0x04 /* encrypted connection */ #define CLIENT_INITCONN_CLASS_TELNET 0x0d /* Hack alert: look for user to hit \r when they connect */ #define CLIENT_INITCONN_CLASS_D2CS 0x01 #define CLIENT_INITCONN_CLASS_D2GS 0x64 #define CLIENT_INITCONN_CLASS_D2CS_BNETD 0x65 #endif #endif pvpgn-1.8.5/src/common/list.c0000644000175000017500000001500511151345317015041 0ustar aaronaaron/* * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define LIST_INTERNAL_ACCESS #include "common/setup_before.h" #ifdef HAVE_STDDEF_H # include #else # ifndef NULL # define NULL ((void *)0) # endif #endif #ifdef STDC_HEADERS # include #else # ifdef HAVE_MALLOC_H # include # endif #endif #ifdef HAVE_ASSERT_H # include #endif #include "common/eventlog.h" #include "common/xalloc.h" #include "common/list.h" #include "common/setup_after.h" static t_elem listhead; extern t_list * list_create(void) { t_list * new; new = xmalloc(sizeof(t_list)); new->head = NULL; new->tail = NULL; new->len = 0; return new; } extern int list_destroy(t_list * list) { if (!list) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL list"); return -1; } if (list->head) eventlog(eventlog_level_error,__FUNCTION__,"got non-empty list"); xfree(list); return 0; } extern unsigned int list_get_length(t_list const * list) { if (!list) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL list"); return 0; } return list->len; } extern int list_prepend_data(t_list * list, void * data) { t_elem * elem; assert(list != NULL); elem = xmalloc(sizeof(t_elem)); elem->data = data; if (list->head) list->head->prev = elem; elem->next = list->head; elem->prev = NULL; list->head = elem; if (!list->tail) list->tail = elem; list->len++; return 0; } extern int list_append_data(t_list * list, void * data) { t_elem * elem; assert(list != NULL); elem = xmalloc(sizeof(t_elem)); elem->data = data; elem->next = NULL; if (!list->head) { list->head = elem; elem->prev = NULL; } if (list->tail) { elem->prev = list->tail; list->tail->next = elem; } list->tail = elem; list->len++; return 0; } extern t_elem * list_get_elem_by_data(t_list const * list, void const * data) { t_elem * curr; if (!list) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL list"); return NULL; } LIST_TRAVERSE(list,curr) if (curr->data==data) return curr; return NULL; } extern t_elem const * list_get_elem_by_data_const(t_list const * list, void const * data) { t_elem const * curr; if (!list) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL list"); return NULL; } LIST_TRAVERSE_CONST(list,curr) if (curr->data==data) return curr; return NULL; } extern int list_remove_elem(t_list * list, t_elem ** elem) { t_elem * target; if (!list) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL list"); return -1; } if (!elem) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL *elem"); return -1; } target = *elem; if (target->prev) { target->prev->next = target->next; } if (target->next) { target->next->prev = target->prev; } if (target == list->tail) { list->tail = target->prev; } if (target == list->head) { list->head = target->next; *elem = &listhead; } else *elem = target->prev; target->next = NULL; target->prev = NULL; xfree(target); list->len--; return 0; } extern int list_remove_data(t_list * list, void const * data, t_elem ** elem) { if (!list) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL list"); return -1; } if (!(*elem = list_get_elem_by_data(list,data))) return -1; return list_remove_elem(list,elem); } extern int elem_set_data(t_elem * elem, void * data) { if (!elem) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem"); return -1; } elem->data = data; return 0; } extern void * elem_get_data(t_elem const * elem) { if (!elem) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem"); return NULL; } return elem->data; } extern void * list_get_data_by_pos(t_list const * list, unsigned int pos) { t_elem const * curr; unsigned int len; len = 0; LIST_TRAVERSE_CONST(list,curr) if (len++==pos) return curr->data; eventlog(eventlog_level_error,__FUNCTION__,"requested position %u but len=%u",pos,len); return NULL; } #ifdef LIST_DEBUG extern t_elem * list_get_first_real(t_list const * list, char const * fn, unsigned int ln) #else extern t_elem * list_get_first(t_list const * list) #endif { if (!list) { #ifdef LIST_DEBUG eventlog(eventlog_level_error,__FUNCTION__,"got NULL list from %s:%u",fn,ln); #else eventlog(eventlog_level_error,__FUNCTION__,"got NULL list"); #endif return NULL; } return list->head; } #ifdef LIST_DEBUG extern t_elem const * list_get_first_const_real(t_list const * list, char const * fn, unsigned int ln) #else extern t_elem const * list_get_first_const(t_list const * list) #endif { if (!list) { #ifdef LIST_DEBUG eventlog(eventlog_level_error,__FUNCTION__,"got NULL list from %s:%u",fn,ln); #else eventlog(eventlog_level_error,__FUNCTION__,"got NULL list"); #endif return NULL; } return list->head; } extern t_elem * elem_get_next_real(t_list const * list, t_elem const * elem, char const * fn, unsigned int ln) { if (!elem) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem from %s:%u",fn,ln); return NULL; } if (elem == &listhead) return list->head; else return elem->next; } extern t_elem const * elem_get_next_const(t_list const * list, t_elem const * elem) { if (!elem) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem"); return NULL; } if (elem == &listhead) return list->head; else return elem->next; } pvpgn-1.8.5/docs/0000755000175000017500000000000011151345372012573 5ustar aaronaaronpvpgn-1.8.5/docs/bnmotd.txt0000644000175000017500000000134711151345317014623 0ustar aaronaaronHere is a short note of how to use and configure the conf/bnmotd.txt - all lines have to start with %I - possible parameters that can be used: -- %a = number of registered accounts on the server -- %c = number of currently existant channels -- %g = total number of currently running games -- %G = games of users with same clienttag. -- %h = hostname of the server -- %H = contact name (as set in bnetd.conf) -- %i = userid of the user -- %l = username -- %N = name of the game the user has connected with. -- %m = check users mail when they login -- %r = IP of the user -- %s = the servername -- %t = clienttag of the user -- %u = number of users currently logged in -- %U = users logged in with the same clienttag -- %v = server version -- pvpgn-1.8.5/docs/Compile.Instructions.Win32.VS.Net.txt0000644000175000017500000000137311151345317021407 0ustar aaronaaronPvPGN Win32 VS.Net Compile Instructions Compiling WITHOUT mySQL support: - edit the PvPGN project properties: -- C/C++ -> Preprocessor -> Preprocessor definitions: remove the ";WITH_SQL_MYSQL" part of the line -- Linker -> command line: remove " libmysql.lib" part of the line - compile Compiling WITH mySQL support: - add a subfolder src/mysql/ - copy the header files from your favorite mySQL version to this folder - copy libmysql.lib from your favorite mySQL version into src/win32 - compile - make sure to provide the "libmysql.dll" from your chosen mySQL version along with the PvPGN exe Downgrade notes (to 2002 (version 7.00)): - open sln file with an editor, change 8.00 to 7.00 - open project file with an editor, change 7.10 to 7.00pvpgn-1.8.5/docs/INDEX0000644000175000017500000000066411151345317013372 0ustar aaronaaron- README.storage : how to use PvPGN with the various storage drivers (MySQL, PGSQL, cdb, files etc..) - INSTALL.unix : how to compile and install on Unix/POSIX operating systems - FAQ : frequently asked questions - Compile.Instructions.Win32.Borland.txt : as the filename says - Compile.Instructions.Win32.VS.Net.txt : same for this one - PORTS : PvPGN porting status file, check to see if your platform/operating system is supported pvpgn-1.8.5/docs/README.fdwatch0000644000175000017500000001724711151345317015104 0ustar aaronaaron PvPGN Abstract socket event notification API ie fdwatch v.01 (C) 2003 Dizzy <> 1. The problem: I wanted to design and implement a general API to have PvPGN inspect socket status (read/write availability) in the best possible way that the host OS may offer (select()/poll()/kqueue()/epoll()/etc..). Also the old PvPGN code to do such things was doing them in a very slow way, especially if the system was using poll() (which was the default with most Unices). When the server started to have lots of active connections the CPU used in PvPGN to inspect and handle them was increasing very much (the code complexity of the code executed each main loop run was of O(n^2) complexity, where n is the number of connections to the server, and the main loop is cycling at least 1000/BNETD_POLL_INTERVAL times per second ie at least 50 times per second). 2. The fdwatch API: I started by reading the fdwatch code from the thttpd project, I used the ideeas found on that code as a start point, but I got much far from those :). The fdwatch API is described in fdwatch.h as follows: extern int fdwatch_init(void); extern int fdwatch_close(void); extern int fdwatch_add_fd(int fd, t_fdwatch_type rw, fdwatch_handler h, void *data); extern int fdwatch_update_fd(int fd, t_fdwatch_type rw); extern int fdwatch_del_fd(int fd); extern int fdwatch(long timeout_msecs); extern int fdwatch_check_fd(int fd, t_fdwatch_type rw); extern void fdwatch_handle(void); The name of the functions should be self explanatory to what those functions do. 3. The changed code flow: A. the code flow before fdwatch - main() calls server_process() - server_process() after doing some single time initializations, entered the main loop - in the main loop after handing the events it starts to prepare the sockets for select/poll - it starts a loop cycling through each address configured in bnetd.conf to listen on them and adds their sockets to the socket inspection list - after this, it does a O(n) cycle where it populates the socket inspection list with the sockets of every t_connection the server has (read availability) - if any of this t_connections have packets in the outqueue (they need to send data) then the sockets are also added for write availability - then pvpgn calls select()/poll() on the socket inspection list - after the syscall returns, pvpgn cycles through each address configured in bnetd.conf and checks if they are read available (if a new connection is to be made) - pvpgn doesnt want to accept new connections when in shutdown phase but it did it the wrong way: it completly ignored the listening sockets if in shutdown phase, this made that once a connection was pending while in shutdown phase, select/poll imediatly returns because it has it in the read availability list and thus pvpgn was using 99% cpu while in shutdown phase - anyway, after this, pvpgn does a O(n) cycle through each t_connection to check if its socket is read/write available - problem is that when it was using poll() (the common case on Unices) to check if a socket was returned as read/write available by poll() it was using another O(n) function thus making the total cycle of O(n^2) - while cycling through each connection to inspect if its socket was returned available by select/poll , pvpgn also checks if the connection is in destroy state (conn_state_destroy) and if so it destroys it B. the code flow after fdwatch - I have tried to get every bit of speed I could from the design, so some things while it may look complex they have the reason of speed behind - just like the old code flow main calls server_process() - here pvpgn does some single time initializations - different than before, here, in the single time intializations code I also add the listening sockets to the fdwatch socket inspection list (also the code will need to update this list when receiving SIGHUP) - then pvpgn enters main server loop - the code first treats any received events (just like the old code) - then it calls fdwatch() to inspect the sockets state - then it calls conn_reap() to destroy the conn_state_destroy connections - then it calls fdwatch_handle() to cycle through each ready socket and handle its changed status This is it! :) No cycles, no O(n^2), not even a O(n) there (well in fact there is something similar to a O(n) inside fdwatch() but about that read bellow). FAQ: 1. Q: but where do the new connections get into the fdwatch inspection list ? A: they get in there when they are created, that means in the function sd_accept() from server.c the reason is: why add the connection sockets each time before poll() when the event of having a new connection, so a new socket to inspect is very very rare compared to the number of times we call select/poll). 2. Q: where are the connections removed from the fdwatch inspection list ? A: where they should be, in conn_destroy() just before calling close() on the socket 3. Q: where do we manifest our interest for write availability of a socket if we have data to send to it ? A: in conn_push_outuque. the ideea is if we got data to send, ok update fdwatch socket inspection list to look for write availability of the socket where we need to send data 4. Q: what does fdwatch() do ? A: depending on the chosen backend it calls select or poll, or kqueue etc... For some backends it has to do some work before calling the syscall. Ex. for select() and poll() it needs to copy from a template list of sockets to inspect to the actual working set. The reason why depends on the backend but it really is a limitation of the how the syscall works and there is nothing pvpgn that can be made to not do that. For example in the poll backend, one might argue that instead of updating a template and copy it to a working array before each poll(), we should update the working set. But that also means that before calling poll(), we must set all "revents" field of each fd_struct to 0 , and my tests show that a cycle through 1000 elements of poll fd structs setting revents to 0 is 5 times slower than using a memcpy() to copy the whole array from a source. 5. Q: what does conn_reap() do ? A: to get the maximum from each possible backend (kqueue was the main reason here) I moved the cycling through each ready socket and calling the handling function for it, outside server.c and inside fdwatch backends. Because the old code used that cycle from server.c to also check if connections are dead and need destroyed I had to find another way to do it. The best way I found was to have in connection.c besides the connlist, another list, conn_dead, which will contain the current connections which have the state set to conn_set_state. Then conn_reap() just cycles through each element of conn_dead and destroys them. This was the fastest solution I could find out. 6. Q: what does fdwatch_handle() do ? A: it calls the backend's handle function. To get the max from each backend I had to move the handling cycle as a backend specific function. In general this functions cycle through each socket which was returned ready by the last fdwatch() call, and calls the handler function (which was set when the socket was added to the socket inspection list) giving it arguments a void * parameter (also set when socket was added to the inspection list), and the type of readiness (read/write). Currently, pvpgn has 3 possible handlers: handle_tcp, handle_udp and handle_accept. Each of this calls acordingly sd_accept, sd_tcpinput, sd_tcpoutput, sd_udpinput (UDP sends are done directly, not queueing them and checking for socket readiness to write, maybe this is another bug ?) pvpgn-1.8.5/docs/Compile.Instructions.Win32.Borland.txt0000644000175000017500000000436011151345317021712 0ustar aaronaaronPvPGN Win32 Borland Compile Instructions This file explains how to compile PvPGN for Win32 using Borland C++ Compiler 5.5 1) Download Borland C++ Compiler 5.5 (BCC32) from one of the folling sites: ftp://ftpd.borland.com/download/bcppbuilder/freecommandLinetools.exe http://altd.borland.com/download/bcppbuilder/freecommandLinetools.exe 2) Install the tools to a directory, e.g. c:\program files\borlandc\ (this will be used as an example in the following) 3) Go to the /bin subdirectory, e.g. c:\program files\borlandc\bin 4) Create a file named bcc32.cfg and insert the following two lines: -I"c:\program files\borlandc\Include" -L"c:\program files\borlandc\Lib;c:\program files\borlandc\Lib\PSDK" (replace c:\program files\borlandc\ with your own borland path of course) 5) Create a file named ilink32.cfg and insert the following line: -L"c:\program files\borlandc\Lib;c:\program files\borlandc\Lib\PSDK" (replace c:\program files\borlandc\ with your own borland path of course) Those two files are required by the compiler to find the Lib and Include directory... 6) Now you're ready to compile the server. Open a command prompt, go to the Win32-Projects directory. To build all apps as console apps (recommended for running as a service): make_borland To build GUI versions of bnetd, d2cs and d2dbs: make_borland -DWITH_GUI The resulting exe file will be in the sbin directory and you can use it with the other files from the latest PvPGN release. Notes about CDB Support: ------------------------ To add support for CDB file storage add -DWITH_CDB to the command line options Notes about MYSQL Support: -------------------------- First of all u need to add a subfolder src/mysql/ where u add the header files from your favorite mySQL release. If you wish to compile with MYSQL support, run "make_borland -DWITH_SQL_MYSQL" in src directory. Note that libmySQL.lib does not work with borland compilers, so we converted it using the borland tool COFF2OMF libmySQL.lib libmySQL_bc.lib You might want to do the same if you want to have a current lib file, alternatively you can create the lib from the dll: IMPLIB libmysql_bc.lib libmysql.dll Note that we're working with VS.NET mostly so there might still be borland-related bugs.pvpgn-1.8.5/docs/Compile.Instructions.Win32.Dev-C++.txt0000644000175000017500000000321211151345317021350 0ustar aaronaaronPvPGN Win32 Dev-C++ Compile Instructions This file explains how to compile PvPGN for Win32 using Dev-C++ ( 5.0 beta 9 (4.9.9.0) ) 1) Download Dev-C++ 5.0 beta 9 (4.9.9.0) with Mingw/GCC 3.3.1 from the folling sites: http://prdownloads.sourceforge.net/dev-cpp/devcpp4990setup.exe 2) Install Dev-C++ in a folder without any spaces in the path 3) Go into the Win32-Projects folder of the PvPGN sources Simply double-click on any of the *.dev files to fire up Dev-C++ and use Execute->Compile to build the binary 3) The resulting exe file will be in the bin directory and you can use it with the other files from the latest PvPGN release. Notes for MYSQL Support: mySQL support with Dev-C++ still unsupported/untested Notes for GUI Support: We won't support building a GUI version with Dev-C++ Common problems and Solutions: ============================== Fatal: 'all-before' does not exist - don't know how to make it: ---------------------------------------------------------------- That happens when the wrong make.exe is invoked, usually the Borland one. It will usually leave a copyright notice in your compile log. How to fix it? add the bin folder of your Dev-C++ (or MinGW) installation to the PATH environment variable, before any Borland path that might be there For more details check: http://www14.brinkster.com/aditsu/dev-cpp-faq.html#allbefore Complains about not being able to create Makefile or 'no rule to make target all': ----------------------------------------------------------------------------------- Check size of pvpgn\src\win32\Makefile.win If it's 0 bytes quit Dev-C++, delete the file and try to compile againpvpgn-1.8.5/docs/INSTALL.unix0000644000175000017500000000407311151345317014611 0ustar aaronaaron PvPGN Install instructions for the Linux/Unix version ------------------------------------------------------- 1. First get your hands on a PvPGN source tarball or a binary package (RPM/etc). If you got the source follow instructions bellow, if you got a binary package jump to step 4. If you get the source you will also need to fetch the support files package. 2. Unpack the source tarball, change current directory to the source directory (ex. pvpgn-/src) and run configure. You will need to provide configure with your custom options, ex. ./configure --prefix= It will configure the source distribution to compile and install in the location. ./configure --with-mysql It will configure the source distribution to compile with MySQL support (in it just tells configure to try to find mysql libs/includes, if it doesnt it WONT compiled MySQL support; read README.MySQL for more details). Check using ./configure --help for all available options. 3. Compile and install PvPGN using *** NOTE *** you need to use GNU make to compile PvPGN (ie under linux this is just "make" but under *BSD it is usually named "gmake") ************ $ make $ make install WARNING !! make install it will also overwrite the configuration files. Make a backup of them before doing "make install" (read more about this in the UPDATE file). Next thing to do is to unpack the support files package in the "files" directory of your installed pvpgn (look where pvpgn has installed and search for a "files" directory, you need to unpack there the support files). Now you just need to edit the config files and adjust them acording to your system. Have fun! 4. (only for binary PvPGN distributions) Depending on the type of package you have obtained (ex RPM, deb, tgz) you will have to install the package using the right package tool. Examples: $ rpm -ivh pvpgn-.rpm or $ installpkg pvpgn-.tgz or $ dpkg -i pvpgn-.deb After you install the binary package you will need to adjust PvPGN configuration files (usually installed in /etc/pvpgn dir). Have fun! pvpgn-1.8.5/docs/PORTS0000644000175000017500000000261311151345317013426 0ustar aaronaaron PvPGN porting status file =========================== Arch. | Operating System | Status | Compilers | Comments ------------------------------------------------------------------ x86 | Linux 2.6.x | OK | gcc,tcc,icc | main dev. platform x86 | Linux 2.4.x | OK | gcc,icc | sec. dev. platform x86 | WIN32 | OK | bcc,mingw,vc| tested x86 | FreeBSD 4.x | OK | gcc | tested x86 | FreeBSD 5.x | OK | gcc | tested (use FBSD >=5.2.1) x86 | BeOS R4 /w BONE | OK | gcc | tested x86 | OpenBSD 3.x | OK | gcc | tested x86 | NetBSD 2.x/3.x | OK | gcc | tested x86_64 | Linux 2.6.x | OK | gcc | tested (pvpgn >= 1.6.3) sparc64| SunOS 5.9 | OK | gcc | tested PPC G3 | Mac OS X 10.2.x | OK | gcc | tested PPC G3 | Mac OS X 10.3.x | OK | gcc | tested PPC G4 | Mac OS X 10.2.x | OK | gcc | tested PPC G4 | Mac OS X 10.3.x | OK | gcc | tested Alpha | Linux 2.6.x | OK | gcc | tested Notes: - clearly x86 is the most tested version - the platforms/operating systems not listed have not been tested or they did not came to our attention however, any POSIX system should work just fine - please report to us any platform/OS you use pvpgn on and not listed here pvpgn-1.8.5/docs/README.storage0000644000175000017500000001633111151345317015121 0ustar aaronaaron PvPGN storage configuration README File ----------------------------------------- 1. What is this "storage" ? "storage" is what we call in PvPGN the way to save account files data (usernames, passwords, many other stuff). Thus it is a very important part of PvPGN and can drastically improve speed of the server depending on the chosen method. Because we wanted to be easy to add new storage types we designed a modular solution, like this: (mostly in bnetd/account.c) | | (mostly wrappers, in bnetd/storage.c) / \ / \ / \ (bnetd/storage_filc, bnetd/storage_sql.c) /\ /\ / \ / \ / \ / \ Thus PvPGN can be compiled with support for more than one storage type but (of course) at runtime it will only use one (as chosen by the server admin from the configuration file). 2. First you will need to make sure your PvPGN version has support compiled in for the type of storage you want to use. 2.1 file (plain and cdb) "file" storage support means to store accounts data directly in files in either plain text files or cdb files (but its easy to add any other support in the future) and is compiled by default, chosen by default (with the "plain" mode) in configuration file (and the oldest and most used storage type). The only advantages of the plain files storage type are that the account files beeing human readable text are easy to read/write. It has the drawback of beeing the slowest one. Starting with PvPGN version 1.6.0 (and their prereleases) we offer "cdb" userfiles support. For who dont know, cdb is a constant non-relational database. We included and adapted code from the tinycdb project to achieve this. Because cdb doesnt have any external dependencies and is pretty stable it is (as the "file" driver) compiled by default. It has the advantage of potentially beeing a lot faster than "file" storage driver (I say potentially because at this moment there are other things in the code which make cdb slow almost as plain files, but this things will get soon fixed). It has the drawback of having to use a separate tool to read/write this files outside PvPGN. 2.2 MySQL/PGSQL For unix if you compiled your own source you need to add --with-mysql or --with-pgsql to configure command line (read INSTALL.unix for general UNIX installation details). Even if you give configure --with-mysql/--with-pgsql parameter it will NOT compile MySQL/PGSQL support if it doesnt detect the MySQL/PGSQL includes and libraries. Check the configure output where it detects the mysql/pgsql paths, it should find the right locations of your MySQL/PGSQL includes and libs. If you got binary unix packages you will need to know if the packet you got was compiled with MySQL/PGSQL support (ex a MySQL rpm file should have "mysql" in the name of file). A more general way to tell if you have a PvPGN with MySQL/PGSQL on Unix is to use the "ldd" command on the "bnetd" file (the main PvPGN server daemon) and see if the output shows usage of the SQL library (libmysqlclient for MySQL, libpq for PGSQL). If you got a binary Windows package/installer just check from where you got it if it tells you if it has MySQL/PGSQL support or not. No matter on what OS you are and how you got PvPGN, when you run PvPGN it will log a message like this: Nov 26 16:07:20 [info ] storage_init: initializing storage layer (available drivers: file, cdb, mysql) If in the list of available drivers you see mysql/pgsql then all is fine. 3. Even if your PvPGN has support for your chosen storage driver compiled in (you see it in the list of available drivers from above) you will need to configure PvPGN and tell to use your chosen storage type (default PvPGN uses plain files, the "file" driver). You will need to locate the file bnetd.conf and edit it (note that in the configuration files all characters that follows a first # character on a line are ignored, they are comments). Find the line storage_path (which is not commented) in the bnetd.conf file. Edit it to use your chosen storage type as in the examples in the config file which I paste them here: Syntax: - for plain file driver: storage_path = file:dir=;clan=;default=/path/to/default/account - for cdb file driver: storage_path = cdb:dir=;clan=;default=/path/to/default/account - for sql driver: storage_path = sql:variable=value;...;default=0 (0 is the default uid) The "sql" variables can be: - "mode" : tells PVPGN the sql mode you will use (mysql/pgsql/etc..) - "host" : the database host - "port" : the TCP/IP port if needed - "socket" : the UNIX local socket if needed - "name" : database name - "user" : db username - "pass" : db password Examples: storage_path = file:dir=/usr/local/pvpgn/var/users;clan=/usr/local/pvpgn/var/clans;default=/usr/local/pvpgn/etc/bnetd_default_user storage_path = cdb:dir=/usr/local/pvpgn/var/userscdb;clan=/usr/local/pvpgn/var/clanscdb;default=/usr/local/pvpgn/etc/bnetd_default_user.cdb storage_path = sql:mode=mysql;host=127.0.0.1;name=PVPGN;user=pvpgn;pass=pvpgnrocks;default=0 storage_path = sql:mode=pgsql;host=127.0.0.1;name=pvpgn;user=pvpgn;pass=pvpgnrocks;default=0 3. Start PvPGN. If all is well you should see a line similare to the one bellow in your pvpgn logs: Nov 26 16:07:20 [info ] storage_init: using storage driver where is your chosen storage driver. 4. Troubleshooting: Q: I am compiling the UNIX source and using ./configure --with-mysql but somehow I dont see from configure output that it detects the MySQL libs and includes A. Did you installed MySQL devel package (on some systems is separate from the main MySQL package) ? locate the following files on your system $ locate mysql.h $ locate libmysqlclient.so $ locate libmysqlclient.a If you dont have mysql.h and one at least of the libmysqlclient.so or libmysqlclient.a then you should install them (ask your local linux community how). Q: I dont see mysql in the available drivers list in the log ? A: That means your PvPGN has no MySQL support compiled in. Go to step 2 of this document. Q: I see something like this in the logs "no known driver specified(sql)", what does it mean ? A: Just like the previous question, means your PvPGN has no MySQL support compiled in. Go to step 2 of this document. Q: I see something like this in the logs "no known driver specified()", where is not the driver I want, what should I do ? A: Somehow you did not configured in bnetd.conf to use your chosen driver . Please see step 3 of this document. Make sure to have a SINGLE UNCOMMENTED storage_path line (a SINGLE line which starts with storage_path and which DOESNT have a # character in front of it) Q: I see sql in the list of available drivers but I get an error "error connecting to database" in the logs. A: You did not configured properly the , , , from step 3 of this document OR your db server has a problem (is it started ? is it firewalled ? did you gave the right privileges to sql user ? etc) pvpgn-1.8.5/COPYING0000644000175000017500000004311011151345317012674 0ustar aaronaaron GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. pvpgn-1.8.5/README0000644000175000017500000000071311151345317012523 0ustar aaronaaron CONGRATULATIONS!!!! WHY ?? BECAUSE YOU ARE ONE OF THE VERY VERY VERY FEW WHO READ THE README FILE!! But because the other, huge percentage do NOT, we moved the actual contents of this file into IGNOREME file because the chances for most of the people to read IGNOREME are at least the chances to read README (more than that, we believe they are really much higher). So now, go read IGNOREME with the actual contents what you would have expected here. pvpgn-1.8.5/files/0000755000175000017500000000000011151345372012745 5ustar aaronaaronpvpgn-1.8.5/files/chathelp-war3-enUS.txt0000644000175000017500000000053711151345317017024 0ustar aaronaaronPvPGN Bnet Emulation Chat Help Commands New Commands: use /f help for a friend lists help use /users to view users online use /w or /msg to whisper people use /join to join a channel For Chan Ops: use /ban bans a user from channel use /kick kicks a user from channel For a more detailed help type: /helppvpgn-1.8.5/files/ad000004.mng0000644000175000017500000010000511151345317014473 0ustar aaronaaronŠMNG  MHDRÔ<d †2œtIMEÒ -á@ˆBACK3œ% TERMi4 FRAM ú>m IHDRÔ<ßGK7FIDATxÚìœ{p\Õ}Ç¿ûоßz¬¤Õc%Û’l˲±0àCq“I™òÈ£ ÌÀPÈ0ÍÐÎÐÇPÒL'SÚéÐ!NHèL eZ’LJ`Hˆ1à0ØÆÆ6X–ei%YZ­¤}¿´Ò®¶çwΞ»w×k()èýÍhî½çÞ{î¹çž=Ÿóýß‘fxx¸ˆºÕ­†Ý{⦅wêV·5iO>ùäç]„º­AÓÞ¨[m{ø;M¦N-ÀÐà@K“‡'s9ØFeK¶8Eç†Ì/Fø1¥7¶µ! òc³ÝÊï¥ëŒn ÏK}­4Ê3ÍÀеwýåŸãK7}C[‡øùñ±3è]¿wÞÿM¤¢ËÊ}‹é%hÒ)LOàt¸püè!~íKóóùdŽ®žšïyËÞ=øñã›ÍhÚ€tbVG7?g5›ø6]ºè>·U<ßd^QÒìzóE×%óYe_£±UœKkšyÙjåïliÅÝX³Ìí^Žz«¢,Ý};ßßê³|ìwu€³†ï¯d/˪ª ¹,ä3èõøplæ æ"åJ¸ÿÏâÛê§ÍêTöSéøEi5ßß"º`³A\g1æ•svw³²Nh`(Ì+Ç£ãSu¨¯A«u¬Ñ&~TÕ¬†*]¿¼’àð%˜ò{Ùöò½¶v¢©”7å¥)åEFÀUwó‹¬sÔév!·4Ëm6‡é‰cGù1Ô`Öòýfš…P„_32{ë6`lä?—‰†ùñl(¢äMiÏüì9´uôbjF¼¯„)™]-°|E¢AI Ö¬I+Š!Ä’tï"\vV4^Y<ï¶þ¼,P¹•嫆jðìö'ö[¬QÜqË-hv6Â^ï‰$áñˆü[œššÐ¬•VËšz¬åûY8T Œ@A|X/et A•@Lvlj=­n´zÍø—oÞ†ÝC^<þÂûxé™Gñúÿ”×E¯{ˆ†b ü >v‚™_dÌöRù0ÆBIž4“…ÃhŪÖÊF/Œ-Æaò¸bç–ì•å"h¦òØVuHÅÃJ:Á1Õìc j¨x¾«Aœ§ãÜ| >ƒŒ‰0:E¹üì`Jçý~?dÉ´«l Z°RëeðŠÙ(nìE(ÁÂB–&}©üKìo»6 "™ˆ¢YoÁxd± ¬-¬ˆ§¡<(klm#—l6 è.,Y8H ªô÷IP­eß}àgE½Ì±æòÕ/ß„½·}vë§Î«nŸÕº†M L Põ92RM¬ƒ¤- 0‚ªÚZº»ñøÄ:›AÜ|ýÖš WæE÷ÀÕ9Lœ…Ùìà@µ›­hioDx~óìÇžÍ&ø9þ–î,©¢é™:œF¼ñîi%R‚SRwª+Ôܸ‡õ ‡[-µHitN‚U^ËHå’<É VQLÖ¹-cyU¤W«f¨ÚÔ0MLMT<¯ËgÅ–Þ~ôÚ4°7 ±çÙ*îÏë©#ºT¥j«ÖÕ¥(´&·rË”%k£³ U HR¢µT*¥I•ª†ª«˜ÐLÁÀĊŒ[wc]÷VÜûWÿ„VocG&Qhs`Ö«*ò#89K"­ÁÆ:u¦ôšøH1JÛà*âh0Îa9ƪâü\6½Ž+Ùpt‰ïK›O¤ø¶Ùç†×èRÊ*¾Q"ÙxTËO&•+µVRÅ331ô7–îcד2%xÒ>½?•-™žß/'l¤¨[Xñ öEÖ~››ª~GiŒyzT´Ÿk·õ"3³€®ö,Å2È0‚GVRJ9}&f– H­ âû/,É÷øß©Ój{ö'OñmûMT[YÓùùK/âà»ño?~™\½Û^«Vÿ2kÔ$ä|ºwý-ë­ªRº€á×’²¬†)ÙP—›õ/Qe¤¯tu^> ë\¨ã14)ç²Qg&WÿN¦\ü8öî1å<Á3bä#Öim 2ÝÞ1Œ¡]8;rýC8pàm~-kVU6:&×ê…xwÝy3öí{¬B¡ªíRjµ²¼¬-;8Àõvœ i„#åܪµEiôj€ªáIéñyá^“.h*'iƒF޽c¾´¥CÔ£·U¹Ïe1(0$×n‘uìµ@úiŒÔn$â°&ׯ4½žÂé½— B®TÞž–ønd¡E6aƱé ô,wa™u£Õ€ç^x£'ÓxèûŸšEØZ®ŸÞŽu"ÚQ¶àÜ ëu!Ç\»š»0“Hâò¾VèO£¿ÍûJצˆ ˜>Úü˜²äð,m¹ª ÇPL ¤çIÍ2 ˆ[6½zû7qw´›©_Ú:Ø»­>E™úT^+¿Ÿ î2Ó¦‹‰)Ñ4²i æÓI µ;p®äÚ`7#Ólçý)p«É†¢Q‡kº{ñ÷ö”Íkΰ?Ú+ÿ–ÆÂ9þŒÿ«½õÞzùE|ûÖ+108Ä>‘å^øÍaœœœeƒÑ8”~zÅ[·ÏÆê@]£v!0'"6;£8Š’æCÉe«V«d¦Ïíÿ vmšáî,š"k¶ëy)çRÕê”?+à®â˜³ƒ¥[u.ˆÖV-&²¸úÊaD‚ãÊ9R­º¢±G¢1,.|ˆ#ŸÇŽ=·àŠÍ[0rn‘ýÄð5»×/©T:–.`št¸¿Žöõ;0;v䢺%¸¥ÙkÒuN»ãcë`JŒGi¿òÁVš³ú¹ Ê1ƒö߀+¾À)™T££ø éxLMzªøN*Tc/«/}>®ìl/¥RÕF VoÉÌñœ.-s‹ð²äв¶f=$ R2°&X¾Eqìq˜0šÂÛïñva3Û¶–Šy™¿‡F£¨H²Ó£§a±˜9ÔÈÍJÀ“ƒ4ÚÆÂÕ:Jñ(ƒã"A3 $]»’û¬€'·p%¤¹k7^N£çÒœ*ý‘Ú4Û|.•@J®gr -Ù÷1‹vv<À·òžà|žƒu,8 'kŽRú¹döÕe>—{r6†¶=ûºñò©cè6®"žObcîÜØQQÆOe÷9É—Tj†»}?Î.¥N/ÛºWçO9HÉ~úÞ¼óÞi u·ó¿7_ÞoÜ}ê¶6­Ô5jSi^›ƒsšý ›9«‰$Lû6 áö¯ д«Ôê}[îÂ/^Á'ÕjLyžù<Öµz* :î6›†N'¨”Îk¹{—\¾ú; Œº ÚXç´’bjÐF`ò<Ú\vÅ…ëïêFº|wnÝVX‚×Èȸþ†/âùùyå>µ X¸|ûù±ˆmB™O­V¯™Ð©šu+æS+MB[‚T*T:ìuãŠ>Ÿ+E!"T)xz¬†¥…KhdªP*Uá®mŒD÷I/ÁSíîU ª¸•mÈÆ3—Ì@Aó™—²HBpyYV¡‡+ù›¡c ²ÍJmÅó3Ð,¦d4ï™ ‡‘ÓÇÄü¥ü†*×/I•(šâ*U+ƒ‹ªïW)_™¿„7åËÝÍ¡Qt5û”ëÈÍk×™°ÄÆé¥4Z-b+âþ\tE6h±ó¶¢A<ÉNhí|þ‘|Í¢]#r:Ù ¯oL¢àò޽0—ΈWOLâ¯ÚÌóWÞ³¯*îpRÙ%7ð'Aµ–QPy94 DŠr˜úìåQš92÷÷ÿ;lÛ®ûÔy×íÿßê@]£¦6Êã°ÅH68*ܺó3qlì_$Êõ< £d™T›ìýâQrÜOVù¼3gÇpÛ¶Nø›ôx;Ty.¿’ĵxW§ÑÐ8CHfLp;ø_"*T¡±±ã œ‡ü‚»G ±e<ÿÌ( ‹†qãu{ðÆëðàß|§I70¹‹Ûøžõ ¤þ¬Ö¡êcšÕ·t ­C¸keô­ŒÐÍDÅ3ÕAFüØ[™§„§Ü§ùÑ«w÷óy½-½]<àH€,ÉÀf%_.´¥À#êüÈ%+ݱ±Ô…м%E RŒ»‚I±Ks„Ôiª¯›ÇQ»¨Ûa­8¯|[¦P/ŽiVÕSLI©&Ù@)·â¬RB) VúÝ©1´µ–¹H‡7µ‹ºž7TÞöH½ªlÎC2Ý <—‚˜H!jÄܧ¾¼žU t¾ä’…ÖªDñFUóµ4P“ner /RÐSÉELù\ÞnC’½E 'sLÍÎÂä´`‰ 8ºØ¹\VxB,S“½€õmí¬èâwD®]º¯ÅnC¦Pdm$Âçgåy‚*]³Ýoç.ßu.\y‰:oÓåÑÆª/X0"˜Xeju…í‹ú•K—R¦Ùå88ò¶oÀèÌY<òÿŒW âΛ85Ô¯<Í~S„ÓQØP·µhu ®q4ç`rÛÐÛeÂëãiÖá98iδÃïPÔ&m«yL ªÍ¶/JALt}pŽò ¹U‡\f­èˆžþåÛØ±ó01ÅTTÐÖnYB´ä½Ì§D|­—u(”ä\]`åk„ƒuhÔвsq/S!KØÛ1qn O>ñ1|Ï}÷ñô7OœC‚) %AQ‚N=OJ®Üí;÷0ee@À+\{w'r×À8}ˆßG 6¡ZCùÈ@%µ‘ú¦wìkmb¢¥…Õ“ Û} øCA@.3Eí–]}ê !šÛN†æøþèìLÍï×h×p Ê Vö-’‹Âµ^Jç÷E§™,Öž.¹jçx´ä…,›duÉ`Ks¡dµÉàCiyȲµ<ŸG°+°ç†Ø%^—È/œ)Q^?ñ®¼|/-!Qô+ísÅÚ"®eE~“™òr$R¯Ú«Ÿ5†/Ch\Dñ¦æÂÈе ¾Rå’Q]KȆ™â¥†Òß+”íÔÙYä­F%ˆIq=²w(j±õ²Mh5¬`„¯(~‰Á”êÁn,=L½ì7rbr×l^Ç#‘7÷Ø8p ŒRèf¿¥Él­L™NÎ%àíÐóº¦ÁM—œ›ˆ÷kïlž7b6R~ïpneO‹qS–£Y´ÅY»sèÊZàc·RàÒ¥@ª´Óî{ ¿=ø"_B¶ï[7q¯ÄÈé“üüïO‰Í£Zês¨kÕê@]£&A9šÏsÕHK0úº=ØÿÂ/q<0ÁϲËЙ |M-㕟=‹Ðü$Ÿc¥@#ié•Ö‡{¬ârÝæ£ßû{˜æp [1qj•õÂâ|vUtÖí qU$)¹zÉÜìw³QøbŒ/¯‘Šƒ:BÚOhÊkypS•2p!G¹C'H¾ÿŽè Ôª‘ÀHK_ľ—C—¸CncRŸÔ«ü<ûÛ”u¥j€8eÄ/uVf‹‘»1©s&%ãdl¢(OÀ#aJ®]J!pö·‹@­He 07м¥N½¶•]ÂÅU=4  ”¯©\_*A*]Š™‚Ð$€Ã%ÀR‡ŸMæ¹J©¶¥H r–5.«>YdZå ùXJå•SчϞ¯È‹T›\³)·VR­´^>7˜åÏ•ïžQ*WœÒj©ÔÒÔ>è^£³|LóœDEpÕ—Òª¾­s…}3·Ïb‚Û@tò W¥S³Y>÷icß”Ôæz¯ƒ/‹qYµˆ§óXçyÑ\)Eõ\çâ8w!‚«ú×ñ¹iiôþ§ƒi´{Ìø`d¢òÛWA55q¶ž~Us†+U|¬/¡”ìÒ<5-!£ B‚)"]·{{©­ ’ûW›‰b~uû|¬Ô5n´ÑÐ[Äÿú}åxÅ9—ÝÉÿqÁRFtl§>:Ž'ž| ÛúxçAÍ…LóSqÜ}Û×ø5ép­Þ&¡6LMð´½·Þ‡ üþ¯ÑÝÙ œÊN*TrãÒ’˜Éó¦ímˆ&Ä\ª´NÿFLœ8À;9šw##hñ|À¨rç–#ìíBõTÿöÁ¿ÀÁ×^Ãñ#8Hoÿú <ÐdzZt"Á ã„v—›«š‹•î[Ú`éŒù5öîÝ‹¾¾ÍüJ‘‘ËLº¥ÛÒTê´ ¦äÞíwiáïëåuÎ#k‹I4ùz¸{6”“¯…ÕMi )U]f™‘àvß?ü™ìÅËWöÿQ Š-p@R¤-‚å¹6)©«âJw<øHÅb~µ=ñ]ñÏæ餸¤K“¿c^ä½”ÔÕÌ'anY©lÉÅ©cªù虳èêP®“yJ…KA;¬° @jåp-ýcjs4(!g)‡íj’ÏWfJjVÑÜáDôB\Q¨S^6ÖvH¹fÙw!HÓ`G}_W»™t)–÷Ôø‡Ê3)2—þ  fîºO¦`¢"±g;JÐ&¨úl¾ÝÕïaß#/Tm1Á¡J߀¼Ù/Nn_'ÿV´¼ÆkXUTìÖòR«½Ÿo)°·iò$ß?†äÙ)ä5V¸üÍ ¥ê+\j°%Œþ©Ã>û_J;ÿÂö-ˆyÖa£ï$^ÿÝû°z=ÜÕKꔓ6ú>ýÜlÝ>«uš\Êòƒ_ÿ<¾ˆ;¿r9W£j‹%ÅHÕÚhE_c3Ÿ_½qïõhñ9q½­™«ÜmÑ ­¾‰þË6ÁúŠëz[9`Ñ ’_O›Mí.ö=‚oOîÀ¦›ï©xÍËölX-WlBlrzG¹Ó§ÿ’dÕ¯" ÃZÜÎÓÚÞàÿ‡æ¬ò%˜’ lÅæ®Ft VäOyѬŋûŸÆWnÜó?ì]ip[×y=H Ip'%J¢%YŠ,Y¶bKÕ8騉=ñ´é’iSg2mê¦?\»ãüÈdjOxÚIÓ©·3n›¤ãÖvÛuÝz©[ï’¥Z‹íÐÚ(‰”(p'6IzÏwß(ÚN§ ðp޼LJ‡·ãž{¾íâÊл{¨éÐ ©{¹Y5Œ ðC(!»Þ‚zw;Þ?uï jsóéc/áç¾øÚW¥£Ž5±ålˆÔÀ˜17†ƒØu¡¯wcù3SœDJë@‹â¥Åa„#²Î€æA19*2}é¹g0pì5Y¿uÛõøµ{¾-dÊF<݀ߺÿ¼ð£Ç0:2Rþþ¡»ïÁ3?ürê~Q¥°Î ?¨Xzìïen|z=úTÕ5¿ÿžß”ù_ýè_pæüxôáï©v÷o÷¾ó¾ùw I1:– OÕžûYë ‹ªL‘û.±&)ª‰ë3ŽÊ»—ÉYA_3Ú¸I†4—3ç5°Ìsb'&,äm,“3ú\¹_±^Œhïù¢¿ò\må.ûüŠP3ê ¯)ˆÉSn:5±+i’PgÓYlêlP\*¯7s’©ÁkïQÑ&„0‰3£ÓboëêÄÛg>µú‰‘Z^”à$}X‰ã>,+žmzìe4ÍÄpìi\Ýw+¢Û÷j³¯[ߣD±Úóɤsç.€ñUo¿þJ¹ÓxϽ ¾Tþþ}…·%0ÉyøÕ[6át²מÅ:ÖÖ uâ”ú¿wnýNªÑâtJÔ%É“ ¹6…ŠÉw$¦Éƒdjª+I‰A5ßÜÕ[Þ/É”°—ä#îÿý›Ppöbk¡¢vÜÞ:Q¿Ý=hYQ¦=:º’¾ÏјN¡ñFt¯ÞÙ$©4µÝ’‚‘.^VŒ[ \¡I—9ª+ARv»ºÔÂHR“G ¨É)E¢ËÅ94zè àÌ™a\דà »oUÊ8&Õ{OÆ;K×£Šapð´tÞÔEV)A“¢i„iâ5Á?ÖeJÔ­Yfj‹É'eÚKÙªÔ?¿k‚Ž›ÛÚ…H ¥mÒV’“Ã8õæ Øùó_@쯿+ëö}öó8úÖQ~õ–U°³c£RA;ªÎõòÈåòòäØIü7%»nvEˆ™¦ð[·vc(™ÁáÃêØ—±2SÚÙ ;’…ý¼^õÝW/GXõNšwìGÞ«^ª¾G2eÑ•žŽJ Ø »oÆõ{{ñÑÙ N\œÁ)™¬›|×.Ö uâ‰gŸ²¼¬éSöàÃB^ÎÀNˆÜnÎJòg ScLt¯_õrk­h.5»ê±øýgÿò}$[Zhõ+aü¨öÚ½¬”4«Tß…s—¤ZROÍ`ŽrÕ$K™ù91åÍT|¡ÌM ¯9~fL›v›X»uþ$:-s0 ʬÑQ„·Öñ‰¤D¡¦/E¬¸©O)òî@rº¡æMhS»¾j‰Ç7^{7í;¨SyÔÍÖrîñ¸˜ÙX{E1ëE,Ó"‰2‰)•(M½&"מò ”Êѹú»MB–¨oB[ÿ ²~óu›«LÀô?¾þÖào»¿÷ÇßÇñ£J…+E7òÒŸTÝ *}ï– ¡RõƆ‡ª¶!9ßø‹‡°ÿÐW…`™ì/$¢pþÜE<þáÁGž”ÿŸzäa©¬cÈ”¦[¦˜8Ýúžœ¿8wÐ_&P; r=}j~õB¼Ÿ,–@7ƒ!R;ìë¸\;·X!ø¢6S³`?.‰ÔGC©Ü²t´HvLІY I³õxHª$QZ`‚¿˜ÀƒÖ»cˆ˜¦]n·¯·o}0$ÇŸÊhõÊûòÓ±YDó©çK³0U,Ïõ«Ÿßzï4n·Î§®pYü§ËÙSòÍ—|(=?‡ …\é ãùwÔzšl[{ÑsËí8°ÿ³òNd–œ8wâ!Sº0¦“ J‘¶£PJŠRÝÜõ”˜–GãÓèrÕKÅ$úNG3«W[ÇÚÁ:¡®QsltëN«Ï'¤[µæŽnP#O{´J950#ѹr~íÕÉñ,ªÏu‹I½ïìaÕÖ!Ÿ"Ê)’«÷áˆ]Ƥ’ƒþPŽŸ<Šhw·ä$TcNŸ+ɲ¯5"&Þö¦¼ñ¯O£±}ƒTÖ¡?öÀ®ë%*Ô˜:ýJåI? ªÑ¤Ê ì;´°ƒR¥Q·º¯î bÓ)t6[­¶Û« ò"~iñÜÙrpÑøù.Üy÷7e™ 5}¤Äãö§øû€C5”¯þäÇeS$;L­¸tæ1%ÅÆ¿^ž«þŸ>ÖÏ)2%ž{þIçrpø¼B"$?¿ï¥ûË_»±Ñ!!E+g^·+܉étÿþæ(ú·ï°Þ— š9×±sT”@§j²´%I•âÎ(K~&Ÿ3U “ȳȫu-ÝA,¤5±–P½ÑòœGž¿·Pón®äPdº$Äêv¨ûQÔ>d^ƒ¹Ì=šRïwW¤ WããhùtZ ´b]œ/bF¼¼58‘{Ô\£#»M]_S‚®ûÝ;wáØÔU9{wÝ´½|~4õªÓ%j¿­.ú îMf‘IÏcfVw>Ò©+8rîoñà÷¢}Ó6|÷û#ÏŸ O-ÍHYC¹ÿ^lÑ.&kZž¼ÍM©ƒÐ‡Qý VO:;zìÖ˜¬ãÿ 넺Fa"pùc‹2à‡¦ÃÜâÇnßÔÜPV§«a:…Ke»’LI´qÇ&j‚˜-]ûJ˜‘3ˆ…|Eå²1/å—0»TEê· ˆ‡Zt$p¨%„âY\Ž!øëtcG-ù*&;û²'rYæÚ[1Q0 $ësb"™Ã6Û¹1¸$6NÆOG¡ÓÛ(“Tœ›š·ö:·ô’\JJ¹¥²ôêý–+}LÂMÀŽ|HX¾3Sj,UîϤRE Ò‘h]§µ£…„¨ÙÉDõjV$/ËÛñ>ó~’H¤~¿=°¨r"»•Ê¥7œ™“¢³©q!ò»Ðè@®VûŸÏœ8hφò>ͨ3r!/ ±+«^ŸX95zŒZ¬V¨Œú5ªÕ«1÷bGBõAœÖs©˜]ŽONÿpÚR~„8¡‡}KEîË DŸªÜ.h•Æâþ³j»¨E´#cYy—HÎôñ¯ ²"¸nsg &SšLýËü\Þ;§¤X¾ÝäK2­WDzKÜ€Ãñ%üt| Å`GÕy1‹ï#´þ£oá®;¾ˆB>‡lÁƒ¶p¦kä3®‹ÏË(JìÐ’L÷ïè”´’jéüÖ±v±N¨k‡>½§FÇpþô¶t݈ }[0tQ›–H¶Æäk²L 6ØÒe£V9ïîìžïJÿ)ý²WbQrvêÀÀ9T²f^¦ÏįžÆ´j4Œ)ÒÕy‹ÌZZ{% Ïž=R@@zÉW¼Bùv$]c¨ ”:­(qšYá&XëEk‰ü„(§jüòÅ4.M”·e¯žjk6™–Þ>1vñŒ\ˤRr~J­M$R¨W%I+íT %3¯Ñ%)2Œò5îšMFºCVcYýš…¯ VR„~ä'K>£!¦‚ŒR³¤_k¥f2Ób®yNüw­êX&÷”¾]¦M°ñÜ#ß¾&E‡×°¹S?÷Ó¯þ°¬B‰…ØûêÙ¾íVÁ=›µÑËÄ?üãGò^4Z„lüÊôý’Mà–A£¸iEÐ'¿$J4¯Ò$ŸSï‚J•êûmŠE$çg…XIª 2£¿qÁê«Ù JØÁcµ¨Cñ½pªcùjiMàýðKG$Jÿ'ïC&–ÎÉVñ¦´´¤¼?ð‘DÁ“D™Ókrt½A²üy|buúúî]¨éoÇHÁ¹ÉÎ:VÞ^ÇÚÀ:¡®Qì¸qn:x+^~³‰‘aLÇ&Êy§$D. üV¸‚$ípºÃ26*sèB .lÙÞ-ÁIöï4¥'p,~m°ƒÑÕQ)Ä@ÐÔ[˜Aa6.1 D™›1E 4yœ?£&XÛÏ ±‚E|òª&™;T£40‰H©EÒÂÑ,ùæà,j_ë©sW伺;­´W«Œ2=¥‰õ˜U¼Ÿæêñô¼D13ňQ¯$`GfV5\~L¤Uû¬Î9¥®GêÓô;!uy—}>£H’d9jkGrFH•å '1+s·U‰©¯-R&ÖÆÄ$z}•D³Uó—„½rÁ4ä¬RxV­ý‡ ½-ZáIB«ä gÖ%ÛÔ8ª­ ¦4am“nx 3áò>Hňeû9ÓO÷™ë?UÔ€ÊÚarNW·7eÀã³*Þ2}¢Åš²*åçv…ºÜ.ä ”·ï”’V!Ò•`@QN©Å‹T„ÅäËÜ]cö]œ·ÞÅ1xðK`ƒŸZ|%Yf:ÓpHª$Óf«!¯‹U¡†/œ•Ïw¶Õ~ýx÷Â862èÜZ)³EÿiÍKNüxÒtþ|x73‚¦öv¥Pkd@¥·‚÷H®$Súó颠%O kn;jZо)¦Årôüål]bN¬ñD/,󹻪¬4ëX;X'Ô5 †Íºí.¼÷ú˘CÖFÉ*FOb5J•?¼–¾6$Kèo¨.Ö—³Ò-Œ)˜ß»¤Óg0RMÄÜß׿öKåÿM~«A!—³d²T‹B&[ŽêÌZDjüMAŽgI°'ÎÑJD“q½ïZ;j`Ei:’j.G¨¦€Öd 5bpPU“R^M¼TÛô·(uÒ·¡£L¨†Hat RXÈÍ Õj I¦¹tFOÁŒZß¡«âtõŠÙ–Š0£:,ùVŸŒöc/hïm´æM0M«#ŸFÑ ºƒ>×Hõµ„mÿWÛV¢RóÑ^_J¯ÈgBûçDu‰CˆÑ~@SòP|Â6øõ³[IœBbq\C´F¡s鬣òþp™CY‹LIž†TWƒý3*ÑTŒ÷PŸ‰•é+¥S ª Õ^ŠdJh“ð\y™QÓ’ô—ssI¨,úÏ4VQ¯mQ§OчM2OqçîÝK“3sO¯ß’H\o1¯:·êÿtå\f~a/Þ}ú Yî߸ýjþökGåšœ½>O¹XC6›D_m—D g­û7ðŸïTvæo·ùŠÎ’XŽH¢#Ñ0^üH`‘O“B´Žµ‡uB]ã ©Òü—*:ðåý{ñòÑcB"$»9õg‚‘Š"‘k{ÿÆäËýØ‹ÂÏLkÅIßë¯8ˆ-m~ù»gTÚ‰V«6QÅS—eÎÔb~Qü|v°ö){ùѾv©ÖÃB¬$U)d]š®»·£Lš¦9¤?ÕÀî›%hþ÷ô¢K(sN‰|~NHš&]úõLñÈø%L¥ëD}Ããz_öë%µ[&Èù€NöèÛÚ+ó¡Ás¢*><7€ÍÑqab#gß’@­…67XChïîÏȶÇ?º$Ùa#¦œjÝ¿‘h9@Gq•*¦â·ÙRvÊ÷ÁZ±òSè»m]åû\G¿o9pʆɬVÒ+ÏcA©í­­«*@ªOSvÐnæÌL鯼à¯n: ±š¹LÍòjêÔ¬»¢”(ÍÉ$Ö UD3Ž…rÜ—K=ß|pIÈÝxÙA¯¿¾Qû:aU›’ÔYd­€-¾§f0tA¦>(L>%5xä:ƒŽ¢ä¢’xw½Xì cnr»;zqrôlÕ1Yf°i÷ü¶·O¾øoêó¸˜øE|~TÿÆš[ZÅìÛ×Ý…K#WuÑþtJ\#;n> rïžÀt¦€hwÂéÄóhU¤ÿÚà¶8"èoÛTöKZÖ_«X'Ô5 Szн'‰Ò |Û‡à÷®îob¥¤Õ@¢g§q䟟€£®¢9ž#Ï‹KY{åEY®¯PÙQí *¢9~ôElÙ~+J¡./$$ßä0҇궔ç=jâh4÷’HcmýhíÞ^€ôIdJd=èéñÊ Íc“Y̨žúÎ]·«^þ(†.ꆭeRG§) æ :Û|¢R“f0¡ÚY’¯1Ó¼°ÁN|ð¡¶U3„>«ÅZuê£8~Rû¯YüaftX1 öAâ¼ru¢!W;H`î Ÿ„…ô‚R2u裉ÓB¢†TM>¬ÉƒZ$î—ÊØ€Ç´ ïµz¸^›x5‘’D ~ðвÎî¯^ c~59Áv"5dÈá`­½zOMùóÕ‚‘ jô1µjɉÖÑ-µHo+^£;JáP­¨S’©;¡Mª¯Ñ_^&H¦4ýš¹¼GEž‹N!™RÒ¤KŸê%¥Fé»åتM¼p\Þ-_IRk ¦‰ù49®Šj>y¦4ta¹ÔÕu°l¡©LÕìnÇçú·ÉûÉsš} ŠXIªÃ—tt<‰•1ülÛ¡£¬iXp«ŽÃ&¿(Q_$‡Ñé!D›v£{ãör…¨u¬M8þ÷»XÇÿìC´4ÕFÚô¨.™\²<Ø— cê%ýK°¦/ký’@9‘L‰¶€õÝ­¨ŸËKÑ};Œ6 B%La‚³öª;f‹£ƒP¡}õ2|sTI¢f2 ™ÒÊÉ Zº¡ &S‚ßå¨6Ìyå0r4—¹\>Ù?Íg4'G›6‰ àD¤þ›œ=väø–Y{xøªn@Wàìh1Õ‰Xœ¹*Ê•äF_$sSi ž´î3Õ¡L…H ‰¥?ù\H¸Æd\Z˜•‰9±f²ƒÇãDbäñÌ÷ä¾­4÷Û·äk'`îÃ^¯–ÊÏnÚ%‘Rm’9qYç~ZÏÍ"K’©Óáâ2“+‰”DÆœYN&ÕÇ:1‚–djˆÓ˜zIŽœh–¥Š¤ß“æY­J’FÓ­/“(Ÿ#}¬Ý$S*F’$U7ç$W¬d ;pb…$îŸ j–QÓv_01MáRmc3yyx^ l¢ß”CÊq\X‚H}[¶#Ðݻ'¨RYÍ‹ñ 3Œ‹^Õ=¶t‰†ñÌ·6ø¤aùÖñ³…³½½ýÁŸõI¬ãZܲk+²ª1=¸{;êZ{qøÄ n?p“|î݉Ú|ù¥Ô×éF°ªw¬TœKýðë\õ2LMëRw‘HáÆVdçà¶r)I¬KM×aRIÊáØ~ýK‡0•]ÂÉ“'‘Œë ;ÕþLN%ð…;¾¬:ìSÈÍæ°œSJu.©HeÍÑ&4x](p×»áá]ªgˆDTƒÔm}ýá´ùII¤…eMÎËÝÀyY$–'á©¿þ@Df3â3šŒ\® …EQª½=í¨ÆÏå +%\‡îî hëØˆ–¦DšÚP«öë  û¤a§êˆü’+k» ÔF%%#;—ÃLv#ÿÅÞ•ÇU]Ù«Ö.µZÝZ,k±-Ëò‚e¼ Â`°Ø%cU fjjÆ$¡˜„-aKB%,a™’šIl* [ŠÅØ`Ö)bclccy“%kïEj©ÕjI­n©¥yç¾ÿnÉ@0J•¯JÕÝ}ÿýÿßyw;×ÓI™ölj÷u“/¢´ÑaŠ)­º§µ¦—8(ß6¢´JÍʦ£îNJWØ‘™šE}F:SxL ìªßVY£1äÿ´ìJË:¶1€+šc__õDA(âóŒ*|IM×€5 &6S\v «Á»]]#Î íÖ‘«µáa#… mÁ:üÆ?¶A{qœ_>ý2•MÑV†Îpõ «ç"c„ú;ûiphŒF"qà‘ïø”ïþA¥Y§f3hef%út¶iY6þ/P“GA.婾µe¨åê”Òsl4lðEGŒ UVŽÈìQÖš³ŒèèÑ¥+Àlq«¶ ŒR~ÎeªçÜnT!Š„Õ÷”øù£1µ^]3Žâ¯Èh”ÊŠryB`w–¨…C ~µs\ê8éTátPjFŒº{£4RïG„Ô¤°X=#ê>¯©]DYivò„üäv‡håYgñûqÒ¬i”›£®¿§/ÿµúüÔÚÔHmîjïð¯»úûƒ„9)|£6yºüäõtPLqDiò®‚B*RÏjLÝã&w»zƇiî¼…œëÝr« i ©9n—_M„‡ÂTSs*9´›N^z·á„L.9aò¤R9k>UªÏ­ÛßU€PI=î#Ôèé§…Ó]Ô^÷žé…f 0´O]+µ@“8 ǵh¨H©­ë¤ä§ÓAêØ·Ùeº˜t~|dgcý~šV’O¡ÞBж¦PROÔKŽÚ‘PbŽ¢¤ÑäeçÒ´òJ ¦JƒEÚøQA5ØL$“ïË(âJ7þè{dXÅ™—.±É‹…XSíêЄ4{)2okÖ&`»aæ,¯®!ÌçaJÁ~C€¹Mh}n·Yu#±Á^6ÿ œ?¦£wj19CÚïúì LLÎåJkAù!¥µ"Ñž·ŒR•S±AS÷[j3+M¦óo‹Æ ­qÈÐ$±OJ–Ú'šXhf&NÊŽk¤M¾8%öµž×g±PX¿7zµysG}3‚Aˆï‡áãô²F91߃Qí¿„V n[ˆN¡qH)}Qv°°ÖD9"X=_1‹ö,<ÁXߌ@4ƒqËŒ"ƳÚÞÏ)6&’œZ«EAûNµ6 MSˆò2uÎijn ¹Õ5¦õ*³Ÿ5åº#Î3åëQÏN±‘ Õëk2i Áå Ö¤dmûp›öÇzÆlä¯÷ÒÒ•Põ¢Å4­´‚Ú<ítd3WàÃÄ8!ÂZ*Òá Ñ"eMRgú”)³óKié©Ë©aï FÜäéñgÛÎ[=!“SŽPǧkää|~¹¢É"ÉíŸ,mÀ[¶h%ûFáçKøPêÃjÒÓ.Ä ª0GhÐ\'åÜP'ÀŒßÅù…Ÿ™hªðÄ0ÈÀò>Ø´Âéz£¨´1u*˜»@öàrŒštƒÙ¶ ý¥R®°¸†{t.ª#ê§îXÜW 0E©8ÌÈΠ&Æ/p9YííhæßbóÅT;‹«y=d8ÛIåF ÌÄAƒ°lâàL1´¦PÂQ¦~>UPÀ!ò’ŒŠ¨W™YlhÞΙl®*¼ÌpïˉL¿É>×qýnVh®…á¸Öˆ$K+ˆZÁ¼­­Íl‹××C—\yS¹LD€ôXé, €(þ­û}Vo2óQÀxÕtô­u?y i3"Hñ³Y”?bXX™‘ä·TEà×€’?M» ½úµyw‡ÛK+W™¥ëJ*òÌ*4àdFøiq§‘ã ‚|Émæc«ç{gýO!˜èáÙìVÏsDÝ×s/\E³k*™Ÿ ‰I)|û#Ñ©lþ•¨tÉME: ü«H£)®ÑÑä»vl%o~w¤èSëW%ïã÷d“ãTÜŒï~ïJ5(èxií©T9½’6lØÀIýø´n{Çí?§7næYö{aó^þãÿˆ6mÚDW¯ý7sûßüö6}\tÁjsÙãO<ª‹‚õxPq «ãœ--T3iÂqŽ%x€/¿âfšq8KéÜsΤ¯ý!­»î†qûa[´ï®»É¿q-ØF–£mÖö?ùØïÙb]–ÜþÏ].õ³ŸÐëó3Ù}2¡¡Â7*5P³=ä¤"j0N…”™L#È©º0S-˜Çç{£Žé1sXó$ñ¹Â,§€ä7¿ýoºã¶ÛÉ–û1¥F ÔL¾ÍLa€– !‚• ˆöíw³ÙVZ)¯3@@ŠJ5Jyàj'±( «í;Žî£†Š½TU2ËØÓaüwÐÈpˆb£xvt€ý©R‹Q“ ’F• ª¯÷›þ)h­ PÃ/¡­à€Q }Î,Ö¬[ݜӊ!H$7ƒšƒ!ªP5È)Dcep%Íb³g›/ÖɵY‹”¶L=KŸNõ l÷㊖ ß­+Á—»·±™ .ñvh%x 猂Ú|¬€´Ii¢ðó}ß³›Ëµ•—9€´7–ÈÄ TÔl÷ˆÜ•ãˆk=®,äcåhÀð“¾Á`ÜŸŽz¦ ñ@>ªö¹Æ'B;ˆO[ 0 ŠgRjÉú{ûØ$]:×EA¯&uQÒaPp`*Å#@)…Åû[w“]=Ñž –LŸÃLbÖvAP4‚Û«Æ?˜ŠŠÒiˆF)Ò êꙦf ËÉêÕ«èý´T3/UÀ”Ÿ1ÃRƒ±«<«xN1IôRóp7\Ü’êôUȯÔx†òqïð&ÿ¾ôÒïð{þÉîø7ƹÝD[ßxÝüqoÐ £À˜»mÛ{tá?®æm0–㺱 "“…®¿Ù<çþ»éõ×ßNhÇ%—^L篾n»í6âzð‡•"QGÿï#|L‰§x÷¯ïÐÊç$ì+Ë06cÛ‡z˜ñ¹¾Öñç}á…WŽÁ~°À¿scý[[ߦ£í‰5‚¿ˆ bæ…NÕ:äž{îá›"³têúõ÷ÐæÍÏÑW‡ên¯£??õ =ùäÜùèÜœ¹óªyû«®ZË¿o¸þZÞÀÃÅZgO¸é—\òmÚ¹swn"Ž)‚*Ò†äY–?øëëÍú“ rÃຟþ„éܬ37싇üÃí%Üœõë×Ó5×\Ã7@ÉT÷ÁM7ÿˆ·yð;Í ŸÜþÏ’.£Þ'YM|‘lšY˜Îh’ß+0…ÙÚ&ö™>#…*¦èÄŠ"2‚N S(mÈOe3 É>%¸— ‹¹ø1k§HòÉ}ûg›º}3˜„þþä“ÌíÛ3¸“båÓ(Ò=`š|AÂê?ÛPž“M¶ „DCMÖN¦||˨ÿ´¾vŽFΩРÕ0ˆõSã‰"¡Á, ôµ›¿¥Ö)^† …Œ>ØêfH,•gý°4R7ÈuGC)Sìaâÿå•ü 4èˆé†v=ðä:ã*ÄÅà.­¹6æù´ ¸+¾E[ M›t•ŒµiS2~ & òaAÔ Z*ªÛAƒ˜€…¤ßfÓäþ C4[Ô&ïQ]ó‘ʈZÖ£/aiˆMLg à³j¡œòéî “}0H:ó2ÇK@Ÿ˜0Ç MÒ˜CØïöTmF‡cMqp ör3mFL¿’&`… ÁK%ÀB£Å±n£%³Ê™5) —K„0€Z-À´‚g¤ªÁÔ‹èe®µ:Ámtê¾wõB5>ACÝfN.±–*€ÛZWGþ®Ã‹÷"¢™ö«OøYñû€{“壦x0 'ºBä‚`:W?}‚1 (ŒÇxÏÑÎ[o¿•6oz•ÇaÔ6·G›wqÁ¼U«V›ë!UÕ'ñx|Ùe—у÷ßKþøúáÞÈ` Áx,À‘û~u?cÆm”¶Ã±¡x´!ÀÆyŒ·2Î.˜³€±“ðaã<YK€ ×Ç®ˆÁ¸¾Àö‚G_FŽ P.ZÈ@„β @Ef8[o¾ž?1ûIÞ—‹ÄňH'.?ý<îÜ›n¹c‹ÄúóÎ>›Û€õ¸)XÏ9÷5KœÆýÏ—_:NãÄd`*7Idݺuü‰Èƒ…Ά 4nß Ùà˜ñ A0‰À2ÑÚ¼ëMBî¨h |ŽÌ°Ópâ²ìAzéÍ?Óõÿ¾Žö`ä¤â“>•;Dù±CTß•FÙä>L´ñ¥—è?ÖÄgm0 ³¤¨c¦&&ŒC3µFùÂ׈IÅYç,§`ŽƒR#cT”Ñoj¥[É´rªÊ¯¥‘þDÓ"yaö5û¶°ˆ»ýü@º#÷ReÝ‹W~ˆ‚:Ø`ʑĖmqï­`ŠÜ¾ªeg’çãÛóÖÔ?ØËZ?øUËó é@°›f©{Z{ÚrÊ„/6¤ÓbJlœ¾v%§Åôk5CÊç–s5Ds?{é(MUcàƒÙÕÛ§¾Sâ¤BLÄ&ÐÅ׃_áfÉ"‘¿¼ÄDFÂæÑÖvfX‚FEéƒ}zòQX0È`Š6r»sÁ´”š†¢‘‘ë,еÇÛ gQV,Äý ºîúºÂ”,¦æoÛ‰kÝ0=¡´NÒ­¦cDc]¡3Ê‹Ëyìûhç[<ñi ÞA‰ZQ‰W^Èç¾ó·°v\iPTʘ0Á˜¹ñÙ§è[K÷­ûþ:^Žñàí·5 Švú?¿û/_/8ÕTZ¶<ý(×zH±ÀrùÖ;ÛäðÉç\ôü}×ûšÛÊØš,¿¿ï~ž€|Õ¦.^s¹™¢T{ZôQ‘ `ŠL`À× ,Ã5Ý{÷½_º?SÔÍû²;‹*ÙŒ‰å"’‡%€CÇA¬jÝ'4ÐAy¹åüÙÒà„Yd¢º–˜Ý%ßz^ì í2Y}·–ó:VÛ¥Ò^¹™8.Îc½öäkÁ¶BÁDí?–ü캫ÌïPñ‰H¢½†ö môýéâ+×Òž÷^äe5%3h¿¯…?E¶îÚG3*´qk ]¾f /ƒYZªŽ“ð›õý<9Ù±”†Ã‹—ù·¶±¦ŠÊ( yˆtµ2¨æM)gS—ìøJšZêÉéšg%M$0­‚0hÛÎþS0$A¦W]LýÑöŸòú`|@X{üT“ïmšaÆ->å"ZræÊqçüÓý¿ Û@»9¨YÍoHÂG ÓòUgño–ÀôV 03ÔîCú•âîðm£¼œ€kíÜxzHÍ!S«æÅŸ/ç±'UÖè^ÑJEKH¬lI¦kÈÃO½2n{ë`¤ÈžÀ-EV†Ø3<±6´dÞó{£·›úzµ¹b}§p/¬–‚²,¿!Óäó#hi+*4J«ÏT̽MOø…Ïž;“v6·šËE }Â*ßÁ~´ñýôl~óöÂÌ Ó/îñãUÞ¸e/“+Ôœ<“íïd0†Üô“[ùý€™ÒM% ‘V&€  ÐÅv¯mzšM¾÷Ð_ˆÃ`ŽeW 6ÐV1^¬®)¢Ù¥YtÄ3Dçýà×tÃÕk˜ÝìæŸÞàRû²b· ëp~+øË˜'Ÿlƒ}ñîáûY×c̃åÏ‚õrü‰ÄjM”ï2žCä=ŸhìÀyÉûZñ@Ú(c¸ˆì/íþ2r\€zB¾>¦üM ^VD[9› ô{õ•7iæÌ™ôÒ«/S´×G#}>ò*Ð=÷Škx;˜r’ð½€Ðaá’%Ç<&_h©ÔŽÎ}¦ÉwŠ} [“Ú:šH%—Ã09ö&ë‹–ªÙò;¼üÚ[õL³bž~±^û«6e¿ûÒS4uÌO‡=šÉ¦Ïã7Ù•¬Má¬3Vès7ì§’ŒQ.î,š$Ù\jøX¼$`EàŠÄÏM/b²ó‰DS ŽVæø5D ¡' ¶atç.öç"™÷µ±&.2¯´€}˜@’LL³â/„©pR¥£FÐŒÈ`{Ð?"G²×˜÷ˆoÑãK€Ë¥ž«ˆ6ñÆ«É ˆ(9OXL¾V2V)P€"—š*|§àíõú:Ìcs„oZŽæ(P Ö«gûég”Ñ“Ï0'`¨“á=!“KN¤ÍLR™,/ %ă´ì¿ö—­tÁùÚwžá,¡¡ŽF¥V0"¸Èo±DãZÅjò…À=… ˆÈ`7G)L¡¡ ¨¦§Æ‰ ŠPÄòµ¶m5Ý0ûrÛ”v€€"JÀ‡ ‚~ˆ€i²$¯vh%„@T&f׈ÔÄq[pϘšO®FíM°¥S¶¬°·‹>O*{Õ«–®‘¤—«)/Ër0Í øF!¢Mü'ƒ*óû²9Vß'>øŠ´ºMàĽƒÿ ‹÷>rTL ¤äà›ðeëö¥ÂR]z¬áèámW$ÓH‘rÄ­奘߭’lfåª0»¾USB[MI£ô0…Búº¤"ðú‚¸ÿÓöUøDq¦^ `Þb04»ÓÉÖŽÂå™ã¸„E&Ë;zB&üM€ºsÝדH¼ÖóùsÙ7—¨¼aÙzsÖ9Üs èTP k¢eÿõº[˜¶Î 4ÉõE±\²„Ê0†XIç1СúËß×AMÝÃܘ|,ª@I¡£QÕÙߥ{ˆN?¥”Šª²É4LÏÿe3ýËù—ò6²L¾7o±y¦áÛÞ¥—·ï§?>z¯ÿäÝ)äïÎ3ƒœ`VÆù>mëä6X¯ÑÚî§ÿ½¸éZÿÈÔÚtóì”™nÓ‘º`ÂÂ×VAjr`ö–êtªk dR´¿Œ +Rh4ZÊ‘x>}<¤ßèŒ;F 5 ˆÜø„¶ ?(Ÿ~¾ö"ZqåZºég‰þsøS{”Ö6¯BÜ ).Ê2jQÚíTñ»´V†}œMÞDæ¤^ï kÉœjry{¨îàAªšSÉäÿ ³ #¯v ʼÍ)Ù.Zxæ S;‡_TL¯|?2pÏâ~Né+¨¶{<ôüæçé¹?m`ŸØ#=ÇÅÜgÏ>‰×£_ ¥âSj¤‚­È$©'mÆMµ‰ï=PE3ß©µÖ«U¸l[V {¥™H¿+›†ãé4ºž¬ÎIÍ ÌÈ;z9º×o/V¯ù‘P˜òTÿ *6:¬À×aÖxE5:ÛŸX/øù4̺ N‚Àä;gþ<êòû89ª MÔÚÜÁÏ*̽1ƒ"saÞŒªs#[$ˆ¬2èʵ? -[ž¥½ï¦;ïˆßQ˜:a ÕEÕN:Øá¥–#nfg¤ß»‹Svî{PǬãY²À\m1]K©1sÝ®kè›’Ú]ËtèëiCí†e_xÛ/¨_gc'£@S.]¾¦ŽP8D&»”Rç|q”Q¨·}‹NYÊf±ÎFƒ'$7»ßÜ{3Šç³ï’©»ud+’|d¸ÏàßDÌês0¨÷t>ÇÀ Ð{‰Ù09i„Œj1:²8‘ØÁz]¹ÆõB— ô뽪f¹Þ×£µ.Y ’;ìñTˆ„Üà ±Ä©Ø2<ªc„áHǘúâš-´Sª¦&§Añ†T,µÙ¾ƒû9¸búi+hëË/Óì¹§Òò‹þÉÜ?2m&œ©ÛùwmQs;î7ê¤Ú8E!'?Þ9)'ÓŒZ¾5eêûÖJûÛ¦™®trUT’¯U“M|o•îWþoå–PÂó#>zf‡&Ÿ˜SVNƒG|TVî2}  9«Ù‰ù«²qÎÈ#]6½ˆŽöÆý[¬@åÜ|õ "ß>ûL3·r4ÏA+.ZN{?9ÀZ<¢°ÿŸ½kmë¾Î‡¢H‰¢H‘Ô“z[O¿›×œ4N›eé²ÆË’ iרÚuŠ)¶fC1léÖ5ÐÌ(6ìÕ,Š-è€hWì‘ q’Îu급íÔ‰cÅ’õ´Þ–D‘âK)‰û}çwÏåeØþÙ¬\óaŠÏ{ï÷ûÎùÎwd¨€õ ¼ÞN¢!SDóÌñ¿ ?|ꨶ*I¿ó„N{65æÛ€$å 0u&"ŠR˜B脾èJ뵩*d¦±&©›8ÁDK Gˆ !µÕ±Y.ýviç‡o;ªžã]~ÌÁÞ÷œ"nk®¦7/O2àBÕ}ßÏwÑ™Ó9UÞ§&£Ó±‚Ï/Qa‰@ X‘r‘? ß›€)‰®¤ùúÄÕEðx Ù›]Ô½ÿV³C\ké jµ¡Â¹D°!,sWpfÀ BtcjýøQ¨Z €:íwöÐcj±}ü›ß$…]ù`>|ïQú³ÛÀÓÞn¢7[€H é»Qüd€z)ÂôцŠÖMsÀ†€©Ž09âÍÀ£”„cþ¨¥›ÁøµbÆÚ„ߊÝe—¶½ô—"¤Mæö–}t"q©à1‡ïœ£ÿü×8½¨AîÈá ÅÐìu)0wÒ©Sºu" ÐÝwt“û`†rÖzì5ÔhcC‡ö^¿¾Ù àé™1ê;\ÇzʲûJwŠât¯ô¥¦-UŒ| ¦fýÔŒ:ëd"RÍ,5À¡ùe-ÇÇŠSi`<~ð@Šž{á»ìüàÏÜk×Qª^S•Oýv¶ÖR*‡9qÁëõìíµ¯CUªî£èô9ªQl6îpR"§ü¹2žT‚^ƃûöñIíT¦ÔÌ(¬D¾.êæ>ÑA à·¾¬ÍhЄEßZT¿ÇZõ˜¹TÆá&PÉ3×H*ÊPRýC#ïóLPdreÄžôÙfI§KF©H*¦…vD*‘#¯ÏÁ—¥LAÜ0­°üz1¤{'ˆR`j’=v‹þuU qN’©3x¬ÖÀuÚHz“½†Š}¢Î*Libù”ƒ75½ÄÇ0àMa·ÔÒßE•·š²®.À@‰ÐÂ$';%á>ô¸ ðØê­ [ý»fÍ×ãLŽ:~Њ†Ì ”ìÙÙ‚ö&þ[: z'%¦81ê ý©RI[ Xé‰×'Øâþ ·.N1[U=É‘xŒvãÆ ü{º1S½. ÞlÌT½µ†!€ê’•nC:WTžŽMÌE-*µ±j§|ñ¸‹çFyßÐ^Ã×XeÖY`ÜÐRCÙ•9ÅŒ]¯é1úM¥½åÉ¿|šÇH ;ÕéÝ_£c·Ò#Ÿ¾•μOW‡!Ö™¡±³åÔÿ¡}å·‰Þ—ffŠÈ(­Tu¯Œq“@ê÷A"ß±OÓ¢„¶Íˆ±…Ê= „ÎM½j†û‘DqÛ ¦ÏÀ(í3ãúb5ÒIõ{üÖ\UÅNƒþH ›í1U5Ž5»…`ÚÓÚÄ©d ¤zQ£Žmé¿CÛR¾´}êš>†¬V¢ZTx˜øæö´/T‹ô÷€³”ÁvÚ׺ä×W6<ßLzÖ•†iþ‘}ÕÚ-JRÔLÇ纺ëèÄÉ!õ=mšW_×HW,/€·ÈŽŽnfƒø?Ü?6¹B]·~Øfñx–„0¢Ác¬Ú`F?où'¿È­"˜ÖlméâöA½ðÉ×` ¼Tá VQçá6Š-ëc`F-²›5 ^^eŽÙ_þÜãDÖïU”Ɉ]vºsü$LuG@½YÁ”ïå¡Ú×ßSP?}ÿÌ{ÌHqR¨`UØÓÕÏé>8¿ðÀoËÍDN\x¼×ú›„¿îžzr–7Ñää  Æðê-öß…ëQMK?UfµHuTÔPs3éÙ§~_·Êt}ÆÕø;)Ê9WéÀ݇èü«gùo.œ?G“c!:úöóä}h?å}‚ü»“j+†·}f´Ï %§¡.N×,öŠÏ‡(®£b1°šÌp¯ÜÌàªñë6™lr‹*„DÑä&§°<îí«jsŒ®ËÀñ°oKÆÝ„q˜þVþ[¤È£q}ôÃu)«;`›U-zRìÀUF3ñü‰ÀcåÉç–FÔɽŽoïéõÓÜ•“ô†Úrõ=DZÊz*¶¸ÖC|Ûiýÿ\L?oØJçárìÒy>STƒ)üeg2Š Q…Ý&"CÖÁ\“™$û>ÌÒ*· µˆI/HÏ6§ƒÜJƒé²SS Ä¯§@VªyŸb¾¦°Äúj¾7X¦©T*àiV ˆ•$Pmø« ´+HkC¹#HÕ5ém=¨`s*‡'Àé]´†a’ T³ðê]Mé÷€i›;X,JkŒ\çÚ©õ÷¸Ì‹KÀJ^ôŠú­©4øÍ™k PDt„»e#‡xT›9¬Ç©ªá­ ij¢ÓC¼Ø0Á•I©»U§`wêû`"¥ –* z)@-d*€ft)¦Ž¯Vf§`†c™ùë‡]aÔrq=¶â(ˆá=·6·òYÞÔ{X£cŠ‘St‘æÕ¾:j±Vü–pª¨Òß]E•^ðÖ½NdQ«×M°Ý +[ûùAµäø¶›L0™˜TedjšWõ ƒÚ À)]Kµ k-Jع1ß©aùp½Ôò×5££¼0í#=£wùèÚ);|Át£ãa:ùäßÒŽþ:}çØq¶Àƒ_ëÄV–Þ×Lñü‹Щüzæ«…;‚˜H÷VUo·5â@6 ¨a!|xíäIVÚá €+Eê ÞÃf§|Í0GºI¤6Œº©b©Åéd=ų[œâ3+EÙ–Xæm%˜!Ad`ÅF:?üvÁs °Ê¶Ïð0¸^8÷: •$¦Ù…¾A€ÀŒé_l0@-öÑÆ&ˆÀ[Wj¢Å`*†jnˆ°eÌ€ô¯­úÍřɡµà– Ì [£u²Ó©÷•ó&}¢!cV.ÜÏ[æãE >“¹ùƒaþ?ê²ÓF¤>«µ/À°Ò—æÍS§Uw\gQÃ'å7Ü'—KpŽjØrµ:e  ”ëHùb" ߯ÀlU¼}µ8I+‚á#Œ×€âWÆÑL3³1Z\b Bõz>Åü6µƒz•ù·\Ió†ô-Ò³"KãpEa îGšZ©NÁ[©´ý|¼Ë– ­Zn%“ùô¾7¨¿o$F0gÜvwivº*f£?üFa¦—±Ø|wj™ÚÆPov05£µ³S ÓStÛâ”nK})~ûü%rF @¦Xí[J Ì,Vï¤: ‘6mòÕðd€ÙáŽz6U@]5›Î» y”°ûÚ›5»]JÐCß™‰æ…9e–^&|¢i@Ý Õ VX¬Ž…¤^¼Ä-ª  a檀Vj±¤ÇÚMâêD?]¶Ê÷é¥ *ßÒ`÷éσ!å’¥”»¶xŒ°UaªU_‚AßH„Kmðí”æS_²Ø`¾£UŸ>p2Ÿ[‰ò}rSbAŸð¥&ê¯òÛ,“÷+ƒ±š©iZÕ R_ï§P{Õ¶WFZÃÇa¼€ØßROíÞMû¬AÞ \‘e³ò†<¶áƒŒsãŸW­Àz}Ìnº`ì° dïà•Mºtjˆí*‘æhŸ=3¶ãoðÓ|‚램ág"jg´X'®T”Ú˵S´ÑHë,DGÃCgmŸ_ ¤`m”H‡Xœ„»Åh‚êÓ_{†þã»jߟ­°Äw·1`¿qê4½?6Í6¡èö96˜yCe€¶ß´r,8å5ø{U TÜÍÌÀë¢Í)i€0£¢QÀâôfÍT Ûjì_JSØ]0EÈ4"U«hsB›™£¦?Üà ëkôØ j‚g13•Û £ÿ]ØãK/ü §-QlìØ³ãûUŒ­yeFÎŒÐÞ™”lí&wWŽ"ë½Ôö€‡~qžžïÏ×]ŸQòè-Ô»”¥Í ;Ô箦7‡†èåU&ИÓfJõ×"²-¾på®ü?ì¨h‡‚·Åï£ÕU}=³ZZM¸”Z+UFÄU=«Š¯òóšÂ¤RáØ0Ìñ­6 Yìð÷X õ²4%¶R¼ŠÛ”+E,=”ˆ²­íµI±ÜRÏ•UÏ-¿aCM;§NEÌ"a©i¹†çH¬çhY¼ƒV–,}¨8Õ…­…Õõ€Õü¿=MAvJºl-ö|~ýZ«0a{A5¢À£i=MLª¿õd)—Ë’«¢A-~ò“T„U‡Õv핃ò|+ £×QI+‘UN7²a¾b|èå¬H,“»®Þ6žG³z=N)w>»"5Róùxÿ²î“ÄÇ/UœÖ㔳ñ‡ÇZšIÚ×¾nølˆ{YÆQ³Sy™=¢®­Lê;ÚLçS¢Ø‡úóÎcSÄÀÀYî—š‰ò"SÃÃQî=F¦õÈþ(}Û"@BvŒìŸI^sðò Тf¿÷näØ)Lµ\îØMóæ‚ ©áiªS'©¶ÞV®q¾ûΧУøãع ±RE¥êõÒ¿-µõtåʃ1L×ϼ{‚NŸMPMC}õË¿iÿ´Ì `ò€´, ²ÃÔFß§©ãì¼H™µ zðŸ~Q{üµ¶í»vu\Ú9úÒ'Š•úhlt‰[j®dòÌÆqE¿wI'3ÔRQ ¤Ik¦˜¯Y¯º¡úíÙwÏ1ž6ƒY¨WÔK‘â ¨â>ˆ¸VT­™¶´Õ¨S,ƒêRr‘•ÄrÀãdϹh2­}—\/µ\R±ív‚bw·ªÞ•$¢°ˆbÛ¼â@ªs˪9LE˜“ˆÎPUióG¡UŸx³òweø9‹2VÌBî<àBõ‹Ø$›‰ +5Tn£í¦L1"O3ªB7¥ ×jïR×®”.æ3+Ùõu.áã[•¦5ƒ¤ÚgpN@Ü2Ï.I"^Sž%ÿF„j]!õ!B4k€)€5Á߯þlÂTD Žã>ÙX¨D»·–‡>à¾Õ0]kVªK¿ÆVÒÍïÁl‘ûAøú¢†öæAµÓ@H+ðÑoŽÔ2ÍNKå^ªµ5S´nD¡ÜÅ%Ì+« f°Ì o€&¯ªsJ]’§±¸d¼›ÌS«Å¢šG V‡­~ë[8„xõ•WéÜ^¦/üîWøö¹·N2Hb$r<¥Fío²ÿ--ꌋ, ]ÕÔ×w@×E=m‚#¤s_zã͈‰Oš`J[s˜ºöý”þ}*õwý«ŸùÝìa¦w­K`ŠÖ1x˜ŠÌÙ¦8¨€¥Xýjõ‹ë;¥w%äÿ¦/ýÛ3|ýëòÏÔÛÒI“-T¹9_ðxS $Æ9¡W‡)йWAë÷é&š¥ð·¿ÆæøÏýù(µj¤÷ktòýYÚÓã¡WN-òê«ïžö[éØílì`†®¡ÍÃôåWÇ"¸Âw ;„L£9wêeºïÑGø>‡:‡µ*·w¯VÊ:˜*_þ¦kËW˜Z£Ø‚ÍiaÀn¥óSë¹ABÚhì„”‹IÍ©­ùhiƒÝ/¹iýÎÈ L][Ö×ËÔÉý“•ÒJäŠå>QÇi8¬rüXý%ÕžàŠ'™!Ÿ|eUŸ´L·°ï!˜¶§t¤7ÄißbaÒ¸ÔJK)7Öm\ÞSÖß9ê°ÒÓŠ¹¨£-:~˜gsUqIB4ÿk€½b¬&»Öm§ÍZ;*ê°SjÃyµ%ÖC4ϧoň@æÛÒÊZÔv½®í^Äf:ØRÖÈÀñ•ˆŸÆG¦èž»èx3¼?Ï-_$OONü¦Ú‚¼pDäûTKmh£Æ½^:sz†ë¨HÇWfx¡€™¯Xh8Tkï×ÒVÄ!hçè ‘Ö=п‡ûOÑŠ‚Å,l9!ZÂ~ÊuR·~NÜ^\J0øÂBX­(…Ë–keN=¿«€¥ÞÑ×D‡÷fšºc„™úR¶Í. ·¤Ööv~ˆ¶` ×O‘ÖC…‹Ó½½‹>òOmû¬+kŽ’×w#eÿó§øÿ¤Hûb“”®8# {8â`„ ¡£ÃI ÷£é—عÝ{7[Âöïg=Èr~œ„õ å€òWÔ¿`‘éX¾¦³uËýÔ¶–¼ˆ·.¦(ºXÁ^¸G|’–׫mOÜ·^d »0vjÏFµMû²a5ÊdOYáÁdªÁB!’ô¬L™¹ž(É´#Dº·8 Ɔç2–#ª¼ÛOwè,å- 6 · 0JÞÊt½u<ɸ‹Ú;D}r7ñV¬J5ï‘+³ë& ÙŸ¯¶–73mVîÛþ´àÈmƒ)—îêo;†”·x5HT±…Qm'— ™·ŒM ˜J`›½) Åß]öáµÌ@-FŠûð=Ú`ª€”ÁÔ \GýS6þ­r…û @T6 ˆ†°aqˆíz#ûõÐN³¢‡ŽCíʶ3˜ÚÆùÖÐdš°ãø°?»'k·Ïìh‡AjuQ ì¸)\®bf –ê÷»4EÕ‹!j¯e0Gd^¦0\8)IÅ!¥IÿJ€¥Jù)`(‚!ÞÃs‚Yƒâ¹EU  ÿÏ?A¹ç~Ìâm7n» u‡ˆ¢÷lÕŒbŠS?Ø[l`…Ù*;”J5Î郷£·™žxòaú›g_¡ùŒ‹UÄcÑrêêî£_ù…{ ¦e ŠÏ.÷¡f»Ô‰UïÜîÜ^ÊÜ¢–£›té[ÿEç_¿JauÒúãÏ=¤ÎnƒôÌ—[éÏþúf¦w=¸—Ëí ¢¹¾Â“RعA³ PÌ”¯°<,„•"¨ª¸„Ÿ'gªÛX|$5o§|‘ê ¨“udÎËî¶Ó¼&¨âqÕ«£ãäÜÔï-µtŠ•Ž8ù­­x¹æµL×-}/f ÎTy E;ºh}꼋†ßVéT7¬ÂÌÓdK¼”*t°Š‰ªáÁ«>[™O‹=d4O! b@{Ôf´nªõi^áP“sÍÓb5og’ùyNï¯þ¶¼è%­NÖËUÓ°w‚šÖÿ›½+Ž»<Ïï®´:W+í®ä•,a[Âò‘0¶±‹1¥I8¸@ÜÁB Ã$mÒ¦I¦í0Iݺ¥%ÍÁ” =`ÚÒÀpã`B0ÛYÈØ²në–VZÝÇ®´ýž÷û½¿ýö§]“þ‡ž™ß¬öÔžßó=ïñ¼úû+ï6æ,RI_€\¡^å:ö-fúíã×oBœŠÒ!§W-äy…)‹§œp¶Û  ÒsS/‡{WWkÁß@”X¥š`…Œ à`L]ßIk·ø¨þ;¨¾s”(`MWƒNe@•n®*¥³]É&©*}æõsµ¹„OaÔ -4P° Mp#A‘ s$œØ„ÖÖ\Ju r¡¤zêB7“ß¼k-_æ¶úB_:ò:Ÿ~é6í› u BE*Aƒýö÷ô0‘‚TEs•ïÖí:¿ òÄžý¯Rtt÷}÷-"N„vå2 ó.“kz,j˜^¾ Vq 2Íœ½™ãv¸ vÀóyÉ‹óÕ««hz,@/~nØy%}û;D§;ÙŸ÷ª+.§Ðj#‚  @ÌñчZôP¯úÝ–öSVIˆÕæþ;ŽÐGŠ{¯r«Ý¹:ÜáÛרã™?(¤¿<»ƒÂ=Ç鶇Յ§Õvx‡ýØ3£36™ÂØGÿíõÚÜšÜGjV÷š@?†óR4ƒ‹‡X•ªÃÃØyT„të¥  J©ühÁ"œŒð1ŒHê…óG¬É Q* Qd ­É÷ã,Î2¦KÈ4W] ózcЈ¶çRBU£Å,ð±‡z—êY¥RP”×çâPg²‡]Œ” (fuâ„;ñø 3ŠàyÔ<‹XR¸N D¥¦#W\ŽÛÌ”åqQÒRH&Yý^f¸SÏaÕª_o2 ²ÝK’)r¨r=H56Ÿh§1IUª€%wJÍ:·º¥fJ©ÑõT79_LZMå<B¬vWW$›’H(ʓùñDüç¾ûwÑc?ÒOXô‰¹¢M%…º¢˜»$™Åf‰áâÉNIòüco)®C FhvÎJòBýzø¾P‹È¯"— “}€ó²¹ù|{~¦¹eyn&ÐÒ"éèD;ŸÊ[Q©ˆœa=zãÕ縨  õw®ý¢"SýZ–R£æfOM/û;±œCMÓÇ¡_ û:U©ÙƒÊ]☄/Œ°¨#ïˆÛ"/sèõ—©ýôq.îyâÉSíÎÚºm'Y2}aQ„³9pG÷€Î¡bq´wÑÃÿð,¥î¾ Ú¹cý¢`±'~€Çú#ì®ô?·ŽSÝÀk¬ppð¸x|·'9"M§LMœ9Ó¦võ>*¯¨b%ŠEHRˆ’…•.HÕÀ¦R<éÞKV©ê~R2E$a,¾\¥™gäÐ\1* äi2i’£ƒ@A&ûßbêËÅå…|l­.áã’ê}`º ¬7T–òQ $Á˜>Û r‘“X~6‡âÌÊ^Q§™E¬>p bEø<#À$â¤è´5ì:>É![“Lås3/K•[šáà˜R»ÁýYB…j%š PÑI_J2•\* Ã¼–Ѽ"M©`’íD¶Ž`°·@HUˆFÈÚ!y…NE¤Arqhw]IŒF36°:Åߨ0 ò£¹‘@¾tKM)ß§þ\y×Ä鿟o¦Ý—mæzW<Ÿ6ÕTr3Š™ÚX·!@é`†|ñDŽU½Z& ¤†¤ âÚ¼qçF¡H¡Pu©vZÂeb!w"\g(Hë›óù ¥ð«_Öï£Et•¯ÓŽX+tÕ<Ö"ÞdªïìÁ¿}˜Þ<ü{qó}yÒTySgN5êJÝôYƲBý@/*ÈÑ4ÅAÊx6´j Ü˹:´#)J+T+výÈIÂÚ ^ªû÷¯¦Ÿ=÷ ¾|ˆJõ‰*ßsug¸ÒX¬eVihc6«Ô™Nýó½_ 3´‚^9ÞÀá¬ëæ½”ùËä­öÐ1*¹ãzúéûzËÞ®Rª èûGu(²bãz)ó´™OäP{G§é­7ñy¯?Kí²WÚV‚Ñ¢uNG¾Âmöý NÝ ú…ǵ»RyþÒÄ͹TEº˜JĪ›…÷•"©rñ…Zˆ{bw©yžÅz3ƒêvP ¢:¡8¾ðä&–¹‘„£Œ¨ÕÈÞÃn6]Ÿè°oTžE,R€$¹Ó€§x”‚qM°+/Z'GÃtQ®ž$SJüO(T,Ï9…‹ßŸõtúM¥PA ¢nÛúÃLÒÕ¥z³è õÊäû{;:Áçs¬èŒ9¡^" EJÞüJ]H5bEo*r©€Ï[A‘±êƒT…DE½ò©}ŸB(êP¨ýjk Ù ¤£‡‚Ǩexˆâ]1vu™›I2õò)B­ü®ÑËŠB&äRϵqÕÂ(dBŽÖI¶}ÛŸñÔ0ÇPí‹· WDF0UZj󺧸Ơ¥y¼ê¹Ãƒüá‡î£ïýðI  Ñ2~{,+Ô%0«ˆáÞÞ®ÛßT¥0º‡Ñƒ)\yL#H¸PíÄk×$±¿9ÑHUë6ðB†Ç‚eV¦bqµ+óü¶rD¾j26ÜÏêGõÚ,ªi§dÏÓ=YÔ‹ðabðÙCÔ=>C·œïã… mŽ_ïv]JÀ¥)•Ÿð'…ø‹¢'JÒ éNLt/º½Y¬ôi¢F¯ª,f¨bÆ,@¨!²1WP©Ô “)€0® q)r’)ˆÔ$SÎöÓÖs‰îÅ“SDŽÅ½l3g¿wJÂà?#'@óêy‚¨A~¢R? ÒUÿN±_”«Ó½Qª¢ZMrÓ(>S¯ ­&pªôÅ)¯8“ Tª{q ³û}q§y#ì dÏ S(ký–e°7ª€¡VÍÃê3€M˜*›-QtÈÃ>óÊtð§¿æJ`¸ñÃ•Ô ¾S¸<L… òt/H5.D8+ÒѪEºßßñ©þ U¾hYàÁ ú7%ê}:UïO*uº X—úq ‰J[ÔR˜7£†Ñ+<§C 'çܧ&ãLº+ÈKfâÁrwä>UîJA´–= p»ÅUujó9ž²IÔÌJï[kHb(LºzêÉ3 µ8ÂUߣa½™Bqnº¦‚®¦‹¨¾¡¯ß³gƒ]9 ?Þ̹Fä\[ÛRט ä‰ï·œräD!Ñ~ÔˆÀ0©Ž…Y±z24©®-*ò¼`ÏõE“id6©lž©J½Üzƒ(FWÛç|×lÐ×y«Ñº¥nÇB¸ß9¼•8•*ÀÆ¡»±sÑkŠÁZjéï@ª"$³ÝmË„šµ¾÷ëw¨æŠËø|]»Þ9bjÃ@æ(›8 ü+dêôð•ó8Åí|«ªÈ=ÚM½=aué–“—½GÛ·UÒ|l„®áÀã¯Hìv3}!vlüÞ>H5êWôÐ7°U$µO˜*§6Qæ•“ôÂz—R8Çôb.É`5Öš£&Z ÚürÚæ_KY+B6†ÚÐ{*£ã <ô±25‰ø?Aw}õþñq5®"‚ð`«½»ÆÐ9•_«Ú $\‘“( nJ%¡…/ÌÒŠì9ç>f'æ¯a 3Oø˜"ò«}BŠój×®õ5¥ÅL‚^¥G(<“PBšé"ȔߥletÚhdzŠ 8.a“ê^S™"§†B•LoÅ&tß!j0>Nx <ês®ÌÒÇ„+¿)BtOZ*ÜÜ68ýr™óv&L’¹JH§bl/èQ_-(­œ/°È“CÂJ©â²zu›-™YlXÊf"g$©gV½ŠÏ*Vî!óÕN ÄÈ»"“Õ©‡!däF¡Fß~U×( ‚÷Ò=ë™XÒ2ÿÛ³zC9?±[k¦B•b£¢¢*Zp»iÒˆƒ\I‘q†üÞXjä*9מþ ΧJô„¢à þ¾s4ÅFú ÓÞ¡ˆÚ§­§2ø¶æZz÷½£43­Gò¡Ú±"ô‹ `lxÅ ÇfÞì#GX…€…4¸\¹ûÿ€eBMTù‚L1¾ g$W DÆõÏ í‚E²¨+Ñ£ØD‚@É2Ì÷[5/E¾"-Ú¯Em4Ðú_˜£È”‡Ã¬âT$„i"UnUÐ5™~lßR™:Ñ34Gè°‘ŽpmÎ'TÏN ‡*}©‚ªUz5F±‹AôßNªïž'rÁ;ËE]KÁ,V‚25ó¬€]¨4;Ï„i^ŽËVZ›·|µIª¶®kVǦ|? å$ y5™&ò”ý}ÍlPòÁ1µÑu{™LÖnÅqiRE[Œ¸(MYÑ 6þFtßïå¥t²±I»H}ÌûËS‘Šÿ†t¨WÇAªÎ°°&X}&&¡¥ ÅKì36*Wþ…øÔ,J2[® ‚/(òsž4D+íIKù¢G•Ÿ§Zo¸ØËÚ¢D6û‚tÕ½¢BC¾ä*`~œ¬ô¿‰Ï*– 5 $ •øð·ï§W_ÐE7ø qâG‡ü¨äWM`'øµ½{9¿ üËoÑ¡ãÑùˆ‹wžÑNºþs7sÕïöÝ7QYi>õ '”Y¥ú@‰bdÓ3Ϻýæ[èžýû˜ü@ŒP—zùËvÊ.0•@{ ô¦¯<@ÅÕ+è®}wÓ¦j„ ô÷3GÂáo<ß¶·Ó—Ã;[f̰ðáÇéŸÿ;ú³GR·Z3$ÜŸ‹Òø€Î£Š:΀øašê ùâs‡®îVrëÇÊÓ‹n0®[¯#$ÿSTêlN€Š=£Ü{жâ k¡KÐøßfžÔ$YôˆJqÒìÐ÷$åˆÀÃàAB¾Xu1’†„û,ªP©®ø0­,VwŒÏ²B ¨ïZ^~&}\¶Ù©NN2…â–·VúI=Öˆ52”(Ôgi@/–Ò‚” ¸Iª¦*å÷_‘&+XÄ*¡] ´D÷7M÷Ò–ÁdêêÞ¢^7©fÚO›G©>  ‰\®«¨«·¶—®Õdj¡k 6õwJ¨ÚÖ–³Lª ’ö.ýZÑcŠö˜îî6Ú}uµJÉ"Ü Ó„‡ß>é¡õR–R§ÈÑ•Q+Tëœ×+ÞÔ ão|wA®2Q wÛÖ*[éjdÛÇÙÍHmF¥ßjòùçu%/ìžÃ«NË*ª4ZÆ£# ðœ\=ÆðšF½>‘1{:ŽÀ©R…H×-÷¢¦Æ2¡¦À@÷(]uÍf&SäPÑ“zëm·ó\T:ñ®Ú{¹É´#tö¥â‹ûÆ»GèɧF?yüoè–{®  {6ñõ|4Io¿y”ó´w–Žajoøˆ>çW¨©U+`éüÈí¸lí8ð}÷±q5ä#wþ>e¯*¥ï~ã!Ú÷Ç÷òs„“·0ƒ€¢É2<%+[¤ÞótòÔYªÞ²“ÇÂávB¦v1’zœWþý5¢‹w§|_œdêÈÑõØãTNUÔÓr.iwn*S,D³Æ\G® ¶ª|A þ‚Šf®arÅy)FÂî}Þa¿ë¾ÉŒôæ~ÓÐå3Š“Òý—ªü™BÍ¢cÑ`‚€Ü B¾9–2˜7,mxÅ3YÅ4æ^¡.‹Rus‚\Aª˜žQ˜ü„Y\©ì©¥‚J–Ο¦ ùfØWÂרÀÑK „8c÷ò¦Èë³I¾u¹n×Ü©ˆ­P3vP6 óÆê­"$>¯>úúþaª-Ï£‘UÑÔÚªèÏâüvE¿þ\^8K?QDp°âsÔê]C™3M´ëÊõL @…Õ‚óý\hT›äIJ SˆÌ EÈ“V‘6FÈóÛ3UwNèï{tÑ ÚÛÆc šäü‡Ó)Iú¬Å^Sêp¹ükµ6‰Rr¼ù1ë´-y‘B'´ß <Íãð/›G•%M,,ïh™Ç{ê£3<ìäO¾þlRO÷µÛ­¤«zM3ÓÓt±zÏ‹JŠ9w‹ª¤èS)Uù§mmmœ#†Ýègyj:,Wù¦ÀÆõk™`Ð*^¾ÀU×즂öþ4ý|;T3—Š<ZJÞ?YOC­ÓöB€Ç>ÖÔm÷·®[­˜¿zæ)û¾»¶•Ñ©ºS\0„ãË{o§¯ÛEW^“ZT*¹çTÈ'Fú¨–Š`Ø‚,‘»©þüåé«_û&µ·œáÛàzm5¨í /Û˜O¾²DI¾3ÄkZ.…†÷ÎØ*“Ü•¢#k€·Ï(ÒÁâbÎz4-A¦¢Nc–Å›PyV/?7É;QœµxC€œ"ŽÈDòN]*M€ŒD©‚L¡lQÝ‹œ&ÇÌ9&¨H?”¡o_•0yšêT€|jÂ( f¿ð§™C5Ÿ;€J]Òw*HE¤æ}qà6rP£ú7qÊj yÖÇæø°‰56g_—Õ#ç*£›âmtùB”sþÓ¡(}9»X‡i#ÓTøîQÊ*¾‚:;â|À¿'þMÅêùñ.t QûH+T)H!_l?”MzOCÞ*ûõH…:ª{ßoè§ßfÁ$ŠP°|‡E¹8•j_ùM±J.*CÊ%Œ+Á¢ed*8zôm>E+ ü~ÆKBœ"r‚°°˜ä§óë‰öS]ÝIzñ•—è­wëèýÇyx:Zz–‘Œe…šP¦€)ß]›?Ò–Ö¾´[»î"êV?„ý_”î¾u •Mòh¸5Á"šín¡ìr]D°¦f#ÿ/YòZ:²¨?£Gÿù úÆ÷2á…{{é¯ÿó—\àòùÝ©°|=vŸKšJƒ00”'ˆô–;ªèÅg[éÀðëÙg½ž—Ž5Ó›¿@ÿvàÁä×üa7W™Rž¶=D®eÚððý8… @¥^wíVÚ¸ñúûƒ«v+Íõ¶a¾‡ÆLB]pûí^T'¤0 $;¢vÅX€°‹zÆ­M‹Ú£`Ê.yÚ‰^{³þð¬ÿeåSÿ¯½+‹ª £§ÒºMgJ;í´e)•­cDÅHQP– ‰â<èoꋉ¢1Æc >4`H ›€‘Å6€ Z¤ Ýh™.ã03Ì-íxÏwï?½÷2õÙ9 t¶Þ¹¹÷žÿ|Ëù¨d雫@5T`p˜êK%QªþR’ªÓ˜+j.DŠ}!}Ê üÈÍz°Ñ]ÆÀe=Ü0tÇ$}{ªðMò¥Be–¡_†©ûQÙn¥»-7{FG²™ð0R5›f°Ò”Ï›#&-œ"d¶¾Üƒ½>œhóâýÒ „ÇGñGa*†zõ÷kqꋾJßè÷1!’‚=}Ô–MEkwGïÜÆ+sŸÁ–}g°tjj:/ÀU]i¼:„|¸p Ò“ÚÑÜ-£ û}¹¸½À+š–¾äžî hdÄø~‡5’ÎB±'À²?•‹Dº q¸8C¿Œ.q±œ†Á˜e_ì;XÛ³ÌPŠ•„ÊÛ*½A N)P¢‹v_ÌL´c_…ˆù\ee™TþòßìªYÚ£!_™OZ2­W.bbnÊÊ<–‰2ÊË·_[XÐÀçó©Çë~Fíª·b‹Q"æqÉÛœÙJ(ÚÕÀ@O³(P¶ë¨…ém#4ÌJu{>7‰$¡&„2Ç·«R•+_Z.ÅKpL.J ËëŒÊ_æV™oýì“p`çzâöêOíDÉøjÔŸ=‹ÙSÖ"äõ£Ä•މwµ“D"ÁB½ªqë×Ûðܼj|úæ“øµ®µ‹+±¯ý=º"ºÍ™õ¬øèò¶*(Ê(‰¬Ð)´ŸÉ¥ÛÜ¢_ø.wáhó߸Üte©áÌŸMX¶f-n\þMrSõ}—dߔƦÚΊ ‰HUq¡Nêå+^´¼†¹ÌM›ß­ò5V±Âí¤ãi3¼àðâÂÕ4ó§™F`Eˆ4-G/îIáïèRuð÷êDÊ?{$ ¯ø1§Ài„€†[ ÝŽbÖ‚Ü~¦¾`|§¢U^¾ý÷#±Ù¦Ñ;þØmù.â c/bõ·®@±‰%Q£wÐdî@…ú_Ûfˆˆ-?–?æªÒB!T9† R5+־βY¹[”w»ìù¥»y ‰J)@’쎆6Ô¸Š0y¾ÕT_ØÄ"çLDgèv‘‡›±ÙíÆdO1Únxåg…# Ùy˜s;€9ŒŠæiŸcg ¡mÝ«Bž*ÌËÊ^Þï¹vMî«낹ڶ£²/Ê×¹Èø ¸ày8gÊb4^¯“ý8¥G޵‹žÀO{ÏZF4áá„á̵ž¡!õêÄjNq¨0¯^Äd͵*ÕJRåPoï|½yGÕ‚B¶\LwEFëÛUxÙkoˆ/ Ÿ ô‹­c×÷Û°mûKè—ªT™é:2ŰÏÝiË‘çMÇŒ™<qlaþ‘$Ô8PSfÌ“fÌãÜ<îIx<§Mð"'e)LzjÁ,!]:q„ÔÑc—päðiÄn<}Pü»Áºf!4lJòÇþê—ŸÇ¥s52uàt]½Ü&æVW¡AÛæ¹&¯¶’ÕS{c¬W• :½×}ÃÝ>œ‹øàwã '—î`HNŒ…ÓÜâ|£í:†úºdÑÀ¼±k¸'ŽcIù´ØöÆB¦‰`ïcUˆv¨ Ï-‡N**ô«¬-Û¸—ªiªäor©¹ý„HÖ‰5-{Èâ—›mËú!U’#IÕL¦„¨Ä8 ÙEMiFFtµuW#˜Ì‡Tûõ÷¢šÈó$V¨$WEªvHÞ3ûÑ 5QU¹$ ÚR]´]$’øH„f2ÅYž‡€FHîJK­ª›¹Iá6ç'I¬2ñÇP«ªÂö|w/J[å9~óbV¯­;'/)—aç_6jjLSVçëíiþ!ÌA‚ŠéÃàÙ°ZB¼$ÕðH»Tøª‰3Íü¿IZg"7üb` ª”U ç²ç” a’)÷›j2×í’ÇïìŽJÓ Õé£È4rÒtõÂèçÉc[)×Э6!J³’¥ZUY†be‘’§T§+ÕãJP­®z} ú¾jà½9i†ê•ƒ*¸˜å€í}‰@uÊ”£n„]áÓkò„Ž$¡Æ Ff j$Ê<%Õ›Ùß×L¸µ+W`¡ösÿ‘C¸©©M¶¬_¿ANZ¶Ýø»»ÄOô÷«ð¥ÍOpÉÛä9ñ—v@3dX3½Ü²é÷Ãp{*d»×®uÉ,Ï·(cß꽨;¶ 'Ncã¦5˜4I'R3±ºgNÇïnÁZÔ]©a|³c?Z;»à§cóªØ]ߎíï¼Þ¾!çÎëMbE–ÿ˜ÉN®lEfuúÐÏ5x[ÂISf>i±T°“§Ï¸Ï ýãî `b†Nª™qÒÿª—spp”8•Jëê•â$’* ÆŒ«v’U†ø Ó( æPeœ_Ðz1êNÅÓùñó£v g¸äï´¿o"låXc U&ÖŒ’öäb‡Þ— ÆúGÿ¾a½€Ç§°È<\±*U·ù;œô£“ÏM#U³ïl£ÈbçG[fíòÈvÖ„rPQÊFS= ’cœÚO~z^o <Å•8{ò¸)‰•ÛÑ~i˜ˆ’©wa-äË@±;Þ›ƒÚþ‡EQÓÓ·²b)vüN^sž)M²)b´Í(pÜÙXI•Ê”•ê*Ò¢ˆÕØÀL{M;ì•ÁÕsŸ–j`¥TÇ;]¨š®/<ìQö¥‰Csk»å\üòó(›Vk)fRÕÀ$U†~©*,óƦȞ0†¦õÿRjjj’^RIÄ«“H"‰Ájö$’°ã_éшNáÝ)IEND®B`‚MEND! ÷Õpvpgn-1.8.5/files/ad000003.mng0000644000175000017500000014053011151345317014501 0ustar aaronaaronŠMNG  MHDRÔ<d †2œtIMEÒ 22þ…ëBACK3œ% TERMÿì°¾5 FRAM ¦Ô IHDRÔ<ßGK7ŒIDATxÚíˆ\WÇw‹!‘-e±PY +ظZ„©R.… BA%4Û?þá(”„a[A¡8(”Æ’Z -Eé¶PRBJÓ@h,öŸ,£%k!‚ïÉ;gßywî}?fgöíì~?pÙÙ;÷Ýwï¹çžs½7¶D´BýpÜIŽÖ]>Æ ×g]øRÝå)÷Õ]°}q½éÂqœ·\TÃ…7LøØ…oºð„ º4_uaºîr°•p}bÙïîÿÞDÒw~VwùCDf™í@üœ8UfÓÒÌ{3ÖkpªÜë-^çiã¿íÂUé/ u—¤`†:$œbO±#2[wy6±ÞìH‘Ï-ûÝäääUùø¤ ÷‡®wi.¹?_vá.üÓ…¯¸ðüNpª¼ÌíÂOv’¾”ÁÉ£áÂ/\XâÏu—§FÞuáë.\vr8`â¹¼&Ÿ/×]H°q ³oïµl>ϰSðÁ€ùêll¥ ݞͪë¨Ù1ÝÈ,uª‚\:¼4,i— ÒòàåËRòŸq=ç†Ç¬”µ-ò²\eù·"ªò™Ûs¿ §ûìGê.kMò™•úŸ•ÁEKtGõç¶ù¿|¸¸]u×cr9$õe™üX`MÕ%0qOHŸ°Ü„ûd–óŒ}ÕѱÍË:íHÚÙaéºÅîH½cÚÊe.'¯†Éëdì.¸ð²¤]”{Œd6£ûÀ%Ó6üŽ-åå¥ì¤¼<3‘ï¦ÅPr½÷¢ü[J¶–Ïã.\’ÏÓ’æ¸|ß“öÞvÎ!"uœ\çOE«”OGk ¿éQ8G( Ðu1Rÿ»¢'Û~e«1B÷”bîµâýŸ1ö:Ò#ºR1oÍk­„󸽤hœ …´]Ûvê¹ÊÔä”Èý^£d&Û3‡ª¶W…:–p;žÕ…÷]Ò™w#'ŸmåP)Y=ø–êyà{k ߥð`L"·ÆÙ1””ë~7à,؉0é$þ„|^±‰ù6¤ ¸-ÆjuÌTkVúÑq«îï.=a°§,éå¤ÙíýFiàY‰4’Ž‚o›ÆÓO¥½-¹f±Œó²_‘ôc=ªò nyßëe}àâ}¿Û|~ÖJ"÷bãzÁ„¶8ó®|©<)Ý+?ì¹çuóÝA“–ËõªÔinضÀ¾=%³ˆ¥Ëp )ןŒ±o®³8TÎëuIsu;̈Œx°qoÉ×ĦdEáJ{½kB“†E ³F®K4„­®ëú ¶7¥[!Ót Ë¡“_ÛØŸ¼ï¾.aÌD¾[¾×å {©â=šöod÷‘”a`ƒGé~áºóÈI;362ÀØeef%ºœÓÀË~ï‡ä'ò}UÊyÊèBCkO®;P¾ô…uã²/zqZ—ž„‹9×kZÖ‰åâ;V.ŸæÏÎ}†6ù ¥3pËuJfU=1„D}n_'rîÁºÕ1s~ÀrŽÕ³Î”Xûз" ݧ òÉœc dH’÷‰Aúüê´ß´%IYÖí õ¶-܆1ÿ ö§C9ŽwÇ FùT代"¬ &îѶŰ4­Sò;®8“ïQ X¡Öy¬äQ 8TJ"|Héaƒ¡J—øq•sr¯·)Ð ¤Œ¾Ñ |ß4rîIÝ×Lg9jòP‡Úñò8,ñ/GÊÀ³¢—†%+É³ÏØ{ŽànεÖgÜC(Ÿæ¯+#gEŽÜŸ†²• y-h¼ú©3mSÿ³’3FN‹žiÈs¨Ú§™nUuéKÉ@mÉØ† /}’Ùß6"ó×m¿ô‚N®•ÌOõDöð׋£¨C  Kûé@¸eÊCbüÉ…íky”6eWÉvö,Õ à-Šœt4‚Z0qSÜ¢,§(ë¬BÆ1ã‡T—RF”<‡JÉ2Qzx…ù°j§5h.ð&ݾ`âu_¦T͹'Qñ3©\ïóòw…²Žµc>Ïšë§LüBN9£ M~!iRêÀŠö„K§°|œ¿î'_72:lÒì’t…NÄ¥ÙMæ€%ŽHùŒÿ7iµ½;9ùÙömFÒôÉ8¦M9¶œëØØ}v¦HW8ø äDi[ìÌeÊ]¡œÜŽQ|ÕÒ1iºTÂPÖ1=MÉIÙi“—.WÚB~Ý0ýŸÃ Ôo›Ù¾¬®oyuËÝÈ)G‹0K]†5–3Þw:cëš8©Ì™¸ ”5À»÷ 6 Q¹S¨êÃùQêw¨úÿ5J÷”R bî¼Î(Ý…Àµ2T°A%oáz³áÖåAîà ‘¼‹ ïPG¦¡{R…Gü|Ä` í¥³~–_KâÞ²FR➈ÉFêrÖ“3ÿýÊ”’½º.eW|töÔÌ)ß²MGáA^©v¥œ[Î5êL¯ÉÿÚÇ2§†)9Tæï/.šïµªŸ½2å®ÐŽë"MœÚ>.˃·Bý¬RêÌbK¢Ö––¸]F¦çMZ®Û|N>j¯ŽÉµ“·žÂe}ÜcäÕÊÙþ ”³Ô2H£t#ñÌiÇ·{¡g©Ä,.ֈʟB-Y—R×(ÑœüÿНT¢Œ-*Þ'át<³='å tŒ»^:V´ÕH…J[P휊/û”^5R—¨„ÛÞHÙ¥„Îpî=æ¿?RÙì£'Ç%nŠƒ&÷ùf$5v‡<9ÿ(–ÕKæÿ l¼k¦M¯Px/µ”ÞQÖÙž/ dA”]fäú²s¼hÒ©¹-˜òü\¾GtÓ&´=‡âP#å_’[pÿŸõ¾;-ß½eÊÛ‘´‡yEí‘‹{Óö7Jô| êÊÓÿy4íÝÕv’¸JèI©AW^>„YjF<ÚézqÓÆÈΘøõµvn\Ï ´(2Ë4mZ§×‘¾UuŒMìįvÒåHþÎ .È5•–-¥œ«äÍ:Ýÿ?ôë›§he”¶ mÊ!R‰¥ûºÏò&ÁÁž‚:åA÷FÅñ€é ÿE"¡òñLaI>ï—d tªô÷Å@<—±cþW9ž÷Òi|è#‡7ÒO*´ñë"W;ÙKé¬îÍyèÀ ÖßÖí¥?Váo¹ð3Àv°¡íjKvÞvk`EÒÚC¥þ ë¨I—7KmR]$Ê?˱#Îf•œ;Ï]ê]²Ð Ÿ?u΢N;ä:ÙÃV¾‚ªqñg¨öðÃù’÷‰ ÎXƒ[Æ™{t8‹’G%¢øü7´T=°Eé£Öp^™2DÊ¥÷ÕNYª~”¿¬:mêZé1 J«më¦èËT$}è]3ÖüòR²wÝüÏÁßbQýxÉ‹·ûb³{M«Ñ7ò˜¥t ÀKÎåú¾s’Æn¯ÍRsuؤ]‹æÌY Š/‡rüí@¼êãf8T=¬äoŸèÊ϶ä¡:u¨æóú¾­‰ãˆ¿’ѦÀénJWÁBµÏ$ècq$z¥+üYg©»'"Py‡Ú)£'ÛÊ>¯¦‡XOÒG/æ{nP݇ 5x3ïúÔM;8Gé¾ —;jH×ð‰Jž=ô¨ø8üJÄØëÛ§üý±\cD%F€ê>Gƒí£Þ¡ì©ní¤TÕq™<>Y;JÇ£Îj…Ì»}½tóÔ¿Wºð]Jö¤ä­ú‰MÔSÃü¨ÓÀ¿I>Ú§vžC!¨ãi‰ñ¸HZ&=#Fi…²\Úˆb½”³gåä‘åßM9CËu<îP2C?S¿Ö{ÞÄ}AîwÃKÛgŒj’‰vð˜CÕÎ`—˜¸=/–¿Ëx úñõïÙÛº-‰³Ï–®Ÿð äÙoœ"ûƒÕ~öù@Š´(y…g[ê3CÙ}I%W—KÊ«O‡)yä¥éÙM·Ï»>£{”³JÙ·3ñ,í;"‡õC4£ÓŒB9°œyæÏƒª…‚´ÁþFÁ…Ä«®ðž¿>y`_ªúÈðÁǃ’ö"Nè”M¿›ÅÛm‹e¯ä©«dWê¶uµaIAd)F‡®÷«BèÛa8ð’Å–ú}IJö𔫔ž&¼’sM£L§¥t‰æ¥‡˜‘<›”³œ²IòÈ}x\tÁß;gÿiNžµÖiƒòØ“§¿Æ9øË”}íœc<ÙÈÜ4zz¹-Nd–ÒWR¶‹ ¶\«zÈ\¤×s{e/KÊ¿è9T­³ÿ´UêŸ]ꤶwí\ä^=J—!ß6ñLw¢F(¸=R§u<îÅ³Ý -us{=OéJÆï{ÕÇ÷)] ìé e]jË-ë¿Â4DÙìÌ=TÂ-J××gßk#èÞÌXüú%#É6¥Gðùà“Â÷WÔ?c(ãPù-:ãèÊ}†ú¶ ÊeO$¾Iáý½‘ô,ß×&¶)”.…ùU²Ê.êìÂ_¢Û'ñº´7pŸ.m`DOÉ,e(±à\w;cR‡aû“¾ZïQg÷‚æÚ¼í ö¤:”袶2ÑA<;Ký1ƒ‹ž¸ð,ñŽèJè­[dSê0J]G)ûÛ®íQëÍŽƒÒgå˜Ø;}gÇÁFÊÞ ô—8üGx¿‡—Ùì›Z¢ûÀ‘üÇþ·UM]ÔèÙƒÚ‰õ¬M •AØ–Z•²<ä|#ÉL~°__#§2êQÿa>}t†y8p–ɺë;€|¦}§(qü–¤ÇŒ uàiŸ¥,ó“‚»Lm#Ç-ÿShd–´)}iëL‡"¿JÉ^'s+’§Ê ò³Ô4Æ+Ic…1•IbÜ ïçŠ(¼ß¤Î£ö}àär )üŽÓ±ú‘ÈÄ|¶F²íÉ£K”ûŠÁØ)bÍgjßA&‘ѧ}yÊKÓ¤øÖòOò›²6¶…u…—Au•¬›7- ëJ­ËÝ[•ɺ ’Ñ´ûó}¾(Qÿqá•ÉÉÉ÷ë.ÛVC:9ïÕ|Þ…ß9 ü(͸"Îã ž‘pDäñ± q2ùlÀ<á|Ýõ…Ï6Žž®pŸú³«Û'®ç™ìMÌeþæòù_Ýõ+YÕ•¯¹ð |à‡û Û— ˜'¯š½ç®¶îúÀ† Ès“øPÁñùM ²Ô [Š<7 €O™=b0<î«»€òÈè3u—l}(99ûž° |®î*q¿ ¿žHöKÈãß.|099ùtݰ­ø?è(ÇPZÅIEND®B`‚ FRAM ¦Ô IHDRÔ<ßGK7pIDATxÚíˆ]GÇ_¤1²RR ÛJ$l(”èÖ²"‰µ¥ðZûG!VÖB¨H_ ¥Áü³­„Dkáµ FB1C¤R|)B«ˆBl(Š›Bh\ZšÖÄbÌKµ·Ö¬bš˜*çôžóî¹³3÷Þ}?öîï†÷ÞÌܹóóÌ™Ÿ¯V°4!¢Ï®îÌIg&«ŽK ×nî•v5ḛ́ç6Zuü}D{“ÚüÝs“NÕ,%pmåˆ33žÝjiw/:s ê8‚Zí#UG`1Áš`ÕqXЬZµê9ùzÈ™ ÷SòõMù|W¾ße:×zÕé`³Ù™×\;¹ÕØ 9sЙ­Î\vnUGr¥³¢:T™2™ôìntf„GVîç7«Žãæ3çsÜÿéÌ#òý¯Î¬sæ˜v;&ëXÕ ±„êÌ<ž]±•{c¾a.G$/êò}Ø™Ü.«Ž×bA¦uopæÏÎt”~§¨þ«–t´5±ÿdÕq] üX-õDgÆv9³i1Ô™kªŽÀs—oá*åŒ4æ Μwß¹‚yÞ®c73ÒÊEÖ9> ¿"pi}Û¥ÛæÁÛ÷S’Ï<2ý¬3ÇœÝÝÎn¿ æ Î<íì~å>Ÿsî¯:]µ@ñqñrqåÂH--°¢úéZRŸÎë^㋵¤~qÚ^2Óãï;óS›gËI7·‰óÎ\”ë1ñw‹û`…ŠÛ ̹ÏOHÞüÐ=wµê´,P~±¢µÁX±Lú‡3_w†;õ./þ"nwÕ’À÷œùVÕqP~°bÊ2ãig>pæAgXɽÁxû“3÷p§Ê2½ê8¯"#Tî”ÑѹÀ:ßIY,½øÏ@4¨ºÙYGmùë¨ân×RýrØ/ë¯Ê4k¢‹ MÁª)_Ý,²Õ® ‹ûzQдž±òvÑ™KzÖM{Io2‘üØ%é­K¾p~ÌêÔ¾?r7ypÕ™ûM>)- ³êô-`>Æ8ªíKÌmÎì·;«ŽwéÕY›áÐ,•—3"³‡e´Z÷Ü·Vž%…˰Ÿt+xD¨¯5¿'¥Þ2‚ü!)¤®§)ÝÙ:ºÔA·™4p훡tÛ5Òp6Kƒ9G‘)SãW;èNõˆ‚äwZ¾ÚÀÙ¼J‘ux‚G¥Óдi:eji`þ°p;ã) “73b?AÞzy@XN9iÜNTÖ óø*ÍE;V®Kÿ“üZÛûÛž–Qpf¥JI›ªž±m¤iìWËç:JFWl§*ÚÕ…þ:Ú‹dZ½ÀHX«$cÇÞ¸)°¾ï0á±f>^UþâµV;:I{S OÉ^’ެÙeØ *¥æ³³?íÌÙˆÛ°„}Ñ„3°U:€L{çòÊÙÔ&~/ØÎTìGLyŒ‹;wÌ{•¦>çψԣ«Röþ±=òañ;T›6oÆ5+ÏøÇ7:•0ðžºép'{­˜ž ãДᦿœ×·i¾P²Õ^a-ñ>g~©B«‡w4)g”êçs$Œ£‘<•†Â›´¬D*QgHâs.' VbTT†y3,å°Wë{•Pªp±²5Es;K™rú[aí7yX¸-ûg™wšNµÒч¤›Í‚쪥Tiaxd·×¸2ùv™R93Š“º:Ô] æÏ-7ŽÿE‰ÛC”%lPV©ŠRö»&'Óâï&ZËF Š$þbŽû÷%sn3v«=?M/³G¤¶‹ G;âèy”* Nà u“òž¾v&í#­ùtIò}4ð<Åâ\òý Ê¥RÎ:ª‰ÿ7J× ß!~«¼ç¥Úí@:¡œ:Ãéè(M”Ý`Uä·*{~¢JüöuŠÒéç”*\Û$™©À3¿ÕvW"üɘ_O NRx¹`¸/èèƒÒ)J®o<¡£ ê=ôà»v§ŒÊûU6í2ö[œÙC¼¼ÐöN}šÑÑp(é,[òZ%ÑóÇõô¢øÙ“žÊD¢À(5”¶H8*8_–ìºrW¸óNǽ·!É˜ÃÆ®a¤4øKTrMÕ”I¬Q玞晶¼Ž#(\¤r>N]©0›Ñ5—qã®-*ÊVÚ‚xð{ÚLÞ´o(_¦BnÒ/Éw_¡–w䢈X¡¬Ò4›÷~Ïo?—THn’<˜—°$3KBY…ëk^þjyÖ=AmOwM›0r7ž”cK­$Î¶õ9~†äóñ«Çxìf³ã-FOm$'ªp¶ÈŒ6%Ýý¼¦döU?Oâñh‰<âw¾gòæÎ€ŸÕR~œÓ&Ž\‡7ËwV@o4ÏƳe{’²´LüÆ=ÿºË7¦$k|{aòÚ«®ßë®õÑHÜê²[CžgÅëãgm¨Ý絟À{ìøÜ¥œ0”#–-RJh=é"eµáI›Ñ”Lû1oIek·…§& L+_×눰¢S¾æ7kçhîŽfÁ;†Cq5ÂÀVìN%£œð|@Nö]¡uTT³æu­P} ´Ãº¾×21a–ÉQþ:jîÔ~Ài¿%Ù¡ôèÓ¦ìèàœ[aœò~7m ¼oŽ2 ïÕwï¡øšÖ‡NÛ£œQjNºK JJ:S– 'Ì{yúzØøÉ䣖©|êlɰ{jóÁÄ£#l»’4Nç<Ïi¼ê¥‘×1¯xíŒÝÛçwÈ{õY-ƒÙÈ»ü:R7qNÕKœ¬ (Z¨ç„Uºžô“JoJ’‹ÉÏížó7œùcÁAwžÂáCÍÿu†…?QKnÜáMN?®%ëßñÞy·ùy,§WjÉÕx·ˆpêÇ‘—7v|YÄ#æ÷·ù®3¯¹8¬ª%»9ON„ý¤3»öy£¹íµÀ¡|éUð›t„x_ò†ß÷ø;ïÌ=Zî’ÿ| ûMgw±Ö%”ŒÆT±ÐøTÙgmñóÿ¼ƒrÖQÅÿ+Æo?vdrùÿÍ™¯Ô’ú¿Á™I#¸xç1_Ž`¯¬Ót¼á…µÝ™_DÞcoº:æåÍ!gþPK.xŠ’YäÙ†ÎðnþÿÈ£\¦×ÅU¢ÞÊs¤d½÷ß5¹âRòå÷Î|əРÍn½€ƒËTòïóµ¤ÞUzQ€{?ï¹ÅX=!éÙ.»}œâJ2_ŠðQgž4ׄþº–ÈÿËÆßKn@qeû®yVyºdü¹Î“Ÿ¬èôýP²¶úåZ"·Îûµ°”c5…Ò‘”]'ýœÕˆŒ½jÂ!ÍvXðFÊîŠ *4œ˜Äë&‰V×!\§yî”ÿ!-.3uMéVòyM±ª¶q›£¡‰]Ë·<ß¡ËrmRdÕh™ûå÷~J7½§ã·Ë¸l4É™ È† nóƒJ®£š-ò›†ŽÚýé?Ý@´ÍØ] ì¨L7±Ø‘l£¨^P:Ò‹M >ï̳4wDÅõ€w¿,ßõøPæ¹ñDëpAÞhZ8«½®O;uÏÂÈÔQÏÍN_/È<¸÷Ü)ï;Ké)Ë Ì<‘™ôìuvÏnpb™É;ìí2Ññ·ÑØi›Ì;gž‰‹)Ý•Ìeó‚„Râß–8LÚ¶x‡º÷e&cÙ! l\¾ë1™š{˜ž3òdÉ05C[XבB¬S¤·ã”=¥Â¸ì¨ *±!‰’©fÝ<ó-OðLÛwˆÝHÙŠFéTfß×Q)®h°Ðõf4©‡ŽGÂÐõ¡®wÄR:åÉŸcðG(]‹Û_Ö\D]ìV5B26å6k~¯¿ ïÙ¶÷œ–Uì(ÓSFnd¡tÇð¨|?Lé™o­ÿ¡'*cõº]¢îjø7ÜSªÈÅÒ,ñ¸‘ÚÉä õ~BÉ’nJ²à>ʲÇ{®J#…§fÛº"v­@q] *5ÎþG¦žøK=›¥­°›î•à6s;e•;.cÝÜ4§½‰ŸÜ¼/+ç–”“ Ê.jï ø-µ‰RMzª!jÂ¥ì&gJ<£‚+¯CÕµm ™uàïP¶xö::iÞŠFƒ¿a(X©) h˜8Oyö-Z Q@iÕ³~áã¿Õmƒ7Âp,æf~kûš–ß ù½É{NËŠ¤,®e#n=µ§€`m›öÝx°×¸—éP'ö™6Iù£Ðzì]”Œ²ÎÅâ9(Q~GËÇØ¿âÌq“îXÇYØ)Q²SœÑë2¹ó MÏjùzö:Šæ)ógK¤iMÀŽ;Ý×)íPOPx$¬ÄDZŸ—Ô-u=CÉ¿½pC=#¿Û‘N(´Ã—…Ò.ÊN1©]_ïD¥ô®É²£Šu¨æ7_¸`w2Ï8ssÁ;~&~yÊX¯àÒ«û˜gF¨à`tóL+µvÎS4ÚZä÷õâwÉ]vMK”ž«%ɧÒå!åÛ<4GÈS2 |X¾s={5ðœ–Õ%iO·–¸•:~@É MI_h3Ïf‰[Âßð쨨üìÊ,åoh3¿g#a4½<`¿[$ož5í»][ ÈûOTiKÓÏÌ·®¼Géf§34Wj˜zÂuI;ßmbÏéÁZÎÊî2f;¾%ì7ÖÍ_¿}PàÖ»@ùžå^–H‡0-6våܤä_ݳãîaZ€Ë³)åQÈ3~W›ÎÑŸº¾iðº\ꜛø¿@Ù5aeg­b"ª µP‡º× (ÊÎ^Œæ¼g 7À 0F¥Þ³À^#åY8k@‘s¬”*+û=ûW¥Óü íøí”•róÎWJ/ `¶‰ý»­;(Ý7qo/*¥·)…Ú×>ÊÇ .ÉxåÓ¶é¡ô2ÝùÚ´Ü1ñ™¡ì-OŸï+x†ëJLiðåé½b·OdÊ‘À3¶žøÇü%sONœØßA s†²ް3&%¬‰˜Œ¤KËJ5ÁÓ±ÊIé}»vsE%×JQÉŸ¡D›=îÙ½kðÆÏH‘ñ7D©öܤô°ö¢˜æ sóޱËëP¹\ ä!Qü¬òæ2e±X¡ì1qònI’<¼Ýüî\a‹G0göºÎÆ£‡™Hmï\Þ¼nç>¸Ž„¦l5Žö¨Ç&¯SP?û¼g¹C¿BéEÑ™’À{¹cõ¯ÊSìâ2—jP:{óXŽÿ¢5â“{.›7bi#O©éEÖPz«›Ê.ۘϑçëVœ6Ž+“‘•ß_Úçt±Fû"¥.ðz‡j^±?Ÿ^#Ï­:þ}ÊnÔ¡Cñ¡u+nTg<;ÍðȃµÚ‡% êŸ÷R‹ J7е ¹Õ¸·(~¦o§Ø­–0®Rø:CîtCÝP$6= "Iט˜6}z‹ŸßxvmDP~(tÍoí0ìò‰®Å·)Ý£Àq¹då å(v‘øhXª(pÇssѳý†Dù4ÌëÐMCK?<µû™€ýÛš¾H˜™µéÒv°‡Ò«S9þº ëäJîPõ†¢E1²êSšÖxB„yL¢-é†L8MËôŸH¦þ"n™)_cÏÓ¢h.Ëâ_GL§ÃõàÆ~Äú¦ŽèßÅéïÎè«Ç8´ú¯”L%6Åè±w(ù•ÒKÒ™…–ü]¨G¤Õu=¦£ØŠÝù=”ó>Î û—t-I/ËTzé:%{Oê”QÂ¥ÿ䢻¼õèÐý‘gêy²xPj$}]õ&o–Mj™…öÝ”þï_fÃeo¸áʺ¬/sm?vŽQÿ,ݵ¢pè¤lºC¹¢¼ñ7€¨¦m¯§ÔNäyé`v‰Vß³Fþç#J§øÆ¥=”}„„$ɮԀ_Þm:%y³»[Eƒ’µ\ïxÔ»¾›0ª‚Ì”6eï#fîí!ܦ´Ó:-⿊ËJÎŽP:a5e Ûz ¹`ògÉ®‰öéDü3¯œ?=Ë­š^F^8™õSBÞ”¶´­Ç{UDщ– T°3†æ±F úG¥wùÊ#S²¥îO,<×T@iøBÿ'œù]ÕK†GzX¡ÈšéŽÞCæðæž`‹IEND®B`‚ FRAM ¦Ô IHDRÔ<ßGK7IDATxÚí„¥×Çw+cÖÔ2†—ü3 ±»VV¸TYa…®¡ª·¥ººÊ(#KToCXÕùgm-•«„Õ¨M—‘•Û²6F+Óèv#mìMþéº.+1Užž'÷yîû¼çžó¾ïýùÞ;óýp̼ç=ïyÏyÎ9Ïs~¾÷È³ÕØ•Â)ý­€_Ź ÎÕ»á܉²Ó9‹ˆüZÔ¡^vzF˜/ÔP:ÒiE]Ó«Œ{¬éþ'œ«Š!Øu®YvZgiðu‘cã U©4|L ‡«†OIk:7Wvz@šÇÊN@ ü5äyôèÑ÷eºòÎ}͹¿³õ‚ýÙ…û¼ì L3N>¿#ú±sßsîç~wÑ…{XvZûà?Îý1tC”ÚçþëÜC—¯{<Ûáþ?ïÜWœk³LÊÎ@89<áþ,;÷©“Á'îzÕý¿äÜ=–׌թÀÉìoNŽ—Ý¿ Î}Õýàä(#pnWŸ¸¼}êù©«ËN#0èhÔ󻮣×òÜjÙé³lN ;J­îW=ÙVyÏ„å²J§äeCòÁ£†ó&_‰6f!#Ñ’sÏIù7¼2>/òÑ Š?Âb—‡YÀÉéOε»ieæþݹ«e§¯|p=Ù”º°,~×uF(£½UõêÌpe‘F9°QÅØ£È¥PW»(÷î:÷)¼]óÌš –<׎oòþ VCÄÛ5¨2b³÷Ô ¶½NÌT® IGŠBÓ¾jhM~ØÝáQ„gPê¹ñK=z[òß™-ɽš‘Í¿M5¦0§²”ß~Üÿ "Dz3þK"×+e§9'?KRZÔËmSO² jJ_˜8+ý§è¢=YÓÃ=‘~ݹŠðkû]÷´Àvå}º¶ªŽÇÖ‘EòsZÜë¶s! 6¦Äïç¾G jƒ¼Qª‘ñ}‘1»/äïæ4ž¬•×È?pî%iàgå>7ø 4£ëÉRWŽËÿ‹ûœ¿mQ„œ[ „©I'ƒ ê~†ÂÜ…QMYÔÕ°Šþ©‰·M¸5‘é…²Óœ‘—Uc,ëRoåÞ²¸š§“BõÍ¢qrݺD8eG*Ðgæúj¨¡‰P7)½Ã”DÈçᛶм{UJF¤Mÿ}ÔÇ´oY†Á½w>â’©¸GbÓÃõaÅ—ƒÀ›òvüz,éÔ:R¥ŒÉï^VXó¾÷œû…8ŸóG ¦0bʇÙòüR :=¥Ô—²•4òîî(uÀüéZíõ1ËqÁ(eÎÓ)£„.Â×Mc¬åÄ=” ¸AÝ ^£t̤{Ý»gk[ ÇÍGN ZFä'¨D)½ŽºW$=¢”ìôWÅÔÉËÈ J;û£e¥3ÇÏÔ)2{“ÕžñtÃRx¢°|xOù¬ð#’GEôICë«ä·­í„::ö»åÜ[öÒh妴œû•”ÛX¦ÉÉl’k~篥žœ2ò»"÷øí^ô’ÒÌyߥ7°eÕ.¯ëROtö@÷Á¼8©²™ ¨ÓcÙ ø¯ˆ@^1~º1Ĭ ½ÆNüj”ì»IëV±AéQ*¿£ï5Sû|àˆ¡§$\sR¹ÑÛ^µvVÚdF!rOg‹rÖô†Ub0¨”t4BráÆ±çùU(1<Û½Nr VgøžÝí›·Îß°²¡ŽcÙð Ãvγ¹ç¥nTc²¡Îˆ¦f®µ¬˜…È3™³7æùÌ‘’Ä£m7KYrš¹¨’Ù¨ƒ’édÝ™Ý?Ö?ßVÝxÎv &~>™’NeÕÈêsJ¦^m¹VŠ´Š,eÉóÌ«r]3ï¶ïže‘2–i¤,º»}ý°^\¡Ù8î`¬9,ˆQæÿœQ vw[O¤dêCydþ¿eâaÃz5òã4÷´²qd<2§?um×_Ê”gð8üg‘{:jmQÚ qü £°*ñw°Œë~…Ï‘K#Ð5­wIC$]ÜèOÓš˜<<%›»T`D»düæDaå­1TeFÉÈŠ7dœµJNêÿÛç9ïíHYmåÔ‰ªQtoDÚ(¯Ág¿²í™â먧ßãâ—ê<æ¼CÛÔ "WÖsæþ%»JÏÿ¹"õÞ¤sb;ÿ)é,¿,שýdfõÈÌ’Qg¯ê—Z ÞµCeF¥¹}s]ÏË3E#”îð‰‚µŒ8NÖ³–JéÑz%ðü¡3¨‹¢,žM„´ãùw ñ;.nM `Iþ_‘û\ùvŒàýBéH_•"=­‚ùÓʳåùo‰¿5Úu`fݯô‘wìÆy†ÓøWˆŠ}Ɉr¦æ È x·±yaŸÿÆoɼ Æaò«®aâ<9@|J¿É[îR§púÚLEÉL ?kϼ¶ä¯ÝùùV }—pþ¦©¢u¢fÂòÿ«Þ=†7/ýˆdgp$ž÷$lhUYöüYÁÙ´¦»Ž•wåÙ;&Œ=>çË"XGïèÒOöQÖlç=?]æZ—kI¯iºùxzáúb×8„Ú˜ø7ÌuO›<£ïÝ£Þåîøé>ÈósF¾:HŠÎdüµ–²‰­4\†ÿB½ë¤jW<ÿfL°ÞCå¢qöÄKéÇ 5´ñ†ß¹k®ZöOà~…:»¢Cy«“ÙKk©Ã( ÓøìTL©3bR.³Ž[5që‘ v­7eɃ¼¥‚i¦£ÖYQrô€Ï¿ÚŸZÆv4Ò`%)+ ÿFäÝ‹¢èXÉÞ )DêtlÅî›x¸¾w7©d›ÁÈíXQbLŸ3~¿?Ù«ïR>Ô1`÷búcTPo‡ðžþÐÍ¡ã%œ} ¯ónôï˜w0±Á¿¹èK½‘‘æ:%ë¨Áå-JFŸ¬ï¹óu:Çí,ùf´ÃÜ4HLÖ¥ì­@Øf^Å¥ôô“îNlS²ó,´þ–¥ » ‹ú\G¥ÀÆñ÷7Vi¾ú©Ólî/¨â Ü«QÁµTb”ªJ:"Sn€;ç™7[ˆ©GFú³Î¤6cï4aúN“÷þsÆ¿gmš’ÎÚ›FLhß‚­ªÙ8ê¦mOw²Ú“„mx ó¸wŸÓÁ¢5§ê†¼eõGjxÔ°tË)CÆw)²Ö'ùJíÐî·,(ï–ÈŒËI7q^‹<«3l=ÿË~Þ%îËæZ§½C†ŽÙм“ËöSö×2Âñý‡â¸ƒrVòËõç¦W«YG Ä­Ï:ƒª_ò®CÛF°vº´!ŠÃNí*¼u›·û¯f¤¡™Q0:½Æ=îÜ©&ó\pã …7Vqoz‹’-ðEׇ4Ý¡i»cöbäy®ˆ<+9ïHiPø£ºnÕ§é ­õ±pÑU¶Þ½¯›öÕΉ¿FTl·oŸéfŸBI‡¸%uWÛƒ]‰Ô\%Ic<Ì“ÆOÏj%#ËèY茸y}O—¦tdÚ¢dÓÏX¿ÊãâÙmò6#Qoç=XÉì¼ãisûé¨ÐˆÖ(©sê¢Ä· ³Ó›‘zREÚf©¨Ì/ËNK´Öb•Ñ w;Çp,FžÓÑÚÌOW˜Fgdlt¥rµgèŽCÀn’iÖkâÿ|ÙùŒä]7BÅ>ªP%Üï&/U’zqe|JÒÈ­Èÿ:¥×­îÀRzÓÔ²ŸêLçízÏ„Œ@!%)íç1|Ü)ÓCWL¸“}ȃ;¯R/ìÿêLoŽý“$?>`®ïRög[µ®Tñ0OžáYŒÝ<¹XƒJC~Œž:#ï)½ÑÊÿY?­=gž3Ò6TºfšÐèjDiÕé¼s9ḗwÛóÓOom¿ŸQï6þa”Ø´@Þ_Ê·ËPüì9K¥% v>/ ÓŒ”s] ¢~ÐaÅܯ _wA˜:Ó*b ¦KëøÐ I:BÝ5GïÞŠ¿Šç_hýÔtZìÂt÷*;Í<ðhÅ=û”üecý}*éÃëRæúcœ÷OrÂ[}R“ö§r<y¦ö êÐÇ…(™Î&-SJFÞª7C§B³€u?,˜b¤°ózpºX¯=å5iûZ)YïQ…¸9*¥8 ˆBË\?õÂëæÿ¸Ã1J¾xs z”üLžå²gPë¾¼Ä85¥£¡?^^£ }}€|ò¯´ü˜Ò£6<+uAê½ýJZ5àúg${ÂRòA•ÍùÕJÏôðŽãµœð»bLýNiáÍBqWG-WiúKDMJ> <­@‘=/4Â¥ 0Pgš©E½¼& Q¬ö°Ü×<(Ù\`GÜ`²vUòNígнá`@É/±¸ãÝ«Sú˜Gßë~Ó€7ú`x9ä%íDäQh“‰Œ©;R5¤ìµC¢mëÉŒðökZË”|rp¹ø['žÇeÑ—©þ@͹q¨l¦ö7aÁPú77¥ KùËi&øSv³„Ô“gþ+^‡¤êXg)û¥?ûx“ ë¢díÕÊbf–‰ÆåX^ëÊLɈ’ß6®“9­@f™¬@'¦¹ã˜(çÜä´#†Q•$/\>V‚"닳Œ#`äÈtØÌ¯!‹a=ëšÓ øµ#0+;€|Ž=zkøXÊÇå£=|, †Œè~ïÜÇe§@œÿ“ßF ÝÎ¥IEND®B`‚ FRAM ¦Ô IHDRÔ<ßGK7¬IDATxÚí]h\ÇÇåáb0*a- Á ÁÁM1, ƒè)¸’m `*" "J—>™ø!~ )†P(„¤!`šæij’І*‘´¤x „¨±kp“š>œÎÑž£{îÙ™{ï®vuWòÿ—Ýû5sæÌ™™3;5ㄈ.‡£Ž[áhºsp\G;'ëŽ+˜ D_øØð:Ì‘º#PlÃÇ¿w„päÈ£&|>||;? ÇŸÃñßpþµºã êE*ÑwÃñ)ÿ¶: Oé‰0ºã`ò9P=Té=þ/ô>Ñóv\wáyš°cáã©^/õr|®y®îô›öVø¸_~þ%¤ù÷uÇiÒˆé Èd4>Âñ­pü!È꫺ã& Ñ‘áøÁTÏæü'¿›êy·ëŽß¡'dÀo¤ÇXiüŠ+‡p¬Hos&q ùgÊê\8–äÜÃÖKå±a‘KCljÃç:õ³ŽÇSò«ðž¶<§]wšG(»"áÓl$T®uÇs éf]Y¨p—ípÜ ÇÅp¬Š¬F¹Hšçkxçß!:ò”è‰çc¹æ˜\×Öþ‡L¹&ß_–ßs‰kRh¹ðv#Õ’V‘½g—È{I&/iÅr(25¤ã¨©èºò+Ó7T¶"ËMiLÜ‘ŠbàôÇ*Ôƒ.G£2È9.ü×äsn˜çObÐ8×Lº?}y,¹ëgMeÊÇ]W_ÑJõ V®Ò•ïœÏ±Ö>ÄcÕÛ³º±.ÖXüDGLeÚVû"òT{û¤Øáu Ÿ¨´8‚ŸNJ׶M¡m™ð“dza‘û:æ>ÛK“ F¹.™:ñ­%›æ”ÑrFò_á¸ilœ dz¶â".š/ Öôòð™ódzû©F˜‹sÅäÇÄ÷&$žg$þ<ËýMIÇ'ržuê%Ñ•oä Ûp0ze+S5˜¹²&el~ÒË“¤ë|8ž7ef[â3f?ö!>JfLX-^ ʶ’$cЖ"×[¥Þ²Ší®ã–䪑ï@½ S$®.4ß-yÖª3`$Fýj ²ÞwÁùŽÑ–·zO&bÉê±ùÝ2:qGòû¡È}3îZë}x˜zž¤®5˜d¼CÔs?)²Y¤ é}°þÅò'üþXÒò…üž•ë~èÊÛ¾õR¥²ùÒü渼<Æ÷Í›ï ɳ3’~nxÙF×E‘‘êÀzD¦›r®I w9e•ê¶¹vÆ]³«Ã$ò=‰y»à< sÝ…ub™`Â7|åAZÀæþX£e Ì_ L€çŒrªküx8NÉ9…ìD”ºm B»ä=Êæ€ñëúgK>iœ:r ‡ý¸à9Ü+º+Ÿm9ÎÊç¾çC‘¥¬BåÊÿºT–ÚÇ“Åð1W]xÛÄs±äšÎŽ _ssÕç2õ«p¼`Ë´9?CûÐè Þ˜wSdq>–?’Ö» d°aî›.Ræ‘ÑžñU“æÒ˜Þ»aõÄèÈ×bßHÜgí çóesŽLøLÁ»[”u –#6LáñÖ'ä… óC‰)pç"çNɹ† ×—[X/FvÕ÷º<¿k¶‹ Yª@HY–s›”õN›egdh[íÄ5›F©YÙ¬;¼A' QA££àžVÄ@Í{9‡ï¯ùÆÆ\>Ç Jôb¨7+{ùiúË£|/µ9§FV[Ø-“gÏêûåsnØxÄO'G½—8IâwÒ…«>lTÐ •AÎXÊ9k0›‘{Ï‘ë}¸{7L:ÎM‰?oìò‚ËŸ‡åûo©7^\ªó&½cë¥RÖ|B^µ"á òûÌžRÛgíFÛØ[Ï´c¢·\™¯$/ê¹-© õùd[wh'¿ J­¯4¹µÅ­¯˜ï½c •-€'ä“ë=1ÌìJ:+ak¦à¾M×H*ƒRt\x2ÓŒA«dìŨþ‚²ÙËîY‘x])¸¦An’;¯çJ ú ƒâ.A•¥m­7ù³yƪï,‰Ê¢MyWÇiàYš:cÇQ½1š‘ôž¤¼wA A¥aÕ«ðyZÒÃåé>w —…Ï÷wåü©ˆ¼ÕXê„7–”÷•Lc|yVX>Ñ3„ÃõϘ{¹òCEËbkZ‘{gĆäÊ}â=öÚ±T¨FÖ¬'WåûªœãÆÑµŠÏa™?áÂøyÝÄõ¬ Û‘gô•í‚x/{9Rɰ‰{F'¦'rŽ$yhîZêºCõüï}~ÿÜ!snž".¢Šïã©ËB¸R}ÀßÍàȽz®²;GîÙHÄ£i 7e“?”1¦ ïèT)À”¯@áÓ‚±V¡p ¤¬”®PoE®ÕøùF SºT£B\N™øoPÞÓÀ•Ò03˜w zäœêÌvâÞeˆ®‰Û’wN‹êPÞ=Kò<«W-‘«wÒ ŸŸsçZUuÂéÕ% fIz”Xeì—TTr•S¯1{ÃܧC5\qhCDu+•?цtâÚF¦ãì¡vLš¶(kþ“œ÷ÉÈÓÀ6‡pÿ0úf'’iúû5Mk‘¸ì–m*nt5(Qùº¼-C7×Å*T~þ"ecô§ öóPA½É š¹§$ìhÌ0¸ûT©š4Â^…= ¯T°Ü=Ÿ°¢ñŸ‘ßÜz¾NCLp2I)+ð,kî qKîmw®MùI«Âû* Sì ßå„\ôÚËîÚ‘(c\Fº^pX¡¼^]¿§(19,ò\ëFf㯽–s­æ«7”[r¤z%V'X[Ô_ñî¸bÃñkJ ;TÑyþFä>7[rF²j/ì™ t©R¦Í5›Rng ®µk¸ÇÚ;¢þ‰yjG½ü5þ\ޏ‘>mÊëΪå WglO›ûUGç"qÐç¬踮ËVÙÏ9[`;H…K€(>Ö®aLØ¢IßÄÏ)FÐêºØÍ¤‚{Tˆ}”K¦ü’œëŒ²e$sTÜ«Pb㨅…Ï]¯ã„—#çøýËæwßæüÈϲ¸FG“%?i«E.á„ì©Pí´ø™”Å m™ßAd^)#Z¦3)='7'r^Ÿ»”¿eÂNKئ c×ç~:ñ«:ñ„+[ä¼áÍ>xHå-g0­{[‡gØ7xW¬õW×ÉTòY—øx÷®Î±¸\%\\Þ×8QVIs”z½¸uÊ\÷•ËÇ0Po3ŒtB^·{¯¤‘+ß]87¾|#†mæEó{VmB"mÊ{VæD/ŽËù£ò[z,#^ƒ|Ì=§%60iÃä:µ=±¡?lÈyñÙÔ½en_í¡j=\pOÇTV»ë2åÝ"žÅÇ­4u¯®QÅ-÷+IW“ƒõd*P‰³$Š¥á•ÆŠ¤P¿%ÏÐBÖ¦¬UÏcuÜ;åÖ~_ejžÓ¦H)qmeƒA®‚¦øøiƒ2ãí×3–¼º© 3EËj^*B½öØûŒAÓŠ`M ÎG%ï±³MýÃ\ž^¢¼Áì¸<´e56ÙLžÖH6m|M8ǹ¬±Ñ’{/EÎåÊ$U¯POQæž×Ù¦[Nœv®€F>†žsÔ|?&ÏÖÉH:±ìLâÞ膱pê- ºcôDeù´ƒ“µ–Q¾ïÅwZSù¼ŽÇJò-:[Øä¿×•¾r'á¬ãµÏ¤ßw¨·“‰°Ô_ß-¹Çº bÓ¨ÕµÇ-.äÓ¥<ë¢üÉõ‘‘ð[S¡´[Sw]ÒŠsúÑq£*¾Ë¯÷òp¥½HÕÇ9 •1¥Ä‘ë´Ä*T»›ÜýŸù’÷ 5ÃwTP¢×nÒ:¹':Pá]ɾœ/Zöµ®z ¿JÞÕ"7öEÙøª<ùenìz=õ>ÌHv©|Œ_ó"&s.“ïDò§ª×©!éçN€ÝO+ Nëw¬PÍß‚÷¶)ÛFu7}áóCJ¸Á©ØKÓW}ö%“7\I>X7Õݼ1²i˱ 2ÛÙ5‰Ò[À^=Š­{ÖÞ2Q¾K‡ê÷=Y¡êÔy-”ÌJ…û8Ã….sµLæ®PæöÝiUF®eR´‚L¼¯È­Ù‰(ŠʶâZ•ø TåuÇ5Åp¶i€Y‘¢ˆ:þ0Š U ›u.S~ý)7%/^u÷kcc®àÜû~sYƒ„Îp>Ä&¥õ-à=Z ÄŒdRGCøkáøJî½Më¿Ý}š‡¶QÄzò3g0‹ÊSKË· g×ÉB…*Eg‰øv2ÿž×%#ËUô1p[ž¯•Û£"7,ÇcMó†ó/HVa”¤S·9½x³ì‰(º¶ž±}‡ r;PĽ0â÷§l¿Ú™Èù\¦¬‚¬:!b· FÎu¨d9Œ\³5U”퀲g—¯(v×üŽ64¨çJdÚ.\ÿ]Š‹&œ+¤Ê`µ»„•@jRZ²R¬ðžfLöÔÛ†Žù~â>ÎWnté®MU—æìV¨ƲEÙÞ­©qR퉾bÂ~jʼŸá›2’e*Ëü’ ›ýòXh>ðÌ•© L£ü®O»ÛJR¾Wÿ>•xÛ*¾³Iýt%]Ê6~âYÊK¦Ï[‰œS2¯½å†îvIÜTqþE…t²}x\žÅe{AâÊ鼒ЋXYàø¬Uó!ƒ² 3$­uÏÓ„q䱓J;•T¨ßPA«•zîÙÛTó6lb$Ž&ÎU­P×(îîÉå¢7>”ÍW^¤üŽ4Zðjo‰z™PI/TÎ =~Jf,ܼë©1¤+g,‡•5õz£l¤ß=X5Ïî›á["ÏÉ1×ÇÅØóÄv%¾Iý“”r 4뛲1c¥#ϹàäE£4ì”ÿ笱åf1YòºÞèä.±ÅvIYi~“ë¥î1³Ô?lõeÞ•¾¾‘gt÷MІóïZP·t«âý}Æ4üþÄ*e ù[¶‚¨;ý&¾© µoVf䚆/`T\¡vcò•Æ+7D^!ÓÖ¸IVMŠO¬‰¥U×Ö ³ 1¿w×MÊ¡3u™qî$´HYh(CE½^âç× Ê6ZÙªh$µ¢²K.NS…+;»þ”×]Ž|¿m©xžôüÕ|É»©·Ç0sV~kO2µ´°iâðŒ„ÍRÖ«Ù¼ÊÖë¶ËìÂÏlÈ3¹r=O3|Ý}jKïí u’™waOJAiR‰ËŒ²t6DºÖôCS)kXGŒ‹n˜~¾î´W”Oi¡¡øø©òØø_aA¥£\¬Û²¨Becq·¬A@n:åÇüf)Û!i¬êõ€—÷j0%ÝÚÃîR¶wn• Iün»üj>v­)[g©Bãwr9Fù‰|èò•m±Qè®4nR6Š]èeã§Ì ¦bíJ9;ÈKë&:.íuÅwZÔî Bd¨÷O–²ÞÅmÊïò¢ÿëgÇ'¢G>&y±b{.ò¢}?/Ðý{ÏÓŸÜv’zîô»”_ÓÈ×ÛµÉ o0hÀY©cLÛPcPÏýºÓ•ʨ“0’ÍȽ]ªèí¨Q. Ê&iiþdè&<çK’ Y(k°_*¸žß­{!s¼Jc}Idh— §ÌƒeÇeÓäË*S6˜ç¤5ø¼1šßËqÒ3¥DÉÍÆä6.ºkšDÑÿÉŒÔ}”ÃÅ·­j$¹m8YÌ[±ïSšgFÙ Ϻn¾ëì÷¢Ù·C-˪êõø×¤ñ5+¶TçRä:#‰†—V¨cõN€r/UŒÃ`z"ÖêßdAvekõ~AÕ&öð'•ççÈMh2FÒþ×ñ|ÂHNü³rÂa[©ÕC/˪Êÿ…Þ"eÿ‡º¹6¶Ö¸A{øÇÀ=õǸ–7et¤×¡Fò@õ´ Æ“ñzÝq"î'E?º”giïO€C€ëy0üoO÷íýÉÀ#½´×ð2ñ?GÙ$/žÉþòÞŸº¿©;€Ã‰Œ‘þ(÷KлáøúÈ‘#_Ö70¹Po)Øß‚ž|Uw\`"¡1ï„€}áÿØè@~Rê3LIEND®B`‚ FRAM ¦Ô IHDRÔ<ßGK7«IDATxÚí„ÙÇgþˆ´Ã–ih­»–†šª±±um-ÑQFÿXÓ¥\­›¢DG«\¥»Ö¦K„²z•¥6ÖVˆM—êí±ÕiˆD‰ÜÝš†•X¦V(Oßgîóä<ïyŸó¾ï½sçþ˜|?¼’9ïyÏ{Þç<ç9¿žsîÜ€Jˆèlvu³kuÒy³è tb2ø­FrÒyÓO¦'M£3g'˜Ä0î2é¼€Ù€ “Î `z˜ŸtAF Ùõæüüüͦûhtš¥û¤¿L72Ýû[ý:`f¦A͌إ쟯e×7ùÊŒØõ’¸›Ù?ìú²ý7»>ήfÏ}žx欤û‚ ;¼+¤ùù‡“þþý û>–ÑÓÙõIvýç ~ç~áéÌADôd=»¾"Agßüþ¤ó5-dòYœëÛ%¶N:?Ó@&“'3YÜŸt>À\¿›Yµ% ûzv«rÉî_£rÎ3‹yigWkÒrP†Ç½oâ´E&ì:!a Ùµ2‹ßu[$ÄX©Â^ð —4¸GM£ëHÔ °RÌŸú£AæzÝ|És½È05iˆ6{æŠäë’VH©ä ÏÐYþÊvîΠŒ)O‡DÖ+ñ^“¼äܳ³›x~12˜pâ,È¥£N—gŸŽLB6&_KVFFÇ»rOGãOPXBºUb³šÆ.êØˆóÎr<7&96²ù}”‡¶ùÞBciâZû²bãI:KR¿šôz¢'ZßWDÆSß1;™PÞ¡IÜWá_¥bf•Â(õ”Ó8Ø‘ÕiJ×ͳM}Єñ»þEý^ßß×u³,ý§©Œd¦Æ³k­"®V€v¤Ô sï²(÷’¹Ï#™M¹ƒjLïIE!§AõxW*•7Ý~M¾m¤SŠæ›íUKO¢t :#áÏʽ…q4Tœ¢ä2ìU<Ó#ÖqîYƒÙ®H‡ãÝUƒiÂÉ¥£å¶è‡ïk§Cê“7ºÖrãúÍ6ywâ-YE­*ƒºq÷øMšÿ³ ‡n\©¢ã—Ý;AýŽ×CçžêǃìúS…\6LCÙvÒÑÆ´CÑh?ã%)'¶÷hPcŒ’®%î±pw³Ïw¥‰ü)ZnT/ŠñçFõÕœ~Œ+ƒQ¢0%ÜÆø&Þdž]T‘:<ß•g*G”w@ò”º—z¿äSG¸íÞÕ2a§Ä°vÍ¥†˜;,›QÜ¡º1 9›oXs*¬RÐ¥šé (…K3*ã‘tÈ¢4o‰¾2÷õ×Ïs¹,qØ(/””a»LßÅ`jܸƒ«£MGëÉ߉|FÝYZÙ¨ xZúy§|Hl Ëïx"­¦è-QƒÔxN›Ú47DÏy åt”6‰1¼âÒ5­ƒ”˜Ù ’˜·™Ð+›FCÊ %yÒ2^ÒYÆPR¿Ñ%Ÿ«ÆË_HØJô†Ô;:£qwjê~í:9à÷-H²¿–¿µ>®;q¦³ùÿ·My¿L¡ÁRg«Nâ­XvÑ;Ú&ݤŽDrܶv€úõT>¨?{ÀåwÖNÉ¿\/x$ͨã”ùL@ýµ'’ÛüÝklG‡ïl™²È*œ¸üÍ…ÊäyÕI;e$_vdóÒ\ Fä×y‹óµH%¼Ä;:ª×”îp®‘Yw­¯E¥ïU¸1¼K¡íI¶uõì˜#‹¸£~¿¤üGËè|É÷6(?Ó¶R·Ub’ò2i7°k”ïÄ”êÉ…ò7ð´Ìq çé™^Í4Tˆ\HµFÔßþÁŠÆ½oz!®xªµ<|MüØ€h^åïKæûÏQ}T®O:ï|J*Å] £pöøÕie¹VL%¹Gå®ðɵF~´‚ÙQTAަw+¢ó|]C7Ñ^il ¬AsâvT÷(x0êTîVÉ;šñ{ÊòÝÓ2¿.åËuO=7B%Û¡"È•SÏm RåhâÆF’§öNÝUûÒ©J¬áFïê¦ÂëÔo‘›z£öJâYÇÈQmkR9M'®'‹n¬'ò]ŸQ½>'á:»p©"o*ûIã'Îb—óa§ú+uÛÑ•ž¦Mam>çPùXAÁ]÷1½#×r«§roߎ¤ã9[ðZÄòì¹èžç\ò`®&äôM^ívœ5©x;bè:œ7öÚ£þôŒžpd÷¤ªòÆ{RyÄ\¶'Õ;ø¢PyiÇÇÊ‘òŽ=ŠŒ%…éðc5ÞÅ… ƒÊk””4ïàvº¨ít椙ÚÂBeeC}_"ÔŽîWÉ8Ò‰¹Rj!CIOïø?­È§ê”'sÍë¼×É{@õ;o #èËRo95'wRÛ å\Q~—ÌßÚh?éÄum•»~\Êú!…N×ç½ng†Ÿ{‹ÂžTÝztDþ厣väXngã|‘ÓR41ñã 7êä÷ÀBýé¯cT<ÖìšÏsãñ‡+ð®(¼»>EÎQaZÁ¢x¥k¦NºîÔ™õÓ(ÜæydÇ—Q˜‚ëP‘Wå_oêP+‡gØjå|/bÔŸ=Ó2/]GaöâÍŠ÷<“([;Q]9âäƒy¼OZ¢ü±^?¤tDQ”ß;yÈRj3vNá¿]ÏÔŠ|âS´~Z‘‰rnUÅ­‘–ngЋ“ŽþN&žÉÅ2y%žo8•Eåx-Š«•®…kC™Ë'™[(x-&7”ò§ÐR­t²â=jD¾êÜãåƒûTs¿. îtL–9Ïx,›8ö€‡ØO 5ê°FÒÕ-£UgRwäŠk–Ä€óTäë±(8rÇ|àCBL}RX6<ãt#õM5ÓmPX×5N;šW§¶­è¹d£Ia™étÉ{W¤l´žUz¢SÂÛ—òSßWåýŸ‘ïuÝ’0oĽCÎú©óPk¹ðÀCû°§H*KáôQ5æ—Mü\A ì´ ñãõÓœ¡‘°Ü†sÉSW*ä[£–…yG‹Ê½5µb Û ž§ÄèŠBGŠåc¾ãÓiìÖ–‰md;Uß1.Iuª*Gïá‘ÔîÑ‘”wtbyóéâ0 BÍw[ƒÙ–ºÃºzÂÜWc}“ÂÚð–„yÛ:1’UÇ”.PXÿ»aÞß÷ å›0€|ôŸ«¦Óß®S_JÒ\£Ð~´ÿ›Âš¶6J©ua椄Ù}Âû²ÆHÅN—=á¨còäU)¶à¦“®Ê1Öo¶¯³ŸåüØCaDÃNO·©+ÿ–‰GUÎZ›ýÉ÷ ;jÞ§ ú¼Ü¦÷%î“ÌNçž«ÈUÏSÉ:4…Ά·'ù¨Ügõ#` ÅåUKg¨fçŒúž¹×v¶âm–3¢ßûêˆAùµEyÏN[ŸÎ›gZ~>JëJ,£XŽ&¼é’Ž(ã=½~)ÊÏyÑ›‘ë ù#Cýužó´GO_ SÑ)Ï©žqÃù+*ú+Œ£ÓÕ¡0J] â/Ð~}Fî}…YÏöœ®$ÞŸ³;`Ÿe?m ö´Tö·¢x9ƒ'ÊY¹çÒÄWC¡Šë”ß"¡ëEj4OS3ç/йí¡:ÆÈõðM®CS+ú™ª´§‘ØhR ‡*ÿ©@•Ÿçi®‡4hÌ ò§ôìÏumÅõIâ\þnI:ÞþSJÄu¯Läse\²¡0SbO¨R5ð{š‚¤àWqZþþJFìF>\ç6­¡ñtºz^ÃfÜÔÉ]/šÆvò£êm¯›hP vŒ êO·V6Ô?µig€tÕá#÷SN4#Ͼ¸e'ÜUd'^›jœ=ÃÓ[s*Ú£¼vËØü\'Ü£°'XO òöàn˜°f• Çðm2SzÑ=þïQQ#É£éÄ2óäÉÂvÎô”«‰ÿºõGÄüMËTqƒ!ß¡ë§ ¢/ŸVÄoîõ{Èë*•ÌpU<»Dy‡¹ŽØÑ»„õÓÙƒ|ß_ˆlR4 —HC{amš‚_Ô±|\EvâuˆêtˆzÏ¥ë¤Yø÷©x&sÆÄÙmh£ç&.CŠÖQk>c$Igãß©ÕyžßwuRß\ãû¸1Õ5AýÉD+'fOÎ…Òh“ÿó,@Õ–¡ßF$“¦ÚîÇ&t[ ÛÝXWJÔœÝFÍ(ì‘á;ÂòY­ˆÓ9Ù=y:½=“#Њï]*»:Á­&â«£Æ+¦ÓUit¦¡A•| ;úàˆõ§ºŽ‘ä°SÎs3Ñ!: ; uæwœ¶ü«këeÇîÉñmD²Ð©Ú Jlë)yöˆ¸P˜>Ž÷Ÿz'‚5‡iÀÁ˜¡àÁ÷¨ 7ºzœc2ò©H3ê™ôoˆ6iˆ¹hgB¤Ý:Ó:Caݶ-o›¹2‚t¹¬} …ó'¾Ž(:[[O(ÚFýåžîª²c3CÝ0‹÷sÛ  °¦z`׺d$þüÞSz|Ñl[aýá>Õíî¤ó‡ú¦=™ÆÓ³ŠÕYïäÞß ¯”32e=ê{Ò{ |N58øPðîͺžÌO:€ƒ…¬ýý »ž– O²ëoóóóŸ›&8ØÈÚï—²ëÏИzþw}èm–IEND®B`‚ FRAM ¦Ô IHDRÔ<ßGK7IDATxÚíˆ]GÇwʼnȖÂ)„WK%²UVJÃÒx)ÁX\ªÄ*ˆ[E¨ •­,ø‡O¡-Å(„ˆ lþ(–Ö’Rˆ–€ð©iÅm &%/bº¥ið㜽çì=wî̽óÞþ¸o7ß »ïÞ3÷Μ™9ó{îÈÄ ¢YçºÎM8·¥éðëW~F*S’еÝt˜f´éÄp•åf÷çCùùÉÑÑÑËõCîÏÝÎ}ܹ/»ë4Và£M ‚Èß?9ws‹ª«@Ÿâ¿®btxØ÷²V¶Ë…{¿òއ›Žü2â0æþÙt<6’(çü‚‘“ €Äßæ€ÌR…JÙ0§^L*P­L-üÜÉý±À3²óÂÌfwÓú«Ð†ÏIü®’ée™OHW÷D†¢…MY£êZ·^z7ºÒ[wM†Á Ϙ¤%—‹×ä_”ÆÉBà^‡ò^ªÌç½ò´‡óMÓñ@Om‰Û‘SR>f´¬s¹òäÕ– ÕÊŽ‹.(ï ̆lÌzÄÅã9‰Óßš UííKÒøÐ†HKì’Þß: $RÈè™qɰš÷Gäº&ã¶÷Þ‘ûç$“wM¦„¤º k “ŽTòµj%n:$º'"³Åök~¥*áxBâÜ’k}ïUÉ#¦†Œã<z†T¦ç+N/Û$]fBú™×4?8÷LDfJî/VŽûš7•“Ržvxå)øü†uÃyK{Ÿ›ršoÉߥ 2 ;NEJ²"Ó‘JUÚ‘ /ë€; S5²=ÊF1Γ7egòÇuq¾ ò̽ÛòÞMaº‘²¡Å˘l¼g2[©ØŒ Qv%‰Ê½ÔTìÁr‚n1þ”Žñ3¨˜÷¼®’.Z¦Ò·+™šg-UT ²/‰h¬GBTÞ›ãB×GXzV¯F·D÷]Ê{=Ìóg\qî©UÔû­Ð ­ÑÐe=áåCûJOŒØ˜W´ñ¤ ­ !“ô%Šìëö ¦Êiïc³soÈõ3nç*éh&PžN‹1?`ã'efVË‚sG+žÛ¦â~·Bö<å•ôŠÍ­Kܺ”Oå¼*;žf[ËC±°^‘ ÆììbƒLeÏè˜<Äá;yÎN‘áwþ>p¼+ÙÞÜöåß”ÄÜáÝoÉýk’Ñc­™ƒTÝK=&÷¾DÞ0ƒ¼ƒ3Ç^smñ9æ÷d]áIŒoK 丹ƙð¢Íœ"7ðÐr?˜²^Æ­Àu5ž:¼g‡Ìw$ýQjœRÞÀíQ¤—0˜±ÞsÆ»·EÞ1C«¸ NÒô´äY]áp½ qÓJ£Ô€–ëשº’œìC–+XÉ uq퀗nSžŒÆi‚Š£Aš~ žj‰ìM¹_ê!JYy]tØ „«eòa¼Æ´‘ãg¿"Ï9¸÷MÉÇ=ɳšŽ8¼§ Êæó¸ kËvN®Éßå=˜iªXLÕ½TÊâŠw_ÄÛü¿TÄì“KGåÙ•s‹’™Œ„‘ô]”÷0V´gc OmÀÉÙY/S0Äm‘£ìxÍsÕ¿5\Z°z²3~xi…1 ñoSÞ;QƒÓ¡ŠE[U:7¿­AÓÞAÕ8ON$¼‡ÃZ¦—{ß2q¹¸ß2eí}Éj¬4 x däÝÖ`¾‘—2{Ã\Û$zÐdÖH>H5si6œ ú9-ïõy1¤ö°üÆ›Í]Šô®"²“²s~ÞX.¢Çò?7¬NEÂÈ\y΃›äž6zöüÙF×9/ ¹B½ó+rçh’çõDÎv&¸Üß²z rgs°!(ï‰2§(oyë" nɼXóŒh/•²JûlȘGžµT¨8,Ìðpσ5þƒÃÃT®Pÿ,¿÷™¥áºT#yÏ|J!¦b£¥í]gΛ‚È…R“µž»X¨Ì5.!C¯½ßÝÿ«]¡n¢|)´‡‡Èjçr|£i š^®¨¦þÚÆxœ®yǘÿž”°îï7†ñ9¹Æéú¾\û6EVÀSq* f,K¦ç!úµó‰Ê ¢sÛøm›òñˆÉ›ÁÞN@—Kqª‘éRqÑa?½T+{±FVåV¤B¥¬aòŽü?ãÜ»dFWBïuÜ Ó<•GóZ¢­t[šÿ%ŸV–J쥊lÈF°Ÿ×åži?F¹í,äù«#É»}M“mH(3ªºüœí)Ê{–¥!¬È3ºdz©ûgÍó;DÑ}«¤…D2ðAñ3kïEüŽÅdüLaâ§aš3¿Õ¢>{°”õv~.þ9Î{*d5#ú[¯ù 8Ìs#5ÿvûE¡¡AY­rÏDü÷U¡:ù8w?%ôöéÖ¦rµG ßhÊstªB+/«_ÎWlŒßßÔéÕÂnœr°FN{Œlµçz•*z„)ÆRòq(/Y#yZâï“+ÇI îï?É¢Œ¼WËW»BFuxÊóû6íSFw´v®F®7ú…ŠÓ§E¿=*cÄí*]XO‘û3rû²¼ošÌ–™„ðÎùy¾"-ÔÖªŸ9#³[Òž†Ó´Ö‘ ÿ¾½{¯”·‚X:‘Ã()ŨÙ^j¨BåÊàœyælä9þÐsŠrƒ;Q†B&ñîuýwš0ñówR>?aÂÙwa¤¬rX Uì¤x…ZíÙ­3 ÆÏü.44¨Øóÿ;yÆ’òÆçn®?¡l á 1tõl)\±¦¬÷ š[6€ÜpàVô¹Ç†‰+Û¾æ)¡B¥b…±¿æyº‚G!ΘðV­¼¯4–&mï—([½Ê=$’ëw™kZf+÷¹RZ…ÊqÖyÔÂ*T*ö<“òÉÛêdRžWó…Ãx§ü[ÉÏ2óÏT]]¯yˆ²¹îM>SõNã¯E5S&ŒÖ&èIèп|)löIÚMK^9;¨®7”U&sTäXþ— EZ)bÜ8£Ü¢p+54tW;TìÉOî]O1ÎF^[^µ=€_ÊìÕéâC/!ƒ™d¨ÜKQ½0ó’N &½î÷ü·Œ¼®Îœ6÷·Q^ñqãá—”U Z9ôÕC „ßV¬µCH^žÑù_Î_[²<¤õ½ÂT0@ª[ Šm ";aŒ$ëM°U#ÖX†ò‡o$õßHˆ\gü6”2`òÒ£‘ûz8Qà`?ü”°Ûتi ïgÅs$MŸ•ÿµ1Û*mTRqaU]£«EÅÆ}ía<â¯S§GßVÆl J&<¾ýž£„éÛ Êz$Ö õ³÷Q•ý<{F2¨ßr.$*Eæý*ÞÏòóëS åó$oœÂpþy(Ê{:'1Sa0+ º Á¿)<äoR¸GÏslþI+¬ÃT悊5?OÓ*1®}å§€_… ¸m`Ø•¾=ê㓆Tœ;ÖÕ£SòKƲ"ŒZ¡ÆŒ¤bd7"ÛK1’^üy驸ÒW{@¼ÍäY /\ÒùôI ÌyGÞ©=ÞØB¨eÏŸR^©iåsN—UŶ6èªæÑOSÂ0º—®m ì-­I ŠåwÉÃóæw,¯¨-óeÉ4XCv,ª™Gõd‹Ü!s­`(¨Ïý§iR¾Ý^5÷’3†M&é‘ÙŒ¾:Ñù:6$Qxâ‚)¬Z‚jÂûÔ¿?mS¸¡±›ê÷¿-—Š^º”ŸËÜ¡>W㮾!¨ˆkt~=òÜ-Þo­¬tnÖÎÏ2s’*{¦÷hE æÑyk,ý­3ƃ!Ý95’ÁÕõæš– ¿'Ú+Îõ˜TW©Èœ–©Ä a,E–²áüv(ŒrÿlJ™IÏ_(_(§úW›Z±¬ø õ$§Þ ö%Q*Îóú{Vu•¯(äsóŠ?UŠwÉî€eB‘yTÉDÛ<Ù ?a<ÃØ¯\Úêa š†…@˜4¬ó¦‚XñÌ@Y_Wq.µJ)«¤4\vU¦fÌÊáðŠ÷-&ïZÕ”Í^ݳ‡‘@ºÆUjèê¶]ñ! ¥†çG»b[T³%§Ï¸LÖZ“?> r…Ê÷ìØLhus¨Œ– *…§#Zj¥ÏeC­‹þ&VR7úh™r4GùçáX8Ÿ;¨˜”é šO´ÑeÏîQÅ©Z+¨““vºÕN×pþ~%®×)ÜË/M•EÒ¾dwÀ @ÙhüÂÊ[p¾- Õù¿û¨PíéO/Káæê^Š,˜ 5\Fñ/Ðð*J»D ‚o,“Œ•çOk÷”£ñ(­³ Ü^ž©Œ«ÜKÝÃ[¹W²Áøjø®’9äCòÿ•€‘Üx†N3†ñ*ÞœoJpN˜<Ìiô’‰ã ‹ µ1ß–Êi¿¹w²Æï’Ý’ÿ¹Ý¢5>uȦå§­qx~EyïZ„Ô)±=Þ3æ¶¼Ò) Ùüé0µ_~ãÜœ;o®}Ö¹o8…_=)•ÅÏ߉弔¿ÅJÙœ,“O^ºêÜWäÛ€ÿpÿ³!}Ûós£ÿ7 ¾·\8v¹wÉ¥KÎ}ß¹¯¹{ÿòÄcß/Ü5Rèõqç~j.ß‘<~îîëj…^ b»£BV·ñªÄ_¸¸Þ’ʕȴûýU¹d$Ë‹þ·}ß.9÷–s¼˜ì-IwÎûŸrîßÝ¢ÿyzà8ßçÜÓæ›«u „#æ.×»šV€ÅŃÃôiÊFz~íÜ›#YzÝ7àóX/£”ªÐ爞Îôñ(þf°.$jì{¤. _Ýp\þ3’}7õMÑÛÈHž·ßS?ÒØz<ð¸þ…ˆÝ«åŸg²çå–VÐú-ÓÒ;'¿“½P¶§pÍÇ  ž¿ }½§GËŸ?õ{³´BsÂÄß¡ŠQ * Zú9‘Éö>ùòO“R–¾"bä¸gt#à_ýUΟ%}7y ìä'3÷.{…/œ õâ~4 ¼}l…tQ°îÇY:¡a¾~§ç?”WºU頻T†:OiµnÈiAä9s´:s=AñE Ý>+T»¿oÍE_k…]Yì`p6¶úåvÛÒßVضÒÈ—8È[I)q IʧøúÊO…ºÐÛ²*ž¦±•>å{ê[)e¦æ¹ ”¯˜n‰7ÕøiS¾rûÅ´7­ŠNü Uónð3Œ’Ox[ÓÔ¯'ϰǢÆ^ïuñÝê å‹8üUgíHB’J¦M°‡ÑO›Êc{ÿ·Í)%¾NhÛbÖ}Éq*‡˜OaÒ•É›ìºÎ3”Àø=.® –µHfJ‚ò9Ó¦W¿—×5òv;\òOmÚ­5¥ÕÝ`!s†((ý”!Ùnâ]k¥õ 0´fi¼Ú|»ø_w"¯ˆŸ®¢Õ£[FO}ʲQFFrü)ß‚dË¿ÒÔh ¬*´Œ½~”ŸËštêØzÂë‰Ï™ÿ7lã*A'³”p8F…>Fôä þ`¨‘DR3V¹Þ,S'ÌÑ¿ë Ê÷¼êœßÂí>¢£# rÓd¾C,S|Öó»MÇVT#)²ûM­C gã®g(?Ì`ÏzŸ^KL>±¼Ñt¸–ËhÓltîËìƒ ˆôNw9w·suyæxÓaÄÿ¬µ¿Z²$×§IEND®B`‚ FRAM ¦Ô IHDRÔ<ßGK7IDATxÚíahÇÇ¥‚kê!(„£ P1‚`U$®)-¦" (&¡ôú!`j*åHŽ@¨±?Ô_B z)LLH0uBCƒ± Q jLhð5_jDŠ‚‰1^çéÞÓ¾›Ù;Ýé¤ÓÿÃÝÍÎîμ™y3óÞìÞÄŒ9Dôš -æ\82êü8Ø|cÔHEÏ«.LKÔ÷\ø ?va~Ôùp°ÙÓªÑÑ=h[[rªò§“Ç•Qçå@ã*✬2¸pÇ…ZÂ9³.4å¼sãÙ”T…É·3¡PÅÀò¹4Rd½×`_¹Ôý¦ WxªeÓò™ïX(òˆüª²²O’µŒ:ÿ»» DNë.Ük× åi«Gß!Ë¢tc§ºß¤/ž1ñ‡åËéð¨Ër e¿àÂ_´R$~&’^û¦¤¯„*K:ÁšTætY> òÇ×9?b=¬Ểç’A”'?saCä¶.ƒ*‡£,_ ÏS‘ø9©÷k.<¹“zrþGÞf$19¾+r¼ï ßeâ¥ÝÞ¯ sÞÛ—JRúÓœù=HÃzcUʽ)¡&ò¨šAµ8—åõð¨Ë¹ùè¤ë.cBz]ÝtáÞ1Ö/'åz=é.°¤•롆jÒÖ$˜EÔó¢Øh'3kž¡Ž@Üá_–ÆØ4ry‘gÊ}Êö„(UŒv¦]“UÈL¯×@Y«&/\_Ÿ»ðV ]E”Ú-ž€ív>{,Ó®·¹/+®¤ÝÜ”º“tÚK{Âô£fÉu­Â¼lâ¹Nfi[dÒ^ÙØþÄýà*|í”YrLgä¸Nì(o!Y‘zøŽºì ²ár Ä¿kdµäÂbÁ5¸±IüÈé„9V‘öÈœ2õÁuØHž2Š~1’nMÒœq᥂ëm¨‘Yèœt´Jäü­e~s㘙4’'Ur[Œ¹oß«H ërÍ¿ÉçEêlÜQn³‘{JG•šÓZRß\÷lö¯Î×ÎÍ“Š¥Þî¾{ømfˆ÷ÑUÄœü¾nêrÙ(±+òÉõÿpà:m9>M‘]Ñ’æ:°˜xn—‹dVÒ§öŒ+Áå嘑Ëu“ï ‘“–<¸i§<‘{‚Näû‚È}Cê£.¿¹OOKšM>¨3)zÍüæ>ýh$­ÖOÅä‹õçm‘ÁÔ=éš“òsš÷E^~š%é“·ENïî­m‘?ÏÊçe²=ÛŸ÷5N°É'Wð}©„WI6,ɱŠÄß‘P£¸yXT6ÝT½cåØëR©u¿±«²7¿m^vPN.Ãz O|¿[Ò!:¸Q¶úc.Kƒž… Šc«Ñ{çñ¬¼o?‘©¯†‰ãûÝ ¤•´-/ÞZ/†>X @έ_©ô>Zg|?^e]ó2L4Ýz(_”M´X¹>8¾$×h‹Â<á·Êò¢ L{BIRÇ-ÀÜ#ÏêA2y Îêû‚¤{Œ©Þ“ÝZÂýžuácÊÜ*–Ý Ú]ëŠù>ÒMÔYi¯S·˜ÛÌsRW×$®î÷uÑyWîðÛØ,e‹T›³uH«õÞ%?i_ººå~7㟕>Æ|¸¶Ö÷¥5sŸO<÷JvIÈàÅðÄ|­ 5íÞ¥üº*ƒQ‰_œ:SÖ!oÝT“c<Ø}¢ò,xÅlÍï7ŒŽ´}­jò³Iëå'8nýè^™94©³‚eæüº§¼ëŠÛ O8tURâ8¹€ÔÙ!ö˜é¤Ú8/ð¾*_ û‚~T÷¶÷ÛWüöœ©^:uÓ`úHžx…`}›”÷÷lJ§ä8~½âj2UXA WÏY§ ³!ç5$,&Þ“Ó¶Íï¨]ܵSzñ5“== R;Ë)3i}—>?Ky«B©’.J+}¹å+LùÔ|5#Ê’áÕÇ;§ýsº­>[þüT9Jz®ÿ¶\s…^Øáɳl¢Ì÷Ò Hv@ÕÝÍLn° \cJBN_™cŸ¤ÖUBÙt²P—߬ï‘YlxeS’&]iT?U(ó%sý¨ë¨-×ñûo…ò ¤9ïØ\x#p?­{ö}—Zì$=›Ÿë)é$”™x€yž:&®85 óÊj¶à|m(vðúÐ…u/Wì)ó»ªKði“*•l™7 9i@•x.Û’Ü£% dIÃ%êø9¢Š1A– çíh$ wÌ'ÌoíRžDÅÆy÷ͽ¾âªHrXŠ\Gg²›d|‡‰åþ‡^åÕž2›¢¼Ÿ“Ëɛ͖Ío5j}s{/]ÝQdˆ¤/KKù õwsžtõÁƒÅ+ÞyÚ>ÖL\E®uÕK;'ñ§¬Ò£ì·C&-Q¶«»júßJ0'K™ƒý,öÊ6^ù.œœKúü¶k"p¬Ùo¿5ר‰¼µžš”M4‚å4ý­—IW«àþ o@z\âfL<›…Û‘s¡kK¹MžÁÔ½r’²Gp¦½óW%ý“þíѧFŽ–ÄÊž˜"´¶x¡àÜ®NEŸÁi/7Œó{»R~kY.¸¯6ä•z_Í$wÀ¹Tv®ÈØ>Áákê(~n´‡åû-*P)î?eîšìÜ‘Ï5Š›ïõZºŠe¥r,¡ÌIà|'›«)›UsHÚd£õ(+Ç«ÿŠýQ ÒÞTaô¼‰‡ò¦Ê²õeJ¸^Î*LìÔ¯}_‚¿ú`ù„üáË”dy°ùÀÔµ²"òY5iµ°|¾câuC]ÒêÃëg§"it·n[ÒæþTÓsЪïÀ±3ýö[s ¾Ÿšã)Ë¥-¸_¾C‘Ç~¨cjf]|޲]»¦|õÈy _ùoËÞ´®û¦|oÉùÛõÉYÊLÞ¯JÜÈýø{ê,ã/‰Ø©­föY´KÎÍU‚û<*¿Ï—œ·Ý1¤“ù+Ô©’óµÎŽižº6K\¯âÂS”9ô›)çEîK‘ãµ@ƒmKã¶³ÂK)÷§°ÿTårËvrS.®[Þ½ÚQÉõ½à)•ó¦MÔ)³Ô¥“±Û`Vλ؃¬4ŸmÊÖ™’sr²¥¼ÿÊ_Ù5}ÙôQŸU#–¥?IäÁ`ÞÔÃ&ìæ•s^‘´çL›PeÙ¤o–(I˜yÌÉË´¹¶N–CJ²â]·ÑK»7åþBò3Mùè‹ÔJ°5I#oâEž/5¡>ZDZ‚evL¾óÀv+!Oe“.û5©‹è¾sÿ‹L+r•áñ’ºh«˜ßïË÷)ÑêÎÉP~7Sïé¸úî^FW*õ’óZJÐîFL¡YÅ(¿µa&íxÕN9Æ>¦û~¾L9y0˜3ÕgÍW=È‘ü²™c¹†H‘çE~ ÷jøJ˜";|å˜*aÝÊ"’ޝÁ+›E´) À¢lÖJíd"ßUs­6•¬ŒíLëîL$íŽüÁ^ÛP…óŠÔ[‹ò´¥M±û¢Ì²°IÙÞžˆ¼êk°@Äê^Úuhè͈’ ™/Û½(IÊLɺ:× 1שžÐñêëÉÀu¬/5e@½9>ÿ)—É®æïQ6é»ÉÓº)çi‰·>ІÔë$6­Î•äÁšÈ?3íàÿªwN£ ­TmÛ2ùz±fÊ`-hDá‰Wð^@ ìu‚>eJ®¨õS¶©Àïˆ[ŸH„â)°ùñc“ÿУ3Êç”­Ž8Ô)ïÐïùßTÌõ—Çr ‘+L‰§å@áÕKt§4uÌ ( ÛŸp/}¦Xe¥×PÖ$¤n*Óljª” ¬e¾¸P›¹HÇñ=½üAÚ%pëßãïúbãä=)eJy•Ü ‘?F¢&þž—­gʬ ¡¾¦ÊÞ®C>ÈZè^~=EÊÃeçGh.Ëuž4²ÑÉëÊ%‹½9Iå\d:eñ­”>“P7V'Ø6^¤·“týœºá‰ [r’üŽ"+}ÜH'¬[¯¤ð‹v´­TǶu%ôµ'Ûuó;(SŠè-À éqÓ¸g¨àh"ôõ@|Õ\çï”c¡ÉÄK;o®mM¥ln¾BÙˆº7cL‹òÊ;B){d(ôv˜\£§À 3&Ÿ@šŠ¯)q§´Ô©*‹ÒsàüšQ:5ÉK‹ï'\K}hU*°„:7Å'UÉ_QöÌr×.SêÁ¿'é“&`”=›yÛÔcQ{ñ¹\=µŠøO{¸W•Œ%!¥|‘|)9ž$g¿Ï{ñýì{¨Pd•zZN¸†æ}[Ö”½àá…~Ê8j-䉨s‘´ˆÎ= QÒVrÏîÇÒÆôˆ`Üï¨dc ^  ñºƒV}³¶Sç*ÊTzÒûY©3kÖYÛEÊÞjc;ÃH^ÞOÙŒkc[ê˜ßM ¯>J•CHR‚Ṳ̀å?Iu|0}=Gk®Qf&µ™V,-å­&Üfjö5%ýràZUJ|V²‡²òjí7rMmÇEó^|ÕÆ—(Éœy¯DIæÚ“Äóà}\uÂNË^ “ãTâG¥Î^\½JütÑy%÷UYÖä³nŽ•º]¼k$/ zÈŸNfôÏMb»ôYç„6¯U­ÌT?ÒÍûÇ úWPoDÀ³T`ò UB βŠÔ*õg¢kË¥ø“g‚<#Üõ÷åòvI”¯5³ÍYYQ±¬T9ìt@ÝoDÚL—r•cMʶøŸ¢üdë²—V7ÎÄ^tŸü¬då±î¶¨„ž[nD”äª7×ñ_[w5¢$“ÔÝBní±µ"õêúK¡2õxµ,1²{6ñÜ*%lªê3_Uʬ›‘4:`B»Äí$¾«H¼ZôÊ\Q½( (á94’‡¤½8_9rc±¼§nÛOzˆ}2{›ÌÎ]êø¸ØAÅ>ÿ©žowøæÞ?;NDÔØ¦´°XI´)àïñÞ<±\¤ÿ%ŸQ–ÏDŽ7}%)OÓ›Hi?ÿc™(½GÙ3¢Å& =^÷WFoõü·y”ùbÙ,½«“|3 òçOM~ø Ik¦\:ɲÏ/ÏRöWƒ¥– 0DÈóSR~-J¾û~+€]‘J]¥1YaQö'ãm0•ãß—ÿô beBþÓqÁ(ɳ¦?ýÈWˆ’¶)ªÒ–¾yw?L*z”ËSNÞ¬Ó·ÿt\0m¥éMäy0}ÃK«;ÊߦìÞ¹…‘¤«Ò}æ åwÐò¬¨îUlîí<äí:gdFX£îÇ!t¦{fl(;÷+äí$§Ì48Vƒ…Wæ­É˜|¯Åú“×w/RfÞkјîĔɢ|Ÿ9èP2Ö.ÊÞ[Í«÷×ÉÛì'}‡'_릭è¤äûO€uþ´AŸícsÓ  Ì_5¶ 9ˆ 2~RcíHzÕuþ¼ºË*2ŽP籯±œ8ô ƒ.kÿaùŒù®î© 0nP;)]º—(ó“éÎÞ×RÎÝOÈ$ãiù~ØÈ©ç×„Ž EÖ®HúŠ„)Ê^My`Íå€1‡zx eÿ¤>´.ø@ÙuWż­ìû=;‰¶•”¿_{žºÁ` _¨óO2ÉfLмßuÜÿàçf0àÕÕÊί¼‘ÉEéÛœLúeÊÞ µç9ì—ÉQg°7ùÕäää•Qçe/!«°“.|Ë…88}9ê|»ÄÿuŠ»?båá IEND®B`‚ FRAM ¦Ô IHDRÔ<ßGK7‰IDATxÚí]}ˆ\WŸˆËBDR k$&öWKDƒEœ*Hd­DÅuZŠ«°*ÑÐ"Œ5ÁõŠ“Jm±†`¡¦ıX[£bbbiÉ& ¦ñcÛjlŒ_Ç{òÎÙwÞ{ßÇìì¾Ùß.oÞýz÷ž{î¹çܯi4X3lª»e@D[¯vÓ¦Ku—¨Ž6»Ç.y}ι:÷jçn“÷#ŽGþ\w9Ö N0öœëVLÓtn?¥ØbÂîqngÝõV®}?Hýø‹sÏ8wIÞ©»œŒ/^¾–sï°{üÖ¹[œû“{?î,Š÷•Lþ?ç¶Ëï§œ{Á¥•X$l¹|‰…«{ÿôZÖ X=¸öœr晽ÎýÛ¹8÷;çþîÜy×Ö÷™xs„¯6>dÊŽŸ§;'VÅ·œ;T2ý¢sÏúÖˆû½ÀïbùÎÔ]Ï!Ñj‹µÂÇ ÜŽÖòäAÓ¹‰išu—}” tkñ Î8ÓFeO$lbÌû×ÿ&á“ !?ëB-k¨²&úNçŽïÎ⸓†úëOÜ»\ü&¼×H,”[œÿãuÔk@ZpGgëêâõ_ç¶9÷qyÿ‚«ÏÝu—sˆõ]p?8w_l½SÿÏ{•s¿uñ^_!Nûg—楺뺚>ô‘FÂ7ºžünçXé¸ÓÕÿŒ‰{Ü=®sî“IJßè´aY1+´±ýé¯Îý̹Û}Þ“Yî‹; ÿœ©òÍõá™ÿåô;Þ£ò’ MÝe*B´¢i^K+¤Sÿ X $–ênç®7á÷¬7 Õ•u6°.ÈuØ*kÆmçöÕ]ÎÖ±gêvÑü>-B,”¦kâÍÚvGH_Y¶ÜsO€oº†n—|ÚŠßî;u×g•éôH ?q_ºUx.¸Ö.3B-CK¥õÖºë啳ò®d\–#$Í!#;÷‹,°³>†¸Ïí.‘?ö­Œ\£ì²ƒd$ÎyjƒŸôÔ|U™B:j3 àî5ˆ›ª4Â霵â¿ËLåóé/S”§Œ@lÕ]—@ÝÖø{JK¦ãB¿¶ {O(ê€Â‚t»ñ?húÏ|Ý4\m1uç>õ€? o-ÒôÂ[†÷zòÎ}÷£<ÕT¯•RGÆ 94Ø)òDyFë2%«Öɹ#Ì'&½,¬ø¶ ʵU¾ÑÂÀ:bF¾Â.'ΔÄ’·KØ0ÑDñ3éz«X¯½Î=ï ¢!öÔ õ–t¦U´µ£¾ù|$¾ öS>ýE tbᣫ ¬Ñ÷T8^•çœsÛ â2íŽya3”ÎÌ–øæÈ)39åµ³W¬¨m‰Ä;,òƒ|EVxÏ*‚ûdp~ŠRKoÍhB‰Uyɼ³åx0·i”sªtEⱊƒ¶[dq7ö-ó½ý’OËóÇ['(Ѷ¿! üKçvEâ,¡rØ g!7_e@ÕÎãùí.Òμø¼˜ÿÍHØ‚8½0Õ¦Ÿ–xç¤ó­ÓŠÀÐi.î wÐ*LaIÞÏo>6:ÿν(åÚïPªI¯éàU²¾4`º¦Ôívçn¬®%ôT´ â÷b´3O7'}Sâ|ؼ¯ê¦J,žŽô§Êüo”° [qï5ƒ¯Ï·: ^÷eÑ1quJuµUþ¾Ý|Éuû˜ÔÕ/·Us%ò§/ ]TñŠ-ËÜ`xÒ–ñ)ÇäjÑ(a’®þ¯ôÂïtî¬Pýéškj ß¼Ý}=+ô)R)e çÆ§¬%jÏÎ^Ó6ûs›OÁéWƒ2%e§·Ô²?;l&7Â× š()QŒ´\1m»m$+Q#s¡‰’4@º¶iÛ³Tá6e×÷JYí–‘aLÿG›Ž¤=,IÉûnùþÐxGùíï%è[.‘_R«‹Ëº3'nË =ÊZ©vPºJÆÒ“>µË‹wDx•Û·ÒìXA}Tñ¹Gòg+ù?íjË^¨„æä³EAy56¨*Ÿ´—µ+Ïy²ÆòÜ„‘ „&ëfeMA¢Ñ†èza̸Ç%ìd ýóÔoÎR:Uóù"â†,¹C,f“—v¾üàf¯³ùÚíô Â’ÒϨAºHPü*OhJ6þÈn6£dÀcáa7èš1ûŸ?ÈÒ£þõ½…‚ø=C;¿_°ÕuEÂ&i™ÿΚwmã¶’¥Î{K7Kù§Œ¿‚/ì˜a¹RÅr¶Lþ&¿¦Î§(§¯QŽ‚âÑ93XHø´8ÆUo¯I?ðŒŠ0üÍU…4¡Á•®âÛ¤DæöÑÀÄY$OÙ¿3Î=dòÎä´å®×›)5  Bÿªä=v ä\ªBã·Š;aò_pPºéÇbÞK×¢TKfAñt M‘¦dH‡;yß:j :Z’´¥vöyßeÜH"4)Ýä¯y0vS:%Ù)+Ð(@µàN®k;Z¶“·“¿¶ùHÜ‚DÞÚ¢¡Ÿ’ý¥ [¢‚ì%¿ëOéN;ÇâR²ö¥ —¿Yîzç.x~”VH2ŽD¾;%üËgÆOS`ÙÃäÑ |«Ï¿$8mWÒ.ˆÛ¢À:¢GçK‘´Ê“º9¬'¿gÊ´KN™z†.KÊóîyW¨­ŠêDåd˦Ø^åí0U°†O[ü.K»ïòúú„—Çe-N–ñ{%¾ÍSZÏQ:&èfÖ÷­ ðӔMCX_d:,¥Wr£6Å­ãÌrg’†\4-ò¦h#ålÙ<"q(âlQí•Í^§~¥UéXþLÛ9ó®¬Ký¸¿Äw4½öYH±Ž-49+ñøwl‡÷.SVx¶5j„Ä«ë6P2­š+ü6ËÜsq{~yMøGývÿƒÔ¿á¯k„ä´ôÅ'»7/óëUéO[)]‹ IƤ—^ù©CgM¼þÂ<5EñÍIºÖ××óúµäyÆÒŽÒ´K!ZÐÎ*ë¶Ë;Óý´ ¿f`Òõ)]”XýÛq‘6$Ê™ñ8§#<ÁØcü:æ»zì¨)ß:㥷·(î¿yOë34Åkì@©¦Ã»Ün?%`7_GË{ßiâ0³íóÒYÁXiýTÒ,w<Š ””NQÿZ*3æÊ9:C©‚Qº³Jôë=?í¨vç Óõ%é4¶°5Y8€S|‡o.-µ#RºÃ[…èî@Ü}¦ýYA)Üp±Z°|&ïjø“òSå#6«3;U©ÕÝÞØuˆòå+¨u*óî@<¢T9A{ÒË“–«”]“Ô¾ìÏeèhü—ûyHXRzóS+§Ïét)+÷Âõž®fúoIºùVÿtȈ<˜§ì^‚EJ-ðè”.e­T]ö×5Py&á@$?x/{mÀ¸hùÔ”ÕWPމÿf“^ÓŽðõÃ+¡™ ÏŒ~ j„¸j½(#,Ê{hpO´£0<]ð–e~*1ÄòP§þ)YÃÐ:u›YK¥ì4/”›Ê0U:«æ ãó”y_$Ïê§dÚ¯Ô÷(¼Ãw™–T`‘›Žt…Òµˆ×¢ìÆ-V2¶7V¡o¥õigtSÚ¥@<.ïóónRv³ÌÎH¾Îqï¢ì™Ô)Ógt`9ÉKÃy€œßW"BrÁøM˜þhã²ßþÀw2BÒ§£çß1y‡T­?åäÁ4x ¥ÖÕ”*–Nª¨v½úEe Ûñx“ ¥èeC‹2ë¢ÖJU¹´/WWž:èNEÚN÷¡a[Þ}Eºcãü7{ï¾ÕÛóikgÑõeu „M›6=ÖH/:ÿ,%ëy;œ;ïÜß"É>åÒ½(¿âÜk)0øü8–O…¢þùŸ:÷)ïw(Õ ™ ø2w¾îíËÎ}Ϲ›ûµsvúãR7ö?ê ‹£â÷F.ÙaoÉ û…sß—¼Úòíö:2÷{©€FZî8·åDáëî¾–—·µ\rÏåx”ýxË„oj$|ÀÏcÒÙc–Jt‡·€Ûm¥ëƹ·ÃÚuò| ’÷yÊßxÚe{yæÑŽÃßãÜ3Î}Ö¹ç„g˜WNˆ y—sÿrîOν#Ç÷L^’ßÏ®Ý;oÿtÂýæ?*8*¯û¤.,ùúÐïzuì³Ð †ó앤!påþrK¨í…—Ùzf>fyñAi‹§ø/ …o¹\|µ%_Ùx›s/4Êã×.Ÿßx~/È·+_{J‰"µ(õþ‚sßæëÿœã«a¿¢mä^ßV”—)Óç âÇí¼£‘ðÉA¡ñmR÷?:ÇùòÑ¿òceQeÃ'ä©ï[E8¸Böñ×+/u¦0ÆßUÚ( J§T“|"/³Ã—˵¼Å _ã“AðTcP²‘J5ʳ”.²7©Ä¹OJ§òn¥t—¨jdèÀkr–È/¦Õ5­V—§å…ÒâÓSdÃǰ@ÉôšÒûY ¬yS2ÕþPN:%kQ4 fèJù—W\ŒÐf‹”Ÿ§dCWàqé1•Íð m)ÝMÌéŽxõakS×w?È‹g.ÈïÏKš^œ.å[Šº!ØÖ”Î*Z&|™¯¨µòEö”,§XÚ<%åºL鬈µ´µn!«þT¤ž½2}&R>YkÊÂå|œ*ìf¥¬•êO¿îºòZy›àA*ØE/<Ä}n«”)dÍ.FxÅßIM94<åùÅâZ©| b,Aýe¶â„vø²@:gÒ] 6 dE·òcî4½—×vJ­&gÄž_¤têÄ_CU&lzïÁ)Û߉¥×=_ÔQWH§¶iãyù&+$ª€=–“Ö®ÅiY‹Ž5ù|–wyE“²ëDMÓ.ÏJ LéyßT…Œ»‹"䣀¥LÉq*Ÿ¤tàÛêå××¾–tä·¿YP×Ú|ºQÉw[4ÄKH(Tx2å²<ñâ¶( \S:Å:–[§’e¼Ÿ²û”~<øU=F¤íÓ+ˆ·‡Jœù¥d½ù ¥Ò|EGûbHdÊ!ï¡ãZç¨ÚÒQd ì×ý‘8*¤BwÂê™Nl¿7a™ÃvaŒÀí$n·¹+Súk·¥„å[¸C;äžóý¡þ¥Ÿ+¥6Q:CPô÷p•6±QÿMU‚6M+Õ„3¯Ü!OžŸ‰äÃBò"¥çW½ð Ø2Èoí?³ôjöíð]) ›*ªŸ£TQ}ˆú¼M?Œ'<¿©aÔIä”?k¦³U¯T]PËöƒ‚üÞ.ùñ g „+¯ÄÖ–{Þ»Ï+z\¦å§”‡é2-q&@9s?™Þ£‚©Z,Vö1?e71öÖ]wS¶íTÁ¢¡äྯuó‘‚ËÃr'X ¤Ï(L¼& ùhÃeP«¬#mÍÓZ÷ ù;=‡ZèT´–[µ,Q+Õ‹—k}¸°ÏH¬¨ý%ÎôŒMi/*/QjèŸV´DxŒ7˜QÍ÷ž í¤Î½ýŒ’eß [¾éi…åZ_¢ôL9[·!?5n–(`-›u&â¯ËLzòM)ñÔÜ :€PÄdeˆ. õ¨÷î¨z`˜oäX·6L‰å¤ÌùEñ{¥;ÿV“. ¸~:ª È½!ä›áJ­ÄZnp"oGð€yØ ìF„$[½þ¹BÿêÌÅŸ-ÔucAPúoG¡u»IQ¼ýÝ©'WÒ«\Ÿ¶¸-G‰¢1OñË.Xæ°Âþ~–*‹ìQªËB3VDî>ìI¼é2åV€˜€4Ú¤jÊ]«yJà)3Ô?å´a5J¯»#ü?”ßöB‡¦Õÿ–L›Aá ÌQPºŒ2ð4rLHþX¾õFü¿ê÷'ñŸ oÆ‚’?º8T7*ÒC§ÿcÓälu?*qfe`8½ž•Е҅Ò æ û‡ z,눗* '?¼ë®çXCÖ&uc„j9¡õŸÚ…áЦEÙ³ls^¸Þ3R <ª XSÏ)ÛžAÚ±@HvTᢊ÷²ŠeÂWŽ×M›aƒ’;¶-xpàõ¿++Ï}}ÂðJ7 櫓›ßôò›‘YfKˆt“y×›Ÿ“F^ÑÁÿõ JÿW´M5®qëÔ¿öõqŠßä5'ñ÷AZËr¯mô¿—YþLê`Rw¹j¤GGëOÙ˜‰]':)O½Ë—/—Øpzp Dåo¢¡ô¯´Ú’nlf=ŒU6¶J+U8ºBé1GÅ¡qâÆDákäÆ2x¶Å²š¤ôHÞØî9 ÈùÓœøM£xm8ÞzyÝ`dºFnœÁ'ŽÊïóä*>{åé8bG•ÈÂOC=Ò0Ò d÷ï†ß¼W$—¬Ô]ŽQ¬%wÆÙJCü#âAÍ-`IEND®B`‚ FRAM ¦Ô IHDRÔ<ßGK7IDATxÚíˆ\WÇd ¬”…ÀºPAˆ„†1,e°‚¡°øG‚: ÅÐEX„Å@) ⱡ ¥"ˆKA,– C—‚8%eQ kc±t,‚u±d k@9Þ“9gßywÎ}?fg÷Íî~?pÙy÷Ý÷Þýqî9÷÷9Õ8Út¨ fåòŸÁýçèÑ£4/Øs‚B<ÜU°Út|Àddd&¸gXV‚Û¤a.w¬éx@#p/C”!+ÈG›Ž˜L‚l´‚{ÝRþ{#¸ç‚ë×7†µ/~SMÇö” ø6‚»Üý¦ãöîy–ÜŸ î5cLÙΪÁ ;b@»rÃ}(׳Õbã¡Ñ9Ô ôÎ…?gƒûap îGG}©éLi(/x^ð|pŸ¯ÿ÷RÈ¿7·1¦±þ|6¸?w"¸ÿ÷åà éü•þrøó™à¾ÜŸC˜GJÞÿ\øóà>Ü—Bø7šNónÀ½vþËóÆòû‘Üð|òß‚ÿëMÇqˆê×§¿zrvyÁõ­Ü'‚û[p¯…¼øWÓñcFzWLd®Â3-3Ì7Ü2+ëছNO"¾ÓÁµS½¦àÿŠ3/Èó…+Á}‡Ÿm: 5ÓÛvÒs+¸7eXö’éu¾'†6~ÇŒôF•óÁ¯ðíYùËÒ•¦óbŒyªùÁù¸%ò~!Êã¾Ô§S‡µ‡.ú`VÊ?ήOßC»ï=ñB…ô·eJmZü.:õ±/aZÑó³òüDêRP‚©Ê ϬHØäùž(š‰«(bü{_ÔùDZ6TÀMxËbÓi)H#Ç·c®Õ nʽyç™UqTÆæJ 1<Ýà®÷ZÓy3N$?–MÞnŠs1¬0?=(æ–1å:õË„Ay¾éx–¤aNê…No¨Ž¼ZðÌŒ‘ƒ[òüÓÁý@ë§¼§+aî÷µØxÒ ñÚžD} *BƒUœJ«$l_‘k­@ôähÐ.¸ß3B΂:ãÜ{`l#ØÛ¦ÛDúJÒΕ³ùi¥î<ÇéZ—pkä¬ö6ÿVÑ»ïïÔ}fÒ‰&³ÜÃ$£:”õb5ßúV)šû3£Çb²¡l±#§ýzp‹¬iñï÷%ÌIÍ ‰ÛïÍõy‰óIcd;Îsm©/ÌiX.9áÎРCrGf³Ñ}ö{µé|;€²Ë%¶AH…á…'—ß TsÈWŒWÏ\·Duj¼ƒ•Ór™Â§¬M¾mîicàÝྒx¾%¢rÜö )³nä·mP¹B;ÏÌ¥¯L;ẦñÄïš?RƒÝhab¤Ef»âVäš§9jIG•?ì„™2ù»I¦gjŒòDô>¤uLÞ\”ßh„µI÷"›C ©ObPfãïP6ìÙXÑ ÷¸b®y›á¿ƒû™­Îsó‘ŒPÁ7®ý³Bù†þ«ò—›ÊƒDœ[×ÖÎßvÀ ™tV —+Â¥D˜slPÿZ,ß¹e®U竾3j Ôy1[ªÍ=ny^îq,&Þ1'JfbæS)›ËNÔ­8_h0ª|(•v»Õ…UEK4B/uÒÛ³2S'mù=-Š;†7¬.Wû²›··*Ä…•呱YãÏF¶_þµ]ËÇy‰ÿiÊï+~Wi¼GxwÏÔÉ«zäq s“‹Ù¼<^”zwqóçy£»â>6ùÔ.y¾’^ŠÒºpþöš§k£gk5rGÈ mNQ¶ÖF¹°›ßÞ÷Ð`1Å=%-÷§D _ükO Óð\&ÚûòW²Lmk°,ì52ûѽ…HPX ·冀؄vqHË;Ï ê\ß–I—Îë°½/~wƒ{'¸õÄ7¾G¦—º[i©˜^ožW~°!}QâÙ î˜1]-OÚáZ6fŠS9OÙ¾Am±»ŠÀ¼—ßÉ‹utÁÒfÁ¡lÏ2âa<6¨KQXê»QÞœ¯ªŠ”åçQ{T>~ÎT¬+ä+Q­¬CÒw›:2³yròÖÍ;Ê7ä¨ä]qÜUIÆs—¬$m®Y>îI}RƒÂuñ#2#E&®§œoo‘?ŒGTlèô}*n°1·œûVá^.øN®¬Ìõ¦ösr2ÍQ¶EiÓ¾£f9ëŠwuñ"6Ž6t¯ñ^[ÿ”¥’ðC²Dƒ¡íÛ‘ëˆû‘—Ó%þIþëݺ Çi\s¾?$e²M%.` »(¿µEo˜·…@s”Ñ»ã‚Say1 ”=ý)¿"O¹ ®{àªôR§DxWM¥].yFóà¸ñkÅJÂø­FÏ·‹„8 ›Tzäl2¯ð>6ªÚò÷æÐ!÷X¡?1jYB¬0MÚ¼mAzÉäDo¼F#ìÁ¥á^êÐö™(îÖ ~S¼ìa,gšë–yw¼—õ'¶|D‰zë®yõÑVŠ‚8wÉ éQqƒ-W6&ŒöÙ L|'W÷)Ñ’º¨ÌE÷V«Ö™‚ï[x1™óÞ½qµÆ{µþi£Kô—au #6¨Ü@߈ürûÆ)ßÜ6þzj™•³{ YéÙr°rR"#D˜G-‡U‡\4ã¢0¹B ¬E´TòîXhÞãË=á9Ê6Ïw(›¿mQvšMò &¬µ¤U9”=6¤ÀÄÃÞ3yÚrž¯cP·•žsßVèEª8TK‰U½4º¾$÷JOÔ*xí…$ ™Ù*¿&NW3w)} ÖçyË I=V³è$)þFj¿†‰çP)RŠWk8»ñsæÞrô¾Ô°Ü=Omä_Kʺ-ùËéå¾·'sZnñJÞÔ*ò¯RÉö¹Èß«[ËUëL48ñ=ùŽ®g]¢+|+¿iÞ—[íKƒÆÝö¼p"}qczÏ\kçÆ“OF¹._³åžˆëE:¸‚Œäôaoªes/ÏÈ5Š7LЋ*ƒ®½GÙ‚Š·œgbå8nÒ¤'µp%×­oP¾§ÌÂÁ‡T\tžWåPÚûNø«ÐÛFŠ×3*â(l‹ŠçQG:™GÞ»fãkî2:t©Î{Í;(?ÌVXÉéµÇFÅyFX§ÉÌK›ïñêÆ*>aKWÙΓ?—ªJPO»yÖ óur ðû­ù½(uÌö.Ür¥¬'£C¤=¹Ž‡Ÿ4åä¡ÊrV?³”Í5·ßá郛’¾8Žl”? 3Ê@‰Æ54ºÇ‘W6`vˆtò+hkïfèÙóŸuE:§_O]Ú>à!z^§Z”õÒã“ÑRº$· .•O”M™¹#ik™¼9E0¨ihÐêfE¤Fò¬æ–Sß•ð<÷øªü~ÁÜÏ’ºÎkvMåd%³k›–ÉÙî#qY!¶-@5Æese½TŠŽ¤ôÜT-å ¾=na6ùóUçž=þÅÄó©“¶fÈ'iô™É•ŠéÙñB*>sµMÙ ÚU©jln:JòŒQ’sòûÇQ˜®Ö ç›VIöäú)æ²Ä¥ï)Jóž±ía”2Ií9µgûê¼/7V®Çi¤ô{ÊÊæÇÒñÔ8ë ¯e°ë=Ú”?ª’Ëì‘èùŽÜ»d~Çò”Ò%*+:‚ȼí„[õäÄÄó@!Ú”ÍÞ%>mÞ+¹§­®¡ÕwžÁm—qߢD¯`Ò¯´ìQžž(>ŽßZÉ»zqÚÌ=Úeù­#eP'B€µ È_6Ïÿ<”÷:?]ðN»:T]Ù‰X± µ'!ŸhxHÏ64)›{ÿzôœU’Ú{¾…Q%Û*ò—wéÐîSRwúRn*ËÉ£D÷(Ÿâÿ>ÃyƇæëZ]À8´Å(òßpÞ]y_Ci·k´Ä {bI™ñAù3Î;Þ–¿*+Ç̽"]²b§X6Öå÷q‰wztÝDlPõ<€‰9nß"Ê@Wö®8÷{^!8árabå…=M»|”V…t«Â_¡¬åF’«%Ïr‹û²ãÿ`ÛŒ¹V¥èÍ¥LœrHԇĠeÿt€óŒ.½2æïǵñ³^M\beÙ¢lŽ•äëä ¿HX6†o:÷»’¯vŒ.2‰ûßhGVúb´&â$©ßš7Ú°«á5/½…fJ†³Bº[V©&h„ù\ÊF-6÷»Úc ìÈÁÔ1ßs²,wóû©þ”µáž^z‰IEND®B`‚ FRAM ¦Ô IHDRÔ<ßGK7 IDATxÚí]}ˆ]Å)MSRìÚ”uE— mêZ»"¦ñ«¼(ÒHl±BcPŠëDý'Z¶ÚJÊS Mµ‚þ‘F„â‹`«Æ’j©¸ Át+eØEÉZª¡’(hÓ´ÐÓ9¹ç¼{î¼¹_oßî}»ûûÁðî™;wæÜ3çœ9óñj5È-¯º}'7U]`îà¾÷8Eàߟ¹0æÂã.\æÂ`ç]h¹p¡Ü»0Pu»úN Þ϶êz½‡Q ŒI¹Ÿvá˜Äqá¸\å”ÅÊó° WŠRåëQ X ÇãM¶U] áäR¨/¸pWÕõ™Åv‹àωÍg°b“v’(=V¢#|'ñ÷åHYF•K«zØ”­Ø,ï¬WÝþ9 - ‡EùÞKÍ5ÉdEÎsƒÒ†å~‡ªÛÌDÑL³´ª®O—mPæÍÈ££µFHÁHžy3/(Ö2£HS…Êm~°`9ãta¥»Ñ(Ñäúm¹¶àðhÕô™-ˆ°¬[¹Ð°Ø…¿ŽujCâÖ ß•g”{ýïqá™!á›1ésCU·s¡áÓUW€±dÉ’7ÜǽÄ]~âÂúªêáê°ÎÕåÅ’Ï0c³P{EÂ%{È…Ûe -¸¼³ÝõSUÑ¢‡8§@ýæÿºÜàÑ…i¼Ã…ë]8¥ñÉŸ\xÓ…¯J¶×åwµ 纰´ê†ûÑóõRÿç]ø%_»ïüí’Eý§óÜWî/„o¸üÿ¹ë¿UÝÖ.hÃÂý¡ ×ÿIwµkËÓ3(sÀ=ÿ‘\×Ýõ¡ªÛY[„w» ü±¶õ‘Ÿ¸ðY×&ͻ҅®}¯Êa…¼Ï…k]ø‡ ;%þanqe¼ë~ŸQ:Í'°Ñåê}¼êzô-¦ÄªÍÈsÂ27÷–µÒÅj÷Êœîf—GTEGc’>¥ºëÓåw§ŒÖÙŠ¼³ŸGZv„ê×SÚ·9kä)t×2÷º°ÊË7 ¶bJF¬[}KÝÝŸMѼìî·5Á3%Ÿ].#‹+%ŽÛQzšC諼ÄuÛ #øëø·—mŸ q]›‘—¶å6¹fÄnΠgÆ{…OØ vÃ<¡MbÝ6é#Þ£NŒ§”aûß¡¥N™Œ›çæÅ4‚Ô‹ Û¥þ$~^ÔNa„ÎîŒ<ïHžAQfD)nÂŒ2ÈSʪGŒ‚,¬¤ÍóG)Ûm9b˜yÒÖAÒÇ(9/øŽéLc~þªa”á4yn_JΣêb$Û‘-Þ“2ö  ÞÕ0ù9ß³)uZ*õz¾ÇmMðŒ—¶Œb7šå+âߣÈuÇiu­cêc 9æ™»)24öšº0-+¯—zúFÏfó-¯¡Húy¦„nŒ¦ ¾ÿŠ”2O LÚŒ•éãsH/þf¿‘:''%]¾ësÊÑþ7iÊ`:ï"1~)2ê¼@p÷ü`Y¹: ´hh’ú0´°Fמ¶4)^P”6ªm="mÜî ºÂ÷-¡áú”w]éÑb}F½FË|¿‚mñîÕ ôêÕ”tæ««¤Ý])ƒujÚª`ñ1M2/Os0Ú³²b#ãås/ϸO¯@9uá¯é¬|9uá2T™~@aœ=›ô(QWÛVý¦»½<¼é¤ç~GJ]$t¿Í¤+OK6il˜^0‡ígãóHñö‹•¡úÖ`–BM¥RRÙNy ®ÆÄ¬0ŸRV%]¶!…j;tª¡!Ê€çYá¦äišÎCµ”ù~ÊJðŒÄMJ}O¸Ñ$ŽÔ*¹^EѪu¢Y%zÂòx .MéOªP•O{>2£ä‚±‡boK#_QÏ(s4‹¿ ÔI;ª2¢ØKÀ¼Ë†ëÅv̹ûГu©ï˜§@ZÒî+Sì½Êš"S9ê7ÂJãÃÊ«î÷B–·³ÔÖ!н,×6PØc§x$ÔFOþ´ºá‘!á<,„{¢`9Ü·¤}$smž,ø¾Ä\jN^«8mGâù¿çCBH˜§gó?®¬5F¸Œæå{s‰rÚ/…é”chȳ;%ÏDH ygN÷,xfÄÐk4å™Ù®+\z^:×#dºÍ5]¼‹Ëº#%ûæqù>KE`ZžÊR¨œ÷¶ù«Ë:ß*ÏO{tà:²B} @SÝjr¼ ç=üLÏÜ£¢h›)VšMê\o È2àdÖ2däSó÷åžÔ±¬r»lÛ…¶Þ”Ü—¦Pyc(¥¼&/õñš“9EV=ãá@àCæ¾N=ҹߡ$š&ÝŽ^ ¾¢eQr”ê3‘2öm犜$´\Ê×È [÷ò¨°ãôû =uQXá­K”1jÚZ”.Ú1&rÞUµBÕöÎx¦ÝfÊÙ64ƒz%\zô­’ô57™RÖuŽ’Ô¤ dˆ ½l¼ï6qj(Û¾@ÉQ"Ó…Þ‰yL‘7¹“‚u•úNQ‡(vùòzPr-Cžâel”ûur¿>—Üv¹"³ÿ[èÑú0¯,5Ï©2mR¼ mÈòIY¡¤#(ƒ5(š Ÿöâ¸Ó!£( (夤[gÔi± ÕÎ§í¡ŒÅ'”²'•’+KíÉ¥htðT #2£fò)¾ä=¿¢¬p o•.X[&³ì ägž‘(æ‹ÛEP³PR£oPâ¤ÀöšÙæûå÷ ùýƒüúßù§òû´¼S÷Ëò~GÞ ú–ô)ÞÌ}ðëæYÞw½6e#”¼¯´ã›»üíýÚ ¤µˆ·NŒHf@ûþÿj{¥ŽwÖ"9ô]t$Æû›yçÞ%xîõI¾0Ãz0Ïè~¿$ýu¥©Ë““äýR¯³jÑænpN-}_8Ç[9ÄÊpŸû½ÏËw£üÞäÅÿÐ…ß mx1óÉ™Ï×?'¿©ý?@›W fÝQ‹e`!ÖÆ&s®X»¼|jÕŒÈ=Ï=¾U |òî­õÚ+Yêä"±ö5–.[m¾[z•X¤º¯Ì·ÌVPìö)´²—¼Ð&¾.em6q- »gs­ÁŒo¦v“:]ÌLc»g2k”ª®¦c~•»«6‡Èâ™Ïr¯^8HáÕÛŒ”²'•âéå´Ìºøü%<çó#»Ãæ^GzùFüwÉ}htÊ#@»ê8k5˜nÚ®õ™NáÛÔ‘?¥Œ~ íìtR¾Óº@^5è–Ê€¢ÑÝÛäM)Pì½*»xë™9ê÷}ŠÖX%½{käØÓ›ôÛøûÐñY²ÅȺ,É›.Ò÷uÈŸ¹D?ŽP/wá|¾ èø±¿Ô¢“an äe j¿\³5óù8LÔ—9ë£ðGø5%[gfx®VrrǽµÈºýW-5·•*EóRŸwáç5cze©E#ܹpŽtòdÏHûÎ+k£žwÝswd½ÃÐæ¢Àkùdž?ÖŒW) øÖÖ"žX›E?¹ÜQ‹G©> >ãâΣ°¡öŠüî ¤=dÊ⟖&}÷.þÌ]íh»G`yÇ2b%`ü«Ðêu*7}°Ï´mÁg”­òþ¢ oºöúÛY?æÅ½R‹FÞ‰xêœKgÚžeîÓŒí¼zï<,N­Ôv9whbÜßr²ÞX:/P¼rìï&O‡•$V÷.Éļ’f¸Å€"wÞ¸)s\êy‡ /åXïK%oKê–·2h’Y€$÷M{_¤Œ‚m]–“> B¯M)ñŽš8õV”=ªÏ–»‰’óU¥éJÞAÝÖEʪS4WvÅsyg{yšRçIŸv¦.!·u§x„¿Îĵ$®îÅeϬ¼¤s²&ç­RÆ‹”œGíjä@‘×§.ïßH†òˆá-ßÛë|Ÿ”™m›¶…¼T›)cŽz&ß?£Í#9éíCó –§ícø«ÁÛ«ÖMœòÊj÷^€ÿ¦Sx%A3áƒý|MS¯ÐÖ™† EöÞHÝõYÐmq­P´×ê…@e€ "’ßᓤ* ŠGÃyÌ\²=:GÖ2ŒÃ'ýèQ`E„:Ód[Nž`Û¨Óõ¢÷=U¨]Ð¥ž“>*Õ™6q«%®«c…oô_i4ä2ÞAŠ]h ®t ¹uG)eA–”¡Uá>ÿŸØ*bîuÝ&Niˆ?öJÚr§F,ó¨*Øv™/3ÞÓH‘bmPöÂ7ÿ[q½&2ò˜ûÉ@>Ýþ4åů˜ËþÒÚi{ûô0i¾‹Ÿ÷ïÉõê\,ª}4mjÆî®`#K÷š¯—w¶¤>{)žÂá ½„~J–çÑVòŒÛÎRŽ  U&®’@ñFæÄ”äÍïˆ@Úè=[/Rï°•ø)JZŠJ—Ñ”2úF@ˆ0>fîu[£Ôò|é#ÿR„4{ætó†BÕy¿û¼ø!IÑ>ç¶ÐøNÁ÷< ñçzñƒ"$Y(®± "HOÂêPø3 Å²@\šB}¼=¨ϧùó§¡þ£Æû/~"ô¾~…¡×û5‰Ó­+®m¥ø4­²Ôé·3L[ÓxÅþçªÒûW)õHð1Eÿ‰|£<Ó3£ Päx#ô‘MþÔþ CK”Rßÿ¯¨XgÌ\ê¦7íhóñ‚¦rÊ9]ãB‰ãÑAÈÕÅ£¼yñ?ˆR×´9C=èœï7JÇÜÙí»æ# -ÆÅÐh!É#ÃÁÀ3¬x§…f»éMéCº§°%q+Rêpš ?–<ºÒœä£4Ç.< Ÿ¹ÌB^,à>õ±Ä©aÛ¦c ¼eOÍèQ’p—÷3¤GåÚ~'"sä ÷Ì!Š=d!^™Z²ÂÝdÊÛ^ >Ò¿õð‘Y7º%<åš+IÌŸR|ÈÍsÿ;ÅV¶=éé ÊŸç;ñçæÂÜŠ½U·§G4ñ­âÕ”\TÄÆÕ}iq!ÃS¨Ö;&üÚήÎ$ߊ@:ÓVGc¹F©gî{{)žëí«ãß<Ú ˜ôFÿ-Ÿ¥¤;›È{U·­ Ú‹„(ö”µÈ;ßäW©nZÿ0Q‰o O5)cÕü;®Y¦*‚J‰7˜&¤Œ ¼&#mAß&2Cÿ_XƳGâ) iè4/øçJSà¹Í‡éMI+$k(>Ÿx«(ë/£ú¯¾„Õ¤‚"7ws1[¸”±25ç™”4’ J¡zm y½Ø¹ %ÿ*«xd$Îîô U·¥D›3Gà9Ïq­ pour chuchoter a une personne utiliser /join pour joindre un canal de discussions Pour les opérateurs du canal: utiliser /ban banni l'utilisateur du canal de discussions utiliser /kick pour sortir un utilisateur du canal de discussions pour une aide plus détaillé taper: /helppvpgn-1.8.5/files/ad000001.mng0000644000175000017500000020634211151345317014503 0ustar aaronaaronŠMNG  MHDRÔ<d †2œtIMEÒ ,) 3sØBACK3œ% TERMi4 FRAM ú>m IHDRÔ<ßGK7 #IDATxÚL½ ”déYxß{ñb_2rϬ}íª^ÔÕ-©»¥F’,©AlB 3á ÏàãŸ9ÌØ³Ù>àñaf| Øa$j©»E«%õ¾TWW×^™U¹gƾ¿eîý^” Z©¬ÊŒˆ÷þÿÿ–{¿í97¡ÁõÙÆãò¹,…ˆ².JKsˆr)Œ¢¹IŒáv‘ŸÆdbóÊš]—Ö€ö '€É½t ~ê˜[œÃÚ¥KˆzH9}TKüØQíFûÝ &A€8á8ÂI€tìan>‡Z-œ WEqñ(Jþ#^û™o^ÃÖþÏE>£”|/Æ‘r•²ƒlÐÆ·ï°PJ£ˆ°±ï^® Ñâ˜/íµ:HeÒü·okˆ|Þb®"Nø‚AsÌÏs€JYŒöÛÈôGy<'?Å÷g¹“™ ┃0åÂɤàJv?úDZ}9\¿ÃŸ%wàr¿ÂfqijOà?ãww0@4à¹\r”J!öø;-‘¿Ú= ;¤,ÅÜS«äñ³(Špy6.ï% ù»áÞ  ~]ÓþN#âº),»ăq"Ǽ‡h!æÒG\ßpðŒußÜGÊqÀÏóÒYîa'…~Ùµ ¯ÎóCîÏÂ㵪U«õ<®9>^¯ÿ*Vý8þéO~?wö>p2ÄÁžƒNã~ñÌs¼Ÿ(òéÿ?öܽž{þÿÃ3_ýsÌUÎbiñÖ¶žåÞ^C5Q–L܈ëõx–:òóЅØÙ¸ŽGQïpK†Üs—²ÛWš÷ëØy&gqÍãpdßžMvßü˽c·WøûÇ«MÎëÛë#Ï€ßõJ×ápâI„‡f¼|³‰÷<ø0¾ëñcؽó.½z ßÜŽ±“öQá}?r²„Av„×Þìsm”Ý,Ïi4Ä0N#ÃóÌeBÚ­ÕÅ×¥äðJ¼”—¬%ØMruvκA‡úãI¨’¯¬d¼Àïù J…Š”ïŠ—BoLSàæ*5Ìgk&G¯âÐÖŒb»­¯ßÙÄ¥½m´)%¿ˆì(¥­§þ%ús¯<éKšgL{(Ÿ!í&÷¶Ï/îôÚáWвFmà™¤è¼øz?W@µVC©VBß[»{ØÜÙÂ÷þðãƒ3}¼ô»¿†¿¸ÝÇ ˆaЇ8‚GWáݵ‹èïѾRÞw*Õ*ªužO!Ä8êsŸFHù¾É†é‡t–úë;aÑInb;ïdï¤gî›ÖáH.´?\ðÒü<–W–iû4]ìí4Ñ }ò÷~ŠöˆWt(—¥’íI†úîrÃQˆýƒ–ÙŠ,ýM¡ƒŸMÙ¥â ÅsMäPþÁlqä'{GÝÖ=e2YË5¾×‡Ã3ê´gv*—õásy~÷ü¼\ ét†ç—JôŽvF’!»Ê™äò³Ç“ý¼ÙlòßcÓý Àïm‡dLgÇc¶×mlRÚ ?ºŠ2}Q*—Ëá€No@c—/ø‡Èf GHÓ¡úüwŒ-1æ¢Ý EÕ§ºÌTbô j qՕØ)U÷˜õǘ”(Œ¼áA¯M‡b4 ±½Ó²›JÙKé2Üä!r£4j™•¾Í×71¡cxçÖ¶wÇ.ÆA‡¡[)qCs4FÚ’•m4îÓÉfÑšdñúÖ'K1NV}¼ºÓ£¢d0;èЩmÓÐÙðõ1×2žŒÑÚß·û(Se˜=m9…Îw¹v¢7Ó§F¯ 9H7E§Qi™~§(sü׎&1>L*?RÜS~sÜ–Ž‚›çuh|¹g÷O€$riâ¤^Æ—~לR*%ãÁcÑó2TÖ §ÃûÊPxÒ¾ŸC*&¤#‘#r¹³'ž'tœÍvŸ@Ž4ãësÀžëÔ™ŒÃDáô]´º2îw»}ìoᱦðÃ?õ øƒýÓ8J£²?Ð5 ˆ¨S÷4¢Ly¼¾dÌåç:røfÔCH½i+ì,CG u††"…§¿ÕÆ=<þÔÏbáèû°¾~—6–`+çwcÊÅÞ„ )_Å™¡o!ëÖ)|ÿ„{6&@ Xpߥg>ºöcØ+Ø™Gabèä'^?â=êL&r„Ö›#ÐÐkø·bÞä/’AÑ$Ïüÿ^4B—Fz*$Z Æ<„@Û¨}‹èF‰ƒv'T mäjC|böA|öïüΜŸÁÝ·ªXNeñîÓw±ÓPŸ'øÞ.ãìc‡ðëÿæ"ž{q“¨€zž:C»3 ÒhÂGKú•q@KƒN4?’¹zi:%}ÑBB®?.‘d7èH‹´Õz‰Æ×££ž`–²Q# ¸¶õ=WÌ¢îÕpt¶ŒÙ²/|…V3À©wSxæâ¯oŽÐ&ZhOà ’Hvå(t/.ÏU†<ÅýÏx)9Í úí&wÈÙrß{´MÊÍêÊQ,..(ÙÚÛÄ•K¯bÔî¢B_àÊ?_Á™OŸÄíÿt×/ðøÑ2~âÁ£ˆúh“Ï?yûCàË/Ü2:³À=Z¥ y²_²S¼ÚanªÙ©PìL1÷H²’æ}¨¹ÐÞJ~ðfY®Ãss8´´€Ú\•v+Æõkk´eô!´9¶ç\g–{Y O)ÒÑä¸çcÊf@½ëÓ™ÏÔ}šÄÄÈy—è[––æ úòèsoÆôr¦‰ ™¹1ߤ÷ùþñ¤j¥ŽÃGN`~î?‹²Íõ Ežk™¯'àÔ«TâÃØe¯×3ç](lÝã 0»c€—ë÷û¦ú£×F#{]0ý{Š{ég;²»µ‰‹ßÀÕ+—/-!¥7Èèé"¹7“J/4â…úÝž±ÀLµ˜-Ê•¡¡ ˆÆ]Gr\à.º!—N`ùÌ4w6¨’MT3CŒrCt:}:Ô]A ¬ rÊPÅ„ìH ›§ Óœ‘N0öPÚ ØÚbs“ŠëRð}±"Tâ¤å,èÌ\¾ÿ`˜¡pR(D¯ìXdp“÷wnžèŸÆç6ºÇ¯Ù ™ ¯5¦§!‡ t0&˜8ØÜ°ÓåFQ\¼Ä(hS·KƒGãBt't2¡ášðõôT://m?Kp{Œ{ ó›rîþ¡@zt¨Ñ0AÐZÿPˆš¶A2Hf*ƒH D‡KG.nŽ)2CMFæ”=2€çåRPÒ\‹UF{D#èäHc!ß””(Jåô+¤‘‰—9TÚ˜BK°óT"žZJôÞJ$Tr²qÂ> ,$oúŠézã¿^÷=Çn Êÿt¶‰qæ¿„Öy¾1Ï<橥ɧDÉ~›Óž¤ÉÔÑûdåônßAþ˜î«vL§:S-Sg®ýRô#%-¤ñˆ S‘B±åÀ2Oÿ£fÌah\T¾±X÷Ý'˜“¶k™S%Ê ¸ØÛêaopÉ®û·ÿ‹Äpïu<ÿÚ¿Ã}³=´“K¸7à£ÅEf¤B»†7Qd†÷JåÓ5üù+¸´FPY~à#¸uôš| ÷‹ŒKz©½õÛpv'hwGdUÔŽ?€­[oáH•×M;(V(‹\ÇhìÒø$@'“qÍpµ¨se.ÒQvĺÓé"÷Ö1¹DÆ!XlŽVF§˜£CÍh Ö˜Ãj/Ð`–dœ‘8OÙ«mEHáˆÊ›þ$GDPJ@9òPô 8~ ËÕ ®Ó ö[8r¨Žã‡vqùòʼօó‡ñ¡OœÄüZGxo5ȆÈr|îCkÅu‚ò=îKš÷Tô !ÑwºžÑØì˜k²¥³s ,Ä”)‡¥d½L§!R0Du6‚B £3Õ<™i{­z£ö¹µü¯ÖqäÈ hi ±P9LPNúí-¼ºAÛæù¦M7†\ìz*З¤³I+šF–&k’®e2üâýhK=Ú‘qØ%—ž`2ꢱ·A泉™O޲´8WæyxöË¿‡‡ÇE|[žÅÓ—oá#gàÁr—øÚC‡RçùIÝ*dûÍQÇÃâ¡€ç¬8—Ì mŽ»SdÕ¢A±>AJÊ’‚P眹Ï÷éˆ]¾p…ë“ËX˜«@¾s«=FÞ‘<ŽÉ¬óÈçó”£Ôfò¨V+\¯l”ƒ.þönƒŸã¡Ïcõð!técÞ~û¶¶vÐjÄüÌEÌÍdi7r´iò”w'aô¼;¡¼ÉëÎfÇ"ªñh µs8~ü <‚–!u|w¿É3   sïÓçôûC(²'’M-4E‚#[ŸæþöiKeuŸ²CbÀi^SN\NTz4¢’}ÓðçrÀsós8rü¾ö5—ß¹(û‘}eø‚jׂ&ņ¥â†-*¬Â¢|m$d›Ï‘ÉEÒˆ%ÄÃØXO†¹îÔÑÝcÃŽ ‘£Pªâò‡ çЈK±ÅÂóß‘9cGáA:ŽHNXŒ/Ë÷M:F‡g#4(Çlá¾8YM„)¥4¢8eªQâT œ¥SÓðF'Ž7œ²XSV1ö$¤ôhÏõ7$‚9=LÃM:Óí%Ï+ê‘aÊh ‡<{|nâ¸,œ©Ïã[Åîé-1ê yô§ÂBüQÆÏ[8·5Ÿ ¸¤6¤ŒÇ¼7 ‹kTBjà;Øã¡•òE”ý=¾nL'–Ágúàç>÷4eñ]œ:š¢˜åi´un§ü<Û+G%f ð¤BìðÜçÃüà÷ââ›×ðÂsoâØ2u#Wä½ hv±°¢5 á»YŒ‰àµm/_G¯;ƒúì“m¯ã øñÝï;†Å2™„œ§E+Â>á…îꊙnê‚öex`9¦cÊ87ÉB÷¼ï^¯…ì„lÎÏ&Ì“¿› †\{HGD#KÙê<¹û7Ö˜¸h0!X¤ÕuyIgL¶2‹cs!.¿ø%üé×ßE§âñ 'ññ'Nã•;;X ®ž<÷8¢Î]‚á!~âCKøÂ¥Í™ÝÊÀñº¢&”ÑmA—ìÒW=O“£Éäxi;ç÷y¤”Y§—ް0ë£>›¡L loܘ2äd;¡%E,®Äµ ±ÓÚÃv{‡â´-´÷X8²‚×jHçîbåÒ]\Yß x'(Kx:½d˜È±#Q‘Úd™Á\aNío`ìHïГãÚßÙÇ~´K×£|¦P«T°T«ÓÞ[xûÆ.ö@ªJ!Xl,Æ]:Ç7†¾zéz­¬ÎÎÁÐnG}diŸò)û'å!†/™p&ã$òcá^ƒ×¦›.&ŽîK#:¨ÓÜÇ,÷»V+±Ïðúž¥pz!nÜØC¯ÙEŽ÷èû£Üa•(¦iì£V®â5:Ó[T¼3§ê˜«ÏaBV;CV_^Æü¡ãdy ë†DýÆý®¡p gë•s“áç Fþ~Y%l'&‹+U¹©%„{d±r‘¥™6´"|ì¤÷+þ>14ãx¾9Ï¥ÀŽ{4r\{<6F,ÇéÐ0d-â[øEN^ìYÜãžé<ô3G!NíIèÕ£CôiÓ<;1´ Q²T&ʸ^Uø3I‰ÉçÈÐóÌ6U”34ç«_DKÉØ¦xO©Èä"9,s|›ðqgʾž”k ±Ö—~'㓎ÑP3¶÷žÂ'ù/ÆÔÙº–ã²ð‹Ð¤Ò±Øzޱ܅ò?‚A’ÙI…yi¤Æ"© qrßS¾Bœ ÂBk²bÁž¬—NÐ9_K¼èœ;Q³Ü±K¥ÍùeÓ%16_Ñ1TÝ”T¼P˜!è ! ßÚÜF™ïùÀ…ÃØjŒðÒÅW ºÚDÄœè!sŒ}ª3a†(þQ²“ upíÊ»¶÷'ªs(´"dyŸþ ד§YÑ^«ÁßÑö…Ym KJyKÿ´i…é‡XoßÁÑC5ÔæWÑÍŒ±C–zb9ƒzé¾µ¶‰—6îàâÍYžiÕ+ ” °\”3΢–q,"a©W9~ý¥ŸäG-‚Ë«ÇVؑԴ(òG‚«)Ê]÷`̵çqd®Š# u:æ4i{{ ¦ dP¥ í_:¤MŽQáúÓßv†öV¡öRF9Ï´ÙÆ]‡µ·p¹ õ™9ÌÍ.áüÙÑ?twï®[y{{'OG½^C!W¦È AP3â~iCF?´ÏÞ¡Ùé`B£LäYCûLíq@åñZ:Ò¾\œ8p!Ï!ïw|/OÌûs#tbÊÿ¸}žÂ¥3ŽåÛØzùpú¾ó¸N†rêGðsÿë¯à_ÿßEàoãÂÙ¬ÓXogßåúù9t…|bl²êñ†æü­Ñ+øÏ¿‚ãËGq0(b¿³DVZÂ;—6è–°º’Æñ“³xùåu…“÷Æ­›7ðʯGVO Z˜'*4dÑëw¨—b­CÌHåü*òM°F»ëï Ó(£P9F_vÎöM¡ÙnR‡(qÏk•*·#CPYMƒR1"vúci*‘¼(šF¨;(µÁ=HH)|/’ÅÏ“ómòl;]Ú®_x_旄ćÃÑwŠK²ù”I#K™”±7Gž¢Goì•s˜ìŽqçÚš]*Ü>Ù7+e.¯êÜzÕŠ úDq©jÇxïÜm˜W˜c2"3™¡ÁZÅb} îݵwоøò»˜={iF“‚õä•´þìÉ6“ª5¸þÌæKtDÃq û-uò™”ò®³¨ÖJdm ®·r††ÔG’‘ -ÈÑ38!îxQ›  = p7 X6ªÛæ,§­ªAù‡JîôŒ=*ä9hµ“â-)^& §Ù+w™Ê$ÌÓK–"rrÉn-œÃ5A•‹aÒ³Ÿ(IØ'ùÂhš«t,dk¡+î»Býª¨‹U17}­3uˆ–½¤lÄý!,¦jUrÌ‘78ÓügÊu§x%Nr\Ó5¹öZî ˆgÕ¡®í˜—Îq/²H‡) Ûö¸_íf€m€±œÜhÊRih…PI9½Ø56:¡°õÚ=’¦ÀºAèØk'ÜÔ!eµG@7˜X$Xé3*½“Tb I8Iq‚¤ ÿèýº÷´Â• 2³<_²ÆQD&p橤B3êáÉ÷œÇ…'>†ßý³oÒÈoã(ø˜?ÜNRèU^K–TŒÚ9§ÒY Š–©híÜ}'ðèƒgp‡ øM2·R4Â'/œÄ•F€Æµ üý÷œÁÿðâ£OfðèÑeœ¯¤°˜£äÈÏÓgUu›BÚõ-úö'–ÃO9Š&$Eä-­ Z®/㨓ß]Ú6))e¨V,a®VÁL®dµA[u0ìS¬•(;Ž*–SÈeJ-ðRc«“,¨‹d2NìºÔ[àª×¥P50¯Q)ª0,Ïãé/¸gÝ?/…¹ú"è1¾Þõwï`ëî®Õ…”ÊyÌPü‚Ç=¤Ž‡Iª©ÀÏ©ÏVá“ü G]lìÙ> à×É€çayé(VÉ`æ—,½©Ž')*+}Tîô^µ/¬4Ã3°}ϘΪÐR•îÃE6ˆ”MÝ+™÷éqG[¤ó!r"ÂëÓ ¨XM´×¥B ¨4>…×-òbdƒ+j›N·EÅpiì•Äv©|Jì*/Œ­gÂò|¢â.QN£5¶bŸ1ÑŒŸX”P¨Ú"”³)\Iôãñ|—`ă<²€ÚÊŒ%$ËMìÓy¼}{›L7F1-çJ”º|û»wð'ß|gF¸ð™B}i{£0Ùwô×ЄaŽÍÀƺ×šÄ 7”)M¥u6'¨ð€3™œåd”µð‚ 3 !Ó™9y¬0D°“AA‡¯mˆªµù*0ïÑá‘e ÆÆ$½lÁ£Ô@½9±OXXzb/ö'i]p­Tßµj’¿rìß’âH­IòsC2Òqh†N¹H«ÞS¸Ní-~R®°~t/izïϽê剕/$!g$ùOXnwl,ÕÓï=®M•ÇQâP]µ¨àÇG’û ,„,°¤E«+FœÏÃáÄôz»w›è¶»&°‘…Ì=c¬iËi»VÑl•Šb˜DÀŽo‘vcÒ–¿5HC£{ÆdÔòѧ’e\T|榓Êä0´¶, h;Ó‚, ‰;©IëwYǪé*qëÊsxó¥oàcŸú8ú•4 çï?ƒ_ùõÏãŸüã_Ä_~áð‹Ÿ;…*÷c¤¶2Þ_6›±\s“L7M'—מ„TÄLˆÛ´×_}¦ûŸø þÞêSØÚˆñpÿéÇQ§‘ÑÈÞ¹}Û{xâýOâ£yþè?ý®ß¹ƒ×N PÎ3¡ªïRR)½£®í8¸øü®…üƒ_þg”ó4¶>ͫ⠦Å^2"Zc•Ì&Ã×(ç|,aÒÞÇkWpóæš*¬xäø1ì 6°sõ5éÀ"Q.fFpá@R4ÇQûÏ¿;LáÌ{?†‡?þ3XMßÁèÎ×Q,PüêÛøâ•!¶X%È q¹‹2?èð<@{ŒÕÃs˜¡.mì;x»>À››\Ý¡CœP߆ƒ¡µ6(oí¤§j¼þ˜6@íR> HzõÎ'Û§cU%<ïUáêÙ…YÌ--Ò94±±±I›ãàV'@›{¾PÞs,‹‡Ï-a£GÀôõ.ÆÝ]ÌòCs>Ï03¡ ³çžäã´×»WZ*MQFéµt©ZÙU¡Yˆùr3…´EÓš$ÃÛ3õ¤zÊ)&©«uÒç&P ì3\³'Ê.fWB¯ mUü˜S˜]2^ç½ì€Ü][§MÛF±PÁ|e³­pý¸»Á½nìàø±y,.΢\©ÑoMÌN¶;»ÑÊӱ͡Îë´¹_ýÞm¾‹óçÞ‹³÷Ýjµ†Þx€­ÝëŠP –¼ª{U„¤?‘'JÚ›%Nù®­‚{úóÉdŒŽ äèÛ*•R÷쥔[‚©øq›L P, CaSù½Ä3U¥’M¨¤t"»dM S ÆI1G±3d¥m:ñ¦sè4;i™Ä ±¨Ú–¨(ãsq3‹4š>oRý—u"ÇÁDU®Ü„D–‹Ì+,GvAçE»QR¥z0 :S±pŸÇ…¤é˜ó•"r³e^YF·q@Ô“³ η®oã‹/ÞÀƒDnD‹=^wnq†:Â+W¿þÄÇ?óI(­,®øOâX‹Ï{q 5ËŽÚm"÷P]~žÂeª,›„mÔ”U–ŠYÅn“X©”4eeüñp‹àd—Ì”?f:¢Â¹Þ€hmlÑ}õm KxCU*¹"c¥ü\ìOñ[²ˆ@NSá5±¾lÚÚQDQe4¬W“{DAJ©—ÓIò%δ@(ˆ”óÌ$ŒÑKrˆî½¼å´pAqpNãvÆj¥æ ë*ª/Þ³åšy&Ê)W™TM'½_&ˆjØ]LKó…N•üÑØ¸”¥´Ÿ¥ñ SºyW¶-ýàû9{ÿ€kOyIu¸3íÑÉøÔ§*çªë#•rÁÒê£ãÒ‰ŒUÝM»†Žs¨Â'å”'Èò=ERÙ˜‘“Eæd¥ð)1E=è°ÓìUS׋c¼ú•?À…3báD÷5¶³Q>òþ/¿†ó/ÎáŸÿÎïàû/øä‡y݆õ9 Uª¨‹rNÃZ˜Å;7ZøÓ7bá eÈç5j励=ˆ†*¬K%ìT½–‚õÁU AùVUëÍÛ7±¹±m2-™oxßhwpòP;|ñê¬?w ¯mwÍV.’ažsðè{=\(Ñ«cƒ |Ò n´FÈð5*R&Ê™$­yæÜ„©ZUÑ,/ m¦½,f‹>Š*¸wFVàåÒ±¦ÒµWª@-‹B®`¶LæÚö,dír/ %Úy‚— ÷aHà9RAª·Šá2±U+$ËQtL¨A!BÈlŽŒpDáÄÈød……”Ѿœª—¶S³3´\ë X±J› «b#ÖÅe9±17bÙLÑ*¶ZT ‹8•%:[;ÄNÙÚÄi,V—ÊDêd±;Üì@Ì.mý[BÎ:p}ÝižŠÝ¡ÓÙD£ý]•N$eFÊÏU,IýökbÒdi(ú|ÿN«‡ãï? ¤h_{˧ŽÓ/âío| ¿ñÏ`èïs?ú£ "íæwâæ2ôÙ|‘Q6Ö÷ö¥WÑ8x û[Sy}«˜$¤„SÐ!LÊÒ"Ò‚õQúVtàŽ÷ÉÀÖé|zÜ9½¼šq,<§~DgŸ’Ô`‚UÄZá[[ ¨v¾:CV>ÄúuôTfO…Nix6°0¯zÜ$Ýô0™3Îëú ¶ …vÊå„‘!Q¡C+´<Žò¼ÊJ²ó1¥Ä ÕJ’‘dÓU…¾eDøDãEw„ÒŒã«E¼ûu|é÷¿€Ïþü XT_[@#ÜÇö~ä³?‰Ç·¿òÑxú-<ùÁ×Ùƒ ÊŽ"Ô² ?üÊ.F¹‡ðs?ûch=üÞ¯ðøû!sñê«/ã y çÎ=€-îÏìì _÷]8†?ùü—høÀ÷ÿ—ŸÃsó«xúk_á™ËB™ÈÇ~cŒ=ÊØ÷ÿÝ¿‹ßÿ˜Et®¾½†ó¾¥b ÕÒÄrXµª‹µ»wpýÍ×ðôïþ&µ·°@Cš'ë8›ÎZ5¬:9mÔ? @ Êè$Eö’µ n1zµ„{ºv2IŸy6r³6 &ÑÛ|מõµ—ðÆ[}üå冥ƒ=t z´€å °½uÛ*Z#êÁŠTå±¶?Â`?À3·p@ £"«Ð³x½Ò2li£ Ž#§Fÿ´Õ¨x(ªÛëáâõ¬ov°2_űå Ê 5?L.³ËÔ9Ÿ†˜÷@Vüî­.Ú]X:kgwhQ·;»½Dö¨3i{9”1ª×qg·ö°ßSø/C€K;š­àɈd—`Ü£ì,ÏV1[Q:ƒ¶a®¬ÚmìQÎ#Ú)¥²dïZ# ,m®r¯æÊ< ðíýY.íËòL[}àòúõnލË]´s©adµ*ޫ߉yï´×™‘g_ìË*¦Ed¾°gâ(œ$ªåÆ Éf dªUÑ’Ðí€N9àg¢›ÔÂdÕâH‡’µ¾ï$µ•áýå !i«Ah´fd÷ ùl‘„lµ(] Uù¬Mе gõŒ§Óu:á¡…ˆ‡ã®m•ËU‚˜ ºÝ&®\&k]k[ÞzyiK+K(V+d |ϯ'p­Ñ ±±¹‹½í+8hì"WžC¾´À=]´ûVZB&YTµZþ.¶Ù ª×P*(¤¬ESf*v-†®H®Õ¤’ß…\·÷ß}Ðû%»ù< i&©Ì´R[*|:ãìÑÁª©}být ·¥ÐÜ£°\Ô0Vì¿7±~«|γ˜ùˆ Êæ4ÙÆC‡¿kÑ1Œ ……6™Æ‚’ãgŒåyõ²F8Øò}žm°Cl½pt¾*Ë—Í.ˆÝªØ)Î`±žÂ,ï;3;—H9_Ÿ‡O¤2 ¸ôæ,/Ô‰Bs˜/çQ¥0^¹v çÎÌà#8‹ÓGŽàÑsó Ûd*.¾þúÛdÜ œ zÎ¥=k»ë–{È©ŽˆT¾øŸ¾„¯<óp¨Þ¿„4AÄÖŒ÷é-ú¼'¢ë| u¿TÎÒÕ4¡pª(JÕ¨ÝoíWr?²ªî£Cs/40Ã'+SÓ}HV6[ˆ fä”" ѱÑ@©ºSB§éEÜ([&,ó.ÕÈLÆîðËU_^ÖZ&“¤¸'ì ‘Lö*>„T"«Øu’A ŠB¤’b&(ô«ÞC…¦­7ÊyÊ©ùæpC«„BRÍ;­"´ü³WÂfÌÙkÂ’UæªêÒ*€ìu*ŽJ©µ€@«»ÓFƒÖÁ¯ÍXˆjo}—δG–U°üŒªd5åD(^åó97°ŠeÉlŽŽ§Dœá¦(s~!OàX‹ÃÁÎc®W½cż—`Zµ¬È®§[Õ¼r(§´}«º‘N#åQÍM÷:|_ŽùZKK2 99Á[kwÐáÄ©E«Ö÷šjrPR¥r/\®¯mY~îY÷•µÝw[‹X9ó3¸ÿ}ŸÄïýöïã«Ï>¹Ã`óî> .Ƹ/|ù‹Äy¼øÊËxß…ÍP_½ú6×RÇ^£‹—_~?õÓ?‹Âê |ù•çÑUíAº„ôáSÈ{®ßÚ3Ã’òUÉ»d /K–D© £à7þÍ/ãÅßþß»þ<–œ­{(g"+þHSFóÊégÕ›k7ã§› ” çÃbu€æþ¾þ|﻾ÓìãúÞ‹%O}l§Ï–éðöÐkÅ톸»ÛÇU²ƒnÇ¥Sppu¿»tv|JöjsÉ&ÓpLÊ<«(ÝR4@!<åÂU$åeRÖo©Ç~§‡­F“û?&‹ °OÛs´RÅO­ KyúµxýÚŠå2Ê%‚‹L Λ{- T!>rÐ<ècm¯××6ðúÕÜØí`¿¯6 2;:½"¯·8¯÷såí´Öi7véo®ï`k¿kás1éïG½Ïr:ÍA[Í&Ϟ̨Û‰Ã{O®¢6SÆVwb-ƒ‡gP'Vø‹oÞÆÕí‘¥¾Ô?éi@Œ?B²ùà¡«ó<‰Ü'‘ðHxBëÆË[;Ë4¿:r,ךּ™´/}WÈXä$k ª–ooÓÑ4c ÉÚ'²#<þrÁA‘4]~$P u?—É¡Z­ò¾ iêRΔ‚sMjQ -ÓèÚÙ‰Œihz£À"yêWa¬lS&—§ó+šƒ•oXßhÒgŸ¦S×:톥Ü|½–$H ÎêwZŠ¸Ò¾ôÔOZØÙqd;ØÛYCëà®õÞ{M£Ó棑;müó’ëh˜N:ki!ÕT˜NPø@‘ŒMÔ6(ꯤkÊF*%=G*„ )Tšî–Ë«_ÓEàpQ.7(eSwlcˆ‚Šåbnn»áÎz“]#2ÉyM QŸ-¢A!ÛmIrf¸ïµI(y-+?Ý62±\W¥Ä×É‘N¼¤‘V7;VÏ©¤@¡^;,ʘs‹hÕ&Òè4P_˜³þ'ž-gæPÐÙ:áW†LαŠb×B;±¡šÐ*w“¼¬cC"äè“ù I˜Å“§Unª”29™Î±P(׊”¼´MÐb·AÓb$c«“ÐäJ¡Xð0e±¹¦ï£žäghÂéŽbllSY¨‚µ¸ð´“ƒ60ÖçªÏRHYL;Ã×ùer5TÌö6‘ýnËбå„TJç8j©PߢÁŽÊWÿ_ú³¯YåüÃ>Œ7_½ŠK—öñ™y Ï}ý‚Ùnß¾C™pâÄy´èÈ 'B‡ êåg¿Iv¾ƒÿ±ï£QÏâîM”kmá¼zñUÜúúãcµ&ž(ímCšM²àr€üp` GÓhú]2Þ…“X]äfÒZµédŒYåêê!'O¡Ý£’]´š»xÿû. JÔwõÆò•2nmmbã`ç––,ž^,•øº=ÌÌT‘Ÿ‰°ºB?>@¾¬~¤>*å8)57瑳¤ìúI¿©Œxœô¡ +æ¹›‚µ¹WmqMk£´^O:S{T >åæ’Žœ÷VóZÉ~l‰gà[¸yb¡p…$øž1Ù9@Ñv¶´÷ÆÖÈ®&ßXKm‚6'“B¨³&jôºc4*ªQ¨ Û ŒqN«lò†­…:ÔÞr¯Vl¤×£S*¹F³'&ÉOçHÊð{˜!²iS]:™‚r¸‘cSOt:ðQ•»µmFÕ-ù–jȯúX^œÅÚÕk–£Ö/Òí¹ÈÖ短 äæqøèª5õŸ<}këëxáÕw°µ·kE+.½ò–Õ¹9*ÀYÌ׫tL[Ü›v2]ÄÕæ¶aù"Y*¼ˆëÆP#/q2Ê÷%ƒ¤0FÅ"D:æSt(ô#~Ž?! p+4ŠyËofxˆí®ÚGªÈTgà‰Âåôâ´!>Ç“BŒ‰5ÛWŒ^V‰ýÈÊdžvi è#‚ ch ¢Gg¯èÙ`p_ÕªrÞInÒ·FÓðmdM؈0Í‘%ùQ'J†1X¾4NrUÆ<½dp„ üØ›Võ$b |f¨|n6ÉÉK3H`ºt~{D€ýÀ&Ù¤ræUƒ• GK¥sß(¡µœ˜rÒÔ,9?¥"Æ}žÁ~›þYÅt–*œrHy‚³ZƇ€Œ€+Mç*ࣜŒzLÁPÞ5ÙK…<®ô²ú÷Š-¤¶ì¾ñ§pù>|ìÿxt8¯¿q­“—ðRóþàé?ÃÎo⇞èàÏ/þ^ }à¡÷âAÚÉZ&Nœ<ÎûZµfðùÚi3õÚËE‚¶•“¸ywÿóÿñï(«þ}ÝññO—±ÓÈÁÏàâ•u,-¢Aq¬íØ‘%,®Öp{ýaw×_ÃÌ,e3WÁýïù”ý½²õ-¼sù5s@ùð“”)’Lùþ5l<ûǨl½‰sÏØHDÆÐ¢ƒÒ0ÌðìÖ·c¼ùxiwgñ$Vÿ$þÎ'?†Ó?`Møß|áe|õ…°LÀÙQª›ô%{QÂV#2Y—r•W¥¾ºŒ“1p/ƒÊs>ÎõõØ3QÒY¦&®=A}é³K5: ‘à­mÄ€FØ%8¦üÕGadÍíqÒv¥È…fÇqÒæpèÐa¨¿;;;¦Ee KÆœT=ªV KQϵ…fS<:ã—6Ú^á^tF8;[ÆGN’ -äqƒÿ^o´±AÛVœ) `-YC´­iÛµÉkeæ å[måû ¨TÒ8tÿQTšUôTöH=îá¿ÿÅ_Äá#g±{mñ,‘âĉ£˜Ÿ© ±¿G»EÙ˜_ ‰.n¯ãjëö†{dŠ!Vê³\/¯îÙ>mc‡¬v†2,@“Isÿè¼ê¼Ï•%Åt+©‘Ü+Âã¼êLÔúÃsªg×Z£r(ð~Õj£Ž63ãW,EÔëµ-…§TewS?¶Â³Ä©CP%4¶B?ž#íZ™²ëg V*wHX³ºá€”g–)Ï l9›ØÞß%»¼ƒíÝ&žÃìÜŒÉ& 1²ÂL‹ôM§¾Éƨz\nHÛ¦vœe?ä¾  dód³ÔM a‘´ÐÚ¬HRŸ“Î àõ­À)íçP#àÉzæê!ýŽ1Ád†`Õ§ãö\ÚÕÀèÁ^Ò§z¯oUm3Öa³¢¹ÑjP½è)b£C IVæ Ã›# ,ªru’ŒNㆈ ÔÇYÌ9JYÑGûüùÄš„ÕØ'JP׈ªã謊յrq×ÂSy=ѦÈë4öɒĪ„z’§Ëhöe½ 6K´At‘åVsµ+ô(hD€jÊϪ7L΀ˆ4ÞÛÂÎÆZ(áÖ%:‘ ²ZB: Ĩݰ†øQ«&šè©0Bhó¼‡SGèFÉ4ŸTX‰ÂV]˜Eª–EIó±Î 'æòºô“]x1ÌòÀû*í²aõn¥ScH_¯±„Í«H·¶1n*$Zޱè9Ö¨ðI:X:˜-Â;PuG!-«»×âù¨ýH9ìd’Ê$ŽCÁÿRŽ— Â'ªŒ¹GêÛ5ïé%S‡Æj5i÷È2nÇI¿ŸÆÏi¼áD36Ç<‡´B=‘å\uë*\ò¼ÈÂ#6;ö,<=0‚ä&ƒ <ÓŒ—<èÀ&¥ ôšq2aÄIB«VÕ瓨_n]o¿CYðü…ª Ü(Ü*2驪Nª)š‡Jn x^Ú'M¸±Bü@âdz=“v‡N;0V›Kñ¾ A?£â"GÑÆ}4º?11n^?]ð¬f@ž>­r!kÑ1 wvç9ôÿô"úщ¿ø_ĉßêc¨—>I¦ðxû›oã[{Š¯ÞøSüç§ÿOñ½8¶ú0ÆÝåfƒ½ îl_ÁÚoþ <5­*´¢”‹@˜X~”´]µz] í‹aäÒfr°‘õy§é ”õSG2¨]Œ°ßHK øPë?tËÈ.†·2tÿ9*ìb?£Ÿ•qKÙÈ»0îP—ÓIEù´åIјAqŽ)M§R«%©›œŠ`4¤€_5é>ïCÓ¯Ô&jè¿:4|»í‰õlÍPï´Wƒaжb÷-ùXm·°±¿C6ØÂÕÀdžµ]%ú˜ñ5§«”t'Ш«hæÄÒ"ââ (Å…£tîM\»¶†>ð>ôÐñ?þ~ëßþ_ݽ>¼Š?~‡êèó»[‰Š³9dJ´sïnâz6—çžF ¯D>Êòþhwz{¥l*ÊE\—±šîãÁcc¬ HÇÂ’¦ÌÅVD¨ÆjêЀr¯\c–6LO„I—£„ yªfu@ˆ8ÔPUUgøÚ\2¤EÃ-ŒÓ&õ‡ô Ä“AœÔÉPžDrôØØ'S'm„Šüôà…q ‚T ÆX `9†“t‚·ÖÖðλW"ocn¾ƒ…¥9¬®.¢Z/cÒïY_®H„ɚ­í$Bª yöà1F Ô¿÷` …fÅ­ 4¶Ñ¥Ž9u…Æ'Ã5UÌÁÓAŽI<ŒÔhׇ¨’Ì©§LR9n5ÌÒoòQæà§óÕòVDP!ú¼Àû?úxå—4ÿpby¦Œa›XžÌ³F]1-C+r¼MàXÉÿdâ%yÀiµ¢ÑSÑ ½ÞµCÓP·é:ZÍ1®…7}‹½Ç¨Tòæºê‰õ<S±9“œžTîÒaÐÐÒfØÓ܈J®ÆÊ¡ÅEåRyp¯puÆÂ0Ö›vr¸LôWœYà}ÉRJ´’y«šûP߬ú\mÞ툅h³I–ÞOP+Í`Žh6Ë÷‹U{¢E2®ŽÍåg—Ñ/uèäÛ6€\eùÖ«åE¦À÷ÎV‘.™>}&Jˆ]¸‰ÁÚ·1¢³w‰ÞõĉB.…ZѧÂÌYÏYÁQ¬|vM|Îl4D×Q.f@ 3¶ñdc*sJQÒ4÷ª¼PEe©‚Z>´ÁÝÊOùÎÙ …sÜC‚DŒ… q.=‚_"ƒÈ*dÚ´&±CB¯ðhš¿“Ó^)gÛ@uÏžö¢¹£±“Ìx–ÒÙØB±BõÝJhíñP-­`Òº#V«§É¸ñÄ š<«0&àj’%ö"cIzì’˜„ÎH{éé<4ž®Ï´ÔƒšÂy4™^)ëS4ÀK)l™¶G´ù*òÐøA‡^­ ¸Ê³,a’‚¶5Íd·OåœXTŽWEY¢ØZµ@…ÈpOr(åJVœöݤòÝØ¸ŽÖ¡÷âÌCOâÏ¿ðë¸òÖ X[k¡¦ðž÷GÏÿò×¾„½ÝmÜÙÚÅ·^| ÏÿÕ3hïmæñ'Ÿÿ2e&ƒ3gA·E™só3(–ëxþß@·³³gÎceyk·ÞÁ /<ƒ'?üÜwÿ)\zãæhEÇ£,Íçñãû‡ð›¿þˆ®w¸T:ÛGï§NÕlÌáîî¾òÌ—èX÷ ´þäýNÓÙ,þýoý+|ñ‹¿Mƒ_Ä.Ïc‡²M¾fƒæ×à ¾ÑvðÄOýüO¿úkxòñ' p<ܾ~ëë—ñÎÛ—ðècÀ?ýWÿ7¾õe²·%¤" ^åÙˆãÄ‚!aÒn ðTðõT—‚Ÿ ÏFÃñó5•ù:.ß;iѹÎà±ó5ÜrƦÞx™*²sgàæç"6,wÇCǺ (SÛ·K6¤‰QœÈÒ½Ô‹Æ#özꢞZÍxwéUТÖY]o2±„ÖwX$G¹š­å­òs§9@§Ñ¡C/ãYï+Ë8:SƒOùð3yÌVɦêdaÔÁ!ï«MÛÓá5Êd{ÇWPU¡=ÑÈ5ð7O~êãŸ@—2ò«¿ú¿£±s?øÔ'ðÔg¿Ë÷ߟ´‘(]ÃËÛÃ1’¡ütW)‹\ÑÚ·lε›TP×R%”½íAhááZY¬efåp2íÜócD阅}©÷Ò¡uÓ® ìWÑcwìvi×ÕšR£€52Éø@¯f²2Öö žûZš2GÂû˪àTiÄ2Ï"KgL"Öuúô‚§ 4é`ˆ­ýž ÍhÈ¥¹Ÿs+Çpöüü—:îl¶ñ.ÁÇ.÷^Ãqô”/ù¥‘Š8Õš¥úXI™ÏXÕd'¥Û0=Úúäé3D<'…(øí™’ŸÉåËÔ÷ï¹jm—rºŠXªpj2’Ãm©Üß±bÅš=‹æÎÔjÒ”WcM[Þ7c!iç—¿§«’Jqîô‰Š•k¦¯F¸ …ÈóËxÛcëU®•“‡D1#XiqWÃ¥íw°ÊÌ`ìBPŒ®âëzúƒJª Y•O«:ªm³6”Ÿ<þK싟eMÏ)žhHÿZ&YðÑ$Rž¡0¸Dgûc Ñççhp¹r%ÊÙfrèŠtÔ××6à+˜™­Ùµl|žX”b{4à±*É4&‹×êwzØ!Ãí{˜¯Ô0;7gqø|!ÏCLŠj²Á÷>r•“<¸*ÚºU†Ê^¤ÔÚ>OFTÀjà¤x”JžS 7½wƒ/Á%3Ñ=M&ËMÈè+ÏÛ$›dðƒ=+T‡F¨£¾^18gd õV¸¤x*íWÉ%ƒòU—Wžˆ¨ÓrDªîÕè?9)o¤Ö£a2^•­®œ±>‘«æåj0¸C¥°ùêeÍ(„Vø‡Óž\!ÓQ¶·y¹ö8²$tk…JHª„5r/ÕZ´giÆ#lì$£ •Ÿ †I8PŒÌ†h†¨ @Ü{OµÀ¨ÿy a±«–¶¹©mµúhÒ ªD ¢g*¬”­­J{Là¢"¤J©lƒÉ&ÒŽ÷=ñ$çŽÛ •ÙÙ vÉJþøÿÎx¹€û~_{îkV°Bù}ãÕ·Ñj6øÚ<Ž9LvàósªØÝÛÃëo¾C}›£HWíñoo_zËæìê,.¼çþñ?úyÜ÷ðüÆoý þÞõãܲq±6=ñ„ªÐh—hTTÙâäÃøÀ“ÃSû(Þ¾ø6¶6náîÆ[6ðã}ïý´òü™Ÿÿ)ÌŸÑ”2Ey¸§Ê]:~òåÙÕª¢Á# %K§5ѬM¥½TêFUým:²›ûmÑÊÕ’MIKSÞç*K9uÇé¡ÊÊNÇ¡8W¯ Ík´4ûéY¥¹"l¸7Z© EĦ ´ú8ÇýΠó`úL «q’y­V#à(TíÒ¡‘KQv«\ÛñÅš-Ù¹1 ì^{„}:„Þ(´>ùÝÆ³kÑžžŽ¢¾új õR>aEÓÚµõ¤h¼{d•Ž,ÌãܹӨ.ÍØSŸ&]‚t‚‡L¯D¨çPëaT{BÐÚ%€˜>£ÓžšÌš.†td´5;§›j3"“_YŠqî$P/N,ã4&¡Qû‡Fÿé)V®1ÌI’æ›N=³ >Ótʽ9á‘›z ÙÓ’Ôª˜6Ÿ`Ï%NˆZ2ÕL *3ˆâL#SŠ’ñ,ªìG6ÒtjR™kâéßšª¥'½Peok$š°w÷î-›Ñ®N‘åÃK(•ËÖïa®¥(“ŽÕuX*éo<63i«ö¬ÎÞzOǪsDùäécê’bÇdÀKh£œ’´A·ßµŸùŸv"oçÖéù6÷^6C<}ôÿÓõPv]וà~ïç\9W¡PÈ‘@Š"ER”(Š•¨Ð ívÛ3cOOlõ,{µÛjY–G–e[²d%+‘(JbÎ$ © ±rúõs|sö¹÷ý5Ó\¬…ªþÿïÝwï‰ûìÍ^¯´sêAÓʼëòA/L”œ6‘ %œá¿¶= ×N‘‡éWíDú©¦j̱äèêÂhÙ˜}”ˆa•10zcHYú$HÀЮ¹:'P„i]§MײôØ962‰p¨¸(Ù9^ë^LI¢ÔMuÃȉŒ«ö§êÊEs³°¶$(@ FÂiÙ8œíbÄé8FºÇQú<ÃiAš´r©ˆ¥å¬Î7öww)ÉÌf”%„°êÊâÔà…†%cNŠ3XÐ^ ^Ð2ŸÊgö$%šŠõkAEz)j*¯k,_0Ùt4%.Où¼°Ž„PP• †Éë‚yÖƒq-¿SÔ–¿¦“d.™!é•è9`"sÝDì‘•&2L÷u£ÃÙÀPÉäªH®gšú žfÀìRl©|ɰL3DÛÕU±Æ ¿•Ð^d˦¢j‚gµ#¨ÚϪ)én‹ºËˆ7”Ø‚ÁuEG;ÊåÚC¬šƒ¼F×lz¿´Ìl¼R)ªó‰¡YX)ãÐÔœ8Æ j%éÞØ]ZGƒƒL½©»X0­‰þÎ>ŸXgœÚ/™Ââ¢¼Ï ÒÝíZÎZžgYò³å;>?;¥û/«°1V((@­à½7·¾ó6 uçñůýýÉ1\{ߨÖYŒ8Û±09ïüðG8}f\n™tèÖ÷à]·Ý'_xU²«26­»T2™dÒ]èSXþ±£ˆáYÆ;ßu6mÙ„ø9¿ô*–qÓ×*–áèëGÄ0UOG0:¶s³ULœSb“ƒžWØÈаœ…®Ù»ÿÛÿõ?©†ï7ïÃñ·ÞBŒFD"ù!±D‹sKøØ?!ï3ó3X*Ì#{¾ŠƒûªÌÙ]wÝ„×ß|/8†Ã‡Ÿ•L,hRÎñòüº2mš½ÌK@ªãb©æ‘—µŽˆáíèç·‚Å¥ |ú$ºŸ_(b^lº'ªãK3y1¢U õôkÆ1%†ç•Ñ&q­B™Æ2.Ù8¤x.W§JÁì€f,$ ð¼F ›åv[NÁÈ~9 òYn<ö.Gcpg­§ 0uͬƒ†æV3ìþöú2QÄSb³dëŲ²nJq?9³,÷X@„™²ï8OÍêJ&”÷龋QÄAî›ìe²iY«†|Oæ7N*°ü°AéíT3>€²ÜBA‚ N”kF Èl4Ñ”uK¹’-5B:‰‹ôЙñT°€üäzGJÔeæÁƒj'aTTlœkxµ]³–*´qtœ„çC§XoV-­¤£í?½ÖXÐ2’5 ú©JTÍ’îk"ÖÐ×Õ »¹:aŸÂ´Þ0­&¥å¨xJâbXM PÑQgmí)Ìse¬Î-úuÉÖ^Ð1PÇôêH#Ñ– –Þ7× uþ°ÎÕu’úþLPØV"03™b+!ª—J ££w&;å—‚ãvõ¦>OBö U=˜o)grÐLà˜¢ŒKP‡¡h¨YØi*AtP_Ãr^Õc%Ù*WxšUÑÑiÙ‚<4bµêk}Ë+« Â±Ž £Ÿß”Œ„D¤gcY0*é:3§2³7Šh#¨t\8lrË9¨X$®c$®)£,ÕH4sk,™0X “_^É©&^T+ÓÕ…ÆM]ZKŸ®ªr€‹@D H²C‰؉$ÃG€€€ÇYÄ@=Ëh}ž=É dR‘pR ÜÑA$Ú7$Ž:$A˜Ð&Ù¤ü "Rc¡¤D<,eÖ̺ɲp›:°d!¡Þa8FÈ;‰bŠ”æzº’¸±ˆ–Åõ y ÍDÌ3l¨~“Cù.¥G‘÷ ³ôÒrŸáñ<Ѥ£eISI÷u“î,¼dˆ!JQѨt*ÂÖE3çÑÝч×]‡ÛÅ¿zoÍÁÑ7áà#/ËYÊàÏÿãÿŠmÛ¶ã#¯a¥TÀr.ŠÓ]—ìÂ…©Yc1#X˜Ÿ–¯ rKØ}å;pý7 CŒö÷¿õm\8sN‚†:Øœ8¥l®ˆ»ßûA\¾c¦&ðìs/`ã¦õ’ÑîÀ¿~ï;èéNaß 7`óºmÈ${pø•×Ð?2ˆç_zßÿîw•Í,$‡¾SîíÊ«®ÁïýéŸÉŸ7aòÈŠ‹“8X~¹yx§©«Ƨ?÷Ì‹Ã~yÿxü™_è˜UPX™`;£·#…ödL鬪¥å5R3Ö‹HÊš­êW’ ްdRIŒ IF‡X@J²Vãjì—ØÔÛö¶ŒÝóýÓÝq%uO†ؼ¾Y“J}?qŽ5Ò:F!©•‘8ðiTLžUO²Õ‘Šê¸6 ²Á:Ú e3ÚÇV—žc&üEÄV¤ålµÉÚqR!Ä€¨cŽbÈYN¥Û-\®RÂE2™›“kmèÜ£« %£´’cNJÀP:¡€-Ú VƒÂ ÙJ tÊV&ט¦Î…Õ%¢äƒ–ÿ<4ΪÂj¡¬GS˜JSË‘q »»)ÙžáœmœÚ”bTšê„”£VÿnF_ÂaG5bÃa£‰‰8ú"ƒÃ޼‡<{W‚û Ú]*7‘‰ËôåƒFgC[<rPú0h°”@Þ3ÚĬ7‡Jü†q†!eƒŠ):;O g šâî²Þløä¤&P)hƒ%®¿ÈLǯ ©¸üF›HÇI:]¶*•íIÖ:,r.6‹éø“g5¢U7ÙN(\I4pC¹K#€žíú§(•âqe›b’¦í í;Ë5lÌ|^K7 ÅÒ‹óšfhUñ©¬Y7ÌF£±sYiš¬ÅS¦£¿ÜØŒ‰t¥¨°Îb†Œvœnl"3-|™À@,•ÌÎmãªÀAMû",_)Ÿ$ñhjô¡ài¶Y# v»ŽÌP?ÓJŽko7Ð4€Ÿz¥dîÏ3šwœ/¥#寥ôÎòò²n>>€tGFŒkÒP§1£"—–ªZ¢Œ©„\Må׸NÚÃãfÑ÷ôA5¦8Ó°£3ªÌ2th\ßj]Á\fSÀÌëéÐ<4ãý)å#çÅ–È^þlª^§DJ!…LÙÕ±ÁˆÒ2rjx¾B¸‚5”vœÔq¬´–%¸·"Úšm:&r´ô)FKÕŽËè!› KFnØô@X7¢Â›†ÔÁµâuö!j §ÈaÏhL*DŸßQÊL+#¦*aÆZLɘ%m%›°c-uÍ*šZŽ#¯3IÚ%KÉž)HæZ—ß].ÕU­¢#Q¾ÒÎ܉ãl£4[ªÈÏK`6*ë5)Ù)gÔúà‰S.()µÓÈU ˜\ZD§d©TJ³\F£<¨ÜÀFD:S'_CG[NG±šÇ;.߇îpÖ mÀå{®Â½½k׬ÃჯàÜÙ =tèO‰“ߺ¶G¿‰Á¾Œôwɾ”÷›x'NžCgWç/œý*F8ÕáÑN,,.è3ýâ—ÿWì½m±6•„ãû¾ðÂÓØº~ »wlTõ˜Ý—ÝŒDÛ %Ã^\œÃ!Éh¿rΟA:F{{R2Äy¬ß° ¿ÿû‚÷¾ëäüüñ$Èä|¹™:®¸üJ\vÙ¥øÎ÷ÿýâ'ìŒ*ùK@˜›èïhC&ÅôbV©ýÚ:úŒKźfAÝ]½âüj˜ZÊk%i°§ 3KË8—gš‰«è¹–üeýûÚ;‘Œ§qâÜ9)\ÞÁvIYœŽdöýÈÈÏ*rV*öÙŬ:¯¶-€¦c³Wƒd ä)ñ»g—ªVPVŸd˜-'1´ì¿‘0DuQ5ÎTIÍR—§Í£Ld„T€â\H¼5UÊÔ))ŠVt$+%{”œsVÞºÉÌÃþ?'$äx$e¯&hÔƒDÛBÛS†3ÚÓ1¡Z¡ª ΰR †töÚqº'õœ*£”ÁŒ6—"êšñ!M gm˜uÔdïÆ a¿á€U¾ñ<{Žª0$¥jØÑùaM†`Y“|(Mí\­D$FAñ^Pgà<¥«/”•¢$ÐGÕ=×–«¬Ž‡ÖÒ Û–¶—`ZDlçÐþÁŠr0`s`F3UÆÎzºVAËpƘ’oÀ§vUrOG CA[z¦ —ëiVIT±–dfÌÇõgëiÓ9ŠÇ ËjJ³®˜ Ef™65¨ 'Ç´’ä&+*:^Ö` ™' íd ž›RŸw4iô‘›M£bù[5U¦# ~C­ä6,ª‘ 1Î’i»«`$ÃȨ©ä¦Ö®ƒù>§«ntO%|ðš!ÛÙ¦½ S^.Û3Ôuêh”ÖÏôæxÝt¶A›Õò×UPé@Q^Ê9Vä+ÙTãö´¶ÔÔŸ›“óD\ô*¡Ð sï\0RODÃLÛk–5{¡ áßë SÞvIh@'CRhÊú I¶#N‡Ù½«Ë }ÀÚ»dY½QV€Ž™,²F—”=3ó2'`(ÜÖa²$O¤´¼`H{°e-¿¼ê*!=ì8ËWæµÄãšëu­3uøµßK៾ö¨–Èa~îø%4–5`f:ƒÚjy6Ç=ÂO*7«j0z>7rÓÌ rSÇBFÌ›è<²ÙKâËZ†Ò×i0bZµRÍJÀYÒua­ë¼£–åuDnæËbôå0ÅÅi­6ŒÚ¾„´K´Íî¼8Çîönå<^˜ŸW-DŽ¥Ë%éʞY{FÞ§ˆå…e¤´wÔkr­>.2¶°|þì³OŠC{ 3’e~ðý÷Šƒhâä©3èÔ¾ó÷¿÷=¼òê+ªCG®ã=âìo¹i/¶l߬Ϥ8Å¢|ë6nÀáC/©ãêéíŵ{oAßZ4Êóxúɧ±ïÆ}ؽóRÌŸŸÃÔø„dDe¼yìMLÎÍèu}úSǶ]—à僯ã‹_ú¯r-óXÉMãÅO!»4¡Þ5F\[šòjÍÁ 7ìCW[/Ò©´d¯I¬ïß„÷ÞüUUùÆ7þÏ<ó$}üåºÄ̾dÇ뎆"˜—5¬85$2 Õ]Íg‹j+º;:õÍÎÌi¯¶_îgaa ‹+YÉJÃòYq” yÕªmOI+ë|nòµ½‘hOÈ:­ &ïHW—8²˜ÚE·ë8GC{fçU›føßò§´æQ‰h%÷7ÏcŒ´y¸––Œ"-™¿èäkâ*ªˆbJŸÆþÔö¨ýöÌ™LË{¤âœ›h¯Ø• %²”m ž=ªäØeûFþ®èfý ʽE‘{ÖײeÁ®J `ô§)“¨*,–p!` UTRÍÈVOï)`އdìå’s$dM{¦”ÍɈþGÙXA0 cHfš†ç˜gŽ=ñG=L_™öTÇýš>ã”é‹Kn×µíĸhÐnÿ¬+ñÀÅ_N+`‡UkÑÑ•ˆ ¨ý2+·å8=?ê‡U{áíë{¬–pýj„Ú:×´"µ’°Ž/h×Ó¾SäE–f£Õ/mZ®bÓ“5e^ÞO«?ë¾>#Ó20£óžj˜ Ÿû„÷^[‘%Øq¥¨ëØ**ìÆñYž³äà*í£ð`Ï* ˜ mêÞ¦?êîví§r“›’¼ïùMÃX£Ïf¦¾Á×1#ØÕ„aï scöèY…“ u $€0-Y“ªó¦h”µœ4% –ã,o°Ü@äi0¬ C”AbpO§åïQþ‚vžˆ*„e/gWÔȲgF HöÝ’‰„JFUeªá¡ ‹AqlÏ—äê®ulŒ0é`,5³¯Ê ×ާ«5x 3*+pÁæ› Ûµ‚ÜA7`#·€FÜü™9lAãý` hz˜®eê€Ý@¾l·™-µ¼ðg õZ2±‡Ø "yWåÄLTìj¯Í1Y­k£}²ü¦ ”x쑸 ÏRšç¥¼–£YëÚë±Ý cX¶ ™õg$VcÄ]3ý]ÝììÏ“bжüÙUX¹Z ”xÕ]$Äp8;[ɉAv$[,+ê¯-ž”ˆY²­JEÞ£¢ ·’ü~Y6þPW·Ê6Í,É3ÝÝ݉Š8ååÅ-Û‘Æ%¦£P;cFRâ&¿Õy%U#£üeÉÒ^yåNŸÅ믿ÙÙi8ð2^|ñÉzSÄìÜœ²'‹ÍÖ ²çž{ö1Úyã˜"Û‡†ÛÄÆqõÕ7¢o`­¾næô›8´ÿ€"?óÙ–çT÷åƒòþ^B4GŸdÚ ŽŸÄ_üÅA¹8‡Û‡Åy/HVƦõCbÔc8>1…¢dãiY›ÎÎn”ÊuÙßCXœ_Æ£>ާŸ}Q¡¾ñ/_ÃÔôYœ=?aªC]²ª$¬ð°ZR(”QæèVÊÚ[.k©”Èš¬Âz:•v6[Òç—ঘ/ëH]—>‡ÎONéü_L3ÉJÚÓ!lX3„(QŽ«rUÚ:>–?9­Æ :¾Ô¢5¤Ì*²¯•³Ê¨-U'JwŠ ÐF-I Æùdâ `N›¢j•_ZƒC`•¥mÑge…¤#¬0yFìžeí9nKÝ<#Så/Õ9Zb†ÎÌ65 ó5—5 ™9n­@’:1lð MmWÔò¬Àh]³tÒõÑFéµÊï¦ô´‡ŒÝ¥ŽiбsP«;ú½u: l˜Ñ“H¹Ê€TWzφ:{ÒÆªì¡þžÉ2µç:­„KYËlËÍõ~×±•K«ZãY‰HÏ´÷TO”åQ+’¡}íVéÞ}[?\W¸•™Úßð[®ÖDÊqZ¿ïóÞ,…+ ƒr»GL?Ý&{~ßXûªnË)ûúïcgB*ÒA_´¸´„ÉéY¬È¹ìhïDOO¯ïP›­ ‰W_kšhH57åg!½SB0©&tëêxaŒ¥¹¦E13?š9f1Õ¨[GêX¶u*ÖÙ„žU”7ÑFÀ5äåŽãghV´Ú3À)*!¨ÎË'áPë­SˆÄÊëH¢ú‚€af )BËs.\ÀAÉzŸ}á9twu¨ƒX¿nNž>÷ï—l?(÷Ò‰¡ŒÎ€n” Tœ\-„-—\R±ŒËwíÃYÅ«GŽˆ“kÃãO>ŠýžS®Ù“'Žc~႞™„dúaͬz_tN 4ÀýÈ@6/:Õú{ûõ ­,³´D—dªKòžs ‹zޏ~+H4Ä‘õv÷)ztF î­L[B‚<Ú$›»áÊVH¡WS­ÙŠgŒ¶êo¨¢ {”e‹ý]’:T› h¶©U/Sýq4£¬!'ÍüJY‚¬º‘SðU\á ºðÍ23Ý6É4 âB8hEjƙۋ§­1?ƒ«›@Ðã¦ÚœÍÔx29.fl†¥òtÌFÀÊÏ)¹ŠEÊ7mûD²|Ouªñ<’¼ž l2TqtÇ–+›Ý6]“ùz¾íõÁ7 3Ï®m˜¹EM2¤€-ǵö¶Ù*Ñ2Ù!8È$/Û4èÚŸMÏ€Pƒj÷™œé„…gûÖ¾3 ˜´¯;j2TùÍÕª˜ë¾í{ó\Í3ò©_={ûkaÛFžõŽÉ:V¬USëPýÏøA|±ƒ &G0ïcnnÓÓ3Üô÷cÃúMè”àÁf`sêó«©yÅeÉŠÁõjšVuN£åÅÉ‹Xkš…jÚ’Œ"Ÿ ë±q¨¬m;®u¨&Öq,˜€Ã±ÔàÓ2§£)`¹^=gUò˳¡œŽZP,h²5n^‚S8PVHºMñ#)Ó¯d9ÌÒO@{ÁZ*%úW^·@¨»d¥t,w¥ÅøÆÄ ³ÔÊ>(£çþ~í‰Ð °D[—ìG·£>LqÚѨF+üžïò3Ô0gj&BtL™\#)×d¢þ&b”âÙÔQ5ÿnküZ~÷7ݪ#äá3÷m²»€¢ß|ghœ§/Ë ²ŽU7ŸJ… r:¶Ûw¢Ö)»6K ˜{е7u0spìXŒÝeÆi*ªÈQ'[¶iØ~­ö Zñ&ZÚ­ ÍÏ=_¢®V7_Ú;-ï7ñ¥Y=cŒhøÂì÷):±©¬4ƒ(Yó#w–4Ƀ*Ÿ×ÑÆQ ù·š‡v1É’râLV²YôK–FÇ;+Ù Ð@oŸŽ‘m%šLhŸŽŽ',ë“N¥´Ÿ_"zS¹Jãâ\«†ø$ÃúMëå5äS®ˆcÐýüø[Zš– Œe¡5£k$cëR6¦‘ÑŒdJ0@ª³`¤ñ0ÄÉ^…§&qã»ö¢»#ªÃÇŸ|+²WIž>#N{ne —\²ëFFt,Šü¯Ó“rO ¬ÚNÉŠ;Û£(fÅ‘ÉuŸ9=‹Á¡mø‹¿þ;5z^~‡P Ðéù%ÉJÆ9/F!£Ùú&¹ž¥|!«Ž´®ê>•[ô9K‰üd¶^)QfÍźÁ~ýÙìÜ¢þ^œŸ¥Å%Ì,çt¶´[2éln9q2#}Ê`uazZ« ííbÐÙR)cëº/..È^}(ŸAÚ”kÎ=Á9lÙ75ã!ZÈO?«Q€¡qmöÆ¿7mÏÖJ¾„\ÅôO=¿í¡:WžéØžMƒÓöT qÉRI\Â^?) MÖeZb ×̵ë<+ ÷åªöYMŸZše勊R<{”lS‹«A¼åüvZ@[ P}=aS~5Δ7À=“Ï”I¬Möw&ׄ„=b×Ñi Í«Ô!6|¼‹^nÓŒ¼X‚„†-²¼KÖ#Ô Œ²¥V¸¦KçEgËÇí#j=¿zdóIž}rçòýxheÆÛjÓq;$ûN¶‚Ùl¢å< Ø'ÐrrÆqMÒeŸÑ*gºó6GlªvîE¢áš-‡í´* üÏ[uÈ Ûú iÐÔkZ\ʪ#å¹o—dkíè†FÆNgŒ/×i¬+ýyÓS33DlleÓ/‡Û$R–,«˜Óèò6,"{–ѳ×ôDaKö†890™†¶>-d: BÀT¬:…Æ”tÐêå 7¦jÕÒ¢¥øA`™caÝM;6@Òž=£Zf¦ÛÃÉC¯œ½u£Xcü7Ç'Û×^»i øÑ³öùå5öúÄÐÓ`åçËò|9TŸŒ'4^CÄMT2ƒ£\v]íòœ£˜—  —x:¡÷§szòÅl4&kF2–¡IüÀŒÀ„r­‚¤¦n¼I2ݼdjdÒÝš‰¦Ûb²¯–t„‚F•døç¦N«ÁéNãèä,&&–UV¬­½O²Ñ+‘Ï9è[#~*‡ëGÐ7Ðþ¡aœŸÀ«‡ŽHpg=ˆÝÛw %Nk\²_²yãú× [LàÖ[?€üâkH†‹rO+X¢fe %Y°‡nºUŸËÏ~ùäÞÛÛ»0:¼Å0U¹5ŒKVÙ­gx͆1œŸ™ÒêC*dZ$DëÝÈ™>ªÿ8!âˆWU‡ÉLè§¼(™i®RT€³ÕqÜÉŽ»::’ øìÌYÔB -‰œ”kX—êBšâÐaq®%qJÔO+p‘òyÄ1-¬LùFÏ[™©®8š½!-á\)šÝ5F7_m`Q²ä|Í€} «¯D ©Ö€s5|Ä+šHhÐ̽T³Áìˆ Iü7ú>-¨ì¤fMýž@²\£¢ó™cïµL)D×kÙTíoS„c‹ÖF²%ÂÉ VÊXjŸ]È*cY»Ø¾NÉœã”O#r_u*ZyÓÔ4‡Úöa†OŸ,™¨W£&uHϬ¡ieH±Š>ÒÚ7ëÆ±ÙöqОŽâñþYf¦Ì ×qýñ#Ob ¿­í˜V‘×ÌoBŽEÑ:–ÂÖ\¦gû’- ‡Åmë‹UãT]Û š{ôGaö€g&ã Í—kÑ·~;–öXÍ\µ C)è;wV3YÕbedY‚Âsç¦ô uvõclÝFŒŽm3Þa–Ù3ª3Ü]µÉÏÔ˜´)•\ØC˜)Hv'ƒ$ËÍr^Ú5"q ¢Ž¥ŒzÓ̙ңŸ>[ºWý¸*Hî2¬¶=­=8G帚ŠÄ …< ç^M¿[‘ %Û$%+ fWg—–Žr¥*"r ‹fE<‘–lÛÕ,ö¦Ø7Ó±8 ÷ªª{®a"C+:ÊR?OÑ¿‹Y1œ%íGhß ÐA4oTOtFM-ßFZ™ PXœ:Kƒ†ž*¨*$¦mz+y=ɸ‘õý”´>¢Y¤>P1ôüâ8 ŸÙû¥`o@=ïÙUˆxØf ÁÂ8d8¡ãdQäc(lzÑ!ãd™‰†ÉÌÄ2…ýµ =‡%hÐÁxÏ’áÃÛöA+_å!â°|Í0­FØrK«—¡ýs òðO6ÓU#È~£NÇq[N~ÛGvZYn³¹ €b­û,`öœŠ&éÙ#‹h/µ*¿CéÀ¤ÜS&N†àŠŽtXÙ•<ëå|]Ý=:µ’_Q#OH†”/éý$Hîaɱyóʆ"Èh¹\ÇÝ÷¼_µ(Ÿ8…žî~ùêUGŸË/itppDöj^i ‰†ÊŸóK³JV I&I•¹ž¹…2z;×`‰?k¬ VŠá²+¶kùoû¶íÏâôé³r]+X˜™ÄR.‹ö¾^¤úû•&³RæºbÍàZÌNA¥‘ÇÉ3³öŠár1;+‘u-‹o~ë1qz\g·l¾QÙ#3Mɹš›ŸÓ5íêêÀ¡C„GÒ”Œd˜Efu$XCçW:¶äiÓ}rM‹â¬W 9Yо6×J2ªÞ~Åœ“(ß#¬8ÓŠ¬a:žÂ¶ Ãð òžâÌ:úSŠÌ¯–Ø£Žk㬩4IMXnª`¼ØùeBß@Ÿ%±•± ExòWKâìh/ÊêPWKŒÌbcÁ€"©¥L›S³ó‘ñXD³uE9ÓÞq¯«ðƒ9 TÊâ!/0Š¢ãmÿŽ×©A¨gÛò95 n Jº^·ã?¦_i”Tê¶PÕž& V9â·¼RÐysöÅY=Ñ,´QSÇGŤ‹Š¦« _MlZ$nȉ»ú;ZäÕó¦ÁAÍô Ux|5~nu8Må°á74MÆi‰òµê4-47hf}µ=çº?fî£jÅjÔ/³^\Ú5>`µìëûþþâ/Ç–wÕþüN™X3Û€ÅØlÕŸK®«jŒI&hO9DciigΞÓj@ÿ 6nÞ*ö+O´O†ïWlýϪCä„<“•0{ 墘Z(!ÕÓ%Q4y;M¿Q×Ð53;õ¦™U"œˆ@%h#hÁÏäû•èÇS’êQ6Ñð ¤ŽËØ¯F‰è¯Al·®pmÏ[ÝízáÊ$ä©xqg™eIöIEš DjÇ9ÂT~H(Ú.,`§,Î’d,DrÖ)*ŽÑ³}±® U ‚ŠP õôˆ‘,ho…—Þži“ ›”ë/KTN”_TxH5<ý^­Ëþ§80öÜèµYZa–É’yZÙWõû1ÝUäjpn®UY#HÒ2êU£½DŸÅ”³¹íhLÈbÅéÚ8„îøØq«þãYTgÊøÀ]­ž1ÏD¡ˆ«†"hAG:àH‚ª±8%­ÌMƒlu”Tzu^ÏU7[_þÆ5%›¦F“onXgêorŸ„Ù¬‘”rHz¹j´5íÅ*é¢>ˆàL_Ç”¤Ya©0'™KX®µOœD3lj|y tØ ¦“è’ «&ÆžLIQ)Œ‰,áÜì¤dJdÚÒj(8DßIQyYo–Z¹wèHYðeÁø5¶n ¶m݆¿ø‹¿Âº±Ú:ÈÑE2³çf$²]Àèèz}ß•ÅyܵïflÞ8‚S“§ðôso¢B²úHbµ€ ˆ8mÈæÎâú›6aÿ‹¯ˆ3îÄ]÷Þ$Ùg?¾øå/áÈ«¯`ÿƒ:â°kÇ õàGßû&%€833‹áÁ8tàÝkm=âô‰qÉvèÌ:ðoýª ‘Bò|ãT¶áõ7‰SŒêÚ¦SmX뜞I¡,A ÓHÎË}„åìtvuª÷F&žÔ]W©UÕ Å¨W)ç|niA"ù²¶Qí±×ÈŽ&Φ¿@‘¯ç§&áÅ‚ªÈR“µÍÄ2ÚÓHQ<·dÆæX•bo5­FÜ€%ɪíQj?²éšáhÏ/®U–÷’IY‡ì<²k̳¢Ù¥ /.ú†—{^YÛ´uÕT@GY” ›¶-â:-TªÓʆŒ³&ò³áƒpƒ®g°Y 8*2gµJ~¢ÙžMRŠ$©' TõlqvŽq.ü ¾>Ô43 Z%°¥ -OäÙ2†80bÏ8Á¨Ï@Ôbˆ1=&R%)#25,žµDïeem2`²ªÐ µ±ãù°x%·³2š¥ÞÛŽ„olü` ~5ÇÃÛ2LÃΜéžh®f†ÚеԔ^k4Ǽ¯ÙCÌþ=ÇÈÊÕët‘ ªMœª…布¹¢d¢òüzÛz0³4‡J±¤:Œ1yF*jœ(ʲfܱLD­eÎ_3Õä5Ã,!©‚‰aO>õ”:Ù±±u˜™™×’®)ÿSSÓšUòr× cóÖÍ83ñ>÷©÷áºë÷âïÿþûxýØkX32‚Lrì³ Oaâdk×nÂw¿ó/8vâÞó¾÷`Ó¶¸|Ïå¸T¾æWd/Ë¡þÇ¿ù^yþ)ÔäìLÍ,"šÏ_BGgããóòÙobóºì½üdg²Ø½kÞ?׎žÒ}~nò<©¸´Œ '4ð(Ur8vò:ã 3­Q†¬QUÀñ¤{ä÷aªs„£bàó†„'`dïÊÕ’ŠÓ$ãe5 X `°³Gƒ¦3âLÉ Ä^s½,ÎTžé¶Ñ5 zj¹PÑq/¢wix9Ûç6Š*+æH6M{@0’¢\µè®fOx»¥ƒ×™fÇèqzå¦Îk†\Óó':Ø {W¹ßGsüžœÝw>&{£EÉõU &-.ÄG˜úý7ÍzˆeàùjÎ÷¨ ³YÉtF]ÎMÎ++ífI ^\$¦¼©DŠú©5-”$Óg"ÕÏÌ— RЕg‡Œ¶Œ»k31µ ;²0Ù”ëYÀ¢o‹aæ>­^¨%¢LéÚ–ž¥ôƒKt휹顶Ĺ툃R;Ú@»i³S¿ÌëûŠßµos©=[¼†½mÕ!®é«ß_œåúã2LPe‘¼ZÅ\¥Cd;‚¶rè£úú†T¡(•J뺰ÿÍ6QȪôsÝÕ¤öÕHâÙ"P‡¶ŸýAfM±J ñ@Ó’öu£ž[”¶$bUrù¦-'˜!ÝP$©ôXèlªd¹t»M?ƒ1‘Š/4ÎlD#ygª¯ðaG,dÝèÙø¥f#ËFL´ÉÁ¯I$œG,Ãg†Síb˜†%Н¿qF{{.I”eÃr4¢a)ñ8—Ö-‘öº±Q퓲d“h™Ô‰M–V,Œœ‹ÈþYR2›`Œ¬ž™}Õ ƒ–¥øm,¦‡n`dÇŽŸÀo¼`¨®HÁÈ*S@rÐÖ*z¿mI‰ÖÛ±f¸.‡±Å‘ëf'E ¨%qîÇ'&´Ç娠Bi»Yå>âñ¸dÛ)É~é騲lÝ–dcñ„‚ž|òY¹ç vo_/÷šÑ^Œg+ }Ã}XZYÁcO>-Ʀ±‘~t´gÄåµ_Ú°„Žå=Ö ‚E)ús¡~×´aç¸\K±ÚÇpZN¸øß= „ƒ®©Âç뵌ßóá¼-Çm¢j…ÿ³ÕBðñï4R²åAzîK’zt±4Ù‘Ä©å%'kO5.÷Ý&Î`aiI³0Vâɸ–y˜âò âÉ4rËYK&ôüJVl$ çžá®Ès:vì¸d 5q`íèÇ©Sg%ˆ+©*FëÓxÊa[Îfñ•oþ+ÚR¶ïèÇÜbWíÙ¢¨äçŸÛå…úzÐÙÇÁý¯Ë~Y‘÷Ác>Žo~ë[غs‹8Õõò %»Yt0;©¤«bç÷?ô‡· ÝÞÐŒúüÔ‚Ü[ ›Ööã’m]Øw㘚XÂÏžÚ¯",[Qã3÷ÐÙ1 Ldt ®Ábv‰”d¯²Î]@{dîíXƒ³¼Dµ¦°¼¦KÑÂl‰¤%û®Ê>É‘ƒVO”¤á²n¹|N3œÞt‡îûÉÙixaa vk…e x‚Ø:4ˆ„SE%;gHî©x³¼"AEñDXU«jÜ–€X[uC*㯭jìz&kúU¬8ÉÑ=¥³å . ¡Ö4”}†:nµ4jzoN«D u0ÁŒS33—F*NÔ³ ;ŰŸë5mñלw#fÈ‚¶W’ìžÜ¿m @ŽLf9"Â9çl·»q`Aß횾®çÎ[*{±ÍއT°Á³Ó Ê«Ä/MÃ…N TÚ ‹;Q LÃé8Æn×üþ¯±=ü»–~/ÊBMhMÚH¶©»;#Ï¥aFŠˆúåÖ¶‹ÎsšR*§%‚:šh{²ÔmZ ’#ö'|i6?0jõ;/:ÿ¾©JK6ÍÅ\œ‰š±ÏJø™¤Oƒ‡‹fèub„‚›oøš¦uõ%3³ ÄÁÐж •¬ˆýk7`‰p ]c‹pÂ]Bñë„áöØç]+mãØyÒˆ¢{+(‰C\*Ô…GBþ#NÃÖŽ­$škG™3™nÍz¼Ê <ÉÔæêqíU8ž¿àu­õ³O˨FÌZ%P†=¾)èH|ÀHÆ1³AÊuÅÚ­„U§5HåRïEãZšâ VH2Ò§Ãå÷¼h‚éDÓ]Hut££»OŒãÉj E¼qüÖ £«ã!ÄSˆˆ!M¥3b˜Úu‘ü¨œ9UБ·’ëЀ‚Ú'MÆ“ °™\. ÜˆËï÷ÈçË{vv‹ñíB"Ó#Î~í]käebˆq¼öÆ É Ø4:¬Y:•X:®SxkªˆZ¼©®µÈtŽ!Ý3ŠD¿Dñ£hïÛˆdÏ¢ò~…f‡^{ƒ}èÎd´Dè%Üp µPŠ¡>L€#¯½¬Ãö½b (¡öjС<”8æþu¨'GpvzQA4£k%Z®éÆõœ²˜ðY)ë•§ÊgEò”„¡iˆµu“›¾K#àZP‘Ó"®†Ìãæku~-Ë}ÌÚýHXõY• Îm9aK.gÊØn‹oßöhà ¥‚‰f—’aíá€y10p¦tƒ¡Z½n‰vL“É“CŸ–}Å” ŸÆŠÕ Ø‘ ÃumF *ÕŠ 츜 ™çÎÌ¢££C _VÇoV(üLi»H@ÈŠ8ж¶,Ê™xíÅ#¸ã7aI²åÉé¬dx)Y›ÕÒìènÃÙ³SâÜqÃM×ãò»±0=¯4†Ô¦¤nc*íI†RÀ/~ñ<6o܉îÞ ÎÏMãÂ̬R7Ž ÆpíåÛqòÄüúÉC8tü,^zí œ8u^Ÿ[§N]$Qh°,kDñv¹–F9&,F›€¢;ÉÆ%†‡Ïš‚à¤í$!û‹Ä*°£Õ ë:×¢»©BÒªÎb~YÙxRmQy2ºäÑmèE<(ûªRÔ²ª+Aír®‚•e™ÒHfÈ/J`P©›q#qFÅrCö¡É|*,Û9¦—q¦¢Á©køy}ìg@K¡!”¨í)ïW x¨ÙXÍd†Å‡Åؤ8ýâ ,éAÓ8P²D錪’‘˜±A•ýjèPˆ8ʺ^ûêN)ùŒMùøzË æ=S®5L7"¿@q÷ÁˆŽñÇaª¬‰-hZFÜùbÉ0­ÙÑŸZ¹®èèL[Hl4qU„|$dÕÕ,ÝM…q+R¢’B„VµWjÄPHh'(âò¼©ÀDú:AT¨*°JI¿5°à™ ê}DtÞæøä2®A47š¦­kTÅ1OY”Èdgì¾:pfò²Þ±XØSÙ6³P1Ê6›-úZßµwlgTaƃ ZºiÀ~éØT*ˆOÑ–“ýW‡?¿ÃÄÄ”Åî aó–í’™*¦§áù=^ÓÊl4k)ÝT;¬á˜J€ èk»ÒŸo±RLÍŸà <êâP‹rcD®ãÏíJI¢Çˆ)-Ô휩Ѵ’c׊+zÁ ¹²j¡úÇÿ_Zßš3Òl·¡$ í’ÅQýݧÌㆠEX.6°¯(b6šLª 3POMMáì…)|ü3¿'NlP^_?3¸~tuö£§gë7]"ŽmýC$ .íç°mëf-ã­ß´EïãÇ<$pcë×Ë& Yt›£ ‰»ŸzîE¼&†½XŽÕ0ªáÿüÑ'qÓ¾»°÷Ú;Äà¤1Ø·òó®þ!tcdÝFŒmÚŽžþtI†|òøQlÞ´^K8…b/|ûÞ}7.½î„=‘,r-º‡F±fh«<ì1Œmة׿~Ë.8rÝç'NcÝšau6|ˆ,U=1×Þ:;îºcwÉlÃoû Ò™F$ bé9"QîSÏ¿ˆµváÚÞ‡™É3ÈÎO`lxPKþ¦Y_W§j¼ÆÂnž€ßë`DÙ¼zîr Ï”ûÚ7xûz4vÎ8`ËA¦çë5ZéjIîw@'­°Õ‡¹û}åæÅ½Gׄ¢ 1“¸º§ùy¬Æ˜9ʤñÌ`?Ѩe1ZK‹ËèíîçØ®´t¼i ¼Ø×ãÞàT¦Ñ>¶|fAåôÔ ÷L…/å UwgªÅ‚ Ëoèê‘ÀÜ–<=ê§–Q'´²RÔ%’ŽIÀ•¥ÊªØ7As¹&:ðºâ¨*|õy«¨‚•¡³i©ˆ4L&FT*÷°:æRÉòvÎ2`ÇjȲEâ`ÈsšSfµœye" ""²ŸØÿd/·@§˜‘°"[ $¯çDçMçi2³ša"rª¯¬ýX2‘¬^Ó½Èi8Õó@I9Eó¼mßRìr¹Ä²»Ñ_­0x¡XF ªŠ]œ‘UÊÒº!½(—X¢ôÔQ¾tƒ—ЖŽìÇ¢|v¾Ì)f®ÒÁ6üvIp¼+Õõúuƒu 3dÏ–ûʳ (-¿Â$WÕjS§ ”¦P~ŸÚ¨¥rM}',ØÊbPP×ò·q¨J,¡|cT1+޶²Ì$ˆN³+ ^ÈV LV«³¾ †"×µÚ§ªÓÊyÕT$Y•ðC¤èe f8uÁ BAQÊ¥èj•‘4£Æ‘›j™R Š}循V +É]8‡®¾Oû¨MÃà®–ûƒ°HJOõ¢ ‹›¨Ð¸¼i2œÄùù,¦—ŠèêÃ<µPEÍ*p‘åEäägkºP]œ”…«©!ô{w7o·.î©§D+˜ŽµÃ­1Ÿ5š‹â8‹U³Ù2qÚt¤s!·f8hÀ;\hÒž˜8‹ùì ¼úŒDob8Üö%Ê51n^W_»O²Ñ Å µaY£\¢Òž|ê Üy÷G°ïö»ñðÏDšÝ;·I¦±¤›Øhöõáòk€C/?ƒ ÓS¸ôòÝ0¢åf›ÏæZ˜‡öœ´ƒb„’&“{áüâ¶]WatÇ âTÇ0<ºIµþ¨ûÍ l¥°Œy @©,Î-âå'ÆÜùãÚ·by½ÔÈ+ ½R áÖÛîÁÈÚÍb´Úpn¥¤z¥·ñl$Æk)J$Þ FUt×ÕïA8÷_ÝÿUÌ/æpóµ{¹œ—C:=—E÷ ³Ñ :@3œ5Ž Ú¬΋ ×€€´zÀ ò¢~ÅÅ%ߦ¾üïRþÞeäjÉl5Miýâ¹Bƒ‚ºjèØLÑ‚›ü¾rÓ™ù×¢ÎÛ«ëþêL¦ñ¥¦d_„Ì|e ÈÀC"ÆL5Yæ?BÔ¦®û-rkź¡KcϤn0@™-7à¾~¿xø§Ê†Ä©}n1-¹l?ð׸û¶KqëÍ—`|v‡¾‰s¦±sÛ6ep½E12ElÙº[^• õ8¿ú¬dŒóâ`gðòþƒ²®ÆøÉY9üâèšä 1êy K°µoßí]‡SÇ!«áïÜ‹Óç.è¬igO†º38pø¤ÎÒE£uNtʳ3‹@WŸdÎ̺›b Óâp*zg4 f–Ó1º¢ò|8s›ã¸6Ž™ñ«0qMÙ_é߬,–Òë…›èL§Q)ä“×÷õ#"I‡Ã9Í0Ï{;®¼;$p ”{ѶÎ_8ŽÇNŒKÜ+YyÍ<~ë8 $K$3ê´rà¤I¡`’5~,Ó“Ð%»ÄÑ 6ú`’üâ¢dtÃÆYv²èÈ’®°-)¶Å«é \ØÂò’%QéééW QúX"e€=²oøWêÍh”ÂR·–U™VÍÄÀ½¾ëÖ­S2††‘„ñÐCâüùsz}•œ\7ï‘3² `ÄV J®ªPœÑ{——€k©PUÇÀ¾ži±‰mŒJFIA:mÎIS®1UÖ*—¨UWTȃŸK W¡ÒÄð†­¸â²«uÖ·^5“µÊ2ýùOdÝ%åABYóÒŠw”ulïQ-èh’$Ȉ§3ŠGaɘìC¨AJŒFÕô#Ýš9C¬^¦$ãÉa¨A¹Š}וh^û¾$Ë »¸ãÝwàì™ ì?ð‚êGïÞµ[Š>Å,0¡b.Ý uI‰‹b`¢¤˜k¾g%-häFË”•=±¸”’0Õ<ÉÄ7l\¯ëMºÍ%¹ïH$® L éì Jf$Jö=FÌ÷=«Q|b0ü1Ÿ j¾)šÔÓhĵü‘Ô LºUĘλq—È8½kâíý(S¢9è˜H½j SûB©¦JY´lnRŒ¾rÃ4¥UÚ¢•ò¿×þ[]ûIYÉÔfs% IfÙ,çäàeµ± eÙ #"ZK¤nÐöÏšF×TeQ€%ÙT+ ÓØ¶y]©vÄܤD½<óÜaÔ m‹ qS£Ý’™Î>ÿðõoâ]w~W^³ˆ#_ÀÚ5#f‹”m£ÝýrÿËÈJÔ}ýÕ» ¢gJ,MÔ:²­/,M!ê–°{Ë6­ÁrýÚ«¯bqê46ì&`ÊÑ’šâµTVÄ´Œk^È-ceé,6oèBWÞ|ã¶ `tl‹¹*VæßÄ×~ú ä—fqÃU—©2 Ñ{!7¢›ÀUAÝ òlª^EË6k6_…~¦¿úñ?á¿yFË©t—á9¶à ¿DËÁ’”ëøTbfŒ‰Îµé`ƒ>3;zì3ç´œ¤¥XóüÙÑÿÞžß·2 F­-‚Eû{ÅG-úÎϱ¥žÕÌÕ¹(­m±¦YØ4ý EKR9‰Ú¹ñ„‚8¯R$¶q$™ÈHà”êHˆ£™Ñì¬p@ %³F:YFÑq%qšµ!j!_Ñõ©Sç01~ÎðB/‡ÊÖFMŒ`¼'ƒ¡u=hïíÀÔÉI¼uvJ²Ñ~yó$Öôõ¢=–`gI–n^²Ý¼\S±xk×n#%{J~65%Î =$Æk'O£T-á’m7atø*¹ÿ9sY±—% " ¹ºå}½y ½mIô¶ÇqéÎu²wszƲùE¼°ÿYÚ¨ìóõ’évȹÍH€5&öœN‹â|\Éf2b4ɧ¼´°„´d²}=½˜[XÐ’,Wg8ÅåE­`„ÉþNç"F‡AY"AIÎ\PÎÙÚÞ~P?Å ù%`aKá[Þ{7fVð«_> ×Ü…û>ûYÌÊ{oØx9®¿îf|㟿©@¨¨IÒEàOÿç?§;ÏþóØ»÷Z|üãÇ¿øEq®iÜu÷]xàû±å]›±eófLMNi211Çžxö箎›¨Ýu£#ø—¯}o¼rqž£zSQÏ¿÷ûÿ?yðA<ôðoðÁ{?Š=WìÆÏ~?n»uŸö)VßÞÖŽ'Ÿx/½ð¢R ªî¦2U4k%*wÓ¦xßûÞ‡~ö3¼þÚëØuÉn|䣯/y·¾û=èëÁ·þákb/‚Úf™Ïf±÷ûð‰O~OÈï<󨣏ö꫱S"ù/ý?‡Kvn—÷Ø'7î»EY¥¸‚T"Œò<«âlî¼ãnÌK V¥:þÑ·%8˜CÅl“ ¬ n¾ýêÈ~ýÈã:V·fl=Úâ!uøœ¯NwôâÞOÿj²§~òÍÂâÊ®ºy®Ýw'¾õÕ/aúô ì»ó.ì¾îø×ü26oß‚­Û¶ãŸþùë¸ïÞêÈàwþõÛŠFþÄ}ŸÄÏ~þ3¤Äg|ì¾O`Iî‘}ì„8þC/¿„_|ÑÌüË^–àbÛöÝòL¯G^œèâò<޼z{®ºÆ2Íâî÷¿_ÎŘ|?¥cmK²'øÜI§IûÇàŠ-òhoÛ¹=ö6lØ€ÑÑQÜÿcy†·ß‚ñ‰q´¥Û°qóFqˆ5ÍXÛÛ:ñ­o}[ŸÛÞ}§ü{QíIgg'î¿ÿ~µi{÷îÅK/½¤Â´Do¼q´ÕßU;É&yðsKpÏú?Y… Íž‡({³óËÚŸ‰f:€DÊÍ %/¯›DÛ5¨°Y¬´D•dJEÂê¬] 3g„èg¨þÜŽØF˜70;» £Ñ¶n‰Š’’½ÑQÕµàK-±iPÂDÆ:Úcå¦îèìGÑþM˜®à؉Yx¡N|âSŒ»ïù´D£bg%úì­˜ÏkôÂòÉÕW^Ž3'Þ‡wë¶^‚H[ö:ŒžÎ6¯\» S²I÷¿üú%âTáuÕ$¾Î–ÆÏZ³5 áà[“8¿ÜÀޫ߉÷ê% ¿^ û®@™Þ€£µOèh‘D žQï^‰ÈXŒÌ âÝw}·¼óc¸í]í®ß!ì Ž®ã¸,¯oª/-Ÿ´LRUq Sgðëûÿ^ËðƒÃ;ðáÏþð2£øÉ/~ƒ¤Ú GMĵ¢`¦·:Ã0ÍÉ%—O¼ï;JES*›§éy:flÇpœ®‚ŠÜÖ׿b¦êƒ¤0Bžöê”߃͚ 3 üÕÍõIFÌø„j.òýøÅßaPÀL•eº°¿°$‘h¹¦`+Õ‚´3Šä¬!]†öüd-IPÔ”7$Ym¡,ŽAöpZÉÕ“&#–}H‚‡¨04JŒå8ªÁA.ÃpE!ù„)‡WGº7“Ó9|훿Âk¯Íj¶P«dÅÐÇMŸL^37µ‚ ç'ÅÎãüä ýY2ÖçžB2±<Μ™UI«:ÊX»~X‚Ù¢¼fZù8Î^8ƒs§K¤nÈ)<~êŒ+sËy¸é^ô¯]‡Á5Z Ñ/æ—022†öΔìÝ8Ê¥†©9[Q jà¡èNÙIåÂê¿•+%EÇ“(>OŠ@1@™`TݵXÒxqì’1Æ 9/HñKv4“Cî¥r‹|þÀÇ6n‘ }§¶½t{o¼Eä2ÎOͪþ2ƒž‘‘a|î³ŸÑ ~ó–-Á /¼ sã_øÂð‘|?ø·ï‹óz ·ß~»dÞí*ýõo|ßùîwqÅWˆ“Û„—Å(¾"N´§#£¢æÝ™RÌl"O!(*… ›·â7Þ„{?ø~<ñØoÑ%Žô2ql“³Ë8;9‹©ùE(k—Š¡WìB*Ṏ£:ÌÜw^v™‚º:äsÈ@EgøÖ[o*ÀkßM7á­£Çä QÛ8ŸËc×åWÊu¿[l^A^{¹dVM<ýÌ‹ˆóù¿ÿê¯pùž+ñÝþ›ä›.v^z¹êõž¾p?¸ÿxãØë¸äÊëà&ÚñìÁ#’˜Ñ10Œ3pÞ›8Ìœ¼/±$½b?~xÿƒ’¨,bÏõ×bæÍ:ò41{ÑŽ6¼ûýRe©õ;.APìpÉaë¥Waûî+qéµ7ã¶܇»>ü)§žœ[ÆÕ×ß„ó³‹rfÄImÛ‰+ä:ß÷axt#ÖmÙŠi o½ý=xãè üô¡_áÜ…Yu\só³Zqb ¢Ù~µ!ömÞ|ë-ÙÓðÁ} W\y-°¾ðÒ‹ ܾc·dÃíZN~æ¹gñì‹Ïá—¿ú%^9üš¶¿zøa ¨~¬à¶î®AlÛº×í½m™^\wýêtÏŸ» ï»ÿâ|å+Ç\±̪·ˆ“íÛûÊáWpöô¡d+hll WÊköI 3%{òé§ŸU>_V h˜Åºe‰àË^vÌP.Ë›eÕ•:æÖÑEõi9 gNO _®ÂéBÞ,•E­HÀðÕRany Y1"ád›Qz°((¿ßáCŒ[‰Š&+5ºœñ*It1;·„PºG®%!fô†Î‹s’ÌžØ{äv$& !ŸÃ2×P1jOþ·¾wÞýI¼ë®bdÇ.<óÊ[g:ÅÙw ÷pþü[È-eU…¥¦¶X{¶¯ÅkŸFCŒÉ®«oÄÄä4ŽÊægÉ'ﱓã¸0ñ*.Û¾ÁÐíÕø7Ån.9ƒ#JX½ù’=¸ïsÿ#îýøŸâö»>ƒE*½£k¶¢­ü¥ç1~ú¤Þ;KEžSW`£rƆ’³é¿ÒÄâ´ݶ~,KrøBÇ—€ØÐÜýÙÿ‚[ßûYqUN°,ÜPp)«Ê8ƒÞ– ãìÑ'ñýøÏ˜=ý:Ú»ð¡ÏýGl¾rÞš8'ÏžÃô!åö¬Äš&švØÜñií Ë\{5#mç茫©B@ü†‚- HÁ3Œ&:ªczU®…Ý{–ÎPûTu‚R¼°Uð|Ù&­„Xâ ´˜qlõ@é9ZæÌsP™hšœ&˜†Ýbe ŸÊJfVci0«÷ÆQÎ#%$¹GOG§džE¬TŠÔØ#GV~wvzZ) St&rH‰ÊHÓÙp»nJÛƒc8sþ¼f³œW…–<š©1}`ÿ1|÷—ñƉ$êÞwõ%X;؉L{Lù™óŪ\×ÉšNK”~ KgÕüüÁŸŠ#=ŠîÎA%:h4ÊÈ.—åg#¸óÎ;eÿŸ“Øá-LÏ•ài²A£®[7‚‘î6tÆ‚âˆêøúÁ—ÿéû8üúI£R+¿CÒw‚¯Þ§³ãÇOÇúÐÞÑ-‰ÏëZjÕ„ìE—” pòÂyœ;?!çD‚”RV[5»wíÂÁ´¼¾eË&üô§J`6¢bss‹:ªx©\ëôäy,ÌMã’[°8?‡÷J–úŽë®Ã~ðCÌLMa—¼Ï¤œ±îîLOÍÉ}– q…kÐˬh}‚-»|Uö¨8ûGgJI––/ä0qvR"µ6Êj£Øt”K·¡nÕQ§\¨–0“]’4¹礦—Ô·XLì Q‘1ܳ†<ºÚê±òknv=bÄ*bØI`-»Ó -/êÃ*ooÀgÎp-›HCg³Ž="bI{½ªy蕵ÞÍß[Ég‘[œÇ†[”Ì!ˆ+‰Áæ-›qdüqœxý®»á®Ã×ðÜ÷©Ï"ºpNâse®Óh³*ÃmÁÚMX@'ÂÏ›ššÀ‘‰4 u{lª#F¨TËŠÑ8Ý[ÖÈ+ŠP‡°Lá@UK9t’½}85=‰‡ò]-ñ-IF}Å ·atã.m²§™ø¨iƒœS( ¯Û€yf|[œðþv‹3ýÀ‡ÿ׿óvyV5ä$» Eƒ}k)!=C€¯°z›‰úª/ªÅH‡j1ûNkpõó}¸¿~ß´ÌYÕæ}+Qm®¾Þâòÿ¿•á–<ÜÛɯýJ³¯HAƒÎ*ˆ–`8E Pˆd9 œ›_A‰ ‰Ö“¡¨¢¸ ¶ázC²ŠŠüþòÊ 2QŽ3†œ¼dœÌˆS™¤2•9òLéˆÁ-K\ÎÎóçg%K5D%»hh W(…tŒFÁ¢Fáw¾ç½ š;sþ¨8}ù9/Iù{½qõùy,,Oâê½W I!Ÿ“Oáš«ß!Už±‚¸Û‹C‡Ç%ó©áÿ‡ãW¿~ß8†º YÙóÉb»6µ±Â‡žÞ1 šÂøÞ¿=¤AD ÅƒÕµZ#=2<†yq’Ù_…|‰XL÷IîYRÓ’»ü}F²‰TÆŒÉäµ:#™«B,Á KèdYãð¼EÞrmòY…zY‚™y9ƒ ÇÓˆ±BpèJ`ëæu8òôxá—ª*T•ΨžÃ-ï¾U m7¼ã¸öªë4°IËsjÊç~I2ѲÜÛÐà0Ö¯SQo:Ößþö·8}ú´¸ìܹSmËÆ±}ûvtuwËÏÀdÊý×ÿUùWÿ—?þCT‹‹’™zât$sGKEÛÀù3'1þƒïü/=÷®¹æ 9/×Ë[¸“€º„§žzqYÏ{î¼K³ÝÅÅí×Rû”æÚ‘Q´Ëç|ïÁðè¯FZî'®ûûßw—©|öÓÿN[l3$æÅã¿~D³ë¡u¬Ì”æNŸ“?{å:žÃâ܆úû°Yî›û{ÓúÍ8oALƒé*ªùY|ók_•,ê¸d×6Tò|fv¨úR"ÒÙ˨Ã}öOÔ±FÂI žÇ™ñ#øè=•@+Žo|ý¿é^éè`Ëú~ÉC‹˜Ÿ—ûx@ì×Q,,,`°;Ó'`çÖuXš» m¶]wÜ‚3'âeq´) è?ò±Oâ­#‡Ñ.Á)Û\wÞþ. ²©¤d’¿ÄôÌ´ìÑ=Ä4¬‘sR–õ8¬ì™ýèû¸ïãŸÄÑ7^•àQîwã ÀÅ!ö©½ïïoÃãOü‰xRžq¯9¤¬TU“¬±œÃK/¿¤´š;vl“O<Š…yîù%¿ùð‡ïQûÆòý<€žîY÷üýWÿ Ã#øãŽ;$Î+`LT"‘¿ñõÆ 7܈{?t~øW˜™i—|¶klÄ#*³L–Š‚ªÔÀ¿;ZB%'ï’Èñ²d¤•’Rç‘H>P+"$O,hÀ!ä±ÍEÚ‘“¨!%Ùâ`gí²Ê8A‡í£ÿü!XEwÙ/6•Y¯¾˜ƒÍßÍë×ËÍOIDNJ¸°’ч#®oØïéêê’¨0Ž>YÈÒ±‰A»ö¶Š“Ìâç?þ6z%;kKÆ4«!gfUAXºS"œŒDâ”Á¢ÏénOËæói`raO½ð>üÉßGWÿ úÅ/$Z»ËógðÄÃ?Á=²a¨ k†ˆ: Ì÷þ-Þ{ïŸH¸¿yø»¸0þ6 ô(0–/’÷E4Ûà`Fú{%Ã/*ê4J`üì>µ€Oýñ_!·²€ïã?¡$ë7Ð߉„<ìÞd£#CxêÀQ nÄžëÞ‹SG_Âc¿ø ÞsÓÕ┢Ê—{=pôUL®$ð‰ßÿKœ>{ ¿úÞÆ{÷íŬDò¿|üeÜpÛ}¸áÖ{•#[j ’ˆàé¾/Üë®Ü‰JaQ)‹µ²8ù¢Öcµ¨AÁÊÍÌ,µaƒLžimu¿wjû¨NÓ tuN,è^ j).r2— ª Î9«‚þ|—OEé3žÀ[u²ž¥“ÓÙW«Ò£™?UQÜòb¡Ï,dqN²¬"Ëí’=veÚ±,Á!õSIBРbƒµ•2ú;zÕKO/-èOË>cgIœ Õú%kcþüì4ñ¸–*C4Ö¯½—\z^xþ—²æÅYŽËÞJK´‚B!kfDGÐ×›‘ç"T2¾M'Äð4*5‰xkÚ«]^Yã:€þè‡hKGðÀŒ³§ ØsÍxüéÇñü3¿ÆâÊ,6oÂúáüTöh3Ô%Ys§8qÖæ°cc—ÊÄ=ò›gäÜ´ãäø9ÌI€ÀgÀ¬ƒ)ÕÜ@‡8‹;%‰c|B²Ü¹³r¾‘ÔÌtQö^B ^v~Q½í]Jа”]Vú½á®^5¼\¯G-B†ˆ™?×q(Õ%q³¥e„d¿Œ$Û°AîWÅ/äY•^¡3¦^­,óà–œ6ï\/g7éñE”$±*Ó&–T‚“å\‹ò¦DŸ¬+ç;)VÀ’¿X!ð*`œ”BPö)i7^"2{Ý@?vnlCXxaÙ”òÓÝ®V¨¦ʘ]”}0=¯BëÆÐ7Ô/? k±ŒÅÙ9,kÀ‘PzÏå\N£Š$Gë®–A œc[Iûšˆµ—ï·H(Âà+hÀÅ ›£&œÃEÓ¢"!E'G!Í®¯*Á\ÝÌpR’2L*LÉ<ò—dŸ×’Ë•ô½2™„8.¹ÿpI«=Ê0¥cGä j(û”jå¼/+82•è“×ç%`\”÷ŒÈ:fì(Œ©0 EeË"ˆˆËý1î_¢åZc‰¤ 06.*¢üÄ*DS:?oPÛ5œ:qTí IFˆ¨×q´ZÍñ›³ÌçIIfjbÃ<„Ùl¶#¶Ë˜Ù„D{A`ªÒ½Š'… ³à6„€ É‘.Ún¶mºÊf³ú>üì¬mßp¿ÐG)‚7šÔ25m>ñ´ÝUÏV5[æï’¬´IU%Zí=–…hCœÒþ…Q¤©4 cÚÓ,5+ªÆ@@‘ä²=7%JÊ¢JhwÃjà9Æ 6”‹“:­‘h)–i” ýw2†ÂÒËÚß-Pb™?XŠRÞÙ VV_”V©EöL\ï•—m™Q‡Z¨H*Ž‚ãT–Ÿš\P K¦]$l\6jA¢¿ôw¥ñÜÓOã†w߃ëöÝ-QqŸûvŽ !ã²D^5èV„lÖfz†,MF”¸†mûqý®ËÔh¬mS¥¯êêlòË‹ÊÛËL& Eû–ö+ïÂÞ?(‘ày9„4êI ô `‹Dœý;nF¾Ô ÃÝM«©"ÌuC¯ÃÏ ç)×gHžY._ {ny~ùèOpaa ¸ï”yŠ%*¢¥=_žPyëðô¤ø2G»nz›v€]%ÖüÓl‘{ëØŒãµH|îßVÆiªÓ\©17âoO`[¿ï|v¤f‹4B盯5v£ê;Ž¡Wc5>_ÁT–;¨;:D"C‹…<ÜhX¹¤Yº‘O:•Ò’5Ëà:kÊÞËMq1î™PR ¹‘w#Âw·"{$Ùíí}:ÏÙÓDÜ€Í8rÕì=” “ÊÎí—ãÿðìåU @‹8qj1Èí]Šf€±ÿÀ!|ùo¿‚¿ýò_áÚk¯ÆáƒÿŒc'_ÁÈØ}ºˆt¨‰qŒ>ô¨8ʺì‘"âüÒrµúJ.;_E#2ˆ#'ÇQ®˜1#:tÃfeæg³*ï”$âïD[GBŒüÆOžU4fg{»Ì‹óàXMWO· ¬È5¦$“%%o‘=P#K‚œDòê(øZ"b”=¨Ž`Ë’-œgFð{ «Ä%9[XËâ„VJu,³½ÃÑ 1üqGžQqµå–ÉB#)w<‡Ž¶´2ºÑ‰Õã0iK´j¥¯ºŽö LŸÖ¤g³+º_Iæ1-™JØ) _2_ŽfÆä¹±ÄÝ 5ÔAå– S˜äÅÉÈ:è¬ÅUm‡°’J~ÚŒ°j;K3vš­hÔp“$£ÌÖŽêmȳ«BÏ׃x~–ãpb¢ªÀR^/íSGG›Ån˜/)0UÌ ZµJ8TÕaUŽe5„é–)H‰@‘b :ت%Ú ØC–§R"'ªðešÒb±jÒߺ§œ“1y¤£DôÜð*™Õ׫¥ŒÙhŒ¢ˆ,ÖòœEíãcd‹•0B#2Ç D.#’¨èeÏ´,pE62ÁUaY¸v‰Ê"nAË×̘ e“UWŠM¥”Ëç寔°(KŠD”²‚â›òYU1´{v®ÃO=(YÉ]Û‰CO?ªd[®ØƒfQ^Ç âµ‹†gÐÑâÆ‘‰‡ÑÑVxvu%¬Ñ\É’ø+‘6k…ëþT‰i†DÒîˆ Äáç¦N¡{d®¸æ6\³7¨=Fx²-“ i“¨´ËÌ]MŽ¿$‡5¦Š1tÌl¨—©)‡9&Ϩ+#Æ/&WFÆÙسÈdRxϾ«ð˧~‹ïüÝ$>þûŽy&‰˜Ñ‡e H3Aeeª)JUÇš¬R lØGÖò9Ô=;Çl òæ_†Ïr:«\“•DZ%utHÞpAø}ZÇeT¯‚¡‚îꬩïHUNР•°[/‚ºobDÊ’M;7…ÉlUçââ‘8º%›“ÌjIŒY2mœ'ê&KnRçRŒ0û¨éH/Âm_˜›Qé¬AÕúl WÌ*zµ#Õ†¼tøÇäÐOOOˆ‘ÿÙz ËÎó:ìÜåí{ïÝÓ=û‚0ƒH‚$(‰E‰¢DÙRd§ä¸UbYqœŠœ…•„vÅIÙ)¹J)¥¬(Ž›%Ë’ìÒb* H‚ ¶Y0fz–îžÞß¾¯÷Þ|çûï{Ý<¬f¦_¿wïÿÿ[ÏwN1fDâ¼G=_ c›´¼ö±Ç.àü¹ó*5¨ºêœu“ƒº~ÿö¶÷pöÔi%4ØÛ­hp7;•À7¾ñ*þæ¯|3S'ðcŸ~¯½ñ>ý3ÿ¹¨4Ž/ÅÄaï¡XGšÈ)÷5³2öx67åß—cyeóKGñéû1¼AÅþ¶Èöí§ÄhõQ*ÝE.Ò4×L¦#‰ú€‘ްR«ê(IV®o¿¸¯‹Ôl)É.×Ä *U`^2f‹b¨È;Ía„C—eHq, Ó³p%¨(Êú}Ø®¡%ÏpJŒ_{(Ž´Þ—€WöŸ#f¶¬CTß;ž©Áމ£]Y3GId"TÇå3XZeg„À‰pǤºq 0r0'h**QqØ|–y›•.J²Gg:ÔñÏË3R•¦+™\TÑí]I"†|¸.9wIp!×Ò•`D‚¶]yM[öC^‚´e1ƹ‘ƒr½üË4Å &˜rÈ‘8abI §ˆ¡DŒ'2jÐ9cË}N•#+$ŸŠ#í2p ¡,ßWºâx†$)HÞµ‘Kɵ%-†ûIqþ²¦]ߌº1&‹By»``˜¦D”<ÁƒgÓ0‘×]™Ò†J¦¯,y¡¤Ý˜JÇn ”ìôŽ ¦FEPKÙ‰PK6*ÓØJÃLŸ£+§$X›R­ßõµ]±EÌ/Lës$e‚àTyÎÌ&Mì;Ò’¼ÚÜK¡É )Z5KgÓðhÈ Œq};¼738†ò|®Á‰›µXn Zo)J×WJ3‰\¢f«lT]Éhæý«—•(ìÝ×ÿ=.‘qR2ŒŽ(U¦)Ëœž"ÂèÐîß»…Õ[×0›Ï è 4?›¼¨ý!I\Ù¬ƒã]¸Ž'3â|»xë{ß'Ö×±ŒýíØÝ^—õz(_PÙ]GI¾ß¸üC¼ñçŒýïá¹§ŸÔua9dÐï*H¤\©cõÎ]¼sã=TvnãØÑe}èÜ&`éÑ“Gq÷öu¼ýæ÷P)µpó½ï!au$3ËËzô”ÁfÈïÞÐP†‚„åi‹P Þ ³P-莉ªCJB„:¨ö!⌢‘¢²LO6¬NÀ¹5!m0ƒíNŒ:¨b„²ÅŠê  ‘)¿'Æàn±‡åŽF³iÉäæ§§ÅàµPé4ᦓÂoàI2Žp°×qÜ›\ûëSù‚ÖŽd’}o kÊžj3Ü¿”àsì´R:b@²©8>÷¹—dOhë¯ü•_Äüâ.^¸ äõ\¹ú^ùóWpïÞ]¿øøÍ.]¾*kì"“šÑƒ\©Ö›>#ŸcáÌÊ’8²Î–vw±0çâw¯Š±NKÀš“3ÒVê5ŽUÐQnËži‰ãb›cO^ÿèùGðôÓÏ`qiç9/{œlLu|¨Ónª‘̤r(—$ó Ú:—HýRŠР‘>1ÑÍdÑèPH‚%1m©„$ù±ˆ‰òé\é, ã³ëÊY£p@”U-ÉüI`àË:öĨ5=¹µXŸ°4c&×j³ÖTäç ³ä™=dâ+KÁ‚}è~ óB%ºBqúЙ*ת r¨´ £§nÙà®K<׊Ö~‡š«Õ“ä…ýr‹ˆt1´=ù^¬µ%@kk@Ï,†ç!™ŠÉúĵ”Ù‘@€Îž 9Ë1Ò˜v¨õi®ËfúFNØýSèˆÑ‘i©C"è…Þ$ÁQ” Fn`–r-"Ê¿Ñ)DŒ´}}t¤¾32âÚÌzŠE¡»Œ„Ôd1"«÷¼†§>B¬ÄAlf¥®«ÖŒéÍI ×40R—D0r([«VÈ,„° §nCCCHMél&'gÕÃ^qWöDO{÷Ü[|g&v¸XDzý‰Ì›Žî™¶èDùe¬ØêÃŒb¡ ñ8à6 ­LDuµ¯ãI|8³Êê∄ˬ¬¸o˜cQC0ÁãçÎ|m¨Ô†è™™WŸ¨CFUòê.߯7|”Z›Öò`D !ô¼i‚Xbá\—Ñ)/Å~'Ë¼Š¢$·ê¤lL(¥ÌÍ=zDÍôþ~Ñ̺º¦Ô9ÖæãAÏé&óTÎ(Ç<(ê¬á±å#ÈgÒZÖejα–ðX>ØÝ+JÐÄ g$ºˆÂ$Õa<+¯Æ•(}~f O¢ùýu¬Ìg°²<…N¿‘c+õ–fôºÁÌáN¡/lØ®bi&…c+ìµuBu #ÅdT. õ7„òƒ¾²Ï‹‰žB!-UŒáÃ{÷±·~û«ò}^s^kíÒ}´öï#i5™—µíuäÞĸé}ÈæKÆŒRGµ¼!×´•…Yý ý¹Q5 –k9zdö°Òú ¤#C,/ÎÊaëɵôMyfd*AH¨LI¡dј@<œüG(È6)óŽÉòõ¿Çª¾cîÐp~×\o«jˆóƒ1ßùÖå!á_C“i›= ‡Ó9È@8ŠáG$ëèa}¿¥YE*jHìÙïR‰1ÉÐ5ít²ì±$¯ãSF,œNUÖTÇEÄAðO©YÓ}Æì”cVh¹XŒáøzOeÎ<‰žçWæåg>Î?F~ݼ=ÏáÝ·ßŵk×qýúuu ì=‘3ôØñܽ{;;[ÌyòL΋CYPƒÔï‰C—ë=uúiÉ-œ8>›—ß@U& äýd¤—ä\ä™'$PÜ•¯mÕx=v|Y2϶·öT)£DF£FS<óóó:(¿'ó”<”'K§óšQ·»»Æ!¶*Ø÷§>§ê¡Êßyž[²·»b\ØÃæ7Iªà³W˜@N‚ OÖ“`¤Մ䜶ÅAp6u6U #A^ýÀÓÌÔÖ¤“ L´Ÿ”s¼¼<+Ÿë¢]i*û’F~؇1^D ÷½ Ó:$,}hÖ}ÂãVLTý)$™“’XaUÌS¹´!ú,ãÉ>ê - œY%rÃÑfF-qjÅFÅJC ó¹)ð£3M%LöÃóRSzá¨YDÙ¡ŒA†²‹#ÌdÜ’Ž’i¥HG´Â€ÒF¬÷º£Ü>gÖÍ€¬O†$¢ä%st£¬Ç`ðÚ…c,‚ÑråS°ƒô‚¦GzªÀ̸[cGyˆÅž¬­’ñÛ&ŒÖsÑöQî™ïNxĵµ5–qSMUSýœž)h_¶R©j/Y{ÌLä”(ÄŒ¥hð=& +Z- Às9+×U0V g×ÃÖ”©f¡ø‡Q¼b¥5ªŸS¦/~wB KOÇzªGÛcUBö/{Í öŒœ›)Û;'Oü…s‰¤ådg—e­ˆ¥Q9ãìýPë3j4è†JÝÕÖ‡/Ô¡òCÙåÅ“©ƒŽ”^†.+~ajJ/XÐIFVß áXd6¼Ñ°œxòÄQms˜×ð>ãÉ÷g}¯ÎH$Áò&ûÜÌt„s’aRC…åª6£‰f[eHUͲq±TE«ÙѨ’Ñš˜ž‰F㙂‰Å`d$²KÊ>L§bZŸ÷Èê¡0툑: ý"ÙS²Ùfri™žRêD#ãPG˜Ñß Ÿ±et+rÓúTÒì7“’¨½34rËÓ^-Ÿ;—“ 'oLÒº™lÓ™¨– •ÿvÐ7Š4pÞ¢àæfsH%lÉ’SŠ~åµ(¥`ŸNµ§Ù¹íKZX” ›d”:Tagfáê|Õù‘¾¡=MC‚ãP­0üL¸ ™,«“C༆k¯ÿ¨ýQ4¯¢Â­ƒ`ë 2g$ãˆ×F[Âøµ½vjÔî .{nVžG]œi­QG\2S‚@XI¡P@^¢bÒ |ÃÏ)H©ópì‘EcŠvíu:ºÆÜçüo:fÔ¢Õ‘'϶¬ºžO=õîÜ»…ÛwoáÎ8uâ8N=Wÿü5]¶û$ Óú^/¼ð<6·ŠÃ[—÷'óOLÒ!Μ|J>g^p§'×,ÙÎãçŸB½=DÌç´pÿþ°JuõúC TÏÈþœÂì̬89¹×ç¹#¿Ž#GŽèµ•ËU Jw”9¨&_lÁÐh±gµ¹µ¦Õ¥T2/N5­Hþj}KÛ: X¹öÜ+ÌLyÝÜË,uEä¬p•ek>›Ùéý{·ÕÒ …‰@ îŸHýX×–Ú3' Ìý (Ó×™#°X†8ÆÏÀ(0m†«=Ï0’™¢ž­X‚¡ïèL4#ÍÚbD‡È€žÙžOjÀ¯üßšŒŒü&Âä@Oº7NÜBU˜PÞ ‡ð “àV³m{\£ Í€}`B:!T÷1àEL*Ì¢§¦fÄ–æ59Ûß/éµQþ÷?iÿŒôZ¨"×uâc¬¿ 󳃺YÈè‡âB9;èDaV;™0º®I•®‘tƒb·YmU]ZÚhPœˆq ~§Ù¨}¥r©©zû5"°¸žÔäãâÅ ÜF!àÌ€ˆŒeTj¡C£z%H˜¡òâ¦åPÍI6Ày±B>¯ÜŸSDâÆbý@Ív†]Ef ÃìÇ`R4/ ‚8qâ˜Î•K• ´…+Ë’gàxs#"ë$s† ﶇ]xâð%›$?î®ün£ÝÕÏa}œ¥)R®1Ò`˜‡œ¼”6A²P)‰Ò#‘”òu¶Êûèµ:#HÂqŠžRNŠeòMm7NQºÙ£[5¸¶ötýaG)Úø9:k©™JºaEVY"JG6x§S×5ÜÛo`{¿.ޝåiÊ5uØÄ— ')†‡Y+4V<8ʳ«¢kXSFm-O9>W’{]ƒÐjõ`¨÷Aä!K„4Ç¡f¦'; ߇¥Àј Z³RE›žª?a‰R³ÞO¨CUœ?¢L¾>4d¤+óFÞGœ¥ö@lë#ÿ6&ˆ0‡ØÑƒ§E&Û8Týo7†ÕbÅj²É)=6/{Th”½â˜ ¿è †iæ³ÆA–%‹cnfjZW¥Z1RšDåÚ&“¢åç!—=K€ƒª¡¬Ñ¥Q;† ?‡½²V`J•=q\EÙ7 YcO¾„ªÐlIPøì³Ïâ3Ÿù¬Žl¬Þ½ƒÕÕÛXYYR€ÈôLNL¹Ì²’9ôò54å3N.NéÌYn ²Ñgf"Ø­”pëNó³§å>²Ê+½µý@XîÍžŒ67wqúä¥Í›_˜Ò,’ˆÔkkÊ,³ºz®^W±qøi­8µ;ôäsÇô޾fnCí£ÑI2¦±Åt¨Ÿ+Ï„í š­…ü´>Ïr«¡™|.–DÝïkž±£Ts,†ý[ꩦ\–V{èÊzªÌ¡gé)E¶(jLœA—ÿþH3TòÍRåÄ 9¥yÎXYS˜À?p¨À_v¨áœPÜÞ8®±ÿ &D&Ômf»K³^ޟͶ‚qä¬ê4;<+•j¬a—¢r-žðA»/×ji7“ÓªÉëë¨d²Í±$ù®oŠó”ë‹ÉÞ™çxD»…ýnC3S*¦0°`æ?Ê"‰+µžäíX’ìŽæusoGÑΔë2C§ö$•7ä0SN=ªt.¯‰£3Œ{9³räqnWÅÙ–5"¯Ù-Ïà™§ž”ý»«š¹>ö¨²ä\½z ßùηpóÆœ”€qz:[×oâì™3rî$ $e¯­èÜe·]Õ¡õã¦ð؉C—…øÜ>‹½õ.nߨ‘Ìð¸:ò¬q}ï.>¾‚µõ |üüYľúÚ«Ø+ïÉY:ÓçÓà¬U¯¢U)ââ£gQfI•-ËŒ²µ$ÐtœXØsì*×*G;ýr ‰ φ>÷ò{Óò;¤Í+6:JÊ›–¬[,1Éê(•Gü@Oö™1…s¬C ÈË}ÐîË>·‡H‹µ¤Äq¨‹ˆG%Ì ”mfSê¥BgÞ¿àù˜$§‡‚°Ãº˜„ã¡3Õ2qØb8Tq¡³ ¥:ĹŽÅB}µ;L80JEm]ÈáÈ,{Âò.î8ƒ3(¯—_~hà½pŸ囘™}Iùu,ÀD´z2£ï„º©ù!V@I«<Qx½IE’…UQò¤óe9œ /ª½ª@?ÓÊ¡S šmµíÊQ=Wv\ ¥ƒPŒ<ðÇNÕR'ËW’a£>CPÎÈaQ :ï›/br´$JŸ)êßöCÊ´PÇØ1ã1&4ônù,9[q¢bƒ÷´5Àñ5VÙTð\×`ix›u;M”‹%ùNþ݈îc×q#Æq’Ò,¤¹ÕÒ¹Fá}ØŠîe–I!‚¾Úö‘ž ?”œc`iår#³Ç÷e Jˆ§(Õ8Ös1å5µg¶¯)û%œ7"uX2•ž4iÇúsûûû¸sgÕjU3S^(:ý¾?‰JºAXrj$®Šg^*0ΗۙY(^½V30|:ìÐ0kÉI” §DÄÌÓ­“wU¨-Ñ~«Å.GÁ=‘À8¾fKœb~Æ€‰¨vÀ O”®< &{†T>¯Ù<éMsˆ& ð£ikeò†™|…©˜lËD'”4Ò²h‹Ý 1ðI ]Ë8r‚ œ¤)¡ðp‰ã°2ÿôû–VɹM Ѧnd»†T<£ ‘ÝRO.4|}ö&YGK\Aœ£-g]Ñ·¶•@×)!Ø“,hipUz-” @Õï³jÃQ–§T,ž›Î³ÛSä¬"w™Q3[å›F«ú\ö­ÆýΉ¦¡ö<À “2¾L¸x' qÆ H¶uð÷ƒ^Í!Ð ÷T̈½Q¸YâÚÃ’I@šÉtެ"X*›6=K‰6iäfÅÀSø}½VR¢ÓÙ9 åPQ­(+ÝcµVÕ•kÃuU@"ù³"U¢33rÑtÛ;›âìÊpk’©E²È¦Q¯ìàõ。Áàg>ý9ÌÍÌàë_ÿxðà^XЃrïï:“HPF¿Í픢}­]GK­Ô¦þ.«8}1`õÖ@ •’°Ç’ß3ɘ¾_e¿¬Á g<ëÛëøwZÆÏ| /‰ßù?~S[ Ìfr$530³u¹Ì,Šå5Ínˆå#ìH@ÆgK@‘©NŒ´UÒø˜Ÿž{TEIÎ þ‘©9”­ŠŽÄùL‰Cnè(]OÅÐãÌPî¡8ú©Ü A •^UÁd–N8xÊÂå‡B^Hki´B ð%ÐrªYGÓwgLYçÁkÒï;Øz‡µ4í‡àFÉÆ˜²ZçDbz]<:,R´ÂuÂi//ܳc‡­~(Qï¦}¥ÔtC”÷‹r^TËž#ÍÞIõzø¬XêŽ =£Òª0Þ$}Õcà„jN<þx¬,ü#òí«ºPKlFÙw´l='$ "NÆÖîoËë¢9K–¢N·§A0UKn­Þ× ‚™‘‘ï¼ùš\WÇŽ,kuæÒ›X^9gèAWçò¦ sÊc[©n©YçÈ{°¤^Œq&Ð*#7óŸÔ0 K8¾8­+JqÙD‹Ó³ úQ–è}!?…©˜¼§'÷H’&-roœa¯H¶|djVûÈ5yFœñÍ2c µ&=Ï4óxo΀`¤‘¢³G¡d &¨¡© mÿž?æ8˜,0Ú¾fgFWu¤N-&Ï‹Hl­‡„ÜÛ¤ äGIÙ©ÈU ,$Àè3;%ðÐ÷“á‡ïoœß€NUöG‹˜·ÒtÐÒá?¶â ´“b€{ã¦Êeg±> ä—­muF‡”kè<¶œûF Ï5Ž\šåP+Y%N(‚õ è0²Šf]F2ÔhRBµÃÞ(ÛÆÚKtÔš”:žŽJû¢:ÅŽf¼'ëÙ‰;*©­oÙ¡Ï 1 }Ûyô1TÚÞÚ=ŸFZΆŸ }gHµ­¸ž©dÙÜŒ~•ªE¢—K \«F*“>+ily<›8å†Ë@QÁ¶zýàã¡r¥Þ˜£Üø$vá(ÜÞ~EKW@È–ošÑ!,\o†ýOnžx"5A=`B[˾ìÇpˆQ««Ã­Î$êù˜Ã1=Ã$2šd¦8äP}ÝÎÖ–¦Ò1ðwHÁù2nD–—9¤ qZsÙ)9¤C9ÜbØü„’:w$íŸN8ZVq%¢¥ÊõÓØÕbâDÙ ñ !?>{3¾…íÒ©\Élèô¦ç§±·³Žýb ‹‹ò°[F‰eU_ƒ€%åŽÜ;I.|ík&ÙIFªí´O6#)ßDRŠ0l7*pTÄ8Àýõ]49.WCÁ[F‰˜NO§4ÒÝ• javJ2aJÁµ”TÃRäî <<ÖDKÐd‘FĘÐõ Â×#ró–N¨¨=Ry^ì·ŒÂr/#NuCMéŒ\`ÿû#ÿ1ˆÂ—Ú <ÝÖ’œ5Ùˆv^:… Ú¸<7.[º¹CÂŒGd ,˜@M?GîK2Ó«÷Ëhu-d£ dÅHWêu•N£ü3îW’ DÅm‹C’x§Äqbó®dI¬Ä,Í-¨°ÃÖξd˜Yeà"*ØÓŒÂðsÿšÌj8éPk‣öR‰´ÛøYì©X!ð‚Q~ØC ‘,Û,±G@¢‡ÌÑ£xøpCœÙŒÎÞ‘¶“å¬jµƒl!ƒ'Ÿ¹ˆ OC»ãáÁýJ[ £ñIö™q޲··§÷\”Ϭµ:îÏõr_&ðÁå÷qýÊ%}-çJ)¨¼··em«˜›_D­¾ƒ­­ ¢™¤8nO‡‘Ê«A÷z³ÕÃôT3JRÒÄîž©ùå7Öò¸¼×ìô4 o¨J€BÀW6WÀ@‚ *2Q„ ŸÊ¢+™Çn¹„x2ù$eÊ©Ipúpo§’KL$g(n™V”qV¦9v”cÇúžðÐÑüާ<ìîeËìI®)óÌlfåºÓñJ’4Ðm°ÄHŽrrÄšß3œÓè@…ìLö¯JÚYŠšötä…òjnˆèõý`RÅã_\;,=ÛV`Ú Êâóßb3÷À8*Û(¦¿lÖÀ슦œåQÃÒq9ÎËs hÔí“Ì¡èÄ¡,þôbðÑøy2štX\Ûšd¨æE£&VÛ?0ý]Õ7UÎxKËäl3ãlÙ2%óQ˜)Ó÷á¹'F‡¥a:¬tz^¯(r?Äßh¶.ëCŒL<ÕÌ?›K"%~‰#gl5LHf’»û”ù+êc’˜Ë&CPRT %Ôyû“}ÅWR!­J &}bõc¾‚¢$jÕÅ–úÞAtcê½ P'Ê’¯|±ÜK5†%óõDö$Óä ¸Â͉ÚõŒŒc4Jùz ô޽:vpx³û‡ÐŸ‡áØ!‡°p’3H6š¦>d m"©l“s~”²n1¿†©L ‰^÷*MÉDcâ`=´<1HD]GAÝZSrpÏXÆÜTÅrUqʵÆPÁ -q°{Ée¶·‘Œë¸0fÐ=yJ²‚X>ÒFa&+÷Z Ë8&eäEY¹þˆ%1O3›CΑ0{c–ªðC Òéíåᚌ9¸sC²¦¦ø­œ‚žx t(H$ôÛ(õ],Ìçec²Ý˾:cÖõ•ÔÀ6ócÞx€]¹…mqf X¸oæGõ™;c:?y.ÉÖ•ªÏ#PLÄ*‘Ïv:DÌ„(:c‡±úË$†;˜®?ãà 26‘ðC”KËôQ-¸ºi»Ø†»X#Gqœ­!®ß/¢ØvP½:ŸM`¿ÒÐLÁ•ˆ‘û–âÖ,!Q݇Ò_•r±ž§c# y67·%óOâøü”5¬ïì‰S˪fçf¹¨¤òù|^׎#+%JÚ!ϘUóX$ƒcÇÎbmý&*Tu‘(™YªÚy–ŒÝ`UjÙv<¢–d(ìù‹i6xꉧpíÚ¶!øëü· ÏÇãWtL'–t•¶Ò´$ØLëág4_ p_ Á€Étþ^EœVÇ(9Æð€Å€Àµ+ بA)ëM •ÉlF’‘¹8º|‚Åbl<¼£-²$YA_AY$©pÜ8*M_ÉÑWÄheœ ¶ª-ÅææftôŽŒQnÕÅbnÛC»xä%ëŸJI¶Ñªh5ˆT„NJ\ùú=ÌfglW—€õæ½U* K %5DØòUHÂ6`BáNL‹:¶'áy8ÜŸïEu|cäi`À@*ÀAŠHùÜeÙ' b©™Jc®„3¾™‰äHˆç™ŠÛPûŽfï“-¥büð$ëHǘ2ÓT§¨çj’ÙDœ0¨W•|sŸ–Éä´àÚ1ÕmS¢³&©õ;@¸ŽAµŽ[)ž–æmIzzêPg󮞇°˜Ö˜‚I?v\ƒ:ÈVÃuå9 Ìz‡%)C´Ž$™ ÇœYêcÛpÓ™5§À‰íÛ“‡ÅʦIº¬ ßôغð‹ìSÛÛëâ´²:ŸÌ3e…E ‚”ñÉÑr<³¬Å“rví´@Ì\çf-“Ð)OBG²ªV†vwkj÷ þ'¡(ø8ÇâEðÆcqÓg¶ Žˆ½U~©_ · ³T"¿]¢=u“ø¦Ñ­‡=’S:TJŽ^«¯âÀ5Ç› Ñ4ۤʉ¼i„‚¼¸îšþ¦ºá„Uý1èÈëÓ&í×Ã7ã ùrn ˆ{¶i ˯ĹAÅ@¹$ÐïHt ôYä¶uPº.ÙÉ>Ë™âЦ“qT% i5ä:¢dUéÀÎŽ`OX6pwPÁ5æc9ÁTNœuØ© p÷!Á?4dño%ë´nãø ÉþÒ–OΣÞÙÁµ÷ÞÆÏ©©i ©IT´¿©Ra112ádMû›¤VÇŽ"¶8A;·_C¤[E³>Pi%3žb„Œoo•qcCœ©DQ1«"× µÄH%õç©BN¹|Sr/~uî°¥ÄârÐmmÒ+G(ÇxØ `„¨eò¤’è€Cà¶±9ïÚqI¨›² $sKN7$º7º1ŠVwbô SÁ%âh”ɾ•#Ž&24à _6·J±18öÇ•ZfÏ#Ó“Q42Sh\ ¸gØ’d¿Q!˜j$ÑQHIè˜ìŽsG,VL27–è%oÆZ©=d»ÚSáâA§‡Õz-Ò®I¦Ê¾sQ 8 £ñŽìÑbq[M^öY²öÊuSž–Ϲ-޵^­ËïJ>%¿sïÁ:ð$bbÌ%`ëŠ`©2f“ËÔ“Ïêµðè¹'±²r«wo‹¦0%ÁR³SB2š”ç)û¾/Q­T|­DhŸÛrt5¸Û#ò»äàf0-Ån¡¸·¡âZZ-b`BAÂþ|ÁE·(ï׫cá0r››·0³À1—ª¥Š¢Q'É5Äù‘d$Ù‰'AïCöà\4+ko›uOuûXâÞnÕ°2·,@Ž\g½O¢ïnÚ¥ªV«\+†vµ‰»®FùD@û{eôš]ÄSqôeýî×¶1h´Œ8y»"×”½,ÙÛÞ/ÚZz‹EâÚÚÙî•4`±ý¼Ž«—7°PH`6Gw_M2é(ˈ@’¤¬¥;™ `™v¬`ä…ÁúdËö‡œâ(pàxCTº-ç'cûXžŠKß`è#®¨+¶$!^ŒiLösŸÙæH×8BÊ/×ÌÈÌi‚¸ÕJÅF¼>²?- zsË~'3+Û0³ÈÞ#‰ÅHdWf¢ÀP*P‘¶†ü-IT¼¨YòÔ²s`2@fÙ$+1+×RhˆJrNø¼’Ì&ûf¼1à!ÇKæ!â5¢ ç¦lˆ0lÞ–ÕÒÛö„½,gPÍìùH™Ë´¬ýZ+ „¥µõ­1hɈª¨sW²FÎAÛqD•˜rËSá«)nd*)k(p•*3ê”yy£¸jxWz ´M±‹<¬iÌN¸«¶Íe™6•Q½á™Ù âˆÃ)WJhwZ(‰- ¦Ä±¢˜’€z~^ÁÙ¸&xQw¨¤+Tn`Ö›§ÿ°]“,9j¸I¬¬ÄäbPH4Zª>Áš3)È–ŽÌʃH+Zr}}]Õ)˜òR-€ÌBü–8^–dG:| ƒ|"èÅ7h^a/Hô?·¼¨%/– ¡õ@ Z—ß»¤#&½vW P!“Õ.cj*­ÃÖäºLd²º€L× 1Šu7°_“,ÎOâÙ‹óxôH¯?¬âÊ8|W \xbÞ‘,ÏÃcÉy4GU¼ºs þìgqþ©sò=,Í”­å›¯ÞÁ7Þ|ˆê(…{ÃŽöñ•Ÿº€ÓŸø„d ¯ýëoàÕ?ý]üøOü |ìÅ_ƽ{ØÝø×ràI]Áå›)8wgðèc=<±`Éç= ÷ÈqÔ·ïâÞ?ÄÜâY}áYÙmì‰ÑûîïáέuÌ"%YF©È§—çqæéáüÅ'±˜v±yë6n_—^Æ‘1•µðº%Ùp}Ô”,ÁDhȤ\¤ã²N ‡8$Ñš­å_·ëÆ´ÔÊ!—õsrS:‘Ciµ«²y[ˆ‰SÝ ©Ó¸0ËŠ8 bÒ³8/¿.J¨›ÓOŠSˆe´/H¢yå·$“‰D~ÝŠu ‚8ÆL‘A„eaB|MÚ`ÄlT ›™¥­|·Ž¬xúyÙ²ÅAÙ½6óEõ*¥äfM¤+…–ÒÄYÀ) %(ÏÚ¦¢L"¦M¨¾òlºÚ?NHº±[D­ÓR9áÊ ¢¸­8¢{‰óµ©÷†0ŸHI9# ؆ÖP©·§$ñw‡I¼²ý, 3ÀLJÆâYâ@d¯–ê¼üDÿíË ŒÄ)Áï+x%Æà‘Ô8³sÀœd7ë#¥˜û?‡8ÅíÇ5›%ÕXe¦qtùˆ¶í;íž*<Ä1y®?|û’2kÍæ¢è؃"çñ¬‘dKÀ7Ê´óŒtãâøPÑyRtÏäæÄ¨Êó”,‹ÁŸò“ P®sÎNâôR ÿýt s™¾¹rF÷#(oг³âÊyu³º—)Zq“Šïö»è³¤Ï)÷ºk¥cNì‰C­ÖÛ*DaˆB 9ж†Ø¹JìNrö’ÿ›_ÿY¼ôÉ%|盿‡wÉP¶‚½F_¤ê _T_UêiŽ Z&le®¼Ù“Ôá–EL >“‘,C«éË~ã\˜Å O<Ž ¿ÿþ{x¸ñPÖ,Ó§×`ckW±xS÷~<ÞÕR#G­˜ñ—›u´© Ë`޳´ûœ0ð5Crã!ŽÎˆgLö ô³b# rïY9û¬Ø+Ò•½E0]™Á§sræ,Ü»S00ýØqh0Ö?8@;i%Œh19’ ü±•$þƒóò1qŽÔô­¸AÄòD;¦$«¸J;˜¼/Âò³Œg< 0I³S× KÆŽAõÚ–¥#®V¹ÈFM²¨þ4ò%àÒ9G”øAéÞ­-Až-vŠ&î+¶ölg¨sÖW¯\Æ•+oá3Ÿ~SÓ -ÓöutYñA¬°ùò™¯}ï$3Gñ/ÿ‡Tæ ÈŽjRJ+:æ9naR0BåÄôZ-m¡¼ßÅ÷_[Û·ñã/¿ŒgŸ:%ÇÓCGž 5q+uŽ$úJ«øæ;W°rl^Î…¼1PQ1˜ 1e'2‘tf3…<æ$R}æ™çHÅ´ŸÊ¾rf:‡f£ŽA¿­Æ<HGhÙ—Ž8-ïËâR&—©3gpúìYåeR!/l€b¹¤%݆d «b Zí@Òõšb,Ò’!¬Ìät$¦-ÙTJ² ßZdôàŒŸ< OxÞ¿‰æöCdI{'“’P©ôQYœº¤¦ÄxM£Öî(f=ŸˆˆS*Kâ2íŸé  BÕ–èÚ"™D¤€Q6\!ÙD ÎÊjÉï¼Ày:÷ÌH9Ž¡j< ’·`Í,‚èß‘|æÈvÊN’)Ñ¡É%C5=¡Ñ^‰o "O{Ô†]ÍÕž1ùuãâôó)ÃÐÃYÏL!£$æVSbaI‹&ˆjF2«¹œfÀ~ÏUǪ³w–;m‰N;Ê/ê¦-ÉnûÊLJ°‘‰‹ã$†ª1¢ðD\ÎHP¥²Žé¸8½¸= ƒsίoF%1ħ‘ûï¦` L…†šŸdeðÃW#]Ö9åã¿øl ÿçÍ®üÈB¥¶¥ëI¤5µÉñˆÉúÊúsÜä½K—ðÝ^RmÏïbà×Űˆ3ŽÇí]´éà‚¤fc>-mF= #JÌ­Ž}äôÑ.V%¼ŠQ´åì¶•5ŠJVµxlNꙺæ#u–z‡ äZ(MÈñ ÇÍhùÓWv@‰ÒôÍÌI¦0Bq»…¸EÙ»$j4l}ì0I[«\†­ÆUnp_{˜ªµûûøØK/!œÃüΛèH¶2‹2ˆˆ3í(&€€®h©10ÈàQØæÿ9L’ÿQô¯È¡¬‡–KÙ>øö?@CØsb»J-qzñ<ÒÙ9Øb£Š;r¬×PƒÞÓ±ž¶’ahö—JIÆŸ‘׊cNÆ‘œ;%÷Ö¬y¨³5FE²1õ}W‹É^Ÿ’×eSŽìEI’ÖHǃ–ÉŠ I‹“º¼µ GÎê‹gŽc †4cxhJÃÜH(“¢t °kdÖ› ,^Û»=4Åp~YìsWÎK½/ûΆørYrÜYÊõ ¦¥³è“žµ¯sì…²“c\ƒ’qÏWÀVL¶šÜëÀRZÇe˜-?±4Nñ˜)%+³š¥´ n"n˜ù´õ˜U&3°L=û$öï]AÂëââÉ#JçHW:ÇL..vD²ïÌ46äP*·°²0ƒXá¤Ø#ãH™¥êwç#€#JÑ™ž3ï/«„"®{S™ãøØÓ/áùÇÿ•8Ú&Ž-g4sMŸœB~=‚‡»UÄS³¸|õ66îãåŸú 3Ô¨Ö¼›:£×§T>Ê¥…Y%f°Ѿ]`™º33J6·9ªÁ¹¹L*‹ýö>ê²5ã ÖTñ˜l 6O-ã³/}³Ge6jæŽêh´S²Z¬(ò±)Ñ/‘ƒœé!³KÙJë\l,í`*Mã멊è¨×E"EO¢n±»úpï×ËøæÃ8~þT Ÿ9>…öíö;6¾³æã“+ õôQÌ=^ÀµÕËEVpìlW³‘N0¥ü ¬Î‡úåÈfy»ò}ìï¾#îITwÛxû[àî÷w±¶±‰z“ýʼ–6»x¿úwgg£XýÁ¿ÁÛ—ÞÁ \Ó(G"Q)²6ðÝ·÷q昃³+äPvž]òâ‡òÃA=ª"0rëw”õÅöM?•ÃûnÖ#û7Þ€e<É(Åqôê-ý嵤¡šŽŽdc¶f–:”¨Ctv—hx;–PåQW²bÎeZ}EÒSRg€ŠD,/2{­iX¡HJM’öØÿ%ˆ,•›A<ÕÒ²iÖH¶:’ÈÒãnQ ‰°Áö}9‘Î$’aJÛ”âÚÝ z­®–¹¯¬di¢ýŠEÕ2e™º]ëÈ. ÈgF÷@ ÄEe5½^*¬Q‹ý.æ×}’²ÓÈ¿–d-ã¸-£šø¢öóÙe9/â?ýrÿ2ä- ‡*>öˆü®8ä.E 46—÷‹ÊÊÎÄŰI¦Vb[>ßjãÑ…o•ä€&%˜”Œ\žÑ¿Ï>÷„V{Ò©ˆ:ŵ­=üËùuì×úX*ˆs“ƒÞÖ%$ý¤%’mϤâf¬!ìS+«ü/Ï`FñO—óÕ-b·kIG\¤K•ª‡ôd]3–òçîmˆmdå9µ1ìÈõ3P™áøc­‘böžxî›5_Qêò”É3ÛªöpwS²(ÙÇŽœgËoÃap a8Ža£1@"ö·|ÝïYqš- ²ÿøÞÅ—~òQ\<óޝÜÅêšdƒÌ„œ%E ¬}ö2aFU”-($Uø‹º»ÁGzªøK?7¥a[ 9§º 5«|³t¯½¿Š˜ì“ÅÙòË|^Fµ\EµÛbS}Y·¶:1ó>ì¹åsòüò–$`OËstå@(‰|H—9R äHlª§¨ç ??âªF'ñ ¤äÏ î‰IDµZmàÁf_87åyI6;P¾\Ë êǚ̖mÚw:§)v–c"½‘£—²8‰C]+uðÚÝ’â¹WI5·Ä¾Ä™Æˆ·ð³qXgfpU3[q–RÔN\*Ä.û¶ñ¦¾exz '±ì Š«P°ží©Ž£œÃ|^Êï«ÂÜF°Ê@g+xAü€$=Gç–ƒH¥RU‘ígΞÃÚÚ}œ97«ˆ_buØ¢ÃHÎ’t¹Ô4îÜz€ûk8~ñˆÚO)$}%“á ŒAl#¥›ì+¾@ÿ-€˜<¿'ö}„ç?ý4ÎüÉi¼÷þøâ?)ç‡jGGsÄÜ_Ûïÿ/|ü³xìüó”Ôm÷´ÜK±pfëôÐ:k§©1pãÆ5Í|%¶µÏ Ör¹¡Ñ©jžö††À¸3D§axr7¶‹xïƒ[x\2ˆÉNãIK#3ÞH­ÚTQ«nß•;@±ÔP©¡¼Kå„ZbHI)ØCéKt‰±7ei~–T_mNiF“R3øÁZ€Eù—ÇN,à“§¼ù`›í!^_ëãâ‘)lerøw$SIãÂ|7˼þî>RÙ¦ b §ð _ùi<¨ðߺ‚‡èÕ€»ëv/×ñ}q1ü9ÙÁF,H¶uo«»²_~¤…³çeÆ*¨t²rŸ x£ÜÆûW®£yK"¡ò`·-UY°Ä8N?ùâ“ø¿÷+Øþà ^ùÝo#hULÄæ¦Ô™…s, ¡œ’çÇqG¢+?wЩí KtùyÌ–è7ž6ÔÚKékôQžË@W`Ô{’‘R( 'ŽE u"'¤ƒ×*9£¤ÕÌX"ýQ»aù†è`Ï10Î¥ªv·£ßI:ÁÀH¹„3K‘£¥ŸÀ8eFŒ )ü “±²÷Úçì—ü/3]J_Läd=DÙ)iT¹¯béb´H3É¡ôQOûΤO$€=HöDšLMVÉ:åàÄä+M*°ª]§0ð”Üš¤Q%Á¶ õZR²*q,Ž=Pçß'N€e*²ñ°{g³5ÒÆnñ2‹.þøœ}ùÞ¬ŠXA|©‹“sMy.+˜;znëC£r†GO<"Ïß}ã]Ì/žÆêÐéD˜üyH°Œ0ðpñîÞ]Ç­[w Ùƒmk½™ðe~p‘ÒkJèÁ'©ƒ¢å`s&”†ÜшËÁÃí’8Õïáòå[xöé§äâNbj!§¯×ö‰üßõ·°SÜ—÷ÝCË‹êìW>BîKfV#,$ÊjJ„$Æg·ÙFF"–¢|þLÌÇ£I:=ÌD3Èdå0Ëý|g·']Æ™¤€cY¼Sô°-þòF GÅH­ùöö>âEÓ…iÌdˆ$®au·…ß}åžÿì_Åç^zïȵ{b¤÷ë7dÃK^é *Žb¯ÌY²(j·×ðñctq|ÿ~C ׫ØY[Ù ‰ù“6vzbPš=1*mŸXÇ– ³ec§ ˜ÍFðw~õ¯ 6—Á‡?xC"_6Òê@ ³ˆ7¢ª:5 ¿+ ZËC,Ow‘‹mIT$ké¤Ðöª ă—‘{I¦JJBJ/ :r/VY©©"OÇÅI¦å«'Ó¾žņ¤’cD*FŒI„å9ׄ²Î®d\1ÊüÙhFýGcQ“ô-s°cDº’¿ÔãËS©É©aNR–«Z²Ù[#%’'ÛS*[u ¤ß¨h¦Ø)Ù¤º³½í»¬‘f1jF“üDÀJ‚°"E˜rgÊ5ËW2ŸUx4.ÐW„ t¤JËŸ1h)1bøÜ†d{£¶µ TøpTöIËØòK©æ®µñ;ñØçs¸}íG¸yç{øÏ>Õ—=j!“;‚'OžÆÿóö2þÙ·/ã·ÿ–æ¶‘äñÅ‘élÉ|X*íö fÄ™ÆÒˆ±ñ+Ÿ*áÿúá9Éøë(Ö{øó‹èQ'´*ÏY%âû7ÿ:}òárÖT2Òä—âäÑʵ Îgâ8){ÕKX‹Ñ(+ ÿB±tF›Ž8 ²/_“L7›ž‘L …—gK8sP¿×Ç[·®â(ƒ"¹–a”­W®“Ì3 É®¨iiÍ4å{¥Aµšb*ƒ46Ê{¨tÛªŽCñðaÏÖQ/°—Î~zḞ±4³×ÊžF9ÅDZ>gßùî>ž;w?ÿ¥“8%vƒì@¶K3¶%Ðí6)!ÁËÚ~Q6ŸCÎr” ÿç„àÏŠ†c/N'°"1´Éf±E©Þª•ËQ1Œ¤JÌæ¦ÍN)Íj>ϙȾÚXá/Ÿ›ŸUDêÞnÞÙÄýUÔ½ª•¶8æˆÎNë5²j!ŸEì@’¶\z[ÎLk ¯‰»ZIP•‰×+’|´zøÉó<.YïýJ˜ÚF—a_¨èdÒ´gtÔ†€=f˜ÖH¥98%Mø-Ù_ïÜay6'Åf$%Àv;ÊêæƒÑ‘³Où¼˜cJ«Ž89CÇ×vÏ™¤t†303¡d&§5¿pu Bºò¹CjãÚÄE\ãÔ‘Zuj–ª †b¶Èâ¦,Qò:}9ݨŽÃ7—?‚|r w%=uìòÓY±ŽE:©˜&S’ˆ¥Äî‹ý¶uwÜã yœ .ŠÄô\åËQ3¢¸Ç­å÷å¾mIPY.ciþ„ìó ®^¹‹GNÓ{lJ ú÷?ûnã—þÚ_׉&ÇføËŽ"l‡:üO¤‘£Œ>—––$B>£s¦Œªt¡ÛÕ.ã‰Z½&^û¾–gRâìmê@&?‰a6º½½…ïK&zãæ ÌÌäqâÄ uÄ$ŽX{°‰Ûź‚"4<~RfL#':¦rIDeÑf$;¬´|•âù™Å8>&™-Äd1ÿx7>¬áFq©e17QŸ ænKy£" 4•ùÜ®WQÜÛÒFâš¹¿½»ðÃ·ÞÆ—~ée<ö<öV¯¢"­U~O²(1$)¹ÈˆÜ[½ÔÃÍý4"9„bÜãQqrK³hËCHŸbIœÃÙ¼‹Ît ƒ‚ŽudÎÉá;yæÎ=~7®ÉZ6U˜WQhCC0f$BØóÍRKBí{Å6òSidåÝ:r :†Êª³7F`’±ö[hj/‚5îd`Kv3’ûhú“WÀ  Ç#¾Ñ£[iDyݸÉ&Å9;#q±CT¤HpÃlR~¸°6Ír,_ã…ê3v8cˆôC`ÇÓžaœ•öwFýÌþ¸ÏrU¢·"k?À~ë-üÙï “Ì!—M+'-Ë©Ôå%ª/Žª6TJ~øC);&¦&…®Iðq)Ÿxü¸òªôUdbyùø²‰CÈd…lQáX’ êÌ¿Ñÿó“ü¥Kâún½×W±qaÏ\Ìa*#ç1#ÏfHF@D1Wlƒøˆ× c*Yäç³ì öծД{f9¹VõŒdœjã*³TLö>«’0  ¢™ÒÐ`’V&<#ÖíâŠÆ5ÜÉž–tÕFíK.÷)ëõ‰g^ ÖÃw_û!ž}þiœ쌬äÝ~KíA¡ÁâRëÊýµLÍQ¥HÜVSjöu.•JfôiJ²ìK@ÇêVŽWò JrÞ¾sG×nuµŽÓǧµÚ÷­W.áòõ;øé/ÿòr~®ß¸©eJjRqžè3Ç<”BaJ•*(/5;;kôe4%åt(¹DD¤ü.UfZ­¦å×ÕP-Æô4  ÃÊF›ƒðÅÝ=lnl«6*gíöö«Uú8/Ñ]ÂâÊV]w±¾€\‰¾=‰-Mǽ6v[­Ždº¼´´€T<\¹¶# Ù\¢è¸9¼»ÓÒ¹SRžõ{Êf›‡m‰“rYgã3è»ýÉb×y µk´ðÊ+߯‹_ø$>qá~téÊkâ(Ú’}UªøÔçfqáè<æâK¸úáu¬oñÄT§–Ù¢-Ÿµ(‘k^NÚó3OàÅ%ëOÖño§vðgX–ÈO ©íE1„ÇÎG|j Û7n£FîSŽ È!gVèÚc¶YÆ3ª‘‚8J1`ÿOœÌNÙÁ 1&é„lÎ^KeÛq*uô;DjgÄ9ö´ä“Fr}/`ï†rryJH°H4( )¸¬¡‚Ý%:ëhV¦"ÇNT¡ÿ“Ä$Õ~ÜÐ:²Ûzµ%#òŒdcK€åê d(5(زË€dR”d?=î“dT¾ .ÒÁj q»f …€mTzc_ÕÀ ÔĆŽeÅôP²œ£Ž$îjy•- –½ØOâ¼' NWö³ÒÇ-í]E% ¶"r4«¶Í[̨­#¶fbÌà’Ýgíܸ‰æÞüò§€#É•fR³”~æ¢]·!÷Þ(¡9̱%Ïß’¨z(Ù¾T) ¤H«a&±ŽÂtŸúø‹xüÂ9- f“Iü¯ÿðÇoÿÎÿ­á®Æ×±†aD—ª5ôüE #IÔÅɲúdûþDt ÁlÊ“½ÁlSîS|Î.¦Ql÷Ñ–ëÜ‘µ­£‰Ss#üÚ §ÄѺØ6‘'ß÷-÷&2²×œ¡ oïí¹øp·7¯ïáöv/,/à1/'t_ÇZ2Ùb@«nÆXB±iË; [8ÛÂÄ¡m Ç®z’©^ÝØÇ¼¹…_ûùgpn!b ¿ "q§-g݈6(  á]Ã_ü£AV8÷ŒpæÞQÇY4®“|'·V>Q ÚR:éÙi$3DÖ÷‘–³°BYÇt Ŧd6¥}}¶Ó$\'YG¿&)D«Õ=ÌøÌ'ÎbNÞcv%¯ÕRZÆ<úK–*Ë5#(ìó»äµ–@+î *÷ô Ò@ ŽùÙsK(8}qõä£@p@ènæ6Ã1"\SÚVt½„¤+f&—iŽ“ÊÈsÉHBPÄÞ»Û¸ßâ©Ç%~4‹T¢Å†¿œ½(‡™©å,5le¯CKËöKÕ³6eºZjµ%ièuÈfåêä‡7”ONîPGdH>£ f¥žQ!=*ã¶§(à`Ûc5˜HȼmCµmõMÙÜOàÚpóÚ¦$;¶Š)dÒF2®^« ±ÑÚ+ag{³s³*—Ìp˜Ò@Ÿ”¯ôEüb “SeãØÜ½{¸»ú¡’­lmmáæ­[ØÞßÅÑ#iÅŒl¬¯áÒµ«8õÈÓÈæqûö=ƒbÀJú3[SS’ùš 5ýdÁ˜ ó ›âÉIáD‡¨\‘ža*R<2q´z(ºU“Œ–H¿n§;ff0˜¤«„[*‰¶üÛ½õu\fƒ‰Ügò~îùü—îâ•{5ì÷¸eˆŒÓrm5‰ÖËýò²(DtÞmH&º_dz²Áõ"Vïyˆ‹õ‚ŽlÞ,JâÔÖ(ã¥Ã^ÅŠ#‘EßgiÐniöÅ&uBÎ/ͽ„ƒw~t ßøÃ?Æç?ÿ²8ýVg—Ð{XÂË/Ç=ó8.½ºŽ3Ïæpr!…ßgU¢ò#Êb~ûµ]L˜)ˆ³ˆÃjI"£-\x/b«|ï®÷0'½[Ï}âYɆªX½ü¢Dm¹ÇA6Þ¦z‚ ¨/kže%QqW"ÃzƒskqÉl=Ù<Z~Éì‚dÙúÅ–ŽñÂÎež ±¶Dó‰¤ÄÒXDU‚rˆ$3òÙeÙðm#q¿ZE§¸¯ª¾dîd¢Œœ²œjùÄ5L.š5KB…é!i@ñqd&f±–Oµ¹c øzü• { t}¶ ¡úâX™ FUÈQ{¤«Ñ(…¤|öÐÒÊ!û­\EBzd2‘ìÀh&«FÛ5B÷ìŸæsy àF£¦f‰t$O`pÈ@0)P"jiŸ”ðcVµß6„¤¤±Ì7K‚q®§5”gÛØ“½è¯âKÏ¥°'÷“`€(̈}>Oö^eíò‘)ÎfïW4urú!-û™±pÔÀnã'?îâûñëÿå¯éÏ °þßþçøÿó×´oI‚ò •'±CGž×BaZ MIƒÅÎj/âdT!È›hó\w–ÎÒºÌle‰)3øÜÉ8^Ù¡ %ÆA®uN5‘%¸ÈäPíQ8ÃQ’õ.!šâP7«.¾se7׫òy|1ÐAF‚Õ*šÝ¶–-m1ÈP EA(ž™=\Šý‹À „&?‰ÿ•xèØü¿ß¾§`¥¿þ‰Ó˜[­`½,†=š–½0@Ô1³‘£ðà0SÒG@Ia`7&,h¹×¬É8ÈRÕ‘}SìÚØ¬ÙX-7°´µãÓy-æhwÈÎ)W¹Ý”ªéToÜÓqªQß‘a€F{K+âŒ%KÚl×ñá‡5¬WÛbÐs°;ff’UÚÇ¥Ù˜1ô#v°-ÎhßoÉyí¢DýMÉN_‘ã ð"’QJ6Ø"«çT-LJÛã>±=vš:ïÎz~HB`8‘qêœ3ç,±lXÔ»Q¼q¥‰ë |ªXÀcÇ,Ï'A¸ƒÛ*Å"…<`ÅUe chàøi fIS93#~r¤€¤´$¶d.=Ï ÒGÖÊVAe¬þð‹efž}¶u"ñè¤Õ¨%Øpz Œ7›Ÿ–5Ê1]ÄK/žÆµ›—qåý÷qíê}ù vv7ŸH¥TëÆÆŒý¶‰ÚèH;¤.+—Q‘äÌÌΨ¢ £)–…›ª¼Õ¬€s@YÙð]öKä=º„ý➎Du*‚R©"Ž|X4¥³Q*P,O6•H4¦¡Õí]e]‘ø_<¿,Ñg ßzÐÓ>ÞõN³‹'ðÈül^¿,Τ‰ŽdV·«<7 <~,ƒªEB®'"Yéî(‚åÐ5Äx$úN‹¡È°Œ(×Ô!PƒE6e‡##9q£µ{º]6™’Ù©L\#µgüü^Àå7Kø“ß{ˆQ+ƒüÙîmŽp[ò“G¦ð0·†©BJI©K-7ïŽðá;žÛãѧÉ囸#×Ú‘ }áÂEq´ðæüìmlêÜ›²J)g±£rp:¬LæqX¾ÖÞ*£{Y綪aÓƒr‹Óž*ÇøY¹Ö>É1 G.K*#¹Ý4òž$]'‘êAìuR0w(Ùƒ›°”ÌÃId´/âÚ:HÎÊ™^†JN|°eèG†vÏеÙÙÇ,#@NCžœš†×**3TÔ1ã¤u@d\’‚™Cäû¹†ÖËëwu^“`3ÒÝñp9r®nT¾±CnM…ГޒÒWTýa´Oð)ÝH af%Ù*tˆEríX\§‹TB RFy""”¸ñ’ÅöäàK¦ ¾ýŽÎ *…"Ì}l2”ÚrÅ=î½…ÞF_ý¥¨FôT”)Ö  ÍÚHUaTåƒD';‰#etY̵Žb›ŸçôŸ§åvËÂ~gÏ¿ô÷pîÌuÌÿä7~ ÿÃÿø$ÀJ)Ïn©RÔþ)\;î„<¿­J³ù –ÊÈpÁñÔájižL4ò,”Ûµç©~pBdž|hßwQHű#Fÿ}¯O©9ÄÄøQ‹tŠ3ðµ´Z’(wWœæÍí.®oIgç¢ß©áa·‰ˆÜ»#A‚Kç F“Ó-mûÚk³cXT¶FpȹúÚY%g4é÷1G]á÷^½‡ÅÔ”œ…¬ÜÇ.½‘>êŒ,Ó+XYøËÎz"Ûæ ²Q˜µj9Ÿ4% Œø³ä¨ˆ»².›bSȶåZ%øV•G›3¤D¢rd­Å‰ƒA…dN‘Ù™é$æVæ%{Éh»j³Ø@µl‚;œýÈ* í®*Ûˆ#âsÑ‘¹²Ë›Í>:ý¡ßI›- 2êbU›xËE׋£Ž¾ÑFµÆýËK[Ï—£ë:x“òºfè!7°Ñ¹fÆ×BŒJ,‘”ÜKWöP ßüÞkY™Íæ$…>ÒÖRÚ‘#uŠhÖ.ÌP3ÕOúEÉj§5Hco•¼ ”‘ã³ÛÛÙ‘Db’mÅ'à-Á ?qpÙ„Dá]D-1jrØÝF’µÛñ’’âS‡“€öQ@… qŠv 9Yίþ\K\kIRîúHõ¢„ú9üÖü‹ØXÁßýê¯â_}ý$3[Ä‘¥SJŒR*— JZSt™8y¨›8rò(fÄ`oß½…ë•6RÉ@Kæc…!- ¶Õ£è¿G9K*ß;£yHˆ‹A,íTñƒûcŠ5[Û+tÞ­N['êM;EÉ€«dZ Í¥dv¶=ÔÒýý¶/{Cçòw­Û—¯ž#µès⨓ç}dÔWÛ*A•h¤xûhÄ Ù=qVÄ@ ð[z?ñÄ lÙ?t::Ï({“û³K@‹áüKeßÃÏ ü[RdzáKÙ‹dÄRêH…¸;’}ت5$ ˆjÆOŽð‘oúóúnž!ÀŸŠ>¤Žx’÷?èh«j$Þ¤#·ÅÙÚ^We2SNT£K阗70’Š}k$IGFx.ääL’‹öÎVÙ–8Øv {Å^M#çO€¾þX.“zXÁÐüLø0À8½OÒÛq ÛSSYÑX­Û«hܧºSÂ{SC,æ¢8³`c®û‘{é’S·­YªrÜÊÞŠ'ÖU$…ï—ªŒÔ®ÉÖµ•‹€3r4³Ò¥|œ_&é•cT Õ ÅÖå £ n›¤ÀnPÙ'bô¦eý˜+¨U fDÖ'•žG½ŸÁýŽ$xïãø‰-‰ïؽýCO?²r é»°Pº“üÒívW¸¬ªF”¯×W»X©”$)ÌjÀC\³YÞ¯'Ïjzþˆ‚™nÞZÅÝ»1=½ ìJdù#(ÍåM˜t·¥ øãÇ—uÖÇ Å[yáÌbŒ²Ùòa)Qo¿ÚD]6Ê—¾ôy<GzíƒhÔ›xë+²ÐÏáÇ_zÖÄùˆA̧Pˆ9x°S“h­¨ôWó‹ózØK’RÇåÂçs1L¥£¸Sî`·`v9†‹GÄú±ùʑ۔Œù»¯ â0¦±×—(¸tk.Vr¹Þ.^Y¯"3êafné™b (ÝqÒh5zèÊÆRQ£ˆ`nGÖÑöË?‹ÿî«7o^‘è¥%iòGßÁßù¯ÿ¼ô¹'Q«¼‰r¹‰kûr(,´ºràå:{5‰Rë¼í¡DuËØÛP¼_ÃÞ©¬šÄ‘rèï­ßÁê½,>÷ùY1Áð©Oþ"¦²6¾þOÿ¹fóq’¯ÿÅÒWÈ óÿ—uî¼MDAž]¿•—Xˆ(  AC— QRó—(h(ÈoB Ñ@)(dÅÁ‰;^?v½Ìwî:8€”†¤ˆâ;wî<Îù¨æ¹Ø’éXCþ°!pÌ(ϼ2éõƶ¾³"­*‹,³=°ÂSSmŸ™zIíÜj©¡Jù8«çUý«b[ñ€ð ³ÀhŒ X2ðƒh‰iª¯ª5¶µèãiÌzÛ«<¯î'—¡sÁܬ޳ðì͢Ìú½r4€ ¸…l("ÓÂ/“¥ d%C涸Ñ]ˆ–ð€q\\(©ŒÅ™û¦tH‰ÐTßÚnkÑ€Ù}·Ó‘QüÝÛþÿ·alX:ÈuÙPÉò°„Œ‘á“ËŒrÚÊØ âØ"¼q>´Ýfl›uK"¯PçþÂ?Ol·â1TùjécÛ»·fOŸÐ¦ë¨ýŒ×(Stp81±ïk¦XÖ¼k2˜Ú{d/ö÷íýÛöòù3{õîÇߺx¤­fS&ø‡‡8‘Mdf@BÅg›™QrÒ³¬Ùò¿GÅ/Üuò8p0UýJRQD|^6R‰ë·"Àï[r•Û÷/—ª0µŒâqyå ñÄ/¦Á(6aŸ-s%<|¸àЕ²‘íàùhj«±ä}5ø´´gÚX_XÙýO"º1Oå•Ì! _þ3k~^åªøÄ¯?œÚÍ Ëülà÷„¤;±°šýç_‘²‹Ù{±PwMRùëM­-tt—òŽtV„s•@‘Ôè÷‹¤ÅgqEŠœÜ©dB@ xDöþÂôóX<Î."îÕj]„|‚g2©H›Ï„$í™<%>Îl¥–Ú`èßõ;à·ß…g^5³ã42á‘°€v«"Õ%lygùÍ8‚´ ¶( KkF(u0LéȺ'^v±ÚÚAkf÷w¶lË+n,f{~èzU«™:U,ÕjSA"œÂjtMÚ~Oâ„–Ö„Ha’àÝ-V*;³k0]ø 您XB8ŠÑM’ÍCežÐè2­7½*fŒU:ÖÖîtT³ƒÏ?ý!]ò‡bä‰.²_GûÄîLFU§^q’ðâ]@Óù¬‹—ÚïtÍÓTãÎ~ÿ\-s =m,Švæ1sôíX¼dâ‰îíüÁË£»ƒ™IEND®B`‚MEND! ÷Õpvpgn-1.8.5/files/tos.txt0000644000175000017500000000261711151345317014320 0ustar aaronaaronYou are currently connected to a PvPGN Server (Player -vs- Player Gaming Network) PvPGN TERMS OF USE: PvPGN is a Battle.net(R) emulation server and in no way affiliated with bnetd, warforge, or Blizzard Entertainment(R). PvPGN is provided "as is" without warrenties of any kind. We do not support the idea of Pirated software and urge you to purchase a legit copy of any games that you play on our servers. 1. Information found on PvPGN. PvPGN does not endorse or stand behind the accuracy, truthfulness or reliability of any information (including statements of opinion or advice) provided on or by means of PvPGN. Any and all statements made in forums, chat or during game play reflect only the views of their author. 2. Disclaimer of Warrenty. PvPGN is provided to you "as is" without warrenty of any kind. PvPGN does not warrent that their programm will be uninterrupted or error free. 3. Limitations of Liability PvPGN is in no way liable for loss or damage of any kind resulting from the use of PvPGN, including but not limited to, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other damages or losses, commercial or otherwise. Battle.net(R) and Blizzard Entertainment(R) are trademarks or registered trademarks of Blizzard Entertainment in the U.S. and/or other countries. Besides all this... Happy gaming.. PvPGN Project Page: http://pvpgn.berlios.de/ pvpgn-1.8.5/files/tos_default.txt0000644000175000017500000000261711151345317016024 0ustar aaronaaronYou are currently connected to a PvPGN Server (Player -vs- Player Gaming Network) PvPGN TERMS OF USE: PvPGN is a Battle.net(R) emulation server and in no way affiliated with bnetd, warforge, or Blizzard Entertainment(R). PvPGN is provided "as is" without warrenties of any kind. We do not support the idea of Pirated software and urge you to purchase a legit copy of any games that you play on our servers. 1. Information found on PvPGN. PvPGN does not endorse or stand behind the accuracy, truthfulness or reliability of any information (including statements of opinion or advice) provided on or by means of PvPGN. Any and all statements made in forums, chat or during game play reflect only the views of their author. 2. Disclaimer of Warrenty. PvPGN is provided to you "as is" without warrenty of any kind. PvPGN does not warrent that their programm will be uninterrupted or error free. 3. Limitations of Liability PvPGN is in no way liable for loss or damage of any kind resulting from the use of PvPGN, including but not limited to, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other damages or losses, commercial or otherwise. Battle.net(R) and Blizzard Entertainment(R) are trademarks or registered trademarks of Blizzard Entertainment in the U.S. and/or other countries. Besides all this... Happy gaming.. PvPGN Project Page: http://pvpgn.berlios.de/ pvpgn-1.8.5/files/newaccount-enUS.txt0000644000175000017500000000257211151345317016531 0ustar aaronaaronYou are currently connected to a PvPGN Server (Player -vs- Player Gaming Network) PvPGN TERMS OF USE: PvPGN is a Battle.net(R) emulation server and in no way affiliated with bnetd, warforge, or Blizzard Entertainment(R). PvPGN is provided "as is" without warrenties of any kind. We do not support the idea of Pirated software and urge you to purchase a legit copy of any games that you play on our servers. 1. Information found on PvPGN. PvPGN does not endorse or stand behind the accuracy, truthfulness or reliability of any information (including statements of opinion or advice) provided on or by means of PvPGN. Any and all statements made in forums, chat or during game play reflect only the views of their author. 2. Disclaimer of Warrenty. PvPGN is provided to you "as is" without warrenty of any kind. PvPGN does not warrent that their programm will be uninterrupted or error free. 3. Limitations of Liability PvPGN is in no way liable for loss or damage of any kind resulting from the use of PvPGN, including but not limited to, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other damages or losses, commercial or otherwise. Battle.net(R) and Blizzard Entertainment(R) are trademarks or registered trademarks of Blizzard Entertainment in the U.S. and/or other countries. Besides all this... Happy gaming.. PvPGN Project Page: http://pvpgn.berlios.de/ pvpgn-1.8.5/files/chathelp-war3-ruRU.txt0000644000175000017500000000145511151345317017047 0ustar aaronaaronPvPGN Bnet Emulation Chat Help Commands Ðовые команды: наберите /f help Ð´Ð»Ñ Ð²Ñ‹Ð·Ð¾Ð²Ð° Ñправки ÑпиÑке друзей наберите /users Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра пользоватей в онлайне наберите /w или /msg <имÑпользователÑ> Ð´Ð»Ñ Ð»Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð½Ð°Ð±ÐµÑ€Ð¸Ñ‚Ðµ /join <канал> Ð´Ð»Ñ Ð¿Ñ€Ð¸ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ðº каналу Ð”Ð»Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ‚Ð¾Ñ€Ð¾Ð² каналов: наберите /ban <имÑпользователÑ> чтобы забанить игрока на данном канале наберите /kick <имÑпользователÑ> чтобы выкинуть Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ñтого канала Ð”Ð»Ñ Ð´Ð°Ð»ÑŒÐ½ÐµÐ¹ÑˆÐµÐ¹ помощи наберите: /help pvpgn-1.8.5/files/newbie.save0000644000175000017500000000020211151345317015067 0ustar aaronaaronUªUªY?‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿpvpgn-1.8.5/files/chathelp-war3-default.txt0000644000175000017500000000053711151345317017576 0ustar aaronaaronPvPGN Bnet Emulation Chat Help Commands New Commands: use /f help for a friend lists help use /users to view users online use /w or /msg to whisper people use /join to join a channel For Chan Ops: use /ban bans a user from channel use /kick kicks a user from channel For a more detailed help type: /helppvpgn-1.8.5/files/newaccount-default.txt0000644000175000017500000000257211151345317017303 0ustar aaronaaronYou are currently connected to a PvPGN Server (Player -vs- Player Gaming Network) PvPGN TERMS OF USE: PvPGN is a Battle.net(R) emulation server and in no way affiliated with bnetd, warforge, or Blizzard Entertainment(R). PvPGN is provided "as is" without warrenties of any kind. We do not support the idea of Pirated software and urge you to purchase a legit copy of any games that you play on our servers. 1. Information found on PvPGN. PvPGN does not endorse or stand behind the accuracy, truthfulness or reliability of any information (including statements of opinion or advice) provided on or by means of PvPGN. Any and all statements made in forums, chat or during game play reflect only the views of their author. 2. Disclaimer of Warrenty. PvPGN is provided to you "as is" without warrenty of any kind. PvPGN does not warrent that their programm will be uninterrupted or error free. 3. Limitations of Liability PvPGN is in no way liable for loss or damage of any kind resulting from the use of PvPGN, including but not limited to, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other damages or losses, commercial or otherwise. Battle.net(R) and Blizzard Entertainment(R) are trademarks or registered trademarks of Blizzard Entertainment in the U.S. and/or other countries. Besides all this... Happy gaming.. PvPGN Project Page: http://pvpgn.berlios.de/ pvpgn-1.8.5/files/chathelp-war3-zhCN.txt0000644000175000017500000000070511151345317017011 0ustar aaronaaronPvPGN模拟战网èŠå¤©å‘½ä»¤å¸®åŠ© 新命令: 使用 /f help 显示朋å‹å‘½ä»¤å¸®åŠ© 使用 /users 显示在线玩家数 使用 /w 或者 /msg <玩家åç§°> å‘逿¶ˆæ¯ç»™çީ家 使用 /join <频é“> åŠ å…¥æŒ‡å®šçš„é¢‘é“ é¢‘é“管ç†å‘˜ï¼š 使用 /ban <玩家åç§°> 把玩家从该频é“ä¸­è¸¢å‡ºï¼Œå¹¶ç¦æ­¢çީ家冿¬¡è¿›å…¥æ­¤é¢‘é“ ä½¿ç”¨ /kick <玩家åç§°> 把玩家从该频é“中踢出 更多的帮助:输入/help pvpgn-1.8.5/files/tos-unicode_default.txt0000644000175000017500000000261711151345317017450 0ustar aaronaaronYou are currently connected to a PvPGN Server (Player -vs- Player Gaming Network) PvPGN TERMS OF USE: PvPGN is a Battle.net(R) emulation server and in no way affiliated with bnetd, warforge, or Blizzard Entertainment(R). PvPGN is provided "as is" without warrenties of any kind. We do not support the idea of Pirated software and urge you to purchase a legit copy of any games that you play on our servers. 1. Information found on PvPGN. PvPGN does not endorse or stand behind the accuracy, truthfulness or reliability of any information (including statements of opinion or advice) provided on or by means of PvPGN. Any and all statements made in forums, chat or during game play reflect only the views of their author. 2. Disclaimer of Warrenty. PvPGN is provided to you "as is" without warrenty of any kind. PvPGN does not warrent that their programm will be uninterrupted or error free. 3. Limitations of Liability PvPGN is in no way liable for loss or damage of any kind resulting from the use of PvPGN, including but not limited to, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other damages or losses, commercial or otherwise. Battle.net(R) and Blizzard Entertainment(R) are trademarks or registered trademarks of Blizzard Entertainment in the U.S. and/or other countries. Besides all this... Happy gaming.. PvPGN Project Page: http://pvpgn.berlios.de/ pvpgn-1.8.5/files/ad000001.smk0000644000175000017500000004420011151345317014505 0ustar aaronaaronSMK2Ô<ÒðØÿÿy Àˆx&083ÿs¤G`“æzÄ ÂÿÝ ÂD31b¾;¯ÀAb|ßÞCô|ýü3<þû‡± ÆÏ× *UV;vÔ/¤Ë$%¸¡úJØCwR9”eé‚ÉQSèÁÂÄ%$aÇ/Â`äÛ!Æ@gæºó·ˆ&Ä<#)QÙ‘œt³0øDFbr‚Cp^6Ò’00}ÉhffÕñëÁ€€€‚¢A¦00Ï< BƒkFz7 9ñ @—Ç<Š êôòi’™‘¸3-/O|£J!a¨Á:‡ƒ aÂQÂó¥ãõ  f¢|ÛE¿Î‚Ÿw4ÙnáÝE&ëaèa¸¥ÍQf#~Ö~0´ìªÅhtT¹ÆŽI¼ˆŒ4»I £B^™™>ˆ\{öƒúƒÓCBFjºãñuäw䃹çÕý{¸TÈ>“,›ÒèÕX©ÇêÆaóqcÌêðÜR[…I•1ª/ã¦õàd1&É/xKÏÌšäÈj9®CÅÞìcjâ@:¨±óoM+^Æ#¨:o„LIÆ„¨%1Õ¨JY@–B%&_‰ž¦øl K8ZŽDHM†&å§'@§Ä©"Gçå«.9Q¹òÇ¢%+“1“‹—Wã¨)1³BŽ¢t \ •IQ É@”ì S4BžW#¾º’u<‚1´.?i:$Kå𕪚8øcÛY„C÷>ŠÒšö[ÌAh1üøqåˆ íÀ~~átïö/•>œj•v ¨x>Á¤ä(~tŽ44Vlˆ­"Aü‹žžV(±54ì&܃@0žœáZ@Ž×P`ø’ÀÛT‡a7'Õ$‚ìGVQYÝP#¹Ð•‘0v(]Ö#˜‰¤£j¢¢õïO)^6$’¾ÊbóŠx ‰ÆÉ=ÁR¦oK”dÌ•*:q¥%çH5âhVVê1õ¹€©)'] ¢Âd1Z¦ª>G$©?ŸÑ Ô’+,áñǓעÈJÄÉ=¦KñÒPN¾F¢$V/DL3FÆU•œnL —‚­‡ORj>¤Š,µ¦´l]SBŒ’¡‘¤kI¥.6™`™ŽŸaEå €€ÿm¸”Ñù=T² ÚYJ°¢§÷ý[ä!6BÐûôÖ¸¡¸è³í4$ÚGÁ#TÞ]("VàÊù æ,ÿLk4a<¼wA%e]¶y̼eÀËZ7Ž M`m¢«ÜDäü§SÁøZñZáùh^ÈŸÀCôŠ#]o[gë‰:Ud‚Îàf³étôxttnä!¼l¡ÂVš¹«|¦i×Ú„öÐ.ìùepúµÕhmͳ–IöcZ ÁÇ@ò‘á!ȳ»¨Gu@ ñb5EýGÌhZñ Š ^l­Ÿs´Sf,,a†ÂÆ¡H,fF?uœ·r¨¶('Ï >8çÁÕœ‰îåX- —µ¯}œÔ͇u¦=Š:ça¨O}@'ö‘ž!ö>òyY¤Á­Œ›±FÆÃNŽU'©'fX8pDìÇ-.X ¹‰’ g‚¤Üq Wâ³A ¸Rá¸W%ÆjÒñ«8½±éWèP.H»I8©A‡HŸª@üŠ‚à‡H~[AùG+|?L‘ç«(ÛϪþ‹ÏhPx3¢<bpg&wÈLöÃ) où~Ñ æÿ þKXÄ€Hº<VàºE¿&#F/1f²IoÎ"]2”ôÉÓ6tlü^j ÍÈ5¿¢B- ­ÊŠ™PDe°à MT ¼ÅêÙ:Öc'/Ô*]¤uƒgÚ2ŠYaQlËe€r¢0½‹à¦:X÷¤„Jåä¦5 .&vzeP¡ˆ“B¶ZŠ‚:ü«¿YtÇZšR‚ø¿ZAª Ê­ö$$,)Ò™±PL&xŽH¬"^|Þ±OÃccVJxøç‡çÊ™[ª¹Z¨oÏÿð/ƒFÏc¼Óé`þj‡Ô-Û ÖtE„0Eø×ÛÓ`¡6¿5lÌvÊ/S†67u7¶zŸ%ï”¶Õ†³•–Î&·‹¶ƒVc‹Ú:ØRl»ŸÓÍŠ2\¾–¾dûeíh où ­Ë üÑ‚:NÃkÇÇ(1s@ãM‘)öD øŽŸê]5§Qíèn×%FêbZtn( ÿ(Ï‚=˜ïñ€–çæœp`ØÄßøN¡êÿ~D=ßéÕFcÉŒ`¹{ŽG—U¶¨8@KSŒZ¨^ 0‚_‰ü5ÙÓ¨Í܉›»]¬(›ÌÂ&J–e<ôã(Ó&7c¤Ø‹qñÉ?²†p,› 3gÐÆ1j±WHRïž²aå2¤BáÓòÿ ‹Ã,‘Mè<²  4âÍ-7“7`Žåõ0ªdÄ™H^³d(0LQrÚ¸ù@€ 000070)2<•        #(#    +""& !0!* ("0 #" 0# 7&%$/$8 7$ 4).1)((1)=%<) +,-=-6/%>2;2569002>8==:=6'ÿ•?><(() ????????????IÓ%Ó£çã¤L Ó,«ä»‘µ3y!ýp‹¥ Þí Ñvsµï4Ù°ùhv‡6Ý|(„é¡S ‘ûý4ëÛä~‚Ø%·:J¸ûØŸ'XÜÏ èÜv4+A AÅRItƒÚlvË`BIÈqu¾~ðvÜø“fB<„zùé®d3ÿ s7ÄZˆÂ¿ùaˆy1@ú¦J"=æ|L’  ¨øk‚Z/ùߦvȃ~HPÌ.qSmôÛ6@4;+ U¿’Né(L%¥µ§ Jšú%nfÒ¯3I¨“±îjIŽê‰GE®X‹’$qŸˆ(J/¥”ü)“$Í ;Bîj'’¶Ñsw+ÛÌ„Áí+„€'G’”xª¬ø6&o˜H©cmü$ ²)I3 uè$` 'x šé&øµi©õ§)laIÆúºnÐ #Åûûl5‘<2"x‡9ªÀŽÇÐprL/TeOUë7ìësÜU…xݧ]~OÛº÷ ÕF< nËb«¢“; ¹æÝ*b]ìÐxoCñÖaw]š7v]…^ÙZÀ— Š }£¾ÞÑŒ Ò)Ô‡lãòøN†K uJj=ðÄX±“ªÌŽÐ«’Z—«Ý¤„JõÚZÊA±RÁëÿ([L="€t´–-øh¼‰wÀD|ùèÿ9USOtµ¸†5ªW1FØ' 6bu‚z*÷B`¬PÔ³Ø)V‡¢*¹¿]P§².ÊJ¨\ë (f%Õàú0H(âS(|__®;àð8êÕI|ÍUáøƒ:­~ w]Ø4S¶HF<hÞ(Д#’4ï™r#ÐP šr#мgÊmÖ2`ï&¾þ‘—ŸñyÆ‚1ý¢µî+ð¹^6T¹œðÒرÁÈîKbÏÖ(A10ï,özOh^ºpòw 7~ýËƒÝ pÃRÍ/! ìø ?ìÀ‚ɶ]JCŠ" ¶ä ådQ$_­]d¤µSSFjU™jlÕИJaÕhÈ”Ro€”Š2+¡IÈÖw‘¯¢­&šÜKN6Œ¯Ž ˜4®‚IšÕ ¿òY[¨0iëQ ÝžD[!L td»_òì5E¸½ŸÄ Lˆ¢Ð„ìc¸zBŸÂpÛ¡m€žB0‹H%hlö ;A1ôb4(Í– £xÌ0˜Ç,1Ç`Íw›1”ÀP?n~óªuWBo0@-Q03ÈÆb&æ|4ãDº¨wÌ„dÕëXªÅÌ$PÜT›¤€¤Ou4«ê,î%$ŒDWŽJ§e'Íjh&úI@%¡YYchúsÜ®­üÑf`Ù7!Blî%'>?vJHp§ˆ"Ù½¹:y"!’¥,wK¶IJY;ʶe Aïü8L’vн(D’ n:&BLAŽk‘¿8Fèôã5R£iÃÃÇUµŒGÎÌfÛ@’Å4Ȥ.⢞ã: V]´Ct³WÄ8T¹J3t]Ãíe¯ºž6[x€å!»5÷Çh´YÕ­WÓQ°™p¸°íÙCþ49Þ¦¸Œ¿lï^à¹ãMŠZˆ÷„º„¢ P^{·Š»<=x»žÆˆ e(GŒxt>mCMÍCýèE<7.*òâºR_kÅ…R…o =ø òÑäbƒž Oý6;»è nšwZÔ ªrÓÁ&ø¨tüuV ý¦ÔKBí[Án<¦m‹Ø3¬E1Œ’Çz0Ø$R€^ð‰¹ldÀP̨—fáÁBËÜõDµãÿ#Q䉧³²ª&Y÷µ¢¶§â@TaÓˆ»`Ÿ ½`­¯ˆv;Ø,_”ÔxY£b½²aGçF…$à)È"nŠóãºÆfìPΡV E=áUN¸¤³ªMÐn6‘ðÐàh—ÍF¤ ÀÆ –HÛ6úµË6lˆÔlʰaô—&j7§4ÿ£ÔIª°l‡6}4,ú“ÂŒ¹óå°ùăÝ á(>îôa`qå;ŸŠØî(î€-RBtýC¸ó©€rG*JO'?…rÂdÚõÐkEií¢é{ù#/Ccl5M™jIÔ¶ í•äehH+ÛÚU+F^fÑP§ C$ëù8z¤Ä¸ðP‚'ŸazL@í O!èá–n,Õ†‰IÉLñp{Búé€]0……Û€BGÁÞ$XücMLñDßC’þò€4ߌ ÛŒÕÓ‹1ý¢cÆ @Á9ˆŽs_¹Š­fˆÔ‹Tîœ@_èåzWïRCƒp.¢Ó›úM0¸C ôâÔ0 zcÄXµAXAš¢Ö¼ê#½I#«ðd+AÖK’ dvq³3Õ¨$n–d4Ý—Ð”Ü •rEBªwÚŠôE¿¢a‡íapx‚§¢Ôòá$œtVI 7iæCN¢_õ&`(ª>Ñ&BöÕc ú\µéI@Õ¢¤³TçO$˜+©Žñ€: ­¤[’ÂŽd0^ÜR(©#ICæ =“äV@…É­&GOŒ{ÄW#Ì f„Ž÷~ùÚsü-š`L̦ ¯-ȰÏ…±ÑãäŽv‰ŽÏ×ÃyÛŠ˜¹òÈ䎤¡ 7Ò7©íl±¦&:Cv¡P'h²Á²ì¸“ñ¶Aï æ¦›]JÑG³@à®íX`MäÓ13þÛtSÑðÿM ß}û¾GòŽg¾¼n ’pg\UºÔ1I|<<…KG¦¯žö°)Ü[3ÒLœë*ÚÐå-°h¡OP¢%(s›½Ô€‚!ŠÁ"÷X€O8;#h°6ŒNÙ:¥uàùûÖYC/¬rTðT¨  dú¨PGk”ÄÃnQ>«^èÖyÁÅžFŒÂàT§^NuUá¬ï¢–Ó€ü(íµ®²uvÀaX¡ò̤¬ 0÷$Cª3ø+•‹Xã ÕLhAªõ8å{¡ÎÎzÆ”ÐÖ ÖØA9•Ç,d×,#õÂÒÐÕÆ8š³7ˆíÜ“š'< >¤¦¯Ôh»P£Ð€Xè?ažêí“èáIá#ó$ôÓw¢íI6ú£‡Ôl0l3ôjþ6`! „Éß ¾l%ƒ°IõIL/cæ±çK“” tDáC’Ð · $¹ßö‚‡ûIY…¡;  dnK@HžÚž`q «4«?l~0>̲ùÒi‚¤ÒAt4Û\L%ˆ£Ôà ½q§>Ò7Ìö1€ÆúwÃxb¼Á,ø™$!zOˆÕ^òŸE-`fÓ„L¯tA@ù˜dáGÞ÷2H_ÌŸšiêã îibhN%£©gá‰ôÔº ¨3ÛÌIÿ±dÛš–mj³%‰~3wIxÚÉî;ùÜÉ>KxŒ2—¾;ëäü“ûC-Mˆ¹N>²d0Ö“íª&Öe¬èµð55®GQë7¯„²ÕWëNOž[ôù€œD} ¹Í{ðHr EõÃ3#B¼‚/šI6ý¿aFSoÙnª—í@ÍQÞÈÃ5(ä6Û:@×LmTO* ¾ *Zê+ £W(Â>ˆÌOÓMµ½àßìŸð­*Ü÷ÄóÜ|H75ðîÖ—ïÁŽÝ—b,GÁ”¢5Þ,Ì,&â}9™EÏTðŠÜDÁïé x¡*‡O™¡1A ‘Õù-çi´Šz´Ìʰ²GÆxëTÀYTH Y³«45S’Z ôvBVH¦À|R  ÿÃ Íæ´4‹\Ä(]2¯1ðoÐø ¡J=ƺð,ºtÞJ8£žÐ¹à…¶Ø˜g¹+_§`ítáiÐá4ݸ,ò!õWƒh'Óæ#ùê‘'ýÔ >6ŸÙg" N•M{ÙQ¤n2'žA{l‚ØA¥¯C{RbÔCÐÛ ½ HõI=y^ýuý¢1õ¸IKSÿiè чúO™TM‚°„#SŸÝÉ–FÝVšG¶ ‹Œ4é |ŠTîØÒÁA IºOh¨©Vd&Ì"C™DŠ/(¥ KB>sHÆþÔ_qÍ/{Z¶ýþS¹Iæê¾…=Iº7­ÄyWnB£ñî9¿Rv;éfOrN û–Ó9»Œ}NºdßÚ~¿œÎ6éTeJ‹H¡¨’‰3hä5H’ú$`^ãA@\ZÂó”ÒEL ¸9¢­…~Ñ"´"- Ñ©ñLbE«„Ãh)[šLCäÔ‘·‘k€Iͪ§C>ž½_¨š .Úbá VýüZ‰m›ËòÓOl¯.¿B§øÁVy¬ ¬÷h?'U6 œw'–ª?KÕñÛ¶ª•Øs|ЮÂͽ÷<ǃ*[àzöŽ-`Wl̼Söç½Y~®š÷àÏÏÕop޳凯—‰ÑŽ¡óççM»•ØS\¿—tü¦‘¿âêvÂ0ð@ßt³C±,*t·úSEY,Az«ŠI™:ë¤[)ðº¥(ÝS¯æÒ¥Š*©Éë¿Y R Æä¯^ä½q¾ZÊjÎ ëñeÝ~m!±J‚C_P‰Ä ’(Wg¾R­§+LÞÛE®º}è6qyFP¶5)64ÿ‡Ø†y5Ë´²‘Á6 tãÅ7aåSMÎ7Z}‰™7–Þ-4ð[Ì'Œ¬&ø(oCÔ‘,†ß¾­†D‹ Ha_2î9¿k"<ÈÁ«™öª¼Ub+îØU”¹M j—ƒ’¥.÷§:h)–*¢‡·Xå,] ò-tþ²Bb¸r ¤õ"Ã}C¯9Zì¬ ¨,/Â"œQÕ½¯Ó{pÚ»þ¢öë³ÁÒ­þ·R‰M©ƒ‰J‡:õ8–¿ €—c2;/Úø‘ ˆÀ¼ Ñ€Ö¿}þ0‹{]DßÔú¿B§´„Ù)SÕ¾ýõŒNŸ 8~òž¶ã—@[µ2n2h+ªã¸öâ´H.Ž]èo?ŠŠ½e¹MÞÖ ›kÞ ¸'1—߯À•§eÛ€++û 8Ëbtþ沜<­ì—äiÅ/ÖuY{ºqý,—MLuÛÆî¢¥:r- Nr$ ÈÒusdÛ ±Šª‚²ýÚ J6êTËȶ••‘`Vu$»À1+’„LšpŒl#‰!q©Ëº<´Ù6È„‹R€#+[ IÖc2°Åñž¸s teÚ Û•9PÑêŠó9éÞæœ=±ì]KÐÓeÛ  ƒ'¿mØý€ùq$S *”Brc¤VÑ ·UÈèâ„÷½ý<Âa”“€Ó“L‡DÂ1Q˜Æ yöñúÑðakDrhÌÖÈLC¾ªè©ãϦ¸ç¢yÁ!ÆWž¡Á+y±ñåãyò[|dò‹Ìt‘_¾Ê¶þå÷ô®Øž·þé|Ûó¶,Ûf¢ˆeÛäÛ ða£-ÏI}<‹¥_–ÅÒêç Ü%+͵X.?[ü’„v\}&I.E+_Ðõ²ÝÈA—ÀèrS\%õr,Ì›åêÿЀܷð¢ÎZ*.ånk@Y*À3íëTg©‚ ðrà µÂ"ø×•¬§Î+=¾ÈU¹‰²"êÞœ)1CíªD¼3ÛÜ(eMLÕ Ed2ØB‘ŒëzBÝĸÀÖ0ôÇøsÛ1o¢N÷®aƱªL¨WRÐÎß놣—xßpÿ„c4ÂSŠK«â+JÔÕ@Û¬ˆd4 ¹7àý[U§e`|CÓYW,5NbD­4VÍk0NU†•¥P€Cª– |Á!ÝRLV ‰É­)$o½,ÕA>ö¥Â-¸ï©;”æL¨L뼨aòJEÕ—ô}ƒŽ{C¶øJäòO²$†ÙŠ[PpžUK„8ýQMkr,rII {’ëDnæ´ÀJ І#Ðj "!'u‰SUkœµ™Ïª#ËhqŽã·q£*$ÆÒ×n§ÆI° tŠsßZÖÂNË›A¸~I‹þ™ ¿K®_¶årsc¿)ñK„˜µdpÅ¥h¢ LpÉlˬ+ À¶¢ 2UÛud#X$$%XÄO’ XYV&Òg! @’m¥7ƒ`dE¸'BÙ¶)ˆˆŒ’"n)ƒ ]oD'cÔ~XÀ€Æ¾NÒÍqn„N`³Ýà´Åò}!Ýtm<é½qƒºÒ½•Ìy€r®u]ÚyÌv'Δë#«Š©µådŒw~ªøãàÆCŸ¤¯‘Xà”ï¢XH Ðj‚ñœ{ `ÁȢؒQ²‘¹˜š¦%Ar-Š`,hÌ' QäÛVÓÉkxZ'K¶­%åø.ŠÒ™âˆr&3y87G”Âä787GòÛÊ([ÊOÑÓŒròƒCq£œü<âQÊOq[YÙV¶~4ކfñ<û/ ¯:ˆ%Л/Ë6ïÐ.—~´áº4ËÀ%?ïKƒß¥»~¾>/»ÊZñ%–„G8®ƒ'ÛM)O„,6j•;wct <;ÈL´¾ªÝ‹å((5€…Äå¿~ôÈQ}í p/µÂ"8ª’?¯‹¢4K¹¢:‚¢’÷¹ ]<AîC¹½¯[ œ^+p½õµ*Çqt ¥6–ðE2ñ ä×íc›©^bFû‡Uއð¬†%Œžõ—1LÇ} nÜÏj/¿ó6IÃÞÑ—po=ÍG(ÂàÅ×ø‹D/"/m&˜p©Ì\ଂ1‰ùý·Q±øÊÛLÎ¥²ÂÂ0S»œ/$øÑ.`‡DQ·— ‹ 0­ƒ|¬LNÁ¤Â ®¹%*ó-¤JÝfâW`Óõ¢tÔÃ(0è…j jG†È‘%Iü ÙˆJŠ’ãþ•Žö"ǰ¨ •œ ³¹$þTu†ð´à ¡`³m@NEiZ áø%>ɉ´ù¥ ös•Éy+ÖÂUk!À9hýÄ™G´8üá†ã7UöÈ ´¿M`ˆ'œ\âPG YɵÁ—å…Y¢ ÏrYÈÂå—=úªÝ”í—ø1Æ®ê÷Û¦@•L¡ü’tfdªê”‘#S N ™:U€â3$ áø áÌçD`e™¸Ë.,’쇅høÉA²% ÓE&`! ¼IÈDBÅ4…Y\,ÑC0#FMÐfÉgµæ¤›Ý¹“î°.´y@8¹‰Ëˆ°‚Î &¹JÆØ‘†$¼K÷iÀFßPtHH$b‹TÕ°oÛæ:pC‹Ý)4»Øý¢cñçÀ›À©È§=Î5ȉìd܃tHÙ”>¤Ov8ò”âIZ2ŠmÄn¬ ßÒdQ¤œ)øQMq”Òdu–Qn2k—–Š”ûZm•r2æ ÏB˜´š4šBØ$¤`Æ–†l¤”ØÞÛ<ëÑm5”“f{y‡<‰éÁŒí÷Ć™d`Æv„I{fëÀ˜f“•r2ÒÒ[ˆˆåÒ¤ˆ>¯†È”ˆŠhX‡m=b­&i”–Ë´yñi¶›)˜!¯‡£$é_þ…$‰-ÏÛ¶hóuIÌ›¯VŸ¶÷’‰ùà.ÓÞ¥Á?.ÓI»¬O±_Ä\},7ÙàYGʃŒÜ‡§íËlpm;ÏrK´_iä½8ºî ì•[Š£]¯£`¾A¡3¯s…ª‚ào¯ˆ롦RO„†€Çj% Ãâ“zØ¢*¡X5‚ *_ÃÕÑ*¦ˆe ¸ 劊ƒ:ð>¬7x’kþ¹Š/ÖG"£üíëÞcm¯ߎ8X.L•Gâ˜ÞøiÇÀÞ0æ¦ôk]8'\8å%ë­C4tLЗîãõ0ã=”DæÒ‹í:ú=‚n/yyŽ 5È#µÈ2bÒ}\€¸ø‹x-ºá‡|÷%Ðð¯Ñ¡ûÖÑf¢lÃå9Â7Û^!­ÂH mú˜Iz’W#Ív3Ä'Éx¯Ž{qm«¥ál ×jæ—ßÕ° '®Aè5úTÃzD Žô¡ñ%yaÍ‚áÃ…Æ#¶¦1N¡b-ÜVÿ¢-0÷øeÁpliIT}¾ÀÚú]£Û©ÑëÈsO\jH‰‹íßšì½?lg_"âòÛ2<âµù¬ª‰¸D<¬™m¤É3I5Nº“9Òe·ŸÎ•³Êë ž™ ÎöröÏYÈô.ðæMQó·o…+dìQ <°óþ(û¶Y¡Hí‚Ä @DϱÀ(ÂI=Óeठ];ì£0^ #L5&«IzM˜Œ#ÊDQv0”‡ž“—LKÊš"ÜßÃ.¿…†À(m‰î{%;[Œ0IËwò¢\—9e’Ãÿ)…J\·ó5ÚëÁv “¡œ¢#™ž)¥¥eM%ƒ®¥½CÉë–ÜkâQ-ß̤†gD“½w”ßFcæë-šðŒoV­Fƒˆ%2†.Lf9 o‰am%¯ ÒÛ¿>f¿#›ŒÐ¤å[‚>ù3r"Âá(‘O“ºÄž[El%ÉåR–ÑÞ%ï²Ëƒ¯”Kbð]¾$¶ße?Úï^>èNž$ÂVn #Ù2xJY–NÛïWÒø­üo€@¦à¢·^įŸRñÔÁ K|ÁË-U믶W¡ †éQ%µüYO9RüëàGÞ°˜˜Ë‹Â•ØRÝ?Ô9 o”%ÃV0O}‘׺e;˜Ê}–Ø™Œ×@Ç­k«¼nÓ™³…ŠL 0'´9ÀùžEˆÏ~êY£ ƒÀ¸fù@ÁÅZyoƒ+IP¿t•Úe»µb¥lË0{ƒßMí]0~?àïóÛ¶€ê"$«pÃÞ“ÂkÙHTô{Ëý!a€$BªH!æ Kci!I,p\ Ù' GD^  nÙ:^Rº,hl¼ é —Dá2ÉF8#˶‘NB¢!2ôpÀšV\ºH  ™t„ü% ˆöM+cNrNæ”À›g2‹Úû€Ì?)÷‡3 °/1ÛÏ#L ìµC¡‡×Fº3ï KŽ4Sd ¥vtõOÐÓ‘B|sDç}ñàì”Ù Aäd&µ Ü‚‡N{°Š,мÂ9|‚¡<,×H5HȬ*žØ„°îÌ}Ï„•©=¤eÛÙsGŠ”p´4½§ŽlUÜx%O˜rSÜæ©qQnŽÇ7%hŽŠbËlÛy8ʶ¿§”ŠÛÖP8eIH­JÒGËÃÔì´g’d¡œâäW„)–L~ ¡t¤¸É’oŒɯ¬l+ëË'Ÿl YÿI*m‘¶ØåÐÎåÐÎåV…vZeüﺀƒße9[_ÙÉfÛ&œ žŒ‘,ð•­d6$Œ<%ïº6ð„GŠy¡ízk¦à§Ô½,}½*·Ôc‘£\&…ÂWs•àWc_ÝN!ÇRŸU¥½rJ]@A­€  ¨J9‰-é¢pƒÕLpÆyƒ2E ^ej.“¿»Vp¦a H¦Ì°Íõ}^Vä$RÃ!xQ)Câ’ÿ‹‰&~³EàäMFið(„×øÐPˆè3jpEâ%z1‘H£„n@ô:c™öõ/®1A|b Aý¿‰¡ÞvÖ’’ $ªæugg˜ îåë S*¤ÛŠÖ¿ÌKð§RÔ`a Îä_(T`b÷Lã,ߣ€E®~ŠñU™Ê þ¡¨9¸}“$Q Mm‹ÐÔÖŠM‰ÝAðO’Ê1b ³- EìÇü!uV‰¥Ã~{¬B€å|üG0iUDA8½¥¨°«nê©Îmkq¤øG4á"Ú9¯\"tPÎ6Å^»…9©m?O…´ÈÌ­“(nœ½…µ#3KI+¸Ò¶ßW›¼ósmɸbÙï·å¢(ჿ̵ÝÐ\¿¹ü’7ý‚Ú¿m[ä‡Ù·vnºBª1ô&,±GjA#BSŸz÷²C)’D#á°Pl]¶ÁM~m»m;^Df™ƒ. ÈH&"ðFD’T—!{L*žQáu‘;€=9‡“™ SN’B ؇$^xO: sâýÌ%¤#Ùhq’Žddã$7ÛRü^:ê …=6å€}¢Ì± `þí%¶‘#ÀIHÅ0å($u:KΣ³H¡0 Œm?ÆüÎÞ¢:"®HíÌÿ²‰šÿ” jD¦k“­ ˆéýâ¸/5LC±,[‘/¦{áyFk£ü4f:[‚ä÷¬aã IÏ{¶`K¸Á4&’‡e‰ßœ§¢½gSÛê …Ä¡*?=ãpõ)o«†Èçù€K~ÏI#8Šü³ÑÂ_Ä"Ï+=o>äW—‰ò<ùLl[L—móÑZO!ðgÙ;­’t‚tÁ—‘,·PÕÛlˆå>áwÑiÃÂÈ“î¾+F;—á7Cø¼`§ŽŒøzµ¾-Lë +r,‚ãmÅ.w+èÛR p͹¬5ðêSêÎ6°€,è ðà–ê,‚c}P•Pe…õíX¢žê¬p©¾ÐsÉ0èƒÊÚ ÅªÜvjX³QÃ} x)]E¢ ‰7±ÄËÉ(£ ÿ¹à™‚­ï4¶F3rR‹D/ ? ºä ŽaôÎÔœ ûÒ÷6+7Ö€.ù†ò€U |NµÏ†Ò8(ßpu6ío øíJ@^P 8“Ô)¼˜‚\/^·]…iãS ùŠVì­™¹Òx¯Ë·rõ¿—¥ŠÀWŽ˜6‹ô5’ºŽ{Y„†3„B.ö®¨ŒhTVŽÛ±'*RP”d,Id¢f°JÄ7¯*ùS€¬bDˆãë!SŸ æud+9Ï!TÊŽ¢•üÏr„®3[Ì™¢¨¶Ê²’sj‡Àõ¤ÿâ53ÈI‹œÛèL§Æ m¤ñx~p®²™Ÿe+¹ü~‰óg)7e³ü+»Yæ—d7?¿,ÖDÆcÅl ±`È4à&dŸ$ë¥zh,‚U Ó"Õn‘–ħ4,p”ˆ 9Nî=8$»¦n€œä ‚‰Æ;=‚| HIœž ‘la€NÉHD@©Ü$É6êH<Л«ˆ3™?±ïB Šž9û&gMHâ¨Òâ[—É#.JÄMˆS„é±ìÕâè\^b©’³ïy´ÈËb±vžU¢aQ;ÄuH±g¤¬šòÂg1™jø«Ì=-‹Ø×¾ÊÕ­Ê[š=§s­£¿] €G!BŒúUpÐ7 •Z°]jÂ/O³c3vƒ`6¼-Öc;ŠFòé†}STÀ¡?al5ŠÙ…(°Ù·2†YÔÀó̘L¹¿ »yœY¢Pp¼Ë›Aºps F¢Ì@„„(Í‘Ë/‚¡ T…Þp6t„HîÛKn ¸ÑwC‡æ§Q1æ@/¢Edü+ÄsÑ 1éë©ctÇï ñA$ÏÐççÒŸh‚ß2=ªÐ~}òT@43:Åš¨‡Z@é…mstS­~yò>ùH?šiE'Ÿ'ÒZu¼O:iJˆ·•>žªÞY\Þø—¹Ý’Ló¾KÖ»OàqÝÝ#=RÞuÔ–t÷qs~m=ù…Á®Ý…H²û¼=l¾$!ª³YõÎ ª®= <ùü¨¤jÏ“|PÞv˜ö‡œÔS‚»Õ!ågŒ+UÒ$ë‰ña¥Â$‰ž»›rÍè@ëxX§×E*H:ËxºpVN'ƒ“Ûñk®ÊIÒ–¼M9ú%¹— ©ÄK´‘Wɘ^Þ™¡¼ÏÕ¿xǘd"ÈXøC娂òE$žñ‹ÄHcòÒËJä&£BÝ»UŽ5u*àÇS•§r ~EKð~® } HGý"ª ŽT夯ȸ‹ÔôC±‚0I|h ø‡I¤¼íïA¯Žª@q{U H+T’5K¨GÖ2e^…§V*œZ­ðx1ÊXÌ{¯«µgAmï]®ØÁ©DP‹²JP§nÊ$ÊÙ u]Ç™¨uTºŒÖq3ìâRyAÈp`Ê(ØSˆ-ªN^¤v%§·|#~t°VD¯F¡V~6zÛlb±×‘‹ƒM²øK½¢e]Ÿt7šuoÐðæn{k-|Ü:šÑ˜ð2¼¼®Ü¶±¨Ê¤›^,”{.éÃ…ñ+Ø0 £ë 6L$«6®•lMvM{'Ó#®i¯lH¼-U'PçvB“ÏZçI†Á‘^¿Em/šn&1ÿ‡êÜ&! «fµ—’„¶”üȯ»è‰d>÷Ø©§û².¿@šÙ¶IøPæ^B:Ç/ˆøL‚¡9iBh~ÈI¾‚èqËNò¹<ò™DJ=#ù‘'1WÅ®¥'“µêÊWøR1<‰ê†?ò‹']ÄÅyƒ š å&"4d­rÜ[2"„$\%‚7é;† 1Ÿv<ƒöƒ§Žd§ýTebj®ðžu@u¥ªAxºBã{Àî`AǶfcjx@›A7}kÜÕò¶MÈèûȬ͘ ÊG U Ö¦T·´KÇxªÝäа! žøÙXÑ là Ü55¢ä+Üuë<ÈZq¨tÛ—¯À[ŠCQÁ•uVêŒ Á¡5ôÚÄZq¨F¶ÂמÛÛ/(\P÷ Äy/ü[þšfêÀèÞ‚0ÇSÒšê¥,Ñ þ"Ç©gS¹ƒx(ê”:flpVEˆÐÕ*h Þåj¾–wDm¬Ê  ¨¬E9-ÀëÊQ34©;iQ•Ûk€N+·ý8ñ­’t ›òNØS‡ìðÒ"¬ß»BÝ·6àZõ°Šžíyï*Ä÷‡ª( kxlìhBÇ]Bvî€ÂQÂÕý1L%tmƾ-õPÚº€ ž)W_¨S0ê¶L96¸ûë°A‡rÓƒ§lšW…Ã2X«öÀŽîºÛ£=6Í«¢»?n;¿CD‘çåD=Æ@˜ü ý©ß Èï7wÒ%ÆÍÏÝ6ã?apÃ&¦È ¢c#š‡HÓ‘è]mÌkĈÖŒBÿÞ…ä1UE¼¥Ç0‡²é!Û©‰#Y “¾Á[MídZÖ¼æ±]Ѥ²AlÃÑ‘/€½&‹xÂÂ(ÐÀˆ`"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6"6pvpgn-1.8.5/files/ad000002.mng0000644000175000017500000000536211151345317014503 0ustar aaronaaronŠMNG  MHDRÔ<d †2œtIMEÒ 4 €OšóBACK3œ% TERMi4 FRAM ¦Ô IHDRÔ<ßGK7 3IDATxÚí=pÛF€7ž›¹¹¸º‚nÅÚN+µ¢ZÙ­Óšnå”QZÑ­}¥£VH·²ZñJI­åÖHi¹`uss•Ox+>® @„$~ß fpñðöíÛÅþtêòCB'ÿýßîŽÿù¿ÿ»aÙÛY0ýLöëV­Ð0™ÿndÁP“̇ÿêZ'¸Åd•Æ7Ý–—öì/¿ëtÔE„¦|lw­@2ŸíeÛi¶½Ñã==îu­Ûmào-Ék˜¶ ;5òaMÑž^_¿f=½O]ëT‘¯nê¿_»V &›.!ü Ç{ÙÖËʾ#«¨vµõü¹Bœ7]ë;'-ôdWDÐó*Ú¶+Äÿ¬£½‚ûìjœðº/Ùö¢k;Üg¤Î×òöX{«²ܵ^·…ïz¨YKã$3ÐU¶Û£´ü÷4ü}YäYà+Ïô>Ï)C|ŸšlÕ=¶J²õ¡%öw Ìu§Ù62Ç£ ôqb×%º/­ß§z¤åe ïŸYð\“ມIÿ½Ãæ•+)'A¼Æ{îF~+£¦>(õaãï•댆ý=*·Ž>Az uªj“ñ\ÓøÉ4`ßW´ÏzúŒi…Å”ÒßÎ̹ƒy=’ˆœ²žÆã nLöiÜ:¦jãÛÂ=“Öƒàüv‘^zÍ—XolQ=Œli)žEd…½<«{¶½ âlrdÞè@‘½4ÿ¾»ÖŒŠÜ¹¹ÇÀ¿Í³MpÍóH^}‹Ä/òƒoMùû<ŸÑãÂû™¼=0缬ǑúàyDF/’ÎcsïíEt_Ð6=-g¡½ÏÂ:Lãßø|¶mFÒÖ)1›¬| I¤Ný¢ûŸ-O}š×ÙgœO4ÜjxhÎ]Þ«ð[:'ƒD¦<¬û Û~¶D.±²w‡‚㦽´¡I«œ»\R¶ØQH[.ŸÓxª÷¸Ô°h(Fìü*ÛÎU‘xâ¦#]’œ÷Ó o›^9¾7ëÃur"•Ä[—ûMFЊÌûäéPã]såe_õ™âgâcâ3ÖÇÞjXäG>í1NUæÀÄûSËåXÓyé¦þþD·2ÝÛð÷c7[ÞDŸª_ÙBǪ˕›æÕ ¦l÷U¦·KeÔçA_ïæøÊGzŸøŒ§¨å -‚/s®= ŸüÁï…½¹ zU¾¶–\ÝjQü†tñ# ƒó¦G¼Ñe¦%gZµó£D·E{¨Ç¾‡¤ç¦UÚ´WMÍê̈ï-q}ëûÌ5Œñ™Phž¿Ûäl†ùjm1ɇóíyßó;6çv.¶—Ó3=•Xo£qt ÓêëÎ7Áùí’ôÎŒœ™²}Ä{¼êj$O6LþÇF1×Ög”ü–h¸g„JåÜ϶?–Ì›TÃáÎW’Òº§™µ±Œ°;ŸxƒÎ\q,Ò˳ó©ë޾ÚE*÷-Ùßl“¶VVój9(Ú:´ÏK›ælÿlÛ1z‹?mù¸-êqè!>æGXvm< GÁõï Î{y?§¼ÚÞÆ@à ;W¦ûi‰îmø»/W‘ù¸$ˆr¦WòTòÖœò6}Äër5ûÀMçzn\í|¦ìê3wË<üÃ5©"¼5¬Ãy\jká×ycÔw -$²xë‘ÓápíQ4±"µ¯áEä·‹ Žå?]Û%HƒØe_÷Å‘ê`ñÅÐ͈[WÌË«¾ßé ²õyôМK4¼™.Òóõpt;>ÝÌ9_Q^T”Êj’~‰.eeÏÚ­ ?Y7­¢=âSí™Iz~Ôý‘FÙŸÔ[—r¯}¦ðªš×è•>T¯{M\}úÿäòŠLîÓwùxúÇûÖcÍÒú‹¦OÒBGIªLr¯ò5-ùb×+=~±IêwÚò í!üP´um¤»‚V~‰Ë+5_ÉîkøK×úAm*ÍŸº%ü÷ÉgÌùÝwÅýIJðÖ5„<´uë™Ëù^Ã[ý~kË~§É¶IïËåÎè'è—驦nF~Û âÜj2»ˆ¯IÃJòÿ8øí/“Žýz’ï=©ß‰,Æh߸ +S_oø†øÐåC…u*]Ÿ»pÏ÷ú‘ø«n˜¦ž1ÝÓJ’â\ÅҺ긙bë)¿¨G8цèNNÖ½ö™Òª¼“êòŒeFº2Wêh8ÑÇKˆúŽ–œ°oä‹“U½PގˤÕñƒôŠCnqî2˜º|šá]ð›ïÁcKã×õ¥s=<ªãëúZ€b^Ï3¸VŽ¥ñ#uÂL¥§• Tj}7-Ó£9º„÷÷ylý×ïϼ} sÜe+6ka‡9#~ê²Y1Œè^_?Ø5,þíˆ.¸zó§×¶±÷Ùg=(s€¾WpÒÄÜ–&f¨‰»¼±iî“4”>ÿ*‰T4‡zy€õ‚uG¹¼b[ô4-Ñ1woè™´:Õ©‰´ÊhôpŸèʶC½—ÈÇ=×FQëLf?únÏÛ=¥ƒßÊâ‹mÄfÒR=ñúëGĆRhdiü¹¦7uyž²íG^_7^ªÍ¤‚8Ïl3ªh—'nZ9Î{?Õ§¯5®E:,¨Ä77­ˆç•·S-£c—û¯L‹HÅ{ózžÈÈâì›tŠ|¿P2uÍ}Ø£ç"¯²XÔÏUÏÙ¾¤Wì°§ú]¹åFóFš¶-µ»”ƒ¡ë`ýÃdúA„DOyÛŒç\ºN>sͼ!_çf+ü¦†{}ëDúA âe¿Zâa"+ES7}?l¬ápQÚ’ò­ž}•%«h…¥ÜSœi¤ûc½NôÚZæËPê”;zŸÆÄåÎ#᳆ìX…¾‹/â±çúÒ$CG¾ò?²­]ÕçWoiÇšîµýì ÚÌûA?°KSCä~:Æû˜ìÿ^ôOZ†ý°eRQþHõ–=x—™ÜÝã·JP¦–öuaÉ&¡yg¯óïSÊÂ/“§µóSßÅ–Û£Uûþd‰O.x/yè\êzŒ[>¡Í“¨ü¥?R`>°ô§:±‰½øÜ?‡t¦ª·5](£UHS^V¶O¼s³gã©#¯Ëv-—‡-<ˆ·«…ú¦ô–oÆ·¾õUxl>¤óF”‹+p¸zå8—Ç#i1Ÿ¿èún¼ñwÑʧälfïÖO¾ŽFÐSª{؆b£‰I[ö‡†¯@:•Ább{º½’wn)….Ÿ ëu8Í-”ê†M)[Ó×+íŽfZpû\XŠÇÑe5ÂêÑ'Ÿ;³xFöóo;zæ¼¾ïÀä8f—ÖpðúC8õî»ÝËB¶ˆˆß€²µŒr¢‹Ã„óÔžýý>½ ïsTùƒxyæö Ñ]-bÐ9€wb3ˆ§ÊzÙ{ÿäË’np:­.jŸ‡Î—G©Z¼(mëº2oØ…ÜZQO‡htï—}ÕüjVZ5}ß[ zg¿¼ÝG_~ÛÔ÷éöú€`Ê ù"’* *ˆvB•;rÞÏfl䦣²Þ5À¿4‹@¸HCàÉ0åãØªm†rÝ.‹S‡ªºß܉á¿ØÙv»Ó“¯½ Û¾ÞˆÞd«Ã†ìJTÊœœ[ÁÐŽ«±xú Ù×$¸˜#W£³:œâëëøÁã?ÂàÀnDç–µ6÷NàT t ¬ÒÎö¾t{_:Ïí4P^Š1ÎËv\D^'PåÓX*h ¹3(µíý©kjïi‹Ñv¡ƒUíëÌcKÍΠ²¶$ëÞ î¸ý“ÈÍ _ÀYjÂD$"0uíè¢Ct—¡†Õ6LHùJóv9µ;åLù¸×'éNJWSÔÙzr>†*ƒ‘FÚooƒ5_)òÕaj«®Qîˆ^†¡º"·¯ eªotȆoßw'nß;‚¿{ò%<ÿý¿Å¯~Ü+×"h®£kd7VcÚïd †apÜ5!y†É ÎÏœF©”ÃºŽ ØåÒqØ]¨˜ f/N§7øA–ÚÃpÌQ=îKÒª­ˆ4AͲ 2¿Œ%«ö[ø<À>z–¬›ÎïÆ²À”×Ù.[Ýì†ÁÄøTP‡iOÿ >àò‚e²ÕE 2èvÖèø[®Åz&…T&'€5S}Ë% ê™Úƒz–^‹ ÑÕEdVT2e„ùÌ&ýYè÷¶Û—8:ë j•óuË£ÇP°f/€4Ul!Ø^WÇÉ!P:|}ðæPóâ+÷߉ ½“VzÆK¸ãŸÂ­wÜ%0MZùý~{Ó{Ú¹¾ ÖËgÆÎβ5okþ¶½¿ÆÐT)Ce¼Î0eÎGcGV©Í6ôØ,$jÔÇPçþðÏàá?§§`¼õ\ ªz¾X¤Ånó£¶Q‡Ëî@oØNj#‹•µ œ›‹ãô‰S²0HÙ¸Sˆ.DÑîÑaÊÆJ°žœ…¹kL¶ª¬3Ë1ìÚ{Pò:!ªÀ¹ÕTÞÖ´³<«\Qº¦*u”i(«^^lnŸ”S eåÌmap2ôyQJ”Û§ÚÊù3ÇOè犌`÷ôaìõ×qe°!ù >^Xa2D[f Æ=ôÚä]™ò:ç)EÚm÷éJu¥¸!e’• @•*+L¶^ÿ…ëÁj­b oR©¼]Ÿ×Ë(ð2TÊ¥µ5ø 4n½á¾wÿ§q)W¾fG_}ÑsïÀ±‘•º×*Ú˜›áÄ€ã´F[/´0Å`_ (ºÚ}{ d °ª©(0(7ÖIa7 8¿¼"ùÙ…eIWc)äZF¸LFô ˆÊäEžo‚)‘íù¢€”M›Î60ØåÁòFK̦ÊWÊÉMªšaªòyáö0@¹} Ó ß‹l¾‰b%$ƒV²ÇÎÍcލý~xl. øM°ui×2›¯éוáÆ6ÐS˜†<^YtÀ’:UÐeržµ^Ð÷oU¨ålYw?yøë’·§Û/0 Ð}xüé'ñ—÷Ý#û¹Ü¥LõÏÛ}öå³ßZ¡²mz>8SJ‘]ˆ§rð”:e0²Û–Ui_w—À‘S>FA•aÊPöø‘o» •²íL¹.§ÍkÅŠñÆf*Ú`¥¾Ck¯¬¡kê: ìºoyQ/O,!µ¶Ö«­38ñàÚé˜Ü¹ÑÓobÏ•ûðôs/ieYñu¸Nya×ê1ôÞÏß…¯ó=ÖN¸*»@;ÁËë\'Üâõ ÇjÀZ2§ïoQžEµ½­@–œ*//¬D¹‹fȰj溸îp—;"}¸s_·ÔÑFXøÃ„¨l÷ºìS °†:ÁÙ`€²±2Uëœò6ßåÁËIj–áÊÇC@(› ¬^oL‡ªnÞ õÒÚ½fEš$ˆrªÃ•Rå–ó‘ó85Ç*¤p£‹pÃ(»6ÄüÄ¿ü¢só¸÷ÁÇ`7‘[áÕB^Þyn1CM¹]©ÅÎ8 Â6­9!R¯5û>ÖßÙtûÇüx=ÐMj1Œ4=§Ã+Ä\¶»Ÿ”Z+-ê’¨RvÝkðM‚5üÕ#š ˜Í´ˆ{úƒ8Mcœ@Ì¿±‡ŽÕ]ßE¥L¶ tÉña¿…ài {j"H:‘+%Q$˜§çÓ˜ša.“Ôžy¿[`½”ÌcfnV*»¬{»Çð“WŽoºnŸ‡Íi¤\ýZ8uc~)F{zOM‘¢c=¿ ¨ÊÞxå-z_~†¿¾íö‡§`ÐÊ<ôÏ`.›C4Z@$âFbíâ>ãR u{Ú÷œCíÌÛš¿mïŸñuŽ.¦°kl³ôòèKãhܦχ²Ë¶jÑæ&vvCæ}gâËðX¼†zP1% ¦xM-¹~3g—Ñ?aǾ+Fðó“GÑoÑ»•Ã.š×N ‹ºU6j£çÈf†ZŠT{rX*ºu×®2ÓKTÍŸ^žÆãùÏè }þW'ñÂ;'F$äÇ¿øOD¾xq°àoÓgo÷Ýï¿m+Ô¡ñuŽ ˜þºƒ~¹pNæS90‰Ý²â†u“ë6ŧÿðn 4R€eÅzïÞûðÄSÏId5‡Êæ±ôÓÿºÀttÈ¥ŽiHOÀ&®]eüâ^1йss(ÕÌhý¤h°S½é´ ®RçVK#媔æ5ãzžÍmvù*¥ªÜ´¼Þ Dâ`&¶­êµUØ Ò2º`hI%U°Õ”2Vðe…ÊÆ`¢K5½wBî (D•òµØäz;êa7m½¾A0ÕöíewnvCܹìîT©j.´o=î„Á–%Ê Vðä”óD¹Bƒ8o³ûW*éÏM‡Re7+«”ª2Q©mëg°Rý¬T}>/Ýôå›p uav1‰f5K0Õ¥|ƒtcN\¯Ö†Ke6» ˜ :Q§ì:Û4«²ëlª.›ça‹È»0hÓ0ƒí2R½+Ç¡îaý8†å€Ó Æjç“a û†°¶rÆF^aËe– *kÕ‰©dgv~Íν¶ß ó¾q¼º¸€r"ŠCƒ¼¾E¯Õ†Ÿ¾y·ÞÛ®_3ËNWç%Eê)ûŒ6@ ­ayÕ¡C´jvoR«[¡ª‚‘xÊ„aÊ3~–¦~£æ0¬gà6:qò±a¿ò–‹úŒK žíyÕÖ¶ê‡ÔðXQVZ9øóU¤Ûî\†¤1ë{Õî1*ÖmÇTHܽaô VÚ€Å9*®ß? Ý&0fË¥/ ©”ëúìá0=Íq=dùu|ü Q¼‰µ$ŽŸD`Ú$@bg™ÍnFl®„°?‰Õä,~ñÔ›âeà=ôGšl¬T{oÙ#Ï¿ˆø*åLÊÜ*»Y?³{á{ðèOŸÅð¨æV©rwnóœ¦ml‚á Ê—Õ.ŸK\¹m8òº 2bëÛr­yWŸ¿mÏ^sÓAÃøp¯y½Y¢­5˜rän­†3Ѩv] tÊ5«Ò—sQ`ý­çj¤\5°– ² ÒÕÅ zIQ¥RqÔ©C’—~›u›=Û XÜsK«²í¨µP¶<+Øäîå.¸3H‰ó¸L·ÕÙ¤¤ÍÇ2\ëñ4¾slƒA?êS³Ç/¥÷„e;^mIàQÒd’>`-Ù Ð.’ÜÔl˜[9Ÿ”yH†(»[OÅ£¢*yî3Lpc€²)¸fJ˜•–±©(^¶1)Cê9ÍM ‚$è©í"fãˆâ)XŽÎR[: —Ù‰Øz ƒ!íàyÒ4=7fzÖ'Gdþ”M¥ü»³-êÛ2)‰ZVù UV¾×N¸Äå;:ÀU¿áeÅ:ÚãAÖRÇBÝ/´Ë+Ó÷R¨n§qç0þõkÿ€ýûváîß¿æJAÊ<þJš.^ q— £—8ÿ{Áó7wÛþom[¡~HM¹dPlóôb²ÜÂã‹-Œ ¢<ÙX1©€"†*GõÖ´wO Ê#u†jÈÓ÷QT.?é—òói®OƒêU»ýKà»[Çõv¸Mf<øÄ 8üñßUšŒ'a!xú 2ɶ›³QL D}e‹:>ŽòL­À¼0U3ÂfþÄÅCª†?SaËùwàü©üó7þ^"†ï¹çn tõà™·ØXy[¢h〮ÒV í9£UÒ*;÷ßH Ë@-«°÷^cÿ>4cÇôùS"c‡Êay‹™-䶉jï·ÁNŠÏïÄtD DÒ>3q¼0›ÇÑEê±'؃•Ôª¤Éœ‰~÷ζÁy¬íêÜj}]š’T œ#¥Í6Q¸ÁØoòà¿} ÇÏ—o.7 ò%ƒÉÑ€?ÿá#˜«Qg•X×®²õ|NÀú¥¯}Cÿ^“¿Éäù2þVó¿ù „ò«pìobá´¸ð‰)ªuŒZsz/ÔÍì ¥“·ï©ù’¸ØXm°Š -h¤2Å©L‚›ÚQªåBVG³KYR2>qý2¯ ðØk ºRìŒúåˆÝÕ_œÍc£×‡sv-Š˜‰Øzý”=sDÿ®TÍÃrÊà4ldÅ•§Ý?uÚN{LÿËÞµÇU_çoµ«]iµ«]I«÷ke˶lŒ¼@œ¤N¦ÓÉ´“Pš&ÍLZhèäÑÉ0$m§¡Í”Lh dZÒB’&ÃH ‰ 6†ø‰å7–e­ÞÏ]íû©Õö|çî]I¶ ÿÿЙYÝ«Ý{û»=ßùÎë–j!)fÍ&]»à›Fm FM$™&]q·OË(¹ø"%Wb"ã3Kݲ*µÐø¥ z~’aÝ/6ŸTPpª`/–†0N:®ëaUød”ËKå_(ÖwÎ Èh½èt¦T7šЂ0@§9_wQüîÝa-Ñ pP8†¹Î%ÇVÖj-hæ+Ú}ê>µ†ÜHÊX…|R” M±8­h•ó6#`_Ò¢0›–ye›ÔÅ[ã)S&K0e´µÂ¢ûR¦o‚)…u®d¨¦«7RTI6™×ìô(Z½U ;Ÿ £¼Ð²¢Õ5ò[ãàÝ@V Õr½FŒ•ö®„å¾aÝìÍ[üzÎyÌŒ™Ò¨8#Ƨ¯ÚгcÃ¥ãkEs –€jfb ަ–¨žÌÑસäZ-S *ãÔ þˆÌ «ä©ÿ{ Ÿ¼ùª¢·Ã`étÿÒí\m»T/§›Wôõ++ õ2žsÓËÿòuiì}ü}ù¤~žÈeYB©ÀUý_äÐé<þä¿âúžõZSGe3œœÄèP_ù½ ¦ÜVx66tà|à<‚Àwö/´lâèK÷aõš+°ïð‚Ï×N6*L‚õ¦çÞ†µÜƒ¦Z—(ärtu_¥)ü]Ǻnœ<ô†&y0î¶X`T3£öÖu(¸ &HPýöý÷á­·öaÏ›û••~þOvhëÌàIÔûZ18 ‡ÓƒFßFeC©xãƒF’ݸ•®w0}8ŠÑ{°ãŸ@‹~ÆD©X¾\]†f†*A?Ì!i³Â!Š¢ô¦t3®÷U Î¿ ëÃÅ*`êïêĦhZã °ÒÑ6 %-õ˜Õ(‘àöõï=ÁÀØÝõKŽý…Ç2êã!ôÙÃF¦í™ØU Õ„!Q’þ­¿‡ËÙ®Ÿ°˜ŸcuØC8sâgÿô7ú~86ª€ë)‚m(’+6I0X×¼€Îdjs' Sekæ²f.. ”ÒLX_±9˜ ¡ÌåÑçàmY¥ I¡ÐMjq KÍCcfSSší¸;ÍšÞ½çÖTýÛ¼Ü[>{5‚³K±Ê[ƒ¨wÚŒ½V•â¾ÌÆM‡dÎ>a˜LF¢áSÈÇÕ}Ï&”}õÓ±ø]^—1¸e—½J·±9ÄpÕÀ/S`3K~U2n·¯­“ë1§ç½ Æ"ë†yl²ÿÍ[ ï»i•\«–׬®H¡©Á‚‰)1’zü¥ãwÖ×!’“WÌ‚¶ÑóHöÉïó`/2wܦ J†Zp‹ÑNàý„ìô‰'žÇŒ€µÃÅu×\§á„-M6üjßQx™¹îoDàÂ&'ñýèÜ¥úx…ð|ø²ÂP/Cá9¶×;aOØñ½Ï"òý¾pÏ6a£çëjª•aL)VK~ç¢òCØ~×'ÑÑ^†yüÆç±ffG­4aÉÙTƒÕµ• °#3#E@†€©­ p=ñ(¾Ï~æú÷¡Íê‚«‘À4¬`-µ^X]å`®êÛnA…»‡ÞéÅ… Êp¾ý:¶Ý¹L®¢L‡ w‚“˜LE# tc¶9+°©Ã¥ñÑ™ŒµT®B7/c–*#8«ñÏ:™3p)t’ícøÝ®çpô˜·%±ªëÜÿ¥{L –žºN|îÁïà…§¿ÙÁ˜·çðî{ÿ ¿üé? +™W–r~úuìùïÈõµ)à«íT#"’žsàÑ¿ ßÕ,àÂ¥)ÿågÄžýùoqä¨_|¬¼bç7þ¸w‡\QÞ¶Ôzƒrœu¥X¥ÞCr> f!ºtí†ZHZç•á23V“œì¸FÄÇÌɵ˜±k_…-²•5¯ŽBR]ÌðÔ(c¥ÂÆŒ¥’-“Ò{QŽ!”[D†`¢PÖžDµìÃÚÔd¥KãªõÎbL:’T0w èM¦¢ç¿¢©i¹¨ÊšEXW:9âÅrÏÌÊXÜoñçSSÞ89-Œ6„®2ÖSºÃ»6wãµ—â£ÂVŸ{»O ³ÜÖrmúp±ø¬“â©—™½ï¾úrë¶¡cÍf Ńð.¬!]Ü ‰Ëþ^kðÖî%ïÉW¾v¿V<çÞ½»q¬÷.ÌÐÓþ);ºßCoèµXÑÓš¬0ÔËTÞ9pÇÏprá¶½¢˜Ç‘°¸Ô^rךEÙÉä”®3®j6gh¯«B¸Ìc{i\‚é’–|ªÁÙ(¾ñà&ä!Vñî7-]€ÔN'j¼Fc ºh)Œ}^Ðu‚aKw“€L\v!w;:ÜrïœêC¤R”~1ì´¡.…­WlºäXÙº°ÊQ¡­î(ñˆ(^¥ìTçn3ܰfa)·0JïDÍF \¦D}pk­…ECœ ¤ÙÅbŽíèhELŒœyG‡%®%,̺µ‡Œû–ßãtÏk|Õd¯ykYÉÛ(\t1S&;­g.9ï*& Ã&c¨ëÚ`‰dö&çQs¥¿çbq&! õÂc±¨8u^€;†}Çض¦£ÙöìïG[í0üßÀ¶]äo•3’FÇsiì>÷6&nO£qãMCe,5—­5Ü»¾Ú:;r ?ü'±ªÝWêÆÜÿ/f„æ<3‰“¦fÇ$SâÓcËꌕ–±¾¬0ÔËTžÿå/tÙ'¯»6­Ç«åÆy7ݼ%Ý·&[MM ,ZR#ìÖc7’ ìÌì­6êQ縸mZÀTc°\—±ÈpŸùÇ#ȶ6 _:—Â\|IïÞÐĘfü2I) Ãßfްå`\t“«¾‰tJ˘ŒbJϺÍZp±„F Ê5Âæ¢'áï¬5’@ðèªk)$%9’ïr×"Ú¿ƒ…+1ëÕ2ŠhÐŽja€«ªçÁÐ"k÷ïy7\û)u÷òžÕa«ìØÓVkS…ï±$ð0^Ê„¡ÉbÂëG+œÓˆVW )l¨àä…ÝÖl H!X²r׺nÊÝ ŒtS´µ» ¯ïÞƒ¿¾ã^Ü÷ð¢÷í_¡ªe Fw=¢Û˜†ÃØù xÖ_­çœ²û×Ï`ðLŸŽÁmÈjÎ7íønùôŸ)Àêu·Ö¹ã‡ðì“ßÅ×ÿå'úÿÏÿý»ªÀ½òý‰| V;Ü–$ì¦ñåép-­íÈÎÏb×k/áÅ_Àúµõʲyï³cc§Ù™bàú–euÆJ õ׆z™Š™lÔíïÆ·/ (ðYlU ‰H0\½üŸ,3R¾°/ÁÔl=È.H¶D¡¹¹V™-÷Ç)tÇ]×àÉ7ŽáÈþüÃÕ¬û˜±Ù¶ÖuÊPûÏ/¯Btð¬¶R‹ÌôóC‡ŒeµÇhQØØ¾F›>°U!•ç¡S–R}çÅîÞX&«ïŃF­«­ZØÙÔ^yÏ.@›Pe**ul8>Œé3q”yZðÖá}hïèÔšD‚#ûʲ ƒEüîø$2Õ-Øÿê3bK4kgá±a|´í* µ©äê´Ù*”aš‰AH&1FÚ.L4æd{9ù#¯sI¬m*ºHåÿFK#Ž@ujô<&„Õ0K—®ÃÀÉUØñ§_5hÄÊŠþëчq߃ßQÐ%ÓT–ì0úñ²´bdô]ym—f¬RÈ¢˜œ¤1SyÑxçöi|ý'?ûÞ¹¹ S¸þÿý¢‚ð}é›ZêT#€é—ý©Ü)< !¹ö“£S¨ÞP# f™  îÜ|‰•2iH«g/ËEÿó:ÌˆŠ¨fœZ@Öl÷W.ìŒ.[в^›0p&«ai–ï‹ìšîüÅ23Jiر‘e-¶JÙX6_®¼M½ d›•f±¸ ®¬ºº~}ñ©‹…쀉( §KcIæSJ(¡©Œ¡´Eé³ÄÂlSGD„ñ[2-.™EJ÷¡Ùç•2±ÐC³) ¦LcÀ÷íÇ+lÖfkÑØ+YjX«¬hÆÏÊtµÙ͈Y¨îDPÙlhzD×ù™ ˜l¤nKÄ F+Û2…ñ<Žç.sê{”-Âr»o¸ëÖöÈ1ºÊÄK.P–gp¥.”³§ëÒtqH9O–á¸|MÚqébá5#ðÑEË$.º|ɦû ÛPØÎÏ\7ÔS,+Ôå±é‹ë&›^,˽G¡A)f$[!£*çF•|g<»ìcºrÉVÉD ˜UMÈ'çô3ž“Ñp^Ù°i¬PÌ, ÷¡¬uguÞX–Ô¼Ñ{–ˆCc¼#ÉÑ¥0µÆö+˜†g¶àe¹‡˜<Ô7”Ö0ÇŒ•YÌŒ‘ÆbüÛ#Éo&§ÙËü¬µ¶ÁÈ„®4ÎÁÌx\§ü]Lo½¾U›:ð…¾Aê¼ËªK2~ëëÝýÁÈ C½LeûõÛp|l}§ß…ëê X¿yŸ9Tb¤XTúÂõÚòjmO@5Ù©‚ªÓà2««ÄÚ …•Ýê¾Evš¦Ì¡«®F­fSÌjoï;¸þ®?P7/³zÉx„†t;³êÞ±Hé±[-AlÙºY¨Ÿî;…p¶ - Épß«i sÞ‡dÙ Ò¾´|ϽVYÙ"t%®JwUSc[d ²é O§Khc<¸~ó•HÎDò˜ÔÅ¥JÁ’ Êøg§l?Œ¨kœsñ8YU«Œ• ×*Ûó EÜŽ€GÇ7ÁsÎæF4ŸÒxi›×8_'ƒÂZƒ³ðxsXßÜ FŽM™¯xHF{™ß˜]‹‚èìiÁ=J³-eõøÚK†^{£±~úìiýŸ›Èx4ñLﯪy¹ú›ÌN&ñµ;®ÂDK#‰>-ëysùT•÷+£YÑÝŒ¬ÄP/SÙzã5Øæ¸¿~ó9LöMhLˆŒÒt÷84Q¡ø P&ñ1n“šK>^ŒÏF=rꂲÔÕ †BK@Õ ãh`RÇ_,ÜþÂ…¾R%8#L3­‰1LDINcHÞ÷Ù]j•[GE©ôé¶³2/›½ªL™­+'ŠÐa_ö˜ ¦á|›®Þ„£§PílÔ²…vƒŽSå°ON;[<”:ŸaûÁø¨Öš<`<ÚÊ^Á’–„–‘‘ÏeœÂø'ÐR¥o B¨5ëñó€ö=Ž¢°ý{m­‘å;ö¡ÝkÅpÊÐdícð¨VdkI&áq× moкÃî.àü@¹ÑI ŽÿjÌÍaV·G¾†=~Íÿëa0J²a¾ßÝ6VªMeã.µW𢖃”Å”–“Åq]k§ ùÁ…gŠ’Q3áªmÑœéî½õš­¥çšB)%ì³2ë4ê’©ð-SîB#YÃ%/@éu3¬ØRP˜c¹ e/6˜ /ÔÌšj&Q™ëõ2·c"š¹}{–s­Ï]rœdÛñlqAlÆQY›’ù›nßdÐ¥žŒ‘°Æ‡d-.V»‚?3Ðun݆nÝ61`x¤Ä€`j_ê„–él ÎʱíˆÈ|ƱúŠ…"ÖŸævV(+µÄ(È=ùjÿ¨º› Ôü-ÁÔ²/ *ÃŒç³ÿp"Óçó²îT‡à¶ÊÔ[Ð*†“µÎN†ñ”Œ·%1‰Z‹ö}b ¤ì¶e»5½—»wEop²ÄÏòûÿ³rQ>8aG#¶ ¼û¦?e[«É ,m0Ý´LF2›; OhI [ šŒÔÓäTZ¸Te)–JÀì?=†ÖŽZƒÝßCÌhøð­/ÞWš-l3Žj Ù©Š0°X±1~Y™ ¡9§¶v£«5œ‰!&ïQi°þ“²ºÕ¿D&½ìñšu©^«SÞVõ4"ïJ¡¹!¢ÉJ¬-œã¡~µ‚)…l›ÇϦ«Ö6(˜ÉŒöë%»f/bãÇd³4>¦ˆE5n;4e0÷/vÿŸšD¿µ^ þÿì] \Õu½3Ý=½/3ÝÓ³¯ÒhE Z@H…¨pH( S88Á„àÂ8 a1Á؆8‰!â8ÁF$‹I¡R”)A²qˆHc$,Ä€4«fëÍL¯3½Nwî¹ï¿žžÑتà²-WéVuõÿ¿ÿÿý×wÞ¹ïÞs%²—?RÒ U’÷ëÔqز*ÂË[ìè8Ø$·;·Å&Ëš[,’׊yL㣗c= ¢ø†&ZÁ ªXµµ¥2qø`==­ÿnhY?^/ߘ‡F³ü—[í`*û«Wó§¸ÙÄÀSU «Ü`ã½ZìAƒ¦gŒu®J­½„i·/Ø*ÖÃ7˜è\6(­ž—¸»VÏ)ÛgËD4¦0°ÎÊbªäöõÂUÌ,[Ð+ðj Ðj"”È ŒRpGCÅöÓÏnï Žf5öŠà%G{EXtøøÂë1{Õù0øj ¿‡+Å€Î/ÒÒL|,žŠ[L3ɘˆZ ïŪÆ5üËòb^¹¯ááILDd ñQîäÎØé™žãôa:+`E–¼®Kµßzþ¬Ë÷×cgêjº î¿æ ô©méå·÷ £gÐy¢2Ub¨‹]¾Õ”M`€ŒŸ¢Ày§WÖµ×ù¸¹PÆÕÞ}r€²ÇðújàšNNP6•‘\SXÄ(O¥6”»"îåÛ¤ø3M%¸a‹I¡èÄœR$êìì¢jŸ—Ðy7'’„±I*Š, zÈÇøTaïàF§’šfQe2[*¸ÁîZ³RåpbÒÔwbP:®G5³öÞˆjp‹àOxŽ cEGáÂú:÷;Ñ÷¹ü tèØQ¾ˆŒààà š:ÑJMÜ`­9o‹T‹ î`²eOóHŦƒ´¼Þ,Š9åªùšjøêyLÛìÌdì¶Ž©¤ Qq YHÙA‰·õþº%KÁuÔØŒeu äåH•o {"RR}òŸÜXͽû„ ¨2Õ.Ø“#ª× ¤2GƒS°UX1©ÆMaVíêÕŒTÆU©²´ CuÁ¼«Ç«¢p¯úÓÃ,z3Ä¥³t-y¬8@>«NT)µ)“ÃL&ÒJ—Oæ72ÓD1ôÙLQ\ÂÌç%`Êž­&»ÏN1î(´:T.*€eÝò~µÄ°äØëYpÎttC·^Ÿß+ÛÁņŠñÚÞåÖ ÂK³|U;õ~8(E06]ã ÒùÛ.–ut i~YZZMܰÐË«™Þ …)ˆ¦0D,0.]kÐRv:-ß³ö«·³c¨g¨é*2UÆ &¶vãzºô3—r¯×³ä6PJ‚HÕ ÉA€Q¡¯¿ô½Û¢žc2¦À}¯nt«”4c3Pº©o(B-]6)ãVíUù©`¨­ /XiQ}&È×ìÔbO)M£r N•Î×ówæBÕ‹j˜.X¯Ûç£ w^*ëARpìä°ŒçT‡û†$©ªÎ)1xO Ž„gÙjwRÁž£uÜéõWhì£ãT³yµ.[QRˆZÊÎæ¡þæíl”ïh¸ÎååÕ`pËÖ6Õ X(õ'eW.UL£l Z¤z5SQ¡Û†Â¥}j0m5稪) c²šåjû Ö¾Ú´° i(\µ" êQ"G´Ê^E›Ö®"›Õ'Œ@ª#}°LÁ€e;SGÅ&ò¸˜"jÛB¼!™Ô̳()9p›Á}†T™Î¦5¢ÖYLµ…ÓŠáëN"3Ñ€Ê9Tªk]Ýá¼H XÁ\n’« ¥|Œbaµ}xQ›[ÌJ‘Y u €©ìiU N%ñƒ‘ÂF˜mâ?…^ày¶¢ÁV›Zy¦x}wͼOûÐψ¾oÚík6Æ3¦M|À<á6vò%°ÔÍ© ¡vñ˜)‚ƒôï:ÕÇo7îAxXÀT'ÀT=Û 5FÊÇ—3Æ'1V VŠo“;CÅj‹¬3dµU8”¨_0Fh6£Ã°„ÍZ+„‰š­³"͈üTu½meK)Šç oaß©ùçþÀh„B&/}0m’çÇ—l¨PYÀH®^±ŠÚÛב;X-ìtûΰ`©Pó‚ >*ð OZWä&ZßUú/=t¢[ò:Mû}Ö~õfjllüºžÁ0ó½0—á¦^3ŸÅÓ_‹á:oß´–f™JlÛºƒ,¾ |÷8]²c³¤§åäÌG(_•!W^5š«•&âä‚BÑL²$ŸX$Ìl‡{å¾ ÖÔøb}H¡Ù²)šlæ§MU—)XÈg¶–’ɼì¿ÒÌÀVYA‘l†ø¾­ÞîЩŽÁú¦j~ެÔä÷Qå\–’3iùd U¬¦€ÓBÇCôé Öñï %&i8¥‹v^,ïÇòö yœnÊ2´zÚœe`í¡ðÈކ(<9Ei¾oq~Îssdö™i,¦Ñ“QJOOP1e&/3Ys Y&§i(Â׿˜¡uk6ÐѾ>Š&NP“§žÒ¶"MMöS1 Õk/ ÑciõÆóåJÏÏÙvúŒ°³c¨g¨u¶¶Q'µÑOþw5(:ÖOƒ‘mvû(täµRðÑ18WÓìDhù­^àîÕ 5É/{.˜¦¸K¹ƒaÞ¾0õ›Ãü?ÌÞ?D'S!ƒÁª<Øi•1¼68x„–7ÖR,T/Q¾P_aFáu¶•å2îO#ßÓië¢öÖv)Hƒ"’GuRÄUÅ$¡”‡%¢|)±—)Ó.cPɉË7o00Õð°Š 69ƒäth`hܦœ°aXÃòuäêP¢øHrula|¸Û“ ¦@µK\oÈQEPˆ¸ È·V¡jì?!ë?¿¿_„ÉÁD:ŽNÒ†µa­õÎó(<EYPªOÛÄí 6‰oÍ5XjZnš,1I€ÆL†s„´¡ª¿ª“ÀXÝÞÒØ)Ö—iÒ/2äp‚Á*·ðâßô˜ëÀTTÒpÀ¶áêR÷l.XD¿jv¹T4®LÏ&%'Ú¶²®×SÊ5•}ÏA¥‘ W—\¢hÁòCj)Û‡~p.ë :wšúùxàZ¸ê(âIh÷!·8ÏŠGòHáÞU.Y“Q ÇMÍ•ªZRht!p-A`ÁÂ÷9uÈ?€¬•e°.Ò·«:jh¤_ô}q~ÿuà(-on:%ÈêøX†œ–˜”ADöyÛwк­¨‰·¢•’sG©\`tìàAA€S!ÖDcÉQjáwµeÛÜf¾.êúv¿ÿ3ò˜äñiÖ‹ÈÆûI¥h”AxôÍ$ou±ð=3ì—CEL×F„érM¿ Ê‹Çþ›>ní²‰ã´yÝA‡Ø¥j¬PŽ-e±qcV`Êa‡Y³B@ ª2žêªäö|J @Û;‚6ò&ݲ´g%¶ÌtÔ,¾‘LI'6ϽrIµáF õ5™æÈòŠœ1‚À€Šä~Ⱥ D`ÂÄÅ›?åœQ.X‹r^ë)I½Ìb45ë£,YJ` v*çpˆvf‚Ò…JfÝ.ÃGÀ€<Ø({,c¦\`uM<¯Æª‚MòÜÄ0¸Ø¢î¸äªj‹_·F²r_î`HÀ•ÛÁÃÈï3ä-"[˜bÖnwœZ²ë”ûZ¨É ÀCP’Ö Ö…Å€X†i®.ñ#‚1[ –˜3.y]µŒ§—m°o “#ùš8?D{(¦0ËÇ9å´ Õ†id$Qº´´(Ãbå£IÃà @û–~›¶¦*¬ë0תöFG•þ4D|îBIÔnà’@ æ¤óbo-f(–p‘בf`õ0pU v÷ K©6èõššÝ¥*4]ë7ÑÔ‰^•WË€\_È÷Ì¿#x¾÷}”’á9?f³N¿ƒ™iFÄN~çòËiÕà m;wƒ€äØñ#4Â"€)Ü¿”T"+ÛD5„‡¹“Š^óÚNùíP÷K4>­ÜÇR\SëRmÆâ¶vºÂâ¿íí÷™f¿CÅÍøãn¤¸@³uë6jl[EO=ö°$õ?ñøã¥u³Ü‹ÿÒWþšöìyVzm×]síyáÙÇ︓ž{æYú³Ûoù5Øw}˜ÚWn¡+víyŒ¥ýóû%K~ü¨[öauü'V¯X+ëc_ØÏÏ{0öûp#E&‡D6ïâK?E÷Þv=ýáço•íÊÏë~†—ÿÃý_–ù/ýåßÓ÷vß/Ëÿè†ÏÉy]uÕ5”5»DEè?žyTd°M•¡ËŠuðâœî!×Ë¥X8cWg‹_òNÁT„Ú¦`ªO0KQIâN´Û7I‰h`ü`Äh¡Úšihd¬´Z1p˜0ߌjHË*jŠþëîoÑßÜ{>Ú-¹­ ndt¤oud%K$X &­Ê}˜‚‰‚Âô¸)@¹©‹@y8¬-â¾^n@:º)èo”ëé¢ù±A¨0LáÖíOgeAÄ÷D‚ÜBPÅKö“ÿˆ6®ÝB½,5##ÜàÀåa0…Cz*,JI¨1ŠZ¤¡“̪¼U ¤¨,ƒiUÆJ=´×Ü,_÷ÜÕu¨V R|$!óZÑ”‹â Þ:n]Ì¡æÁ8!ŽŸí¡PÈÈ‘ + B¸Û YÅDÑP7š¥6:>ØG]c³|`'{ºÅxt@¹|Çr ÚÒLÓŽî^š­1ò(¦" 70Ì1S+Ù+1ÆÛÙ¢: ,ÈÇ7‘~†éòT/ 0D!ô€¼S˜f¬$ \·À ,ÓíŸ4 Ç•t"ì87±°r#R€ùºhBýŸ>à ¾À|Ú ¬sJuä.q2>'c§rïp¾¨“‹ “¬…"‘µ²´Ø×üåx[Ì´büÇP ªšÜ¹7üiläŽK¢ÀϹb„`Šþ¿VîT’‘60EðQÀHóÂ2¿U© ÀfÂhÈïýl¶¯lÕ$wÞ#Ëuê €.bQP ’¡TÕB?x눜¯Ù`ácÐF ƒv5:ä˜Ôã]23F©µÙ/:Ë£ÌL§Ó"3è¶xÉ Õ+«ÒÈÐB³ºq›øœã¢,±|X:>¦4}ɨ*…`ºã§vº>Žw$mî=7^K7Ü~‡ Úc¼çh§î¾ûk`_¸í.T´{¨(…vSJ ŒÓ“=D»>y%ƒé %•µÎ®õfW_{´ího¹éf!!x[à _ÜæL¿yï]‚c†·` ¶qËN™¿á³WÈ÷Û Ø»yPpÿ †¿býVúÆ×¿¦’; ¯½öªì뾯~Ž;H9ª ˜hY‹ªâ„ýW4‰‚Ý~ËÝr-°þîG/)W-¾v‹;'‹Ïãc3T|w­î2äf‘ÌBÏ'ˆeº‡ƒy€( ½ÙVÖÉz¸àX=œŒÔYÌUÓ۷ʺ»~o—ܼüÆ‚“Ô†ßñÁ1à!ÀM]xéNjoZ&`樧¶u[v Þtí%”«p–Ž"˜SÄmbÓjLp§&@ép” RBiÓéÁ„†´¥É´)É$CšƒcÛÐÁv°ÁÛH>°,!­NëÜ[Çjµ»ýž÷ÿß­/×ÓÌøÑü{ü»úö?¾ç{Þãy…µxLSíT;Àµ£nW.ƒ&h*rf¹Çežþ2|«£zeçô­{ïTs-n´Êl:À=(ç²WS4ýc5ÕÑáž!ê꣟Ì~B]þUòZ )èbv ×rZf>§¬ë*` `(íUóúk¯a·/W ã+…¡c DÛŒMjŽ0Ôyn_eiŠ •ÇæUäÔ¬UI5‘Æú8Ûz§9™3Ž$b¨“!+»x±zÓĀș㠦b¨í«¼l=-WLß—á¦Ò?íøÕ‹ZY/Èz¿U%<‰µÔвˮaF‘¨Ô\nU±4Š­“.Ìc¶ »$‘I{çÔñbp]žC=ñ%† ZEŽ1VÐ"ÀGÖ¤ X2yÇêpÀ-‹Lá4o²5åØ˜Yš…ø¸E’ŸçF蔀ðz?S“¸Æ£‘¸š¼ÆÉ‚¸úåöxèX"ý¤v`f)ŒS)€ÝŠœCQ?ƒ^º©/n`2ƯA<#pUàgZX,ÇMqˆXHQ(+Að^m³r'çí«]y” “Ía7ºñˆ C­Sç$”H¾`Ðbñ-äñ€—ãŸ~½h\M®M+í\Ë pEÙ{Y0/®­`píúÄkd"åDkŠp&  ] iäÂBéeЬ³œk) 4»^W:`€ŽÈb¸¥ž^0+¹–.á¹ðƒÞáã A¾÷|Ú"ž"ˆDœnY¨wQÂJ/°f°IdÍÃdÎ{à‘F*ˆtñ¸›[.¥Wñ­¾üŸÙ[" óÁ{;vð|)ìTFÓ’7 Ò²wóèöÇÿÆ æ1 ðúž=oÒÕW‰ÞÛ¾MK5ãµßmßa™[axî²/âÇÏ~ço鶇¾Íâ3è6uë·P÷ñQ¾Ö6¶ÜÁ ߎL%îf©À !sÃý~ƒ±æTÇ,õX§>æs~ikkÂ|Ú¯Cý†cPSÁyïI| Üq£á^[)Êàò°2ûƒqˆ°6¶Ýýã ŠB¿SÇ…Õ˜+¾OV+b8Aø,,õóæv^æß'cçÿ¡CÆ Ã÷É÷š»|%$GÆg)?>̟žèwÈ6LTàlÉÿÅWTù†Óݺ`“Ø¢~4-ÍCÞ]SVKÛ;·Ò›î¢û2ï¿Ü}%õÄvQ]ÆZŠ¥{øµýä²fÑæ·tß]7ðk…áf©bøþU…ÚÚ=Éîúaÿ¯Šáö ó¤næ={0Síè ÛTˆ¼CC ªhÛ¶¸i‰áNk¸Ìu gøŠK× ®Øfe¹eöîz›åGz¦)Ýí§ ëí4—®ÅP1iùL!¹Éиª©ç6]϶·ÞA­W¬$‹ÍNÓá±}þ™')-8 Ø‚–”4>¤‰ØcârÛ*¨tQ1]}…VpÕ4X«C] Yüð˜Ök°å²ŠDûqœn+ͧa]ãÚf]V-ÖzÀE VmI£¾éù÷–£0R|&ÍÀ “ت|¿¼ÿýŸm;éž Å8±•F 0ÑÖ5ƒ)op³h»î‚e¹<µð¶4 …{‚ÌvØ]©7t7Ÿ ɨb¥Å¥YÌl˜#~ƒ™¦þ”×øt,®^‰™Jí)ž4<F¹ \Úòºdþ"1©º(Óø,ìëû»iemkÃÍ‹-α£ÒÂ×ß–e·xK‹‹ÚÛG™•ã8<ª˜î[¾|+`Šë` ;;1ÚOå.mòë­42äåyO¼wp5â59v6`«¾@œ66:©µÂAûýô‡?MÞs#îáÇžà1œi~^HÌÓ<ßaþ…×Ï<>˜Ìy#ܱ˜gAnðYœkl1Gèd.Æœr$ dn7{éRÇ‹kˆï[Óÿ_׺šC1ø|ÿ¡}C£ õ}湟-U÷6þ7¾€f,Âûæ1Ê.åJømæqŸéxžîøÎÔ³í|¶“ôÿ•Às¦±þ_é\ŽÁùdÜÝwÿýgÝÀ5eê¸!ϳìŠÉ†²OÚ'uÿ3nVd› É:¨ïܾó^!îÚñÇŸYèÁë§ _þŠ…ëlvQC55¯2f~ @…ûO¥Ïz._›}=ÅMî^OŸ‡Y/‘`Cž¾Y&ïcA‡òš ºª¹žÞÜû!÷ôüÚOðx¤eÜ–w÷2¨þæÅg¨$gŽº5%ħºNœ,ç¦î Z»f-?†žñ¢ôiÎ"EÜÔׯŸ Rõz/'/Ù5IGt AâÜÁ—YK)šç¤¬ »ž‹Õ-:2ÞçñBã7\±Ïb¤¼w€ã¹žî¤«,‡{n&]‘™G‡ÓæLjö MQH@T\³Ç EÃ̦BÁùÌ =iFd°?&#,"¥–qmœ‡IÅ䪩  À–×S™!ZÓ)–×»ô0åkFﬠD̬T¶Rdï0aU€)”‘ÀTYJБϒ“øÒ«Ö,½å(H v…½Ìدº¬^Úú,(þîñoòý±{ôBš9G…ÏÁy‚ëéìBÍë ù޳͡s>ÞW u!Áï ýülc=Ýû ½øÎôÿÎvŒRÿ×¹\©7ËBì\= ´K_V†Hn}õmºù¶ ¼*//­ ¡¡Ï;­â˜¨Yl©Â•Ëì2Õå “Ç ´ƒ¡NƒéXä„+y°Ÿ–l¥¶Þ~N0BL1Yii—­Ž%-A3aÎ\‡B“Å¥@xxš¬ÎC`‚¯›ÙdbÔç¹G/„}^…»…‚Ó¹„…Îáç²Ï™²˜Ïç·-9ôLßsªÏS ußûÏvn?—=ÿ_œûZ/Ì÷/h «´1<ôÀ}´QQA­¡¥ ƒ¶.²eïüË¿V“QRMHê‡ãñd7˜©Ùyî4é #,ÆgÒá•î/þ™@­)ÆñÄÃws²✗dY¨lÃÝôÆÿ]¿¼„²­ÔLÐë/¾@_ûƒ[¨ßGõùi¬1*Ç÷Èg PvE}¹þ§£žyæ þή¶òôgINRŸº¿ÏÏcß3ûåŸþ€¶m~ž~öò ttÿ1®I-µÄ˜æ3PŽõ…˜ #†d6IF2â¨ê(2“D†oGÿÕ#ôÒAol}‘–¶rÙ2­ÅœžÖçätÈ`§x>’—Ì 0…™F§m†«—û»F“ó¸qµ¶mÚ>°OÙŒúSikgѵ}…c\{ŠRd÷‚µ(Î’™=þ°b¨sšÌb)p®åßêõÓdû©{¦‰÷†X* î_ÔI£´ ×?•ÕµEt¼ë{<Ý‹Tsø • —UåÐþ]PË"W‹3(PýÉÝ÷Ñë¯o¡OÚÑßú.ߣ]Á ª-îL>·CƒÜ̼£û0/Eœÿ©ï|/yïECÜè^rðã6¶ÈªÇï@6ó©¶[^ÛÌLý«<¿ ø<ìòý­ÚÒ/Ì.ÿÏVãñÙ b¨™ 5ØßK˨f-]LðÐÀåe²žXgËH2ŽuJ‹§åêϱRO/+d7"tåŠå”nS7Nÿƒ:ÆH Ï‘µ÷EW3Ç.å–ù>ã÷ÐiFb¦0ÌgÕ¬·a}3ƒº¯ïÎzª›Ö”sòQÌSGÛ@ÖVÍÒÜîꬰÐz;ªåýî׆)¤èàÆëÊhöÓjÊiT€=I‰J;—Ñ?’²„óVXÑý‹L̾P€]µÍ—oFÔÞ‰™ÝÊ!‡ÔòÉöÅ¢e*4žò=š;pv*Â5©á±Ž¥;Q»h—”„Rtëh?ø 'WÔ6¬¤_¾±…–,[Ak6Ül0Ô±¢u%Þ‚¸5רÒÝ«Å*Oxmä N’ÖäD›H³ÝÍTÙ°†Bæª+8¶îU@¹­3LõÎt**¯¢®¨BhÅBï»a mTŸùõ»°û±}H§GèÕ݇ø»V,©¤÷;z¹TØ)€9é¥Ð´ÐÅð‘ùËrƒÎäy`Í{k•Q›*i8Ϊ¶žvnp¾qýUFm%J^6]¿FMÂmdÍÌã,ìO'|Ie05ÅG3ìÆs-iHK ²[ò×ÿ鑯Óßó)ªŠÓ×ïÿSþ?¸6OGÙ’—ÂqBB@tÄ ¦h4NÓZ-*~bV¦kFܼ'pÔÂR€…YšM’„µâý®AœUH$8?×;ØO7«s‘|_K­“kNaË]ù´»³—*-Îê¾ôº*j? %­Õ×VRÏ€ÏXXàXˆ‰³Õ|D$[ ¸@±®c<ãÌRdK-5Jüð>Î;K*ä›Ó8¹=¡5ÕÕ2àÁ3 ù 0Äý¸ GÏÈÿÒ®c@… ?r ®^Ý@|ý&úöý„ ²ÜùéqZ³v- ôõÓL̦Π“31µMÌQÙN«ÉÇ’•Qóó‹AŽDRHŸØé˜ó‚´|/*0%MA´tª…pWE§ôçI°Fj~^PÏ«~Ù«Érg2> i“8ÀVXl¡ÓÁ` å¢TÈ ÐôVº›ŒŒ?°PØ¢æN:zî…·èÝoPgï.:ºïcÞ~òézê»ÏÒ/ß}•?‰IÙM}Æç‘܆ŠZT0â,“ fƶqæß/­Üp£‡£™;•بÙÌî^lE$ŒbPJƒö°9~j6dúòñN“š”»ÀÀpPF=aÄúþí¹WhÿŽ÷hãËTa#w8ö󬾯É13gþüºÕúšjŠä”±;1Û2÷2S/ÊŠq›:$A ƒ1ItÁ×-ohäI&%+δä}f)÷n‰:F¶<½ãŽSy^N þÃs°X˜ÙE,.ßQ“[ÚÃ\[©c±#mÜ® ®q(!‚ äq-Â+ìSÜ™ §Y$p=ÿÒffUˆÏè.[”ËŒ'ò´>ª¹ ¦h–‰ö~RÚªÿ Í\°Tq÷L±•ò¨™ëPñ:ÜïÆõ¢k÷š™pÌQBÃbùjœæö|ˆ³"ÓhêŽqáb?$Å™"¼¶JOÚ“EFF2Ë7_Ÿ#P 0›ÍãÄ$k®•¯ñùŸŒ’]û,½ì`Ê×þÛ++–R0œ É¸fÔy˜úÔy˜‚¡f”kÉ~©&`ŠM]mmÛ¶‡z<ƒ|žâ“ zûÝ#ô£—_¡Më–PÅb-i†Epn†6§l16±Wå¦`¦ùùÅ"öЧkuzF†z!iôï³M<ìò…1NiÀÚëÑŠð¥)»puæ ·íϸ‹2\¾êjoó°[ª4x,+Ln†êªtš;Ñ£PAMNÖ1C†‹Ù\o {ðÉïq)a§Ø•ü­_±‚u•4ž”„$&U~œQBe%@OL,¢¨š¬Jòr¸œn_¸|Ö4òªI‚’ÞGf@™,¨˜x¦z‹›c¦TL-®qúùÿ•¶ì9ÎY¿0”ÏŒ¸7ÒÐðAŠxû©È1C»οæjèž[o¤ˆ:_И%r«ã3DUn:ÑuˆÜõ¥t¢w™ÊåŒØßu¨8íá\°m#üÉ?}6uÞ{¼ÓƒB ¨s¤ÎÙ¾ÕŠƒ—˜þÿœúm™ú‚!ÇU¦ÐKõ 7º½C’Y±S—bPí}A#v81ÑÏVPŠÆêÞ© 'ášË›e°@"—Yù×cS¹–U’°¬p:¥[ãûřŤŒ¥O\o«†ŒÝæºjvóÂÝ †Ú”«@:’ `^áдbxj±‘7›`yŽc& TÌÌÔÌPˆˆ•Êk¤« !¦ä£°\ÂÙv»¨øœQ«ŠómÑ€R„ø>´BƒÛ ŒK›¬\g;;£Àtc¦¸öá&-/«¡H¸“ìî|#ÃY à)µ§3Ÿb˜VýÏ¢µ Ä{Ø9b‹V_Ë …v„ÁÉq…“3,DS£ K Á ì*/¦¬MwÓÈžÝÔ¸¶™ßoX¦•†p(ÂIeq)ÅÕ½~U…±@5êYt«EÚ\ß³·Ý}%'–Øùž›¶*¶šI©åÈfVå'?¿˜ÌÌTOï=m õ¢sóš-£šî¦U—Ôsû4ÄR¡BôþLJ烩ôæìïëeå0:°S¼/ÌNÜÂ0.”vf\Ü’iRB¯rÍ×ß…Aɲ¨‰ Âó“gJ'vÑ¿?ù/´½óçtcã]GuS`Ò~œ;4´\Gm[_$·šH_ÛÝÎ%7üã)rï**»é!*\w;eD‡OúÉCzMj´h†u’‰U¯”‡H X ®jÔÊõußÂñÏ:E ½ ÷-nR¬¶‹üÜ ¦0s7<¶é÷%êl§¬WÒÒâ,ŠæWëINn wõ0˜ŠÙÔgÐyn3dübbò‡µéDJò40õªEDF1³£Úòl týŠ>ì“bYn*jnT,•8ž:R¶ŠÂ Xs¸eÍh^tÈŠ’Wý–‘„‹ê  šI%.:üÑNn¦é80U°?€¸Ý¢—‰äN*æZ¨•r*ÐñQîUÿ—Ø4Ðëc÷,\¿bûƧç±O@ æ-@VÊm8®ª X2|Íà˜Â ¹§p–ƒ &Œd%10TÔáâw ¦ˆr…ŽqYÄUœÎV:¯‹ظÞÎì‰<þIš™CÐ0M»ÔùóÇhRwdùÖ.vº½y&°Dp@Ž¡*¶f8ªÏclÑbMÏëÒ’‘°¯NÔŠ:uVŠX)DH¿n=c~f¨Rf“­»ˆQcªµ~SìÖaW¿ËOõMU´«ýˆ.Á8Eˬ ÕUêÍ×KÌP­eSÕ3…! •Ø)@3¨Àßa)b0-È soß4k±?â@XG ¡wÔ_.ÕKþ`¯à~0DzaS”9[473Æ^\¦1ç`Ä«V ±€içÑã5R˜ÂÄ] †À=™c0E}›7ÿçÉ Â–Ï sG³ •„iÉŠ8 üv˜¦Žï䤤PãÍ´û‘ïÓ¯¯½‡¶Ýúôÿ²wî±q¥åÇ3ÛãÏxì8ŽíÄŽg“ Ɇ%!°»ì.°°]­Ú-H+ø£í.U¡«V‚V-”K+P%*T¡¢¶[XŠ Z [JawÓt¯IH6›{|‰o±=¾Žgâ¹xúýÞï|gÎ8 üÑJÐn^iô¹Ï9sÎ÷|Ï{y^yîìMT™7«Ð£ç†ô}—¿r\~ü…¿–üÁ?Ö|ïÇœâRÐå«l†„çÖ†e;vÛyì˜*AmÙ¾Cݽ€l“‹”ØiÙì+A0»÷fFk7ŒÚ[§G|¯U\ÚàˈaZ8_·*ÅRT]¼ÄíHΠt£è•Aã¯äb9¤ªH€+ŒôØé³–¥®¤¤µ<.T·ÒÏÔŒ€ìk™& Í]VŠþûÿž™Z• §ŽÈ™Ÿ¼¦äÀ”ÏMW ³_-(akÒ0W­_n²‚'õyD`‘`xÞ+ÙY ¦Aƒ¡Ç û·ä1TÔ®ˆºÄ&Z˜­0ÂÐ0˜N:Öb ˆ(8VÍo›‹ƒb¾QR†å ì—5ë±>úŒ’Cr%)´~S±y’eÖ|0Dy܉4–Î% ;eÄÜë)iYòöÆÉýÕT(Ý6e3t¤ÁøLÍÆöZ ¸|,—X.ßOÆ/Û0[ÀxŽN™sÅ,NðÌà¦ש³ R‹9€”Zeܽšxd’Ýë»õpÀ:;2(•¥YÉÌä„fÍâ71Š+ØI·ºr°Ÿf$­d«@ÆoDûxÑîïíݤ£ká=L‰«ÎLdeìêØÏüž {9מ‹Íõ~ÒÒëÑÀÆ•LÝ¡¾^ݼAC­Vº³¿G††eèʬÜ{×V¹ôÚ¸ôß6 ¢!ÕB6L ×®Ñy@TšÑe¾<軂'Ê ²wÿVO+¹E^Q’ËÅ’”’«ÊÔ󆥺vnŽ×mémUvK&0Œý´ùý\‡Ð‹Ï©\%ñS@ûðà1¹™ÝÿK¿¡qObø¥ÌvX–3va’1ÿË®Ûäòȼ–Ñ‚wedÃCÃ*¬O¼ß>–“éñiI5Óð>n@7+s¬3Ü<ûÂ_|Nþå©?õï_¸ÑóyÛ®°*2øþåò•³êʧNXbqÉæ5 ¥Î•y­\ÒLïsçÏVž ©±øà˜3 Ó„1bëdÒ³°|½ úÛª–Õ@H}úòóVýø…²°u›¸²™–Ö˜a=0Q†Y×9 ÛÁ˜¢s3c1ÇJy­s sß¹SèCßú+yæèYyúåWoøs\טÅ{±^89"›ôy¹´q«ÔuK¹¾Sv¾5,ïókù0ÀôòCwÊmaÍ^%Á¢Á°Û}ÍÍràGýבD=êZ—ïÚ _·O9à K_*úYt[ ã……œý­QuA4[_›©8·&6‡+¢´Æ¹{ú‰Inû¦ÝÌ Ó¹…²ü9æÈÜ!4^W˜”å«¶ ˆ›XÑgò1W˜'µšÜÏG#ê*ް·ÑÙ’~Vxe\ÁKF»±£§Æg¼×}Ç“kƒá1"”N<ì\צ P¥C ñQb¦˜Õàè﫹¨¾|Æ@WJ’¡‚EÂ,#à6´Û…  ÚÒÚê»|c¡¢u_6YIP—Ñ À¬½¤v_Œ¡5ÖÄ"@–׋©›Ñ‚iIŸ£–3‘›×ïÊ’I ˜:M\çöuŠG0Sl0ÏóßáâE©h­pÈ&6¯*x–6šã3l@øöeuýöv?ãe;ñ€ö S¥s Ì7êu¢ÑÚXo­“ëêˆjü‘޸ܜ±0Òd ‘š²Â$ !9²×-݈«ßÏ­T3Òy¼RÊÊÌeª;£M!‹ûx­ÁRß°m§cŸí5|ñÔ19üÜwµ[ZYÐ ^4ºÓ°“ šÁŽ{Ý•Çèõ?=ªn`@VKx<7÷é†d" <½Q0åýª›}ËÔ‚Øq¼ÞݼAÛØÖ,gÎ]2K—¤’ã¼pòYuQ_úòâKÒÛÝaVèiua~-*w<icÀ #u®_VÙ¡Q3Kµhñý—Ÿ“CÏg$ÕÝ%ŸüÈýß18»¨-Ú˜Ü(iÙ1lÂLæwm’\ã~Ù#/ÈÒg/Êåiìš¼ãï?+€ý›çFT¶o|jTò“'äÃï)+˜ÄE³CÎN褄‘%œ^.IÖ«w 2T Aa ,«éD37oG•ˆ&â0ÊàºïíûDCdZ¦¥JqY“‘;TÉöµõ¨ËžØC-›6™Ï¾4(Ãëj:mVϸÇ k†™â~ÅrÙEÛ.ÌÌÕÔ“êGÄw}ãnM¢Ôc€6^$.¯äóš Œñ9‹u/Kyº¨"¸ŒÑb&¶X¹Vu!›GìouÁ2fXp “Gœ6+Ÿº¬@€»‘F¯jü¦ÚŸnPunßµî_wÿÍíM{å¼™üyˆyêJös×k¬ö~³õRò:¡87õ|]ÊÆmãôêÎô€µ¡ÌÏê÷Ä Ã¬XL8‰ÂiUI‚‘&êˆì.IÊx(’ù@=¨vpáÜH™óËœ&ùD•©Ç Ø2®¨=ά,¥}n§a§ËÓã².´A"f&òt‘—ë—¤°B‚ˆ-+Ãåë”pÓº ]_b¨=KvA½nheUµž¸Î màZ¶ ìXëòÕÿ.[Q@Ü ;]YR·/ këI+Ê`yžÛÈhÆ<_Òn,€ñ‰ã\¿Ÿ*¬¶Íüb­ÒÜ!K¹e}]< ÈO„ߟøèzß5!¡LV­Y½ ÕŽ6x”X‚qKWUÄcÛÝwêçÂë¥.˜ÅqwMLôè³ÿ&—®ØÅ}TšµKËöÝ{¥3×®.؆¶„öG¦éÇëÝ‚îßÈÿüãþÿ H€).ßB}AYêùÉ1-q,”n.¹È¹GuÆPE|F (1¦¾ûgú¾ì)Ã,úddó 2ž ·¨om´MÁ ð.4B-){ð‚4tî5¯xAYê–+¥å©Ï¨8þS_º"ýÛ×Kwò€üöˆlÜÒ.ßvR49Õ)½÷ÊýO JlÛ}5ßE ÕõIuæJ˜z¼ž£À\'šCž“GÞûnW ³Ä5+Óƒû$û—Ø*ë fø:Léô˜êoiÛPû¼ùâ„5Ó·¹SAZªÉ!ùü ŽY/1C][+%ß%¯IU,xð4vj˜IØ+ ×Ñ•ÏM,†…®¿6jK: +Ëæ—tþ®Ëd ÈÔIs¬NzÍÄô KÍ' <Í%ûú„Ô–,ßÔ,3^3’˜ˆËž™‰Éäü¢Üó†&_Ã7(šï\º0QçæÅ[u®aÆ~36¥í±Ãm<½Ñ‚¬w(VQïDÿZA„F0jRõü­Ô)h¨ü TOÏ—¢®7-Äd«96¹\YIš"8ã<#E”kÊVìŸh§jæÂ Ù-ot ¨âÖuåÈ$ÖðINX{ª$f½wϾû4,;}Ã=÷ÊБIÏ6ûÜö¶˜üÝ×Cª€•ô’¦Ú“ËȺå­ÓròØe«l C~],å?»woõ eEàÚðSªC`“äìÄiÙºi»Lx ?ÃòâÖö^e‚€dØcíÜŸ+Æ|…€½²M]+ n¶^2̱-fYuîéOÉîþGüïwBò(yqŽEÝaÖxLUÀ6ÙÓ¢ÞµÞ^[‚CyO*šRVJ‡@õ™)yó]ûäSþ‰¦N7²8æZdû–]o?;­ìuj.~Š!òPS ã•Í`gÏéÅHBƒ{ v#aÛ‰pr?üÖýÚ³7ë»~@Óù‰ÅÝH$Á—ýK&îÈÈÿ\aà}²gÿ„üí€rlÄœôSI-L×À{d´²Áš?ñÍ!iݕݛ|0…b¸|éŠåaÒtRadáÀ>ss@ª5ªÆ¦ÇÎùï…¤qó¢`v¯SG<×ÚÚD¥`\#a &žêï»"¹#h¸¶`tU³Í~´Æ#R·Ù¯1à ;Àýèê"q[ºúHF—…š4¿·&÷q 3:·fp;Õ`}œ¹v]zœV"Ò“Ž¨>pØœSd%Û?Ö&–d¼ŒU­I5 ê”\f/ Ú8Ð)73ž§I97 PE‚ÏLW2"G¼X¯3׃`Ha0έÉs,òØŸHƒSBõM×TŒcˆÚR”°/ÐàÀÔ)!R€Ë•‘ø§»a.ƒTq#¤.kUi8®‰C:ÒzLë¼™œ—Øj»²SöñÜhEÁ†Š«7ã5':\×-ɶˆÖ®âòÍxîQ\Øœ,D‘ýL J0¤¡çjÀåK9Lxu^"õ!Í4 8yá2|a‚0Sj‹yެ`'ê çº'NAb5­”ÔØ…3Žä•áxÁ†Úk-Úlîß (qT×ê 0‹’÷Üg"9¨¡Åêç>úë’‡üe0׎€©÷,ŒoÙ-@½©¦ÔžR2SX£ÍËv8i'te­0ÉtˆW¸8j0ÃéAŒÂøßÿØ{äÓ_=(ß9p\þù{/Èóã!iß¾[~óñÇj~ƒ*EŠÚÿ” _\¾Ò5`Øi—>OÝ) ºzÏ›äøS‡äÄNJ‡dä“¿u›J~ùÓ5ÉÛ}ßé íöA4h›ªTU~P4þÓƒ‰³pÈ–K~ÙŒÓ"fDÏó’y×-½.W_èê€Ó*¯ŸW1ìÀt}gUwsÆgóâ²¥ÜUIÍMœÐLǯæ×[80å?á1À V‡1rÃÉdâ¤Áç׎”cð:ÄÅÎÝ©°¬6ŵ@r=|ad »rI|[œ­QN®U¬ Þ1R¤ÅÉ‚ÔwÖ>Œ­ºŽ›Åϱ}ob¿lÜT/ÍÅ„zÜB ãwê­1¯£sõÓn £ˆ°C°µ#ûín¯Ý–;€©ÒJ[J²Óã_×%å©’Äf¢š\¤ûç¹zƒÛ~vï”^îã‚eH‹¿Þ¾¼ômî5Ë…mÒÑœQ÷/ †ÛzB ¦€ªûq¯¼¦ÒyZËJ††Fä›/žòY(e'€Íå³U¥2JiÎMÔ^+TP)Iÿ:Ž+fAL¶¹‹yâò…™’Ì36•µJJú”ž?}QŸs¥2%z°TD (©„é¤TÈ­J¹Î2H²p¿óÌÓò¯Ï®þ&sÜñxŽÀýëj"  PEœ,_~  zS6k÷—ï$éhßÝ6¹&È>a¦ú¿fê¶Ó-Œo™ÜrùÞÌpóFWª¢¬fÔ†´?QÅaª(¬²)¯öÔ© ¹ä»ûûel.*ßûáÓòð[î–¯ârЀØþ¸\zÛNI¯³+Ê SÄTôÁÕ3g&Òó ¨hò>òXHN˜ÇÞ] ÉP¢"Mç^Ð÷àØùƯµÈÿä.Y˜>*oÜ1"‘+o«ùlâ²#c!iC©É|ÇØˆ½ØG×H!’Ý‹Á”qiʺl‰“¦€^“¿JyZ²=Ý&Ëy ®Gõ\ºÔžòb§d4—õ¢½^¼Ð,îd}¿¹  ùi:¤‰*°’I(dw¥$`3ÂåÛmP hF½ Ö%ë Ó‡e½¸ß톡ii .^Ù =ºÿ© * pgKKÔ†ä`nfIÅPí‘Cͦ˹%»/@š…Ö¸èÏ– °”æäX>%»«ÂÈ.IƒÏ62êÿn°tÅ,FÜc€kpt»Xî3gÿS'a¡aFwŸã¦¿ÀkLãêõšõ‹»—&Ý”Ø,k¶o] kŒø]bœ’~„¤ ¤K†=ºmÆhW·T’+æÓ#2»TPW¯sñº,`Œ˜*¬”zÐÐä¹:8f³y‡KRÏ©ë{§lœ©—dûV¹°:® êê¼Ç¼Ö½Ñþ×3§Ì9´0'Ÿùó'äÑÇ?§ áö Àg.ÌÈ®m}òÏSb‘vêô9ë¹I5.ÚDsVÁöIŒ1žÜ«L2–6‹SsMR:¶oß[äùWΪk؉!”š`Þ»\±ÇЩ.Áa’ÔV·´õúb4¿—ä2g€´Çþâ7p.hg,a3€ú–W/Q|Ðg½zä£x¬_åÉ’g 6i¶<+Àj¥2e/ïúHnùâmªëûü/Þ–—^~Q–.­T 8³Úƒ‡%ÖãfJàðPÙr–­VL±ïüéµrUÍ-ÒÒQrÓíñ\%cÒvÅ3;ä/rKd×ûQyá\·N<¼Ÿ­®Î- X½¼\?'ªÉfà‰ËfèÂòî[¯èù‚ü4õ"Sò.”ÑÀÊm<é.ŒÔ`f5¥ç"K§‘’œ+7reeŽŒgèDI˜Ž  ÅCE6/µÒS‰+³”É5X—ie*#€Éž­Øñ$K ]ÐÑ>Å+Õñãwê•ã탲¦Ì]ô™Š1nX€Ô<Õ˜§±kD$P;¦Ö²–‘´ð(›g3›Ts¼¯ª^3­\딈ž·¼*Ä%ÎC>ÂÈÃVÇT‰IÑá…ê¡â­Ro !ħFg|AÒÛ·«Vî¼i³z¸6ôHÝÇí²us©xmíY%&½wÌåZ,Ö‚’ƒfAÕ¼<EHÓfsõ˜1_X<× YqÎ’xáxš†ZHdýȹœ—¬^¥9Y¸§¢.‘‰ÇF¼CòKiOÔ¡ÂÎít#=±óëíVp-ˆ„´µ¤¸Îž¨æTY`²QŸ ù òoþå—ýEp°a…Ù…ÎÍäP§·@ý ;}¶Só§Ýmm~H7hèù"ô˜â‰ÚŠÏÕLÐIhõêù>û÷Ã=É‚EKü‰+¸âǘ\­Á9ì^ ‰ÖoPo’ ñ­(ž’Á“òg¿ÁŠ¡x—nAkyâ5çûȵ:ñ0É2[¨·yØó¹„i 0?ËøÚkƒySŒãHI–þ.äîŒåkÞ¨[óZ“/·ª¯s¼RóLùm´a;ÜÞ­!nBéêfÏïÔšÌcÅ3LƒÞ+ÇD £ݲ(4¤â4öDCBù)Î" Ðã2R¥Ç|¦5!ÞióhŠŒEËýÏ;Þ”X”™Yx¹»€*»$$ÏîÜ/ÿëëÊÆ^"¦‡ËB™qMŽ–óɆ¸ƒ <èÿÚÒÉâò £Ûe^A•#$üáá µ"KHïS—q;ªbûz8ªéüÎv<]rœDdÐ ÖëÌ=ì_sËÖåþ1 8—“béSð§ä‰/Ý”tLy‹~k#IX9xoéç¼Ïà9 õ΀é…m†”4á‘.[²H²Sc<-§œ•žIv9“@ʤfxÒƒ¾ˆ€§}›Ü?”îÞ/uœ×VÏÖðc¡³r¬?zJ'ª¢ÌÉ“4ùÛ¥^î´(-&&*4V#Îûfº+jB¸Wzxl@ÚêÌ ÇǼ7\¹F*––ÊÝŽGò~$*w ,”¾nÐe\CKXó´R’†zÇ&{£Óy¨„…¹i1<Ô†Ö˜Ò5ª{w¿Àkå<Ä"€Ö´p %¥Ì –Ø$¼+0kk:ª9)rJ±h¡ÄÏéd›™3í$˜)Môh?L@•mT±‰tLñH ·’9gú²fß®´Ôvšq=$ÿЊ5–kªsÙNg„,˜’CÍ9•ÌÊ%*K@çwq–|~c–,(QÀ\Uz£DK(ˆB0Ê>–!-¥YšÊ€ý˘ Zažm“B\kÇo>Õ L­LÂ’£KŨ)2’29‡j¥,Œs@ÕøäRW½çBZ7Û+á¬ZÀ•Ppå|ï59)J²ÃkµÎ.äLµÁwçQwŒddJ×°Œ…*$«jµ^‡<éÚe—)ƒ·½·Õu`Éxã±Ê]: cî cÎ}3+ì—õV6"`ާ`æÁi<Öàù›j3€:Ñ`|õkµ}^"€¹ÂYA"³u0X@óEä=²ûŸ>úˆ¼ðíû¤îl¯z«®òJDöëožÐ¶Zx…ÅÎ Ô‘{rsx647éu?ª«U/’ºÔvéV@<ÞQ¢ÀÊ–ÒR,4 (xþrî jÖÎîWGɬ•R*“¡~¤KÂzÊsðNýßî€jH<–sêTP¥TÆöúzÇ3å17훯¾èL—¯×k«õpxØ•S“DhמÓëf¦&É•02¥9~h8R¡ï õ_9åõ‘ÙÚ. 3Pe ÆÌ˜¹ÈôaÁЯåIÙ¬²6CÙˆª•Þ`Á²3&· xÄc}â­RÇXàøìGºgùáää0óï² 1{-5€g]í5³î‹‡”p@BRTƒ9TÎàò#z)˜:{ :c1×ëNc–ï‘Ù¬9¸‰;ž½Îëi ž?»@A6âiìF*Ë¥bvDûœ~èÍú%å €¶XÂ+elϪ+`žíÒ.Iì£ÎØ&·\Þ6è‡ómù~OPØÃ”Ý$ßNž#¯Šñ9#Í)nèךeEEú· ׯ¸þ/,Ô;”ø­„{Ù Hë½Vˆe¥¥þøfo¡aÒ/÷—yµŒAoH±wÿ÷,@ñNdz]°c|ôÅSuQFÄ 'ÄK¾42§\cX4wé¶t2Ú®5ª4pÀëfqaÆ<MÕ6Ï3X{ʸ¿ëô¤T³dE³›Ôi +YP^(|ãNõ$Ù6kŦá^ÏíMjÙFX÷Ë×mÓüæÀ’aÙþ½oÊ-×l–›¶ÈÅÕ5²¦¦Jzà~9ÙÔ)›s·ßp“\sëõþw¨,i>0ýéSOË=|¿<õw÷ÈÖÛÿL^xn§¡®Œ{†Tí(³f¥l[y§’”¾vér]å:ÙVò'ò7_ß!Ïþä1ÙÛЭ¯'Ì ˆZ‹-XoZäÞ8ÜœÁ°®Y°d†ç‚gvìy[¾÷ý‡dÁl×ó²pox Oú=¯Ä„X¹›Mé@€z¦Þªã-19¡å+±&g¢ïЛ_5€ÇJt#´´¦FrŠÊt3Ã;Åú²Ý0;x¨Ám“ Ö·ºÞ‰õ% ‚«á„k$%dcgNhþ2ŽJz†È²†£%ªÌ$ÉŒp^ª…~‡Ó‹äâ¸ÿùçò.Ü•ÆòfVŠ%çPkÍ„je0FT dÞ';šaì ¬ç{ŒÐ¾DþP¥t†nGÀ3_“œïxÅt~ {ìÛe Ë´Œg]w¿õéž… yÌi—È&ø>Q~VÆ«¤y".ieéÚ «˜È}gúTÈ£œ†÷žó}Êv€ŽSöx €µ6ìþꥨ¼D¥:é6ƒ™ðƒþTÚ·±ËLL™ŒakÖÀ¾l¢]k®í±àiÑî Ë»òxý𥒕îz©ìQ["Á‚Z?×#%Í/#‹ËóU¼¡nÿNÿÚDAÈ“Òë”ð19{XåCí'U“y¬«AË€X0 ì€Ö4|~«ÞÇC‰(yžÁÚÓÅ¥E“îO{ ËqryݺÍê4FÿÓêå eÚivŽsSKåæ›·iyËÅs"ºr·Ô`éŒ1V”Iö~°[ª¶Þ+‡ß’KïX%þõ埻G¾þWwèµéÞûÕ»¥{,.͵˺«úº€)¢ü›ªJå™ï~[zâ%yí·òÀŸÿ±¬^U%üí7¤¡¥ËÙBV2`ÄÙ¡ìrPÂÍxÈ5øu­¼Öj[­¹9û—¹CϱúMöP±éHIöÀõ±Ç¬@s‰„Õy0”i&«ú ”Z0Œ€ÆúêôØ@5ø<ÒsV<7Ô­Ò}cåÞõ§xÌKÅRÂy~íi±'$ŸLRJ&!ÝG %Çjà Ó 30¥ƒMä|®6'„wŠØ~Ϭ©yP&@dëÕtÏê —HsÈ] Å.œ£ Ö'—Ï\ÈC%\Ç]1Ç 1ôAïSÿÞ§{uTSæåû{€¶»7Ws¨öZ€•çIPB3ÑÖ¡ j@ŠàÈey! ûÞ½ºPóÓÆ¨¬p¾©‰‰ue2²v©‡[DJcyò¿ÇjåO>•yÝ œíJIé8.Wo¬‘Ñ舊£ ß ¸–ŒÊ‘Övií*Ô°pLjãµ9ó`Nâ)Øàt•!§ªcÉñflÕñ{íúe °”·Mg}IbŒaˆž€&5פ%UÛÂÑRòæ¯Ü&7nÙ ®»E×äiÍ)]qðR¹^°íX¶€dCÏ –è¼ôÚv¹ïÞ¯ÊÑ£'ô5<ßÐ庼ï4^Xé_#01ÂbÉç’½ØýïR $—D;“BŠ3±¦¦é«× 0 /[¹ErWøyT#Mp=Tdˆ œ÷ÂÒíç]ï+5<*³²‹54†Q$Ÿl᩽BQ>šÎ‚^j!iˆRËŸò<`Üïµ£s ²…XO;Aª<_l@æ•HIz¯æNO#£¦¶ÏÍrþ—¨RûŠ»·åu_›®Õâ ú}­ÞÔñDO<×éLÁ5'¤{Z À:ÒéÜ3¹érªÁõ Sr£'¢½z Ã—ÇØEÎ-n‰KütTîl“ÓÇ>Urj[䜖z¦åo=ïÐ W¬”C'Gäıó]á~\cïi¹LÑVõ`‹ÒçÉÉÞÓ ¢„|©1…õmÍÒ2s$/s™ ¤_¿x¶‡võú,ýÿ¬ú .R×ò¬Œá`ºÃî¼R“.´…¨.­Ü¸‡Z£Ÿh7h“Ö GïÚµC dãþÑtΦå3Ξ…Ÿy—AQ‡äü(ÏÕ;Ÿ¼ö#ùï—^Uŧ}ï¼#gº{µ¤gÆ&Û  ^À¢gÝúÈÑ€RGôŒÜ~à nŸ»b©¬\Ué—ÇKeü®3ÎãåÕ󤫹^núÖÃr¨v@vìÓÖpUó‹$ÞzÜ× ®¹d¥nfugS¤·uH~ðÃ'#i¹ Àßùþãòü õRY³X2-óÁÔR<-C.°òžëo«ÔçyøA¹ù®;5Äü÷ß#¯ˆÊ¶ûÿEßÇuí½õ­R0ž¤ö6™”ä‡|SeJHؼÔë·¬—kVh½(ù¢X´Qsš¬ÚST6Ðp&…Å’êSÈžh9¢«âÁ®V-=hê™Ðº[®Uˆè}ÙBIq~D|à¬67ÄS¼p§Z^á¤Ï0¶o²™—JŽ49—i` kÙGz¶„bíÚ#KMèòÆÏu¤‘t—ˆd Jm"{ÌöQLÿÇ™î3“ê_?˦ ùbVJƒ™—Íw_P<Ï™8Ïû ŠM¬Ö‰ÅLeï¼z_';gç7n\,§²BrÓUÒ4tNlhT Ý’W ;ËMÈ•žõÈ0‘`÷¢òõXC·K>r¼ÔÏž“/]ú9ù·_‘½Î×oª•U‹Ò¥zIHÇlADšR†%2çr9á¼â‹­ìL7 3:Ôï ~Ä}IJꔑ2DuIý{\ MÆ:º×0}­Ü-è©Z5襢ŒeÛcx§0ØÛœ·Ç€( J5èÑšÁü¥.õTô¤¾Dp`ü"]ˆ‡:·°@Å‚fÛÖÑâ~Ï‚tmåöÛý»¤pn©–Ö¤1Çå¨UăêGäL?9ò©<÷ìäÅŸ=®)œŸyÌé]òÑÁCr¢nŸ–æ 5LØ™ïd›)›¹€™8>e3ÔPððÃkeÿGWl•¾±6yUö¸“‹ãÒ÷ÔÚµ {íÂýáƒòëÇ_T„²Ã²s÷«²¨b…ì~~¿,Zp£ä97Êü”Dès@Ü^ ÿô£çäòšåòï·®—íû›åÒ/,•?k”¾Þ^i9Õ(ëjŠUÿ6gŵJÖÉsŽQÚdÇ‹?/•ù;¤óݘÔ\)]‡Ý›åÝcmò›½{娩ÓR7ËÕ[¿"uoèbgSå-Ãi^þ18“ÁTkݼ|*{nê-W];éoJ.ó¾oUúyTÊjô7{ÌßųÇåD×ÿµwu±M•aømG7ÖÁ ÃŽÒ :‚ãWþb"ƒ`PŒwzaÀ@¢&&Þh"zaàÂÄD/L¼â ^H2ÇO0˜`ˆÌ 5ÈFæØ]»Õ¥ëºuum×Îïy¿óžžÕvEÜÅÞää;=çôœï´ç|Ï÷¼¿qÓ+‚Áƒ ìK°ŸÂ¦ÛÉW¹):¨:aKÒêoa§È… #‡‰ôc`µvòv­` u/Ô¾HÖ € é­Ð(ƒ«€¬´½=€Å§¦hB= `¨Q…‹ÖêœND¹šMb©žäu`æ¯ïk¡VC‹]+SÍ‘b)€U‚ˆ\ä¤Bý´X‘ÞW$‡/X*³ìXœû¾¾¡†:+Ät ‰ç—§1¿"f¹½ef¢y´(3‹õ¡p–³ q5cl“FÔ}¦F\¿l°ÃÝÆ§è󛾯Îå–;8iÂ…¶nz¥ç6ÖSÙ¯ýôx]¢¸D/x—Ò£Èc¯¤Æ¥êýÍOçXïG¤˜í´˜°JêB´ð>´&p™ºlLÍãRm`¥¢þ”T¯ÉåÁ™cP5CÂO ò奼Š)’ŒcpÈÌû{QKk‚{+˜ p–ë>äO-aV 0°ŠÍ6…J$1 ¼áLq/faªªÈÎ%öa„ê“B0µÚP‹%K–¾{+4J…+Ë„êÌ5šnKp"1ûªõ:æž´X¶H&Û$ŽÁ6¬Cí ïZìãä ‰©ç ¡0›öБAj¾p…c¤ƒa=©ô„µ†$ãÔ̺ܧ¯úæ,ÛLm¶€Ž?5g—ð–le f؆ /dq¢Bø€ÐÍM^öâÇ{Ç¥ìä;é O¨¦$üV0I\©n³€• #ZQ‹ó€ŸÅÎ*ï€{E¾úÂqDUl°ÕW2+YŽJˆC…:“Y˜£ÞgÍ» PÍ^×`ªˆ*èéèd0VL` Ä0ÅXAÙA+˜Nš¼_s uºÌ1Ô"¶Û)68G’ ì”Nê€ àîÝ÷<«b[ZZ¨_1 ¨ÎP† /-Ân&C=€P™¤šÌÁöUĸÙÜuì˜qݣݛÌëã!…¸Æë¥sÏÐ5€k¥žùô=.û6 ÐùïÂÔöÃ%:ðê…ì ¼ðÅ…yÆ…T‚Gß=FûŸÜC>§—>VŒ·32 æô.Úº{%µ\ê¥7^{í¨þ® {üt>Øg¦£ƒôEc„éC©”ƒÖÔƒVoßblŠ5Iذ®‰gó’vCušûM0•6ËtgãjàJƨ¾ÂIý¼uÔÈ“·)AåËm:?1–Š3 ÐuDílO•$°U8©J[ TeÒIå8Q„ùŸ•»)•R-©˜¸ÑŸ¦ú¶ÕѾ%Š5eJ¿nª#9źa§Î%Œ'Ý©”JîáÄ·u†§Ar³}vEÄ'B-*¦‰}êNõoÕÕi kóI0ÓF#µ#Ö¡FS+Û UÉ;› WÓÆ5º¿7Ù$›gþbÞÿEû(ÅsƒôâïÕ´Æ‘¡þ'|´6¨ô P½ó6íMSce9ÛLá„tã«k´z×C¼AÁ*Ÿ—j*‡hR½¹°ÿFɽVM†1)p9˜Q4·¬{šš¿>ÉßûÞ?Ä%8#„ñœVÍ7œà&ǧyùŠX3%Aâ«53•–4[]Q£`º†Ò Å€¹}Ëx-ìÕ ²cC\׮р*Ûı …&¶mÝÁêY$ ™öß&âÌTÁ\;ovó»(Õ­><ú2yꟙæÈ¤ÕÄ.rªç3«2@`2ÀR¼P ÀŠÏµ¸YÄã–«õIŽac¨ÓŶ}Û6óÁ@ný ?ÿ—r?¯5Ûú ×µ^¿,3g“wÓ¿bçšé3óÐáÃ÷ü^ál‘Lÿëcîõ5ÿ/A Ø™¥©V˜:fñùÀ=d*FÈ‘ZÌ÷"÷$­_¸Ýzï…çœR¬ß³A ûsâøñÿ'cI©ï`,@¡…;=ßL×¶î+µ~7ß+uÍû=–Îüø pï„V•ÕIEND®B`‚ FRAMô¹ ƒÊ IHDRÔ<ßGK7šIDATxÚíÝnã(Ðæ´ÿÿË9v£v{M603ø=©Zµ›8&L°||ÀÿÝ¢.íÞñXý©i TÕÓ·ªø~¨V#ã퉳÷u{ë åøÛ~E‰|í¯Üùͨ‡‰ÿqÌçê>é¸lìŸè ©  ¢ûǹº8ûü,¯oI¨ðœNúÓ‘º¨^Õãg1 ^Ó©~ê©‹]êm—r°€„ ïéTû¨/.IBz¼K–#’éíËO> ÐÄ,_vöªCîí$«Ïú|{†dqkü¿ÈX«ŸP¹ªGç˜!¡DY³×z:gç쾉FøZà# udÐïŽÕrœÖFr{Xì»™QöèúlmcXÏÆqæùQ‰µê(õì í›\Ü;{¦|S?T̺‡Úô¨Ç´ݱ‰}|ìQŽÄU®Ìõ1jŒ¨J£ãQësg®ó=sìtë$ÔÌoj±“Iψ/ƒUmläëd›À”ÅÌ©2/Ë{æ/fùB »$ŒÊ‘²3_ߨco—Lÿ•PG]óŽ¸ -ö7ÿر|Ñ÷q£ÍÜl•¬q]¢|3jê‚‹?Vì3ùú\Ǫ¶¤Í>qtÙLÏŒÀlÄÎC•º\1"ÜòÜ«g;G–óY™v²´œëPNáÎ0Sì1±v¤.nOþV½ZÿÈ6z?KŤún#Ö•«Ë~må*wdb¿V¬Ï:Ÿ•÷¢¯´jD³´VUïψ'¬Œg\ü¿šØéѺ5ûØa‚ÒŠ²ŸyíÞ;«gù®¼O“á’©ØëÛ­Ébg7WØe)kùfÆ•¡ÌbøQdBM[)b'À®çe×re·Õ÷Œ>‰åh<ÓÊ1:¡V¾ü(ö˜Øw¥?Í­Fކ3ŸçQ±e¾ÚÐÛôrDÏò%ëÉ;|úÚ^ÎL„ÉÖî2Ïú=:‹÷ës+H±SW¥ €³¦íÖ¶Ë€køšlö0*•¼KŠ·ÎÇ·£‰*; »Ÿ½Ó:T8ëð•[ Pà·SóŠÜCàê†LЕP¸ª¡+],›`¯føÊw@-ÿåÜéŸr>!IEND®B`‚ FRAMÈTÎ IHDRÔ<ßGK7ÊIDATxÚí܉Žâ8ÐÎjÿÿ—Y¡R ñU޼'µ¦‡¡Ê.Çà$üüÀm£¨ð(È£dÛ•=¾<¾c®)ÄßïØ&=œµó*müžÃ*qŠýÝJ¹lcÅFÏ<î0ɤÕŽ9“Û/wh“vjç'ÔÚ;ÿŒ BKìR\Ÿ²U:W³{~³ÐÎciÿÉý;:€@Ïb;~ýÎß~·”ÚqL„ZuB}„ˆ¥šógËD©s¶Ÿž[ºìÔ²ä]û¦£äõÙsròÏm‡³jâ]¡ZÛ;§J•¼nN͵ÔMª¶Sí™ê¿’˜Kö‘ÓQužú{NÍås÷Ó;®Kß4­¸äûòmàå^N±÷~Wµÿ#ó±È8smËÀni›³êë§ôµFÖBi[¶¶}î¶Gáã­íÚ&•w¯>¬½^÷é¬Î#ê":·Yã*¶ò„ÚÂùÇ6+´Éãí'"—y÷|Í–}§&Í#c›9_áÊøg¨ó¨Õ¿è¸.·ê’ïKÍÒCj»é;­2¿’ý¥–‹Ïbx<¯g¼ŸâÿïY>3×ÂY?]™OÍø«Y!ØAÍ©ªÒçÎXç¥ý ãï£Õ'Ô©%áO…ÛkR˜í¢ˆã׿%çÁZ­û¨ñêÏÙk!'¾oÛ¥ö3BTçž«ŽÎ;'þššê%U«ã¶G^‘q]j‡%ߣòo»˜å`Ùªõv¨;ôõêùç,MFZ¡MJóYi©ôßð—]>¡¿º‹)ŒúÄKšþˆ³RÏ_¨]&TþïÊBùæå•ç{ +tzêÕ7¯åÄ–v^ö\ÙÑuÞë´Ek_.ýAh‡%ßR5ÖãåtäÌpåDp$þ¿’Ú>Y ;Lª+×ÌŠùÎ|ìZ%®û&Ò¨æ á’¨gÌ!ç»0{|ŸîÕíPËìµÐ_dŒµm=ÛØéáÛ= Qc%b?³Þ1k\IËJ¸™&AØÍè+nàÎK¾£™L7bBÃdº·ÍÄ;ûÒ )ÀÍýÄ)þ Å‘_IEND®B`‚ FRAMÈTÎ IHDRÔ<ßGK7ðIDATxÚíÝa£ P½ìÿÿ˽ì‡&›¦Öú^rÉukuÀÂ(XÝ6JíWÀrÞó}c´Gp¹½rù–²ÚCïõ¤ÂÉíˆ~]ý½{õÊxÞÕÛÕõ³’^ õõs-Û>[OVÙèìßÕ°„ÒNVñ(ü{Ö6KÖ¯}òsuLOcåÛý¶ýåuÏm½ÚË>6gªÝI¨ôòÚx?u2¥ó®GÊYg9›(úkîÛ·²x>9ÂŽ qGâ-‘±O3bù´?£ë)I–Ñù̬¤ûé{ô.6Iµ#C¾´(¹"r}ô~¤Ã¸jèmô6{”!;Þ¬}Z»þžjÒQ{h=H‰$S t •lûÉ{µCcwMR“×wÖ#֙ʇòÕ$ÖççV¯ëéòå*gg·™Ås¨ëhÝg‘¸Ï¼ë#ÃÔ£µÌ–¹Ï2Ùr8ª|Ñý6KOIBåNö—ÿ×Ϋe$ãšõ%” Ùž±Õž9eu¡ÏêœÍ"¡Â{=; «UiùkãÝß¼^©c^06Ãþ&9Tø^ÑŽ~¥$˜i–z™%ÎéI¨d;›¿™¡qšß]íl£gRù‚­¿zîóÑmbµïï­ò¥ÅÑ^ÆÝïÖùÖvDGuÑ»“ŽÌ×År·º¿ƒèw};XfÛúÎ ¯ð®éI¨ôRscƒ«d¾0z£‡GågKã)YGæ²=ã½ýÒzŽ$Õè ;2ʵڜôô ùÒꊟ¬d–rEΊeÄœqTºíÒ žf¬ï©H¨d¨mÔ5·~»[y®ŽuÄ6{tÚ+vîµIµeÙ¿¿±>ûGg*™j6ú±j¥÷¸ÍxÄVÉý[·×òÌÎÏêüæþ&³~gzTâWQÙsj}€ÉT6ÀüFîpÿ¤ÊŸ({ +<IEND®B`‚ FRAMô¹ ƒÊ IHDRÔ<ßGK7IDATxÚíÝYnÛ0P»èý¯ì"Ò%ˆmRÜfÈ÷¾ G•†ËˆÖBúv6v_pÌG°x ÙÏÕ ôõ üýÍ߿ۊüXÀ ö]@9*t`@Nå –® ¨y~Êe+^JÒaѼlÄt:XÌi<™OÏêóJü=÷•á¸%1¬ˆ¥6ÆHõÔª¥,ê'Bì«Î±Óë?Ã<Ô’ík+îJö¨«ÉµŽ®Ät¯Ø®¤l¥u¸ªžJ»â$ÐËÕê™?Wâ.±b@• Yò¸$žwÇ*•*³?C}Üê­vûˆzÆßk_¥û)ÙnUûÔö£Ç¿²ßÖ>]óÿwÈŸÑzæBËö#c/ÙöÈ<Î> ÖØéD0£ÓŒº {\üÛÎz”{tÝÚ6#½[tâê~V‹Ï4§ ¨»7p†g2ÿz~Y¶x‰)ò3à+±gË‹®ñZzðïžÉFò¸ya"ºLmT¢æy[Ém¶'ÐÚgR3Û¦ôۻ爾”ŽjßvËãßNP¯¼ ùÄðêÿ?Û¾6k“¶5ö«mÔ»}JÖy)B¿Ü)ÎFæñwz¾A{%öÖsËVy¼Ã€Úúí^ð·U'†-cì3¾•ߟ|6²þG½ÜÔãDšUÄ«ÏSò8ÂT¯yüGög¨³euBöaîm„)*ŒýBJ™š—“²ÌGÈ> ¶Úíd ÷Qrç„z¯`{–eD™zì+kWÙá–/pžÑs&èëô+ÔE¸Ý ¼Ör·I/b@ÝÛ¾{°¯Ìì áô[¾-óºv»Ò›sͺ¾™ês·~QRÞË5ÓýÅçG D»8}@-ñÙ¡£ýÀ+±÷šÃ¥ |g2cÞ +Ú'Ó‚«ç³Œýþåßïî¬D›ëÝÕ jI#n÷Ý竬>þÌØK–ÌõqU¦Ð긢¾X´º^¢Åž¹>Þ:a@-µº¡Gül׬}­Œ}w«ûå‡w<²è 3ë^7:奤ÝNà%åÉVælñF,÷©uX"êlOރحN«œ2 ~8º¡±`Á˜r®»Èm“õÊ*r¶Äž¹\MNP?ìÐн¹ŸY'=ãÙ¡-{•gæœYÚgõñ{Æ'“8ñjíÛˆQ= 5.0.19 [IRC/WOL] -- fixed client not getting proper information when account is already in use [VCHECK] -- added STAR/SEXP IX86 1.15.3 vcheck entries [MISC] -- fixed Voiced clients unable to talk in moderated channels -- updated STAR/SEXP IX86 autoupdate entries according to latest client versions -- fixed admins not being able to join private clan channels -- fixed clan leaders not being channel ops in their clan channel ChangeLog for 1.8.3 (since 1.8.2) ========================================= [WOL] -- added Dune 2000 Support -- fixed possible steal account throught hardcoded password -- fixed malformed time format in startgame message -- fixed log warnings/errors rising in login process -- fixed RA2/YURI bug when host of game could not change max players [IRC] -- added some missing channel modes -- added proper messages when client was baned from channel or when channel is full -- fixed bug when IIRC was not stored as last used client tag [MISC] -- fixed malformed output by /cg list command -- updated IX86 autoupdate with latest clients versions [VCHECK] -- added WAR3/W3XP IX86 1.19a/1.19b/1.21b/1.22a vcheck entries -- added STAR/SEXP IX86 1.15.2 vcheck entries -- added D2DV/D2XP IX86 1.12a vcheck entries -- rewritten all STAR/SEXP/W2BN/DRTL IX86 vcheck entries to match new ver-ix86-1.mpq file (this fixes connection problems on Windows Vista systems) ChangeLog for 1.8.2 (since 1.8.1) ========================================= [WOL] -- fixed possible server crash on raw list command [SC/BW] -- fixed client crash when displaying empty friendslist [D2] -- fixed stat string in D2 open mode [VCHECK] -- added SC/BW IX86 and XMAC 1.15.1 version check entries ChangeLog for 1.8.1 (since 1.8.0) ========================================= [WOL] -- fixed bug trying to join unexistent games -- fixed bug overflowing the max players game limit -- fixed bug of not showing Yuri's revenge channels -- added address translation support to servserv sent addresses -- added support for usage of /commands [WAR3] -- fixed possible server crash on ill-formated clan invitation reply packet -- properly display tourney wins/losses in account profile [MISC] -- fixed d2dbs accepting d2gs connections from any ip -- fixed IRC /notice disc bug -- fixed warning and reactivated reconnecting when using mysql>=5.0.13 -- fixed SC:BW string representation from "StarCraft: Broodwars" to "StarCraft: Brood War" (to better match battle.net behaviour) -- fixed possible server crash caused by /ipban command -- enforce (stricter) limit for maximum channel name length -- fixed problems caused by login via uid -- added new "account_force_username" option to bnetd.conf -- fixed malformed tracker packets on 64bit machines [VCHECK] -- added WAR3/W3XP IX86 1.21 vcheck entries -- added sc/bw IX86 and XMAC 1.15 version check entries ChangeLog for 1.8.0 (since 1.8.0rc2) ========================================= [VCHECK] -- added sc/bw 1.13f/1.14 version check entries -- added WAR3/W3XP IX86 1.20d/1.20e vcheck entries [D2] -- cleaned up some mess about dealing with D2 1.08 auth reply packets which we don't need to support according to our minimum D2 version required -- fixed joining of D2 channels by non-D2 clients [WOL] -- fixed a bug where players couldn't join newly created channels [MISC] -- fixed logging of invalid strings for client tags -- fixed /ladderinfo command, fix usage of uninitilized variables -- fixed corruption of account data when using files storage and when there where already broken UID accounts -- fixed the clan max members to be 100 not 255 -- fixed loading of all accounts in sql2 (ex. when doing a ladder rebuild) -- reverted dynamic SQL lib support that was creating problems -- properly fixed "sql" ("sql2" is not affected) friend list bugs (reverted the old fix which was creating new problems); might still be problems if using old versions of sqlite3 (that dont support ` quoting) or using ODBC -- fixed connection loss problems with mysql>=5.0.12 (mysql versions starting with 5.0.3 but lower than 5.0.12 will still have the issue, upgrade mysql!) Changelog for 1.8.0rc2 (since 1.8.0rc1) ========================================= [SQL] -- fixed friendslist-related (my)SQL problems [VERSIONCHECK] -- added W3 1.20c entries [MISC] -- updated bnmaps.conf with the latest Battle.net maps ChangeLog for 1.8.0rc1 (since 1.7.9) ======================================= [SQL] -- inserted additional indices for BNET table in sql2 layout -- added runtime loading of shared library files (DLLs) [SC/BW/W2BNE] -- fixed problem with parsing gameresults with unexpected order of players [WAR3] -- fixed "clan membership lost after invitation" bug. [IRC] -- fixed PING problem occouring after about 25 days uptime [VERSIONCHECK] -- added SC/BW 1.13e entries (XMAC & PMAC) -- added D2/D2XP 1.11b entries -- added W3 1.20b entries [MISC] -- enforce limit for topic message max length ChangeLog for 1.7.9 (since 1.7.8) ======================================= [D2CS/D2DBS] -- added pid files to the confs -- fixed a bug where server could not be (un)installed as a win32 service -- added check and modified the default motd to not have a too big motd that was crashing the clients just after character selection [VERSIONCHECK] -- added SC/BW 1.13c entries -- added SC/BW 1.13d entries -- added SC/BW 1.13e entries -- added W3 1.20a entries [SQL] -- reorganized optimized and made more safe the existent codes -- added a new sql layout called "sql2" in config [MISC] -- fixed security issue where an op of a channel was able to set the topic of any other channel -- added more information to "/finger" display (if issued by an admin) -- added a new command, "/tos" to display the Terms Of Service on request ChangeLog for 1.7.8 (since 1.7.7) ======================================= [D2CS/D2DBS] -- usage of the new conf API [SQL] -- fixed a bug where case sensitive string lookup SQL backends whould not see old accounts when searched with different case; this is a major problem and if you are running any non-MySQL SQL backend you MUST upgrade; make sure you read UPDATE too as it contains very important information for this bugfix [WOL] -- initial support (HURRAY!!); almost complete Tiberian Sun (TA) support, basic Red Alert 2 (RA2) and Yuri's Revenge (YR) support [DRTL] -- fixed problem with joining games of level 50 characters [BNPCAP] -- 64 bit arch compatibility changes [BNCHAT] -- added --arch parameter to specify architecture -- added --lang parameter to specify "gamelang" field of COUNTRYINFO packet [MISC] -- changed that if "servaddrs" option in bnetd.conf is commented server should not listen on bnet addresses (now that we have WOL b.net is not a priority anymore) -- optimized some "compat" codes -- updated more places where people get directed to IRC with the other support channels (should reduce the "n00b" infestation that PvPGN IRC suffers of) -- added versioncheck for D2 LOD 1.11 and D2 classic 1.11 -- updated versioncheck with latest client versions (War3 1.18a, SC/BW 1.13 and 1.13b) -- updated bnmaps.conf with latest maps used on b.net ChangeLog for 1.7.7 (since 1.7.6) =================================== [STORAGE] -- fixed account corruption bug happening when trying to register new accounts with existent accounts usernames and using plain/cdb file storage Changelog for 1.7.6 (since 1.7.5) =================================== [MISC] -- renamed old config variable 'servername' to 'hostname' in bnetd.conf -- added 'servername' config variable in bnetd.conf for server identification -- expanded bnmotd.conf to use 'servername' -- made the hardcoded WAR3 motd use 'servername' -- fixed friends join/leave whispers to come from 'servername' -- fixed bug where d2cs was not able to set realmname even when 'allow_d2cs_setname' was set to 'true' in bnetd.conf [STORAGE] -- updated sql_DB_layout.conf and the code handling it -- SQL storage types now use a unique index for 'acct_username' (speedup) -- added sqlite3 storage support -- added ODBC storage support [DRTL] -- fixed handling of gametypes (character levels) Changelog for 1.7.5 (since 1.7.4) =================================== [BNCHAT] -- fixed win32 specific problem (can't read while writing) [D2CS] -- reduce enforced maxchar value down to 18 (fixing possible problems when having many chars with long charnames) [WAR3] -- wins required for specific chat icons now also configurable via anongame_infos.conf (previously only affected profile icons) -- discard games with no winners at all [SC/BW/W2BNE] -- fixed parsing of ladder_games option in bnetd.conf Changelog for 1.7.4 (since 1.7.3) =================================== [SC/BW/W2BNE] -- write a message to creators/joiners of ladder games of alternative types (those specified with "ladder_games" in bnetd.conf) -- adder "ladder_prefix" to allow only matching game names to be counted as ladder games for the alternative ladder game types -- fixed ELO calculation for top-vs-bottom team ladder games [D2DBS] -- changed codes to use the common network API for send/recv on sockets and error checking thus hopefully fixing bugs of not ignoring properly some errors [BNETD] -- made difficulty of a closed D2 game known to bnetd -- various clan related bugfixes -- enforced max password length (was creating problems in some cases with very long passwords) [MISC] -- lots of optimizations (lowers CPU footprint) -- improved win32 winsock error reporting -- fixed many clan code related crashes -- optimized plain file account loading Changelog for 1.7.3 (since 1.7.2) =================================== [D2CS/D2DBS] -- fixed problem with d2cs and d2dbs not exiting when exit signal is received and exit_time has expired [FDWATCH] -- fixed a bug which created problems with some backends because of reused sockets not being cleaned properly [STAR/SEXP/W2BN] -- fixed problem with topvbot "team game"-results being discarded -- fixed possible overflow with malformed gamereport packets [D2DV/D2XP] -- added workarround for D2 classic client side bug (open bnet games being listed as closed bnet games) [MISC] -- made topics.conf being reloaded on SIGHUP -- made '/games all' display clienttag of a game -- fixed problem with language specific channels with limited user count Changelog for 1.7.2 (since 1.7.1) =================================== [WIN32 GUI] -- fixed problem with running d2cs & d2dbs as services (gui versions) [D2CS] -- The backup copy of the charsave file and charinfo file are now deleted when client deletes one of thier charactars [MISC] -- fixed problem with language specific channels -- added UNIX build configure options to disable bnetd/d2cs/d2dbs builds -- added "sync_on_logoff" bnetd.conf directive to enable saving of account data on user's logoff -- fixed crash with short/broken cdb user files -- fixed trying to load invalid usernames (like "") ChangeLog for 1.7.1 (since 1.7.0) =================================== [FDWATCH] -- redesigned and rewritten most of the fdwatch codes (the new codes are now called fdwatch2) to better support OS which have sparse values for sockets (ex. this should help busy WIN32 systems) [STAR/SEXP/W2BN] -- fixed problem with topvbot game-results being discarded [DEV-C++] -- fixed compilation problems [D2XP/D2DV] -- added "Diablo II Level 100 Workaround" for mods with a max level greater than 99. Option in d2dbs.conf to activate. ChangeLog for 1.7.0 (since 1.6.2) =================================== [D2CS] -- made ordering of chars on char-selection screen configurable -- fixed "d2cs not trying to reconnect" issue -- made sure maxchar limit for an account is enforced -- added WIN32 GUI feature [D2DBS] -- fixed "deleted a ladder char and created one with the same name breaks the ladder" problem. If your ladder is broken, delete it. If your players want their chars to stay in ladder they shouldn't delete them cause new chars with same name will remove the old entry -- added WIN32 GUI feature [STAR/SEXP/W2BN]: -- changed handling of gameresults to be democratic -- fixed problem with win/games ladder [STAR/SEXP] : fixed "v1.11 can't play ladder games"-problem [IRC]: major cleanup of handle_irc.c -- hiding IP on channel join/leave to non admins when hide_addr=true -- now on IRC channel topics are supported (at least their output) -- PvPGN can only handle being in one channel at once, so the server now makes sure you leave the channel you were previously in. -- added /NOTICE, /ISON and /WHOIS handling -- now the real MOTD displays when connecting via IRC -- allow changing /nick before login -- allow another try on a wrong /msg nickserv identify -- added passfail count to IRC connections to prevent bruteforce logins [D2] -- added the option to supply norm, night, hell to /games d2xp command for finding a game of a specific difficulty. [WAR3]: -- droped <1.13 support, added 1.15 support (CG,PG,AT, clan profile view) -- added code to detect the right w3routeip if is set to 0.0.0.0 -- redone major parts of the AT code (old AT teams will be lost) [LADDERS]: -- added .dat/.xml ladder output for STAR/SEXP/W2BN rating based ladder -- moved textual ladder files from ladderdir to statusdir [PREFS] -- fixed handling of comments (previously it skipped the whole line no matter where '#' was) [FDWATCH] -- removed useless template usage because events field is r/o for pollfd structs [MISC]: -- updated autoupdate with latest clients versions -- fixed "message_cache_lookup: unsupported connection class" errors when broadcasting message (ex /ann) and having any connection different than irc/telnet/bot/bnet (ex d2cs etc) -- added client, version and country info to the /finger command -- added clan and clan rank info to the /finger command -- added option to bnmotd.txt to display info about new mail -- adjusted /whois command to be more like on battle.net -- massivly renamed configuration files so each has an extension -- added scripts/pvpgn_hash.inc.php so everyone who needs has a php- implementation of the commonly used passhash algorithm -- fixed problem with topaz-chat (and maybe other clients, too) not propperly displaying tmpOP on initial channel join -- adjusted friends/watch game/server join/leave message to be more like b.net (changed message type from info to whisper) -- fixed channel behaviour to now really allow a common channel for all clients (different shortname, same special name) -- changed all 4 bytes tags (clienttags, archtags, etc) to use internally integers for comparations instead of strings -- changed almost every place where sending username to send the logged in username (if differs in case) than the account username (this fixes some bugs like modifying some account data when logged in with different case and also gets us to closer Battle.net behaivour) -- added /moderate command to moderate/unmoderate a channel pvpgn-1.8.5/TODO0000644000175000017500000000321111151345317012327 0ustar aaronaaronPvPGN TODO LIST AND WHATS BEING WORKED ON: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Release v1.7 ROADMAP: 1. DOCUMENTATION (client and server documentation; a FAQ, HOWTO and a file describing all configuration options) 2. i18n or some sort to support different language messages to users Stuff not programmed for any specific version release: * admin protocol (design an admin protocol and implement the server side and a client lib) * w3route server and serverside game packets * extend/redesign storage to be used by both bnetd and d2cs/d2dbs * complete tournament support with crash recovery option * anonagame stuff a. the new W3 AMM introduced with 1.15 patch c. move w3route functions to its own .c/.h file (for w3route server) e. tournament stuff 1. determine how games are limited to 30 minutes & map reveled at 25 2. complete the process for finals selection 3. make struct to hold / match / advance / eleminate finals players and functions to acomplish this task 4. add stats recording for tournament games (did race wins) * changing data references from accountnames to UIDs .... * design a plugins support and move in time all the code in plugins (except the core code of course) * add gamespy protocol support (gamespy master server does what we do in bnetd keeping user accounts, records, stats, channels, publishing games to requestors) very nice ideea from Mivabe * add some way to be able to read/write specific "runtime changable" bnetd.conf entries (like while server is online doing /config "allow_unknown_version" "false") * optimize PvPGN using "inline" functions in all "small" functions pvpgn-1.8.5/CREDITS0000644000175000017500000002372311151345317012671 0ustar aaronaaronPvPGN CREDITS (also please see the original BNETD credits bellow): -------------------------------------------------------------------- CREDITS This file contains the names of people who have contributed to the development of the PvPGN BNETD mod in some way. This file is not complete and we would like to thank everyone who helped us in any way. PROGRAMMING CONTRIBUTORS AmAdEuS a.k.a. amadeo WIN32GUI-mod, WIN32-Installer, WIN32 services code, initial IRC mods Dizzy Project release engineering, general code maintenance, storage development, fdwatch development, some documentation and lots others. Bryan Biedenkapp (gatekeep@gmail.com) Westwood Online (WOL) support. Lot's of IRC fixes and enhancements. pandaemonium a.k.a. aaron W3 ladders, binary ladders, commands aliases, channel topics, channel tmp ops/voices, anongame infos language support, SQL db creator, bnchat cleanup, WIN32 build files maintenance and lots others. Pelish (pelish@gmail.com) WOL/IRC rework and many bug fixes. Soar Clans, friends codes optimization, D2 stuff, w3 gameinfo etc. TheUndying aka Undy (kainofchaos80@hotmail.com) PvPGN project starter, initial code maintainance and management, initial W3 support codes, etc. Zzzoom (servers@3dgames.com.ar) For persistent SQL connections patch, password brute force attacks protection, various bug reports and very usefull profile dumps. MISC Eggy (eggy@neostats.net) Win32 binary packager, QA testing/reporting, supporter (IRC, forums), misc documentation. U-238 (mark@darkterrorsdomain.cjb.net) Webmaster, Mac binary packager, Mac versioncheck maintainer, PvPGN fink package maintainer, supporter (IRC, forums), tester, documentation writer. David Wilson (dgwilson@paradise.net.nz) Documentation writer, supporter (IRC, forums). Lots of other people who do not wish to be mentioned here. BINARY PACKAGES: - Birzan George Cristian (original Debian packager) - Dorin Lazar (RPMs) - Mihai Maties (RPMs & src.rpm snapshot script) - Radu Radoveneanu (Slackware packages) - Robert Millan (official Debian package maintainer) - Max E. Kuznecov (FreeBSD port entry maintainer) ORIGINAL BNETD CREDITS: ------------------------------- CREDITS This file contains the names of people who have contributed to the development of the BNETD server in some way. This project has made an enormous amount of progress since the development has become public, and this is one place where members of the community can be thanked. PROGRAMMING CONTRIBUTORS The following people have contributed code, code ideas, bug fixes, and debugging work: Mark Baysinger (mbaysing@ucsd.edu) For the original idea, original implementation, documentation of the protocol, starhack.ml.org, the tracking server, etc. Ross Combs (rocombs@cs.nmsu.edu) Various cleanups, release coordination, / commands, config files, etc. Rob Crittenden (rcrit@greyoak.com) For many bug fixes, protocol work, file downloads, man pages, user icons, better channel handling, autoconf, ladder, etc. as well as working on the FAQ and user support. Descolada (dyn1-tnt9-237.chicago.il.ameritech.net) For the hashing algorithm complete with a sample C implementation. Gediminas (gediminas_lt@mailexcite.com) For work on the client command "readline" code, the initial help system, and a better /conn command. Oleg Drokin (green@ccssu.crimea.ua) For patches to fix bnchat and bnstat. Damien Clermonte (clermond@esiee.fr) For portability (to cygnus B20.1 on win32) work, testing, and helpful observations, and the TCP keepalive patch. Denis Moreaux (vapula@endor.be) For working out the correct ladder equations. Philippe Dubois (pdubois@matrox.com) For working on the Win32 port, UDP stuff, auto-update, and the bnettime code. Typhoon [Marco Ziech] (mmz@gmx.net) For lots of good work on the BNI utilities, BITS (server inter- connectivity) support, and his bnetmasq.sh script. He also answers a lot of user questions and put together most of the web site. Dizzy For help with NAT issues, a much improved help system, channel flooding prevention, new /-commands, a mail system, and more. Razvan Jianu (roger@hell.gameover.ro) For many useful coredumps :) Also for the /addacct command. Qlex (qlex@eoliss.com) For kick starting the Diablo II stuff, testing thousands quick changes, moral support, and digging up all the information. Kenshin (kenshin_@hotmail.com) For helping Qlex with the character stuff, fixing some major bugs in the Diablo II code, and starting work on saving characters. Hakan Tandogan (hakan@gurkensalat.com) For always making RPMs for bnetd and the tracker and some patches to correct startup/shutdown issues. Also for continuing Diablo II work. Jung-woo Sohn (logout@aeroguy.snu.ac.kr) For /watch feedback, dobae flooding disconnect, better disconnect game result handling, and generally for lots of good ideas. And also for spotting the failed account creation crashing bug. YobGuls (yobguls@yobguls.2ndmail.com) Actually contributed to the DSBot code, but see next entry. Eurijk! (wc2@zefga.net) For pointing out how the new cdkey hashing works and also how version checking is performed. This was some really ugly but important stuff! He figured this out working on DSBot but kindly explained it to us and showed us example code. He's also working on the Prolix bot project and has provided lots of useful bug reports and other commentary. Fred Wittekind (rom@twister.dyndns.org) For autoupdate version range support. For pointing out all the update MPQ files we didn't know about. Also for the message force-command patch. Mathieu Legare (Mathieu_Legare@uqtr.uquebec.ca) For picking up bnetdStats and making it report all kinds of statistics. Onlyer (onlyer@users.sourceforge.net) For new commands, Diablo II protocol work, Diablo II closed server work, FSGS account conversion, etc. faster (lqx@cic.tsinghua.edu.cn) For Diablo II closed communication (S2S) and for finding that check_alloc bug. sousou (liupeng.cs@263.net) For Diablo II closed database server and ladder. esper (esperpale@263.net) Diablo II closed server gui and ladder. sherpya (sherpya@netfarm.it) For lots of help with adbanners, the d2close merge, reporting bugs (like the 100% poll() CPU usage bug), and lots of good suggestions. Also for work on channel list reloads. Yoss (bartek@milc.com.pl) For helpful suggestions for the mail code and for patching the emote flooding hole. Also for the /admin command and for the patch to fix the "operator can ban admins" bug. A big thanks for much improved kill and ban commands and the new dynamic ipban with better address matching and timeouts. Roland Stahn (blue@cs.tu-berlin.de) For all the work tracking down the versioncheck information for revision of the STAR and SEXP clients. For information about Blizzard's numbering scheme. For helpful packet information. Also for the bug reports and simple patches which probably should have been fixed a long time ago but he was the only person with enough patience to figure out what was happening. Specifically, the "all countries in one channel" feature, the empty game pass bug, the multiple game with same name bug, and the memory corruption after autoupdates. For updated version information. For diagnosing the autoupdate crash (bug in server.c handling closed sockets). KWS (vizi@csucs.net) For the nice bug reports on gameinfo parsing on game join, win32 socket and file portability problems. Also for patches to update versioncheck info, implement IP storage, the patch for better eventlogs, and Makefile improvements. Jack (jack@takeovertheworld.org) For Diablo II open game difficulty patch. forester (laterk@inbox.lv) Working on the Win32 port, bnetd GUI for Win32, small patches. TESTING AND DEBUGGING CONTRIBUTORS The following people have sent in ideas, bug reports, and minor patches. 187 (187@infoceptor.com) For bug reports and the idea for the /news command. Shin DongJun (djshin@oslab.snu.ac.kr) For some bug reports and patches. Jeffery Jones (jeffery_jones@mtlusa.com) For the game address translation idea. Maxim Tereshenkov (max@ostin.ru) For the stack trace which found the 8-bit account.c bug. Yanoch (yanoch@loginnovation.com) For suggesting the /kill improvement. stacker (stacker@mail.ee.ntou.edu.tw) For lots of bug reports and also the sbnetd front end. Mike Hindman (mhindman@bnetd.nmsu.edu) David Fitzpatrick (dfitzpat@bnetd.nmsu.edu) For lots of ideas and all the help with Diablo. Homer (homer@ogn.de) For the helpful info on game info strings and ladder maps. Alvin Sim (elflord@faerie.cx) For lots of testing and figuring out that Diablo II open gameplay was actually not too hard to implement. AsmodeusB For finding annoying the gameinfo bug in connection.c :) forester (http://forester.yo.lv) For pointing out what gameresult 5 means. jerome (imeepmeep@mac.com) For the MacOS X package. acbcdde (acbcdde@hotmail.com) For Win32 Makefile and config.h fixes. mojohead ( Andrey Ilyin ) For d2dbs/d2ladder.c fixes. OTHER CONTRIBUTORS The following people have contributed their time, talent, and other resources to the project: Josh (josh@bnetd.org) For a wonderful web site, quick mirroring of new releases, testing, organization, documentation, and user support. Tim Jung (tjung@igateway.net) For kindly hosting our mailing lists, domain, web pages, etc. as well as regular feedback and testing. Allan Clark (allanc@sco.com) For putting together some nice RPMs. NOTE This list is not complete. I have lost track of the names of some people who have contributed, and likely forgotten about others. If you think you should be listed here but aren't, please contact the bnetd-dev mailing list and we will take care of it right away. pvpgn-1.8.5/sbin/0000755000175000017500000000000011151345372012576 5ustar aaronaaronpvpgn-1.8.5/conf/0000755000175000017500000000000011151345372012570 5ustar aaronaaronpvpgn-1.8.5/conf/bnmotd.txt0000644000175000017500000000050711151345317014615 0ustar aaronaaron%IHello %l, welcome to %s! %IRunning version %v on %h. %IThis server is hosted by %H %I %IThere are %a user accounts on this server. %IThere are currently %U users in %G games of %N, %Iand %u users playing %g games and chatting in %c channels. %IHaving trouble with a command? Type /help to %Ilearn more about it. %I %I%m pvpgn-1.8.5/conf/autoupdate.conf0000644000175000017500000004527411151345317015625 0ustar aaronaaron############################################################################## # autoupdate.conf - Auto Update Configuration # #----------------------------------------------------------------------------# # # # This is a list of client tags and their equivalent autoupdate files and # # version information. # # # # This file will be ignored for certain clients if skip_versioncheck is # # enabled in the bnetd.conf file. # # # # Only the first matching line is used. If no lines match then no upgrade # # will be attempted and the client will remain at its current version. # # # # Note: if you want to use the autoupdate wildcard entries, you'll also need # # to uncomment the corresponding wildcard entries in versioncheck.conf. # # # # Do not include "/" in any of the filenames. # # # # The versiontag is used to identify a particular version as specified in # # the versioncheck configuration file. # # # # It works like this: versioncheck identifies a version by reported version # # number, checksum, clienttag, etc. The autoupdate then uses the arch tag, # # client tag and version tag to find the needed update file. # # # # War3 and War3x clients have different mpq files for the different game # # languages. This is accounted for by the server, and the client will get # # the correct file. Only one entry is needed per arch, client, and version # # tag. # # # # Example: With the following line: # # # # IX86 W3XP W3XP_107A W3XP_IX86_1xx_111A.mpq # # # # war3x english clients will receive the file "W3XP_IX86_1xx_111A_enUS.mpq" # # where russian clients will receive the file "W3XP_IX86_1xx_111A_ruRU.mpq" # # and german clients will receive the file "W3XP_IX86_1xx_111A_deDE.mpq" # # Make sure all the required mpq files are in the files directory or # # autoupdate will not work. # # # # The avaliable language files are: # # # # enUS csCZ deDE esES frFR itIT jaJA koKR plPL ruRU zhCN zhTW # # # # The format of this file is as follows: # # # # archtag clienttag versiontag -----update file----- # # # ############################################################################## ##### Intel (IX86) ########################################################### # =============== WarCraft III - FT (Expansion) =============== #IX86 W3XP W3XP_107A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_110A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_111A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_112A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_113A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_113B W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_114A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_114B W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_115A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_116A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_117A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_118A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_119A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_119B W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_120A W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_120B W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_120C W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_120D W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_120E W3XP_IX86_1xx_122a_2.mpq #IX86 W3XP W3XP_121A W3XP_IX86_1xx_122a_2.mpq # Incremental update from version 1.21b #IX86 W3XP W3XP_121B W3XP_IX86_121B_122a_2.mpq # The next one is a WarCraft III - FT wildcard entry. #IX86 W3XP W3XP_1xx W3XP_IX86_1xx_122a_2.mpq # ==================== WarCraft III - RoC ===================== #IX86 WAR3 WAR3_107A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_110A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_111A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_112A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_113A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_113B WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_114A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_114B WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_115A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_116A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_117A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_118A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_119A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_119B WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_120A WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_120B WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_120C WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_120D WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_120E WAR3_IX86_1xx_122a_2.mpq #IX86 WAR3 WAR3_121A WAR3_IX86_1xx_122a_2.mpq # Incremental update from version 1.21b #IX86 WAR3 WAR3_121B WAR3_IX86_121B_122a_2.mpq # The next one is a WarCraft III - RoC wildcard entry. #IX86 WAR3 WAR3_1xx WAR3_IX86_1xx_122a_2.mpq # ===================== Diablo II Expansion (LoD) =========================== # Note: the following assumes that you want to upgrade all Diablo II clients # to version 1.11b. If you are still running a 1.10 or 1.09d realm, you # will need to modify these entries accordingly. #IX86 D2XP D2XP_107 D2XP_IX86_1xx_112A.mpq #IX86 D2XP D2XP_108 D2XP_IX86_1xx_112A.mpq #IX86 D2XP D2XP_109 D2XP_IX86_1xx_112A.mpq #IX86 D2XP D2XP_109B D2XP_IX86_1xx_112A.mpq #IX86 D2XP D2XP_109C D2XP_IX86_1xx_112A.mpq #IX86 D2XP D2XP_109D D2XP_IX86_1xx_112A.mpq #IX86 D2XP D2XP_110 D2XP_IX86_1xx_112A.mpq #IX86 D2XP D2XP_111 D2XP_IX86_1xx_112A.mpq # Incremental update from version 1.11a --> 1.11b #IX86 D2XP D2XP_111B D2XP_IX86_111B_112A.mpq # The next one is a Diablo II LoD wildcard entry. #IX86 D2XP D2XP_1xx D2XP_IX86_1xx_112A.mpq # ========================== Diablo II (DV) ================================= # Note: the following assumes that you want to upgrade all Diablo II clients # to version 1.11b. If you are still running a 1.10 or 1.09d realm, you # will need to modify these entries accordingly. #IX86 D2DV D2DV_100 D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_101 D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_103 D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_104B D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_104C D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_105 D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_105B D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_106 D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_106B D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_108 D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_109 D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_109B D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_109C D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_109D D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_110 D2DV_IX86_1xx_112A.mpq #IX86 D2DV D2DV_111 D2DV_IX86_1xx_112A.mpq # Incremental update from version 1.11a --> 1.11b #IX86 D2DV D2DV_111B D2DV_IX86_111B_112A.mpq # The next one is a Diablo II wildcard entry. #IX86 D2DV D2DV_1xx D2DV_IX86_1xx_112A.mpq # ================ StarCraft Expansion (Brood War) ========================== #IX86 SEXP SEXP_104 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_104_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_105 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_105_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_106 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_106_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_107 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_107_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_108 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_108_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_108B SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_108B_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_109 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_109_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_110 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_110_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_111 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_111_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_111B SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_111B_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_112 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_112_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_112B SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_112B_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_113 SEXP_IX86_1xx_1161.mpq # unfortunately we don't have a SEXP_113_STAR in versioncheck.conf #IX86 SEXP SEXP_113B SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_113B_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_113C SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_113C_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_113D SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_113D_STAR SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_113E SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_113E SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_114 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_114 SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_115 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_115 SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_1151 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_1151 SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_1152 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_1152 SEXP_IX86_1xx_1161.mpq #IX86 SEXP SEXP_1153 SEXP_IX86_1xx_1161.mpq #IX86 STAR SEXP_1153 SEXP_IX86_1xx_1161.mpq # Incremental update from version 1.15.3 #IX86 SEXP SEXP_116 SEXP_IX86_116_1161.mpq #IX86 STAR SEXP_116 SEXP_IX86_116_1161.mpq # The next one is a Brood War wildcard entry. #IX86 SEXP SEXP_1xx SEXP_IX86_1xx_1161.mpq # ========================= StarCraft (original) ============================ #IX86 STAR STAR_100 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_101 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_102 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_103 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_104 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_105 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_106 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_107 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_108 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_108B STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_109 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_109B STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_110 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_111 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_111B STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_112 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_112B STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_113 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_113B STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_113C STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_113D STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_113E STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_114 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_115 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_1151 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_1152 STAR_IX86_1xx_1161.mpq #IX86 STAR STAR_1153 SEXP_IX86_1xx_1161.mpq # Incremental update from version 1.15.3 #IX86 STAR STAR_116 SEXP_IX86_116_1161.mpq # The next one is a Starcraft wildcard entry. #IX86 STAR STAR_1xx STAR_IX86_1xx_1161.mpq # Incremental update from version 1.15.3 #IX86 STAR STAR_1153 SEXP_IX86_1153_116.mpq # The next one is a Starcraft wildcard entry. #IX86 STAR STAR_1xx STAR_IX86_1xx_116.mpq # ========================= Diablo (original) ============================== # note: Blizzard doesn't update client from 109 to 109b. #IX86 DRTL DRTL_108 DRTL_IX86_108_109.mpq # The next one is a Diablo wildcard entry. #IX86 DRTL DRTL_1xx DRTL_IX86_100_109.mpq # ========================= Warcraft II BNE =============================== #IX86 W2BN W2BN_200 W2BN_IX86_200_202.mpq #IX86 W2BN W2BN_201 W2BN_IX86_201_202.mpq ##### Mac OS X (XMAC) ######################################################## # ===================== Diablo II Expansion (LoD) =========================== # Note: the following assumes that you want to upgrade all Diablo II clients # to version 1.11b. If you are still running a 1.10 or 1.09d realm, you # will need to modify these entries accordingly. #XMAC D2XP D2XP_109D D2XP_XMAC_1xx_111B.mpq #XMAC D2XP D2XP_110 D2XP_XMAC_1xx_111B.mpq # Incremental update from version 1.11a --> 1.11b #XMAC D2XP D2XP_111 D2XP_XMAC_111A_111B.mpq # The next one is a Diablo II LoD wildcard entry. #XMAC D2XP D2XP_1xx D2XP_XMAC_1xx_111B.mpq # ========================== Diablo II (DV) ================================= # Note: the following assumes that you want to upgrade all Diablo II clients # to version 1.11b. If you are still running a 1.10 or 1.09d realm, you # will need to modify these entries accordingly. #XMAC D2DV D2DV_109D D2DV_XMAC_1xx_111B.mpq #XMAC D2DV D2DV_110 D2DV_XMAC_1xx_111B.mpq # Incremental update from version 1.11a --> 1.11b #XMAC D2DV D2DV_111 D2DV_XMAC_111A_111B.mpq # The next one is a Diablo II LoD wildcard entry. #XMAC D2DV D2DV_1xx D2DV_XMAC_1xx_111B.mpq # ================ StarCraft Expansion (Brood War) ========================== #XMAC SEXP SEXP_109B SEXP_XMAC_1xx_113E.mpq #XMAC SEXP SEXP_110 SEXP_XMAC_1xx_113E.mpq #XMAC STAR SEXP_110_STAR SEXP_XMAC_1xx_113E.mpq #XMAC SEXP SEXP_111 SEXP_XMAC_1xx_113E.mpq #XMAC STAR SEXP_111_STAR SEXP_XMAC_1xx_113E.mpq #XMAC SEXP SEXP_111B SEXP_XMAC_1xx_113E.mpq #XMAC STAR SEXP_111B_STAR SEXP_XMAC_1xx_113E.mpq #XMAC SEXP SEXP_112 SEXP_XMAC_1xx_113E.mpq #XMAC STAR SEXP_112_STAR SEXP_XMAC_1xx_113E.mpq #XMAC SEXP SEXP_113 SEXP_XMAC_1xx_113E.mpq #XMAC STAR SEXP_113_STAR SEXP_XMAC_1xx_113E.mpq #XMAC SEXP SEXP_113C SEXP_XMAC_1xx_113E.mpq #XMAC STAR SEXP_113C_STAR SEXP_XMAC_1xx_113E.mpq # Unfortunately versioncheck.conf does not contain entries for 1.13{a|b|d} # The next one is a Brood War wildcard entry. #XMAC SEXP SEXP_1xx SEXP_XMAC_1xx_113E.mpq # ========================= StarCraft (original) ============================ #XMAC STAR STAR_109B STAR_XMAC_1xx_113E.mpq #XMAC STAR STAR_110 STAR_XMAC_1xx_113E.mpq #XMAC STAR STAR_111 STAR_XMAC_1xx_113E.mpq #XMAC STAR STAR_111B STAR_XMAC_1xx_113E.mpq #XMAC STAR STAR_112 STAR_XMAC_1xx_113E.mpq # Unfortunately versioncheck.conf does not contain entries for 1.13{a-d} # The next one is a Starcraft wildcard entry. #XMAC STAR STAR_1xx STAR_XMAC_1xx_113E.mpq ##### Mac OS Classic (PMAC) ################################################## # ===================== Diablo II Expansion (LoD) =========================== # Note: the following assumes that you want to upgrade all Diablo II clients # to version 1.11b. If you are still running a 1.10 or 1.09d realm, you # will need to modify these entries accordingly. #PMAC D2XP D2XP_1xx D2XP_PMAC_1xx_111B.mpq # ========================== Diablo II (DV) ================================= # Note: the following assumes that you want to upgrade all Diablo II clients # to version 1.11b. If you are still running a 1.10 or 1.09d realm, you # will need to modify these entries accordingly. #PMAC D2DV D2DV_109D D2DV_PMAC_1xx_111B.mpq #PMAC D2DV D2DV_1xx D2DV_PMAC_1xx_111B.mpq # ================ StarCraft Expansion (Brood War) ========================== #PMAC SEXP SEXP_109B SEXP_PMAC_1xx_113E.mpq #PMAC SEXP SEXP_110 SEXP_PMAC_1xx_113E.mpq #PMAC STAR SEXP_110_STAR SEXP_PMAC_1xx_113E.mpq #PMAC SEXP SEXP_111 SEXP_PMAC_1xx_113E.mpq #PMAC STAR SEXP_111_STAR SEXP_PMAC_1xx_113E.mpq #PMAC SEXP SEXP_111B SEXP_PMAC_1xx_113E.mpq #PMAC STAR SEXP_111B_STAR SEXP_PMAC_1xx_113E.mpq #PMAC SEXP SEXP_112 SEXP_PMAC_1xx_113E.mpq #PMAC STAR SEXP_112_STAR SEXP_PMAC_1xx_113E.mpq # The next one is a Brood War wildcard entry. #PMAC SEXP SEXP_1xx SEXP_PMAC_1xx_113E.mpq # ========================= StarCraft (original) ============================ #PMAC STAR STAR_109B STAR_PMAC_1xx_113E.mpq #PMAC STAR STAR_110 STAR_PMAC_1xx_113E.mpq #PMAC STAR STAR_111 STAR_PMAC_1xx_113E.mpq #PMAC STAR STAR_111B STAR_PMAC_1xx_113E.mpq #PMAC STAR STAR_112 STAR_PMAC_1xx_113E.mpq # The next one is a Brood War wildcard entry. #PMAC STAR STAR_1xx STAR_PMAC_1xx_113E.mpq pvpgn-1.8.5/conf/d2cs.conf.win320000644000175000017500000001747111151345317015244 0ustar aaronaaron################################################################################# # d2cs.conf - Configuration file for the diablo2 game control server # #-------------------------------------------------------------------------------# # # # This file is an example configuration and may require modification to # # suit your needs or your site. Blank lines and lines starting with a "#" # # are ignored. Use quotes around values that contain spaces. # # # ################################################################################# ################################################################################# # Server Major Settings # #-------------------------------------------------------------------------------# # # # Your realm server name # # Here you put the value of the first column from the realm line in realm.conf # Example, if you have the line # "MyRealm" "My Super Realm" :6113 # in realm.conf then here you put realmname = "MyRealm" realmname = D2CS # This is a comma delimited list of hostnames that the server should # listen on. Generally, YOU DONT NEED TO TOUCH THIS but it might be useful # to make an internal-only server on a gateway machine for example. If the # list is not set or if it has a entry with no host component, the server will # bind to that port on all interfaces. # d2cs default listening port is 6113 # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! servaddrs = 0.0.0.0:6113 # This is a comma delimited list of game servers. Put here the IPs # (without ports) of the machines running d2gs. If you run d2gs on the same # machine as d2cs you put the IP of that machine here. # Example: gameservlist = 192.168.1.10 # (if you have a d2gs running on a machine with the IP 192.168.1.10) # # YOU MUST CHANGE THIS OR D2CS WON'T WORK PROPERLY # # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! gameservlist = , # Put here the address and port of the machine running bnetd (or pvpgn.exe). # If you run d2cs on the same machine as bnetd (or pvpgn.exe) then here you # put the IP of that machine. # # YOU MUST CHANGE THIS OR D2CS WON'T WORK PROPERLY # # bnetd default listening port is 6112 # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! bnetdaddr = :6112 # Set this to the maximum number of concurrent connections allowed on # this server. DO NOT TOUCH UNLESS STRICTLY NECESSARY! max_connections = 1000 # This sets the realm to Classic or LOD or Both # Classic = 0 # LOD = 1 # Both = 2 (default) lod_realm = 2 # This sets whether you can convert a clasic char to # an expansion char. # Allow Convert = 1 # Don't allow Convert = 0 allow_convert = 0 # here u can enter the symbols allowed in accountnames (additional to # alphanumerical symbals which are always accepted). please note that # it is absolutly mandatory that u set up the same symbols here as in # bnetd.conf or else u wont be able to play D2 with some characters # (those whose symbols are allowed in bnetd.conf but not here) # same warnings as in bnetd.conf apply here - be warned - and just # change something if you know what you are doing #default setting is "-_[]" account_allowed_symbols = "-_[]" # # ################################################################################# ################################################################################# # Message logs # #-------------------------------------------------------------------------------# # Multiple log levels can be defined by connecting them with a comma (,) # Available loglevels are: # none # trace # debug # info # warn # error # fatal #loglevels = fatal,error,warn,info loglevels = fatal,error,warn,info,debug,trace # # ################################################################################# ################################################################################# # File and Path section # # Use absolute paths in these lines to avoid problems! # #-------------------------------------------------------------------------------# # # logfile = var\d2cs.log charsavedir = var\charsave charinfodir = var\charinfo bak_charsavedir = var\bak\charsave bak_charinfodir = var\bak\charinfo ladderdir = var\ladders newbiefile = files\newbie.save transfile = conf\address_translation.conf d2gsconffile = conf\d2server.ini # # ################################################################################# ################################################################################# # Misc # #-------------------------------------------------------------------------------# # # # Message Of The Day motd = "No Message Of The Day Set" # Set to non-zero to allow creation of new realm character allow_newchar = 1 # Do you want d2cs to check client for multilogin for security reason? check_multilogin = 0 # Maxinum number of character per account # Max allowed value is 18 (enforced by server) maxchar = 8 # Character sorting. Options are: level, mtime, name, none. (none assumed if # not specified). #charlist_sort = "none" # Do we need ascending or descending order for charlist? #charlist_sort_order = "ASC" # Maxinum number of games will be shown in join game list # Zero = infinite maxgamelist = 20 # Set to non-zero to allow show all games with difficulty < character difficulty # Otherwise, only game with difficulty = character difficulty will be shown gamelist_showall = 0 # Maxinum time in seconds that a user can idle # Zero = infinite idletime = 3600 # Amount of time to delay shutting down server in seconds. shutdown_delay = 300 # Amount of time delay period is decremented by either a SIGTERM or SIGINT # (control-c) signal in seconds. shutdown_decr = 60 # ################################################################################# ################################################################################# # Internal System Settings # # You may just ignore them and use the default value # #-------------------------------------------------------------------------------# # # How often will the server purge all list to clean unused data (in seconds) listpurgeinterval = 300 # How often will the server check game queues (in seconds) gqcheckinterval = 60 # How often will the server retry to connect to bnetd # when connection lost (in seconds) s2s_retryinterval = 10 # How long time the s2s connection will timeout s2s_timeout = 10 # How often the server will check server queues for expired data sq_checkinterval = 300 # How long time will a server queue data expire sq_timeout = 300 # Game serer binary files checksum, use zero to skip this checking d2gs_checksum = 0 # Game server version, use zero to skip this checking d2gs_version = 0 # Game server password d2gs_password = "" # Maxinum number of second that a game will be shown on list( zero = infinite ) game_maxlifetime = 0 # A game will be automatically destroied after how long time idle max_game_idletime = 0 # Allow Limitation created game with password, player number or level limit? allow_gamelimit = 1 # Ladder refresh time ladder_refresh_interval = 3600 # server to server connection max idle time in seconds s2s_idletime = 300 # server to server connection keepalive interval s2s_keepalive_interval = 60 # all connection timeout check interval timeout_checkinterval = 60 # game server restart interval # when sending SIGUSR2 signal to your d2cs this issues a restart # of all connected d2gs after d2gs_restart_delay seconds d2gs_restart_delay = 300 # ladder start time # format: yyyy-mm-dd hh:mm:ss # be carefull: # all chars created before this date will revert to non-ladder chars ladder_start_time = "" # number of days before a char expires (default 0=unlimited) char_expire_day = 0 # ################################################################################# pvpgn-1.8.5/conf/bnban.conf0000644000175000017500000000032011151345317014511 0ustar aaronaaron# an example wildcard-match entry #127.*.*.* # an example exact-match entry #127.0.0.1 # an example range-match entry #127.0.0.79-127.0.0.84 # two example network entries #127.0.0.0/8 #127.0.0.0/255.0.0.0 pvpgn-1.8.5/conf/topics.conf0000644000175000017500000000017311151345317014740 0ustar aaronaaron"Chat","This is the public chat channel. Feel free to chat..." "Moderated Support","Support is provided in this channel..."pvpgn-1.8.5/conf/bnhelp.conf0000644000175000017500000001770011151345317014713 0ustar aaronaaron############################################################################## # bnhelp - This Help File is used for describing the commands to the user # #----------------------------------------------------------------------------# # Entries are separated by a percent sign (%) at the beginning of the line. # # The commands that correspond with the entry should follow the % on the # # same line. # # # # You can enter comments by starting a line with #. Comments extend to the # # end of the line. # # # %whois whereis where whois - looks up some basic information on a user, including their account number and their current location %msg whisper m w /msg, /whisper, /m, /w - sends a private message to a user online regardless of the channel they are in %ignore squelch /ignore, /squelch - ignores any future messages from that user effectively muting that user to you %unignore unsquelch /unignore /unsquelch - unignores a user so u can listen to him again %away /away [] - displays a message that you are away from your keyboard whenever someone whispers to you or does a /whois command on you %dnd /dnd [] - prevents ALL whispers from displaying to your screen %who /who - displays a list of all users in the given channel %stats astat /stats /astat [] [] - displays a player's game record %status users /status, /users - displays the number of users currently on this server %time /time - displays the current server time %channel join /channel /join - switches to a channel without having to use the channel join screen %rejoin /rejoin - join the channel you are already in %me /me - displays emotion text, as in 'tN is rolling on the floor laughing' %kick /kick - kicks a user out of the channel %ban /ban - kicks a user out of the channel and prevents them from returning until the current operator steps down or leaves the channel %unban /unban - allows a banned user to return to the channel %whoami /whoami - looks up some basic information on yourself, including your account number and your current location %uptime /uptime - show the amount of time the server has been running %beep /beep - enable audible notifications %nobeep /nobeep - disable audible notifications %version /version - shows the version of the server %lusers /lusers - shows list of banned players in this channel %games /games [] - displays current game list %channels chs /channels /chs [all] - displays current channel list %connections con /connections /con - displays current connections %finger /finger [] - displays information about player %admins /admins - shows all currently logged in administrators %reply r /reply /r - reply to the last person that whispered to you %announce ann /announce /ann - announces a message in all channels %realmann /realmann - makes an announcement in the real u are currenlty in %copyright warranty license /copyright /warranty /license - shows the legal information for bnetd %news /news - show some system-specific news %logout quit exit /logout /quit /exit - closes your connection to the server %kill /kill [] [min] - close a player's connection to the server and ban players IP for min minutes %killsession /killsession [] [min] - close a connection to the server and ban sesion's IP for min minutes %watch /watch - sends notification when a player logs out or joins a game %unwatch /unwatch - stops sending notification about a player %watchall /watchall - sends notification when any player logs in or out %unwatchall /unwatchall - stops sending notification about all players %gameinfo /gameinfo [] - prints information about a game %ladderactivate /ladderactivate - copy current ladder stats to active ladder stats %ladderinfo /ladderinfo [] - display ladder info for given rank %timer /timer [] [] - send notification after a period of time %netinfo /netinfo [] - display a player's IP and port information %addacct /addacct - create a new player account %chpass /chpass [] - change a player's password %quota /quota - displays the channel quota %shutdown /shutdown [] - starts the shutdown sequence or cancels if duration is zero %lockacct /lockacct - locks that users account %unlockacct /unlockacct - unlocks that users account %friends f /friends add - add user to your friends list /friends del - remove user from your friends list /friends promote - promote user in your friends list /friends demote - demote user in your friends list /friends list - list all users in your friends list /friends msg - whispers to all your online friends %mail /mail [] - mail management commands Syntax: /mail send /mail read [] /mail delete {all|} %flag /flag - debug tool for icon flags %tag /tag - debug tool for client tags %help /help [] - does this %ipban /ipban [] [option] [time] - ban management commands Syntax: /ipban [l[ist]] - shows banned IPs /ipban c[heck] - check is IP banned /ipban d[el] - deletes ban for IP, or rule number index /ipban a[dd] [time] - ban specified IP for time minutes (time = 0 - permanently ban) /ipban h[elp] - show help screen %set /set [value] - set an attribute in a player profile - if no value given returns current value key is like BNET\acct\lastlogin_owner %motd /motd - display the motd %tos /tos - shows terms of service once more %admin /admin - +username to make user a admin, or -username to remove admin status of a user %rank_all_accounts /rank_all_accounts - brute force adds all accounts to war3 ladder %rehash /rehash - forces reload of bnetd.conf %clan /clan public (alias: pub) Opens the clan channel up to the public so that anyone may enter /clan private (alias: priv) Closes the clan channel such that only members of the clan may enter /clan motd Update the clan message of the day to MESSAGE %ping p latency /ping, /p, /latency - returns your latency to the server %command_groups cg /command_groups, /cg [] - adds, deletes, or lists command groups for user Syntax: /cg list - shows command groups avialiable to user /cg add - adds group(s) to users command groups /cg del - deletes groups from users command groups /cg help - show help screen %admin /admin + - promote to Server Admin /admin - - demote from Server Admin %operator /operator + - promote to Server Operator /operator - - demote from Server Operator %aop /aop - make user Channel Admin %op /op - make user Channel Operator %deop /deop - take away channel Admin/Operator privileges %tmpop /tmpop - make user a temporary Channel Operator %vop /vop - add user to VOP list %voice /voice - give temporary voice to user %devoice /devoice - remove user from VOP list and take away temporary voice %topic /topic [ [channel name] "topic " ] - used to get/set a channels topic %moderate /moderate - used to get/set channel moderated status %clearstats /clearstats - used to clear game statistics of a given user/clienttag Syntax: /clearstats can be one of DSHR,DRTL,SSHR,STAR,SEXP,W2BNE,WAR3,W3XP,ALL # # ############################################################################## pvpgn-1.8.5/conf/channel.conf0000644000175000017500000001241111151345317015045 0ustar aaronaaron############################################################################## # channel.list - Configuration for permanent channels # #----------------------------------------------------------------------------# # # # These are the channels to create when the server starts up. This file does # # not change the channel that the client requests when it logs in, but it # # can be used to give that channel a different "official" name. # # # # Quotes (") are required around the strings, but they are not allowed # # inside them. An unquoted NULL means there is no entry for that position. # # # # NONE for special name means to use the format "shortname-ctry num realm" # # e.g. "D2CS-Starcraft USA-1" # # NULL for country creates non-country specific channels. # # -1 for max sets no limit to the number of users allowed in the channel # # # # ---special name--- -----short name----- cltag bots- -ops- -log- ctry- realm max -mod-# "The Void" "The Void" NULL true false false NULL NULL -1 true NONE "Starcraft" STAR true false false NULL NULL -1 false NONE "Brood War" SEXP true false false NULL NULL -1 false NONE "Starcraft Shareware" SSHR true false false NULL NULL -1 false NONE "Diablo Retail" DRTL true false false NULL NULL -1 false NONE "War2BNE" W2BN true false false NULL NULL -1 false NONE "Diablo II" D2DV true false false NULL NULL -1 false NONE "Diablo II" D2XP true false false NULL NULL -1 false "Warcraft 3 Frozen Throne" "W3" W3XP true false false NULL NULL -1 false "Warcraft 3" "W3" WAR3 true false false NULL NULL -1 false "Human Castle" "W3" W3XP true false false NULL NULL -1 false "Orc Stronghold" "W3" W3XP true false false NULL NULL -1 false "Undead Necropolis" "W3" W3XP true false false NULL NULL -1 false "Night Elf Tree of Life" "W3" W3XP true false false NULL NULL -1 false "Dragon Roost" "W3" W3XP true false false NULL NULL -1 false "Human Castle" "W3" WAR3 true false false NULL NULL -1 false "Orc Stronghold" "W3" WAR3 true false false NULL NULL -1 false "Undead Necropolis" "W3" WAR3 true false false NULL NULL -1 false "Night Elf Tree of Life" "W3" WAR3 true false false NULL NULL -1 false "Dragon Roost" "W3" WAR3 true false false NULL NULL -1 false "Chat" "Chat" CHAT true false false NULL NULL -1 false "Backstage" "Backstage" NULL true false false NULL NULL 0 false "Moderated Support" "Support" NULL true false false NULL NULL -1 true # # ############################################################################## ############################################################################## # Westwood Online Channels # #----------------------------------------------------------------------------# # Note: The Westwood channels should be formatted like this! Do not set the last number above 5. # The proper game type numbers are as follows: # - 14 = Dune 2000 game channels # - 18 = Tiberian Sun game channels # - 21 = Red alert 1 channels # - 33 = Red alert 2 channels # - 41 = Yuri's Revenge # ##### DUNE 2000 Support ######################################################################################## "Lob 14 0" "Unknown" CHAT false false false NULL NULL -1 false ##### Tiberian Sun Support ##################################################################################### "Lob 18 0" "GDI Barracks" WWOL false false false NULL NULL -1 false "Lob 18 1" "NOD Barracks" WWOL false false false NULL NULL -1 false "Lob 18 2" "GDI Comm. Center" WWOL false false false NULL NULL -1 false ##### Red Alert 2 Support ###################################################################################### "Lob 33 0" "USA Command" CHAT false false false NULL NULL -1 false "Lob 33 1" "Korean Bunker" CHAT false false false NULL NULL -1 false ##### Yuri's Revenge Support ################################################################################### "Lob 41 0" "Unknown" CHAT false false false NULL NULL -1 false "Lob 41 1" "Unknown" CHAT false false false NULL NULL -1 false # # ############################################################################## pvpgn-1.8.5/conf/versioncheck.conf0000644000175000017500000017772611151345317016145 0ustar aaronaaron############################################################################## # versioncheck.conf - Version Check Configuration # #----------------------------------------------------------------------------# # # # This file is used to verify that clients are the same version they claim # # to be and to tag certain versions for autoupgrades (see autoupdate.conf). # # # # Every combination of archtag/clienttag/version/equation/mpqfile needs to # # be listed seperately. Each combination has a unique checksum. # # # # If the exeinfo field is "NULL" then the string comparison will be disabled # # for that entry. If the checksum field is 0 then the checksum verification # # is disabled for that entry. If the versionid is 0 then the verification # # of versionid is disabled for that entry The versiontag is optional. # # It is used to identify a particular version even when the version number # # is identical to another (e.g. 109c and 109d are both version 1.0.9.0). # # These tags can be used in the autoupdate file allowing it to know the # # difference because of the different checksums. # # # # Multiple matching: # # exeinfo = NULL will match all client exeinfos # # exeinfo = "war3.exe ??/??/?? ??:??:?? 1568211" will match war3.exe with # # filesize 1568211 but won't care about the file's date/time # # versionid = 0x0 will match all client versionids # # gameversion = 0.0.0.0 will match all client's versions # # checksum = 0x0 will match all client checksums # # # # Note: if you use multiple equations/mpqfiles be sure to put entries with # # corresponding checksum for each archtag/clienttag # # # # versioncheck entries work like a firewall chains, bnetd will match the # # first entry, then is safe to use entries in descending order, so if we # # found a badversion, it will be tagged with the tag of entry with the lower # # version. Last line can be used to match all version unmatched so far # # # # Do not include "/" in any of the filenames. # # # # The version number can be in two forms. If it does not contain a period # # then 123 is assumed to mean 1.2.3.0. Otherwise it may contain up to three # # periods. If fewer than four parts are present, the latter ones will be # # assumed to be zero. For example, 1.8 would be interpreted as 1.8.0.0. # # Sections will overflow if they are greater than 255. # # # # Typically Blizzard will add a 1 in the fourth position to signify an # # expansion pack and 10 to signify "b" versions. So Brood War 1.08b would # # have a version of 1.0.8.11. # # # # ---------------------------equation--------------------------- \ # # ---mpqfile---- \ # # archtag \ # # clienttag \ # # ----------------exeinfo----------------- \ # # versionid- \ # # --verstr-- \ # # -checksum- \ # # -versiontag- # # # ############################################################################## ##### Intel (IX86) ########################################################### # -=-=-=-=-=-=- Latest Versions -=-=-=-=-=-=- No Update Required -=-=-=-=-=-=- # Warcraft III - TFT (Expansion) 1.22a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 06/27/08 00:01:35 471040" \ 0x00000016 \ 1.22.0.184 \ 0x909998db \ W3XP_122A # Warcraft III - ROC 1.22a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 06/27/08 00:01:35 471040" \ 0x00000016 \ 1.22.0.184 \ 0x909998db \ WAR3_122A # Diablo II - LoD (Expansion) 1.12a "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2XP \ "Game.exe 05/28/08 01:44:02 61440" \ 0x0000000c \ 1.0.12.0 \ 0x3d421510 \ D2XP_112A # Diablo II 1.12a "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2DV \ "Game.exe 07/05/08 17:19:40 57344" \ 0x0000000c \ 1.0.12.0 \ 0x243ac143 \ D2DV_112A # Diablo II - LoD (Expansion) 1.11b "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2XP \ "Game.exe 08/17/05 01:12:38 2129920" \ 0x0000000b \ 1.0.11.0 \ 0xbfc36199 \ D2XP_111B # Diablo II 1.11b "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2DV \ "Game.exe 08/17/05 01:11:43 2125824" \ 0x0000000b \ 1.0.11.0 \ 0x602f8323 \ D2DV_111B # Diablo II - LoD (Expansion) 1.11 "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2XP \ "Game.exe 07/26/05 23:22:13 2129920" \ 0x0000000b \ 1.0.11.0 \ 0xfb0c59b2 \ D2XP_111 # Diablo II 1.11 "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2DV \ "Game.exe 27/06/05 23:21:18 2125824" \ 0x0000000b \ 1.0.11.0 \ 0xbdf86a85 \ D2DV_111 # Diablo II - LoD (Expansion) 1.10 "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2XP \ "Game.exe 10/13/03 08:35:30 1198857" \ 0x0000000a \ 1.0.10.0 \ 0x210126ec \ D2XP_110 # Diablo II 1.10 "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2DV \ "Game.exe 10/13/03 08:34:46 1194761" \ 0x0000000a \ 1.0.10.0 \ 0x3132dda6 \ D2DV_110 # Diablo II - LoD (Expansion) 1.09d "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2XP \ "Game.exe 11/30/01 04:00:17 448675" \ 9 \ 1.0.9.0 \ 0xfa39efbb \ D2XP_109D # Diablo II 1.09d "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ D2DV \ "Game.exe 11/30/01 03:59:45 444579" \ 9 \ 1.0.9.0 \ 0x41e223a3 \ D2DV_109D # Starcraft - Broodwar (Expansion) 1.16.1 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "StarCraft.exe 01/09/09 22:57:43 1220608" \ 0x000000d3 \ 1.16.1.1 \ 0x0a85372d \ SEXP_1161 # Starcraft - Broodwar (Expansion) 1.16.1 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "StarCraft.exe 01/09/09 22:57:43 1220608" \ 0x000000d3 \ 1.16.1.1 \ 0x0a85372d \ STAR_1161 # Starcraft (Standalone) 1.16.1 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "StarCraft.exe 01/08/09 05:23:44 1220608" \ 0x000000d3 \ 1.16.1.0 \ 0x02623d85 \ STAR_1161 ##### Mac OS X (XMAC) ######################################################## # -=-=-=-=-=-=- Latest Versions -=-=-=-=-=-=- No Update Required -=-=-=-=-=-=- # Diablo II LOD v1.11b MacOS X "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ "XMACver1.mpq" \ XMAC \ D2XP \ "Diablo II (Carbon) 08/16/105 17:00:00 5877766" \ 0x0000000b \ 5.0.1.70 \ 0xeb219644 \ D2XP_111B # Diablo II LOD v1.11 MacOS X "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ "XMACver1.mpq" \ XMAC \ D2XP \ "Diablo II (Carbon) 07/26/105 16:00:00 5877574" \ 0x0000000b \ 5.0.1.69 \ 0x6a5e0678 \ D2XP_111 # Diablo II LOD v1.10 MacOS X "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ "XMACver1.mpq" \ XMAC \ D2XP \ "Diablo II (Carbon) 10/29/103 12:32:05 5691846" \ 0x0000000a \ 5.0.0.65 \ 0x9b01cc98 \ D2XP_110 # StarCraft - Broodwar (Expansion) 1.15.1 - (Broodwar Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 07/16/107 18:00:00 1400709" \ 0x000000d1 \ 0x010f0001 \ 0xa380ad83 \ SEXP_1151 # StarCraft - Broodwar (Expansion) 1.15.1 - (Starcraft Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 07/16/107 18:00:00 1400709" \ 0x000000d1 \ 0x010f0001 \ 0xa380ad83 \ STAR_1151 ##### Mac OS Classic (PMAC) ################################################## # -=-=-=-=-=-=- Latest Versions -=-=-=-=-=-=- No Update Required -=-=-=-=-=-=- # Diablo II LOD v1.10 MacOS Classic "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ "PMACver1.mpq" \ PMAC \ D2XP \ "Diablo II 10/13/103 01:26:09 4829910" \ 0x0000000a \ 5.0.0.57 \ 0xcc2c2193 \ D2XP_110 # Starcraft - Broodwar (Expansion) 1.13e - (Broodwar mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ SEXP \ "Starcraft 09/07/105 10:00:00 1593704" \ 0x000000cd \ 1.1.3.9 \ 0x375482e4 \ SEXP_113E # Starcraft - Broodwar (Expansion) 1.13e - (Starcraft mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 09/07/105 10:00:00 1593704" \ 0x000000cd \ 1.1.3.9 \ 0x375482e4 \ STAR_113E # StarCraft v1.13e MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 09/07/105 10:00:00 1593704" \ 0x000000cd \ 1.1.3.8 \ 0x375482e4 \ STAR_113E ##### Intel (IX86) ########################################################### # -=-=-=-=-=- Older Versions -=-=-=-=-=-=- Update Required -=-=-=-=-=- # =================== WarCraft 3 Expansion Entries ================== # Warcraft III - TFT (Expansion) 1.21b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 07/19/07 18:41:12 409660" \ 0x00000015 \ 1.21.1.156 \ 0x1b735294 \ W3XP_121B # Warcraft III - TFT (Expansion) 1.21a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 12/28/06 20:35:21 1572307" \ 0x00000015 \ 1.21.0.119 \ 0xab35b5f1 \ W3XP_121A # Warcraft III - TFT (Expansion) 1.20e # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 06/13/06 06:13:05 1572307" \ 0x00000014 \ 1.20.4.186 \ 0x8771b225 \ W3XP_120E # Warcraft III - TFT (Expansion) 1.20d # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "War3.exe 04/06/06 00:19:58 1572307" \ 0x00000014 \ 1.20.3.182 \ 0xbbd3e672 \ W3XP_120D # Warcraft III - TFT (Expansion) 1.20c # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "War3.exe 01/05/06 02:50:54 1572307" \ 0x00000014 \ 1.20.2.177 \ 0x97c8e59b \ W3XP_120C # Warcraft III - TFT (Expansion) 1.20b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "War3.exe 12/07/05 23:59:26 1572307" \ 0x00000014 \ 1.0.20.168 \ 0x57e714c1 \ W3XP_120B # Warcraft III - TFT (Expansion) 1.20a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "War3.exe 09/23/05 03:16:24 1572307" \ 0x00000014 \ 1.0.20.160 \ 0xdfe00da5 \ W3XP_120A # Warcraft III - TFT (Expansion) 1.19b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 09/20/05 04:03:24 1572307" \ 0x00000013 \ 1.0.19.158 \ 0x9c73744d \ W3XP_119B # Warcraft III - TFT (Expansion) 1.19a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 09/07/05 18:58:53 1572307" \ 0x00000013 \ 1.0.19.153 \ 0x892fa500 \ W3XP_119A # Warcraft III - TFT (Expansion) 1.18a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 02/18/05 04:38:43 1572307" \ 0x00000012 \ 1.0.18.142 \ 0x087fb830 \ W3XP_118A # Warcraft III - TFT (Expansion) 1.17a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 09/15/04 22:42:18 1568211" \ 0x00000011 \ 1.0.17.100 \ 0xd1d89b0e \ W3XP_117A # Warcraft III - TFT (Expansion) 1.16a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "War3.exe 06/28/04 23:37:02 1568211" \ 0x00000010 \ 1.0.16.38 \ 0xcc882269 \ W3XP_116A # Warcraft III - TFT (Expansion) 1.15a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 05/04/04 01:18:12 1568211" \ 0x0000000f \ 1.0.15.156 \ 0x39b3974b \ W3XP_115A # Warcraft III - TFT (Expansion) 1.14b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "War3.exe 01/09/04 06:11:44 1568211" \ 0x0000000e \ 1.0.14.152 \ 0x36fd6e73 \ W3XP_114B # Warcraft III - TFT (Expansion) 1.14a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "War3.exe 01/06/04 03:44:50 1568211" \ 0x0000000e \ 1.0.14.151 \ 0xa842edef \ W3XP_114A # Warcraft III - TFT (Expansion) 1.13b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "War3.exe 12/18/03 00:53:06 1568211" \ 0x0000000d \ 1.0.13.149 \ 0x0bb5600d \ W3XP_113B # Warcraft III - TFT (Expansion) 1.13a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ W3XP \ "war3.exe 12/10/03 23:42:46 2150400" \ 0x0000000d \ 1.0.13.149 \ 0xaf284a18 \ W3XP_113A # Warcraft III - TFT (Expansion) 1.12a # Note: this version check is sent in both FT and ROC mode #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # W3XP \ # "war3.exe 07/22/03 22:43:15 1568211" \ # 0x0000000c \ # 1.0.12.148 \ # 0xa9c022bd \ # W3XP_112A # Warcraft III - TFT (Expansion) 1.11a # Note: this version check is sent in both FT and ROC mode #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # W3XP \ # "war3.exe 07/01/03 18:22:52 1568211" \ # 0x0000000b \ # 1.0.11.147 \ # 0x5fce4f04 \ # W3XP_111A # Warcraft III - TFT (Expansion) 1.10a # Note: this version check is sent in both FT and ROC mode #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # W3XP \ # "war3.exe 06/17/03 16:37:46 1568211" \ # 0x0000000a \ # 1.0.10.146 \ # 0x75d1c16f \ # W3XP_110A # Warcraft III - TFT (Expansion) 1.07a # Note: this version check is sent in both FT and ROC mode # exeinfo is NULL here because it's the date of install # but that's ok because we have the checksum #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # W3XP \ # NULL \ # 0x00000007 \ # 1.0.7.142 \ # 0xde80b55b \ # W3XP_107A # ====================== WarCraft 3 Entries ======================== # Warcraft III - ROC 1.21b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 07/19/07 18:41:12 409660" \ 0x00000015 \ 1.21.1.156 \ 0x1b735294 \ WAR3_121B # Warcraft III - ROC 1.21a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 12/28/06 20:35:21 1572307" \ 0x00000015 \ 1.21.0.119 \ 0xab35b5f1 \ WAR3_121A # Warcraft III - ROC 1.20e # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 06/13/06 06:13:05 1572307" \ 0x00000014 \ 1.20.4.186 \ 0x8771b225 \ WAR3_120E # Warcraft III - ROC 1.20d # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "War3.exe 04/06/06 00:19:58 1572307" \ 0x00000014 \ 1.20.3.182 \ 0xbbd3e672 \ WAR3_120D # Warcraft III - ROC 1.20c # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "War3.exe 01/05/06 02:50:54 1572307" \ 0x00000014 \ 1.20.2.177 \ 0x97c8e59b \ WAR3_120C # Warcraft III - ROC 1.20b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "War3.exe 12/07/05 23:59:26 1572307" \ 0x00000014 \ 1.0.20.168 \ 0x57e714c1 \ WAR3_120B # Warcraft III - ROC 1.20a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "War3.exe 09/23/05 03:16:24 1572307" \ 0x00000014 \ 1.0.20.160 \ 0xdfe00da5 \ WAR3_120A # Warcraft III - ROC 1.19b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 09/20/05 04:03:24 1572307" \ 0x00000013 \ 1.0.19.158 \ 0x9c73744d \ WAR3_119B # Warcraft III - ROC 1.19a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 09/07/05 18:58:53 1572307" \ 0x00000013 \ 1.0.19.153 \ 0x892fa500 \ WAR3_119A # Warcraft III - ROC 1.18a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 02/18/05 04:38:43 1572307" \ 0x00000012 \ 1.0.18.142 \ 0x087fb830 \ WAR3_118A # Warcraft III - ROC 1.17a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 09/15/04 22:42:18 1568211" \ 0x00000011 \ 1.0.17.100 \ 0xd1d89b0e \ WAR3_117A # Warcraft III - ROC 1.16a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "War3.exe 06/28/04 23:37:02 1568211" \ 0x00000010 \ 1.0.16.38 \ 0xcc882269 \ WAR3_116A # Warcraft III - ROC 1.15a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 05/04/04 01:18:12 1568211" \ 0x0000000f \ 1.0.15.156 \ 0x39b3974b \ WAR3_115A # Warcraft III - ROC 1.14b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "War3.exe 01/09/04 06:11:44 1568211" \ 0x0000000e \ 1.0.14.152 \ 0x36fd6e73 \ WAR3_114B # Warcraft III - ROC 1.14a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "War3.exe 01/06/04 03:44:50 1568211" \ 0x0000000e \ 1.0.14.151 \ 0xa842edef \ WAR3_114A # Warcraft III - ROC 1.13b # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "War3.exe 12/18/03 00:53:06 1568211" \ 0x0000000d \ 1.0.13.149 \ 0x0bb5600d \ WAR3_113B # Warcraft III - ROC 1.13a # Note: this version check is sent in both FT and ROC mode "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ IX86ver1.mpq \ IX86 \ WAR3 \ "war3.exe 12/10/03 23:42:46 2150400" \ 0x0000000d \ 1.0.13.149 \ 0xaf284a18 \ WAR3_113A # Warcraft III - ROC 1.12a # Note: this version check is sent in both FT and ROC mode #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 07/22/03 22:43:15 1568211" \ # 0x0000000c \ # 1.0.12.148 \ # 0xa9c022bd \ # WAR3_112A # Warcraft III - RoC 1.11a #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 07/01/03 18:22:52 1568211" \ # 0x0000000b \ # 1.0.11.147 \ # 0x5fce4f04 \ # WAR3_111A # Warcraft III - RoC 1.10a #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 06/17/03 16:37:46 1568211" \ # 0x0000000a \ # 1.0.10.146 \ # 0x75d1c16f \ # WAR3_110A # Warcraft III - RoC 1.07 (Used for TFT 1.07a in RoC Mode) #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # NULL \ # 0x00000007 \ # 1.0.7.142 \ # 0xde80b55b \ # WAR3_107A # WarCraft III - RoC 1.06a #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 05/23/03 19:50:08 1461715" \ # 0x00000006 \ # 1.0.6.0 \ # 0x302dca19 \ # WAR3_106A # WarCraft III - RoC 1.05a #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 01/30/03 03:08:10 1170899" \ # 0x00000005 \ # 1.0.5.0 \ # 0xbe284ba9 \ # WAR3_105A # WarCraft III - RoC 1.04c #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 01/16/03 02:44:48 1166807" \ # 0x00000004 \ # 1.0.4.1 \ # 0x3f06d9fa \ # WAR3_104C # WarCraft III - RoC 1.04b #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 10/31/02 17:29:22 1068499" \ # 0x00000004 \ # 1.0.3.0 \ # 0x56f4cc37 \ # WAR3_104B # WarCraft III - RoC 1.04a #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 10/29/02 23:26:17 713495" \ # 0x00000004 \ # 1.0.3.0 \ # 0x0e529b2d \ # WAR3_104A # Warcraft III - RoC 1.03a #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 10/08/02 20:54:49 713495" \ # 0x00000003 \ # 1.0.3.0 \ # 0xae4ac7fa \ # WAR3_103A # Warcraft III - RoC 1.02a #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 09/06/02 02:41:02 713495" \ # 0x00000002 \ # 1.0.1.0 \ # 0xa67d9a0e \ # WAR3_102A # Warcraft III - RoC 1.02 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 08/12/02 18:21:15 713495" \ # 0x00000002 \ # 1.0.1.0 \ # 0x03d8be54 \ # WAR3_102 # Warcraft III - RoC 1.01b #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 07/10/02 18:59:10 713495" \ # 0x00000001 \ # 1.0.1.1 \ # 0x062ef7dc \ # WAR3_101B # Warcraft III - RoC 1.01 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # "war3.exe 06/28/02 18:41:18 713495" \ # 0x00000001 \ # 1.0.1.0 \ # 0x62c2e1a2 \ # WAR3_101 # Warcraft III - RoC 1.00 # exeinfo is NULL here because it's the date of install # but that's ok because we have the checksum #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # WAR3 \ # NULL \ # 0x00000000 \ # 1.0.0.0 \ # 0xf891f129 \ # WAR3_100 # ====================== Diablo II LOD entries =========================== # Diablo II - LoD (Expansion) 1.09b #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2XP \ # "Game.exe 08/31/01 22:40:56 428163" \ # 9 \ # 1.0.9.0 \ # 0x1436c138 \ # D2XP_109B # Diablo II - LoD (Expansion) 1.09 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2XP \ # "Game.exe 08/16/01 23:05:03 428163" \ # 9 \ # 1.0.9.0 \ # 0x15abc72d \ # D2XP_109 # Diablo II - LoD (Expansion) 1.08 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2XP \ # "Game.exe 06/19/01 02:24:32 428163" \ # 8 \ # 1.0.8.0 \ # 0x3a8664ff \ # D2XP_108 # Diablo II - LoD (Expansion) 1.07 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2XP \ # "Game.exe 01/23/02 06:39:26 424067" \ # 7 \ # 1.0.7.0 \ # 0x4f3079e6 \ # D2XP_107 # ==================== Diablo 2 (original) entries ===================== # Diablo II 1.09b #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 08/31/01 22:40:35 424067" \ # 9 \ # 1.0.9.0 \ # 0xb9cb2cb1 \ # D2DV_109B # Diablo II 1.09 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 08/16/01 23:04:40 424067" \ # 9 \ # 1.0.9.0 \ # 0xc43f1764 \ # D2DV_109 # Diablo II 1.08 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 06/19/01 02:24:04 424067" \ # 8 \ # 1.0.8.0 \ # 0x9e488d3d \ # D2DV_108 # Diablo II 1.06b #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 05/16/01 18:55:11 419971" \ # 6 \ # 1.0.6.0 \ # 0xb2fb38b7 \ # D2DV_106B # Diablo II 1.06 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 04/19/01 02:05:33 419971" \ # 6 \ # 1.0.6.0 \ # 0xaa348e13 \ # D2DV_106 # Diablo II 1.05b #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 02/01/01 21:21:16 399491" \ # 5 \ # 1.0.5.1 \ # 0x36869f98 \ # D2DV_105B # Diablo II 1.05 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 01/27/01 01:16:00 399491" \ # 5 \ # 1.0.5.0 \ # 0xd6dec09b \ # D2DV_105 # Diablo II 1.04c #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 12/23/00 18:28:04 387107" \ # 4 \ # 1.0.4.2 \ # 0xc6d40aaf \ # D2DV_104B # Diablo II 1.04b #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 12/22/00 18:08:34 403587" \ # 4 \ # 1.0.4.1 \ # 0x3882960e \ # D2DV_104B # Diablo II 1.03 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 08/01/00 00:34:00 346243" \ # 3 \ # 1.0.3.0 \ # 0x0120ed90 \ # D2DV_103 # Diablo II 1.01 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 06/26/00 22:31:00 346243" \ # 1 \ # 1.0.0.1 \ # 0x5aef7e66 \ # D2DV_101 # Diablo II 1.00 (installation) # 1.00 have 0 versionid used as a wildchar in versioncheck # but we don't care because we have exeinfo and checksum #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # D2DV \ # "Game.exe 01/01/97 02:05:09 309379" \ # 0 \ # 1.0.0.1 \ # 0xac5e46cb \ # D2DV_100 # ==================== StarCraft Broodwar entries ============================ # Starcraft - Broodwar (Expansion) 1.16 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "StarCraft.exe 11/06/08 01:10:59 1220608" \ 0x000000d3 \ 1.16.0.1 \ 0xd206c475 \ SEXP_116 # Starcraft - Broodwar (Expansion) 1.16 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "StarCraft.exe 11/06/08 01:10:59 1220608" \ 0x000000d3 \ 1.16.0.1 \ 0xd206c475 \ STAR_116 # Starcraft - Broodwar (Expansion) 1.15.3 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "StarCraft.exe 07/25/08 23:34:58 1220608" \ 0x000000d1 \ 1.15.3.1 \ 0x2abff892 \ SEXP_1153 # Starcraft - Broodwar (Expansion) 1.15.3 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "StarCraft.exe 07/25/08 23:34:58 1220608" \ 0x000000d1 \ 1.15.3.1 \ 0x2abff892 \ STAR_1153 # Starcraft - Broodwar (Expansion) 1.15.2 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "StarCraft.exe 01/10/08 20:23:42 1220608" \ 0x000000d1 \ 1.15.2.1 \ 0x8fbdf18d \ SEXP_1152 # Starcraft - Broodwar (Expansion) 1.15.2 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "StarCraft.exe 01/10/08 20:23:42 1220608" \ 0x000000d1 \ 1.15.2.1 \ 0x8fbdf18d \ STAR_1152 # Starcraft - Broodwar (Expansion) 1.15.1 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 07/19/07 02:30:05 1220608" \ 0x000000d1 \ 1.15.1.0 \ 0x99e92077 \ SEXP_1151 # Starcraft - Broodwar (Expansion) 1.15.1 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 07/19/07 02:30:05 1220608" \ 0x000000d1 \ 1.15.1.0 \ 0x99e92077 \ STAR_1151 # Starcraft - Broodwar (Expansion) 1.15 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 05/08/07 19:13:26 1220608" \ 0x000000d1 \ 1.15.0.1 \ 0x1eec4ebc \ SEXP_115 # Starcraft - Broodwar (Expansion) 1.15 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/08/07 19:13:26 1220608" \ 0x000000d1 \ 1.15.0.1 \ 0x1eec4ebc \ STAR_115 # Starcraft Broodwar (Expansion) 1.14 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 05/10/06 00:13:58 1216512" \ 0x000000cf \ 1.14.0.1 \ 0xf5280a9e \ SEXP_114 # Starcraft - Broodwar (Expansion) 1.14 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/10/06 00:13:58 1216512" \ 0x000000cf \ 1.14.0.1 \ 0xf5280a9e \ STAR_114 # Starcraft - Broodwar (Expansion) 1.13f - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 01/13/06 05:42:48 1146939" \ 0x000000cd \ 1.1.3.11 \ 0x5c5e4509 \ SEXP_113F # Starcraft - Broodwar (Expansion) 1.13f - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 01/13/06 05:42:48 1146939" \ 0x000000cd \ 1.1.3.11 \ 0x5c5e4509 \ STAR_113F # Starcraft - Broodwar (Expansion) 1.13e - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 09/07/05 19:06:42 1093632" \ 0x000000cd \ 1.1.3.9 \ 0xdee278b8 \ SEXP_113E # Starcraft - Broodwar (Expansion) 1.13e - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 09/07/05 19:06:42 1093632" \ 0x000000cd \ 1.1.3.9 \ 0xdee278b8 \ STAR_113E # Starcraft - Broodwar (Expansion) 1.13d - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 08/25/05 22:23:54 1093632" \ 0x000000cd \ 1.1.3.7 \ 0x5b3cbe07 \ SEXP_113D # Starcraft - Broodwar (Expansion) 1.13d - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 08/25/05 22:23:54 1093632" \ 0x000000cd \ 1.1.3.7 \ 0x5b3cbe07 \ SEXP_113D_STAR # Starcraft - Broodwar (Expansion) 1.13c - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 08/18/05 23:42:08 1093632" \ 0x000000cd \ 1.1.3.5 \ 0xbd7aca6e \ SEXP_113C # Starcraft - Broodwar (Expansion) 1.13c - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 08/18/05 23:42:08 1093632" \ 0x000000cd \ 1.1.3.5 \ 0xbd7aca6e \ SEXP_113C_STAR # Starcraft - Broodwar (Expansion) 1.13b - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 08/10/05 22:19:41 1093632" \ 0x000000cd \ 1.1.3.3 \ 0x02cfab16 \ SEXP_113B # Starcraft - Broodwar (Expansion) 1.13b - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 08/10/05 22:19:41 1093632" \ 0x000000cd \ 1.1.3.3 \ 0x02cfab16 \ SEXP_113B_STAR # Starcraft - Broodwar (Expansion) 1.13 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 06/24/05 17:19:30 1093632" \ 0x000000cd \ 1.1.3.1 \ 0x02bb0696 \ SEXP_113 # Starcraft - Broodwar (Expansion) 1.13 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 06/24/05 17:19:30 1093632" \ 0x000000cd \ 1.1.3.1 \ 0x02bb0696 \ SEXP_113_STAR # Starcraft - Broodwar (Expansion) 1.12b - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 02/18/05 02:14:10 1093632" \ 0x000000cb \ 1.1.2.3 \ 0x0eea30bc \ SEXP_112B # Starcraft - Broodwar (Expansion) 1.12b - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 02/10/05 02:14:10 1093632" \ 0x000000cb \ 1.1.2.3 \ 0x0eea30bc \ SEXP_112B_STAR # Starcraft - Broodwar (Expansion) 1.12 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 02/10/05 05:36:14 1093632" \ 0x000000cb \ 1.1.2.1 \ 0x796786fe \ SEXP_112 # Starcraft - Broodwar (Expansion) 1.12 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 02/10/05 05:36:14 1093632" \ 0x000000cb \ 1.1.2.1 \ 0x796786fe \ SEXP_112_STAR # Starcraft - Broodwar (Expansion) 1.11b - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 05/26/04 00:46:00 1048576" \ 0x000000c9 \ 1.1.1.3 \ 0xd1ef9ca4 \ SEXP_111B # Starcraft - Broodwar (Expansion) 1.11b - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/26/04 00:46:00 1048576" \ 0x000000c9 \ 1.1.1.3 \ 0xd1ef9ca4 \ SEXP_111B_STAR # Starcraft - Broodwar (Expansion) 1.11 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 04/27/04 05:12:02 1048576" \ 0x000000c9 \ 1.1.1.1 \ 0x706c67e6 \ SEXP_111 # Starcraft - Broodwar (Expansion) 1.11 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 04/27/04 05:12:02 1048576" \ 0x000000c9 \ 1.1.1.1 \ 0x706c67e6 \ SEXP_111_STAR # Starcraft - Broodwar (Expansion) 1.10 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 03/28/03 04:21:58 1064960" \ 0x000000c7 \ 1.1.0.1 \ 0xe20a2ca1 \ SEXP_110 # Starcraft - Broodwar (Expansion) 1.10 - (Starcraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 03/28/03 04:21:58 1064960" \ 0x000000c7 \ 1.1.0.1 \ 0xe20a2ca1 \ SEXP_110_STAR # Starcraft - Broodwar (Expansion) 1.09b - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 02/21/02 20:54:04 1083392" \ 0x000000c5 \ 1.0.9.3 \ 0xf76df1ed \ SEXP_109B # Starcraft - Broodwar (Expansion) 1.09b - (Starcraft mode) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 02/21/02 20:54:04 1083392" \ 0x000000c5 \ 1.0.9.3 \ 0xf76df1ed \ SEXP_109B_STAR # Starcraft - Broodwar (Expansion) 1.09 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 02/05/02 07:17:26 1083392" \ 0x000000c5 \ 1.0.9.1 \ 0x9333e69f \ SEXP_109 # Starcraft - Broodwar (Expansion) 1.09 - (StarCraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 02/05/02 07:17:26 1083392" \ 0x000000c5 \ 1.0.9.1 \ 0x9333e69f \ SEXP_109_STAR # Starcraft - Broodwar (Expansion) 1.08b - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 05/19/01 02:28:22 1082880" \ 0x000000c3 \ 1.0.8.11 \ 0x95b346ec \ SEXP_108B # Starcraft - Broodwar (Expansion) 1.08b - (StarCraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/19/01 02:28:22 1082880" \ 0x000000c3 \ 1.0.8.11 \ 0x95b346ec \ SEXP_108B_STAR # Starcraft - Broodwar (Expansion) 1.08 - (Broodwar mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ SEXP \ "starcraft.exe 05/17/01 03:51:08 1082880" \ 0x000000c3 \ 1.0.8.1 \ 0x5063884e \ SEXP_108 # Starcraft - Broodwar (Expansion) 1.08 - (StarCraft mode) "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/17/01 03:51:08 1082880" \ 0x000000c3 \ 1.0.8.1 \ 0x5063884e \ SEXP_108_STAR # Starcraft - Broodwar (Expansion) 1.07 - (Broodwar mode) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # SEXP \ # "starcraft.exe 10/30/99 03:54:30 1043456" \ # 0x000000c1 \ # 1.0.7.1 \ # 0xacf13dce \ # SEXP_107 # Starcraft - Broodwar (Expansion) 1.07 - (StarCraft mode) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # "starcraft.exe 10/30/99 03:54:30 1043456" \ # 0x000000c1 \ # 1.0.7.1 \ # 0xacf13dce \ # SEXP_107_STAR # Starcraft - Broodwar (Expansion) 1.06 - (Broodwar mode) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # SEXP \ # "starcraft.exe 09/28/99 19:41:34 1042432" \ # 0x000000bd \ # 1.0.6.1 \ # 0x1acce912 \ # SEXP_106 # Starcraft - Broodwar (Expansion) 1.06 - (StarCraft mode) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # "starcraft.exe 09/28/99 19:41:34 1042432" \ # 0x000000bd \ # 1.0.6.1 \ # 0x1acce912 \ # SEXP_106_STAR # Starcraft - Broodwar (Expansion) 1.05 - (Broodwar mode) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # SEXP \ # "starcraft.exe 03/08/99 22:37:32 1042432" \ # 0x000000bd \ # 1.0.5.1 \ # 0x9a2d64e6 \ # SEXP_105 # Starcraft - Broodwar (Expansion) 1.05 - (StarCraft mode) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # "starcraft.exe 03/08/99 22:37:32 1042432" \ # 0x000000bd \ # 1.0.5.1 \ # 0x9a2d64e6 \ # SEXP_105_STAR # Starcraft - Broodwar (Expansion) 1.04 - (Broodwar mode) # exeinfo is NULL here because it's the date of install # but that's ok because we have the checksum #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # SEXP \ # NULL \ # 0x000000bb \ # 1.0.4.1 \ # 0xfd581427 \ # SEXP_104 # Starcraft - Broodwar (Expansion) 1.04 - (StarCraft mode) # exeinfo is NULL here because it's the date of install # but that's ok because we have the checksum #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # NULL \ # 0x000000bb \ # 1.0.4.1 \ # 0xfd581427 \ # SEXP_104_STAR # ==================== StarCraft (original) entries ========================== # Starcraft (Standalone) 1.16 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "StarCraft.exe 11/06/08 01:14:14 1220608" \ 0x000000d3 \ 1.16.0.0 \ 0xcab35ce0 \ STAR_116 # Starcraft (Standalone) 1.15.3 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "StarCraft.exe 07/25/08 23:36:39 1220608" \ 0x000000d1 \ 1.15.3.0 \ 0xc9fc7927 \ STAR_1153 # Starcraft (Standalone) 1.15.2 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "StarCraft.exe 01/08/08 23:45:36 1220608" \ 0x000000d1 \ 1.15.2.0 \ 0x91c0f907 \ STAR_1152 # Starcraft (Standalone) 1.15.1 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 07/19/07 02:30:53 1220608" \ 0x000000d1 \ 1.15.1.0 \ 0x34702730 \ STAR_1151 # Starcraft (Standalone) 1.15 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/08/07 19:14:08 1220608" \ 0x000000d1 \ 1.15.0.0 \ 0xd892b992 \ STAR_115 # Starcraft (Standalone) 1.14 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/19/06 00:05:06 1216512" \ 0x000000cf \ 1.14.0.0 \ 0x1f109657 \ STAR_114 # Starcraft (Standalone) 1.13f "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 01/13/06 05:46:36 1146939" \ 0x000000cd \ 1.1.3.10 \ 0x0e3d3732 \ STAR_113F # Starcraft (Standalone) 1.13e "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 09/07/05 19:31:20 1093632" \ 0x000000cd \ 1.1.3.8 \ 0xa21f8b5c \ STAR_113E # Starcraft (Standalone) 1.13d "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 08/25/05 22:36:16 1093632" \ 0x000000cd \ 1.1.3.6 \ 0xdef3af2b \ STAR_113D # Starcraft (Standalone) 1.13c "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 08/18/05 23:52:34 1093632" \ 0x000000cd \ 1.1.3.4 \ 0xe888a7ce \ STAR_113C # Starcraft (Standalone) 1.13b "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 08/10/05 22:24:39 1093632" \ 0x000000cd \ 1.1.3.2 \ 0x934ce3ac \ STAR_113B # Starcraft (Standalone) 1.13 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 06/24/05 17:26:11 1093632" \ 0x000000cd \ 1.1.3.0 \ 0x3462622c \ STAR_113 # Starcraft (Standalone) 1.12b "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 02/18/05 02:18:55 1093632" \ 0x000000cb \ 1.1.2.2 \ 0x90abd67f \ STAR_112B # Starcraft (Standalone) 1.12 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 02/10/05 05:37:38 1093632" \ 0x000000cb \ 1.1.2.0 \ 0x2132ae0b \ STAR_112 # Starcraft 1.11b "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/26/04 01:25:14 1048576" \ 0x000000c9 \ 1.1.1.2 \ 0x7e9ce2f1 \ STAR_111B # Starcraft 1.11 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 04/27/04 05:46:02 1048576" \ 0x000000c9 \ 1.1.1.1 \ 0xff88c010 \ STAR_111 # Starcraft 1.10 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 03/27/03 04:30:39 1064960" \ 0x000000c7 \ 1.1.0.0 \ 0x8515bf6a \ STAR_110 # Starcraft 1.09b "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 02/21/02 21:48:41 1083392" \ 0x000000c5 \ 1.0.9.2 \ 0x96d28df0 \ STAR_109B # Starcraft 1.09 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 02/05/02 07:37:20 1083392" \ 0x000000c5 \ 1.0.9.0 \ 0x251098be \ STAR_109 # Starcraft 1.08b "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/19/01 02:01:50 1082880" \ 0x000000c3 \ 1.0.8.10 \ 0x7859c173 \ STAR_108B # Starcraft 1.08 "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ STAR \ "starcraft.exe 05/17/01 04:12:40 1082880" \ 0x000000c3 \ 1.0.8.0 \ 0x7b58b906 \ STAR_108 # Starcraft 1.07 #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # "starcraft.exe 10/30/99 02:20:12 1043456" \ # 0x000000c1 \ # 1.0.7.0 \ # 0x79126108 \ # STAR_107 # Starcraft 1.06 #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # "starcraft.exe 09/25/99 22:40:10 1042432" \ # 0x000000bd \ # 1.0.6.0 \ # 0xfea28485 \ # STAR_106 # Starcraft 1.05 #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # "starcraft.exe 03/08/99 22:41:50 1042432" \ # 0x000000bd \ # 1.0.5.0 \ # 0xc243123c \ # STAR_105 # # Starcraft 1.04 #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # "starcraft.exe 12/16/98 22:24:18 1041408" \ # 0x000000bb \ # 1.0.4.0 \ # 0x2779bdc8 \ # STAR_104 # Starcraft 1.03 #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # "starcraft.exe 10/09/98 23:18:22 987648" \ # 0x000000a9 \ # 1.0.3.0 \ # 0x1309eaad \ # STAR_103 # ==================== Diablo (original) entries ======================= # Diablo 109b "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ DRTL \ "Diablo.exe 05/18/01 23:10:57 757760" \ 0x0000002a \ 1.0.9.2 \ 0x23135c73 \ DRTL_109B # Diablo 109 "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ DRTL \ "Diablo.exe 05/12/01 00:53:17 757760" \ 0x0000002a \ 1.0.9.1 \ 0x0dcb0513 \ DRTL_109 # Diablo 108 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # DRTL \ # "Diablo.exe 05/24/00 01:16:01 764928" \ # 0x00000028 \ # 1.0.8.1 \ # 0x09eb1213 \ # DRTL_108 # =========================== WARCRAFT2 BNE =========================== # Warcraft II BNE 2.02b "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ W2BN \ "Warcraft II BNE.exe 05/21/01 21:52:22 712704" \ 0x0000004f \ 2.0.2.1 \ 0xff0d4c4a \ W2BN_202B # Warcraft II BNE 2.02a "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ "ver-ix86-1.mpq" \ IX86 \ W2BN \ "Warcraft II BNE.exe 05/15/01 20:53:19 712704" \ 0x0000004f \ 2.0.2.0 \ 0xb52bad87 \ W2BN_202A # Warcraft II BNE v2.01 #"A=2383634235 B=711286254 C=3710735432 4 A=A+S B=B^C C=C+A A=A^B" \ # "IX86ver4.mpq" \ # IX86 \ # W2BN \ # "Warcraft II BNE.exe ??/??/?? ??:??:?? 704512" \ # 0x0000004b \ # 2.0.0.154 \ # 0x0 \ # W2BN_201 # Warcraft II BNE v2.00 #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # IX86ver1.mpq \ # IX86 \ # W2BN \ # NULL \ # 0x0000004b \ # 2.0.0.154 \ # 0x7133f5ed \ # W2BN_200 ##### Mac OS X (XMAC) ######################################################## # -=-=-=-=-=- Older Versions -=-=-=-=-=-=- Update Required -=-=-=-=-=- # ================ StarCraft (original) entries ===================== # StarCraft v1.13e MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 09/07/105 10:00:00 1388225" \ 0x000000cd \ 1.1.3.8 \ 0xcf5a3fe0 \ STAR_113E # StarCraft v1.12 MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 02/09/105 22:00:00 1387464" \ 0x000000cb \ 1.1.2.0 \ 0x5ecb12a9 \ STAR_112 # StarCraft v1.11b MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 05/25/104 17:00:00 1358712" \ 0x000000c9 \ 1.1.1.2 \ 0x510432e3 \ STAR_111B # StarCraft v1.11 MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 04/26/104 21:00:00 1358518" \ 0x000000c9 \ 1.1.1.0 \ 0x0c065d2d \ STAR_111 # StarCraft v1.10 MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 03/24/103 19:00:00 1350192" \ 0x000000c7 \ 1.1.0.0 \ 0x8ae3c718 \ STAR_110 # StarCraft v1.09b MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ NULL \ 0x000000c5 \ 1.0.9.2 \ 0x0 \ STAR_109B # ================== StarCraft Broodwar entries ===================== # StarCraft - Broodwar (Expansion) 1.15 - (Broodwar Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 05/08/107 15:40:00 1400487" \ 0x000000d1 \ 0x010f0001 \ 0xe02b5360 \ SEXP_115 # StarCraft - Broodwar (Expansion) 1.15 - (Starcraft Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 05/08/107 15:40:00 1400487" \ 0x000000d1 \ 0x010f0001 \ 0xe02b5360 \ STAR_115 # StarCraft - Broodwar (Expansion) 1.14 - (Broodwar Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 05/17/106 15:00:00 1392433" \ 0x000000cf \ 0x01140001 \ 0x32c2574f \ SEXP_114 # StarCraft - Broodwar (Expansion) 1.14 - (Starcraft Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 05/17/106 15:00:00 1392433" \ 0x000000cf \ 0x01140001 \ 0x32c2574f \ STAR_114 # StarCraft - Broodwar (Expansion) 1.13e - (Broodwar Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 09/07/105 10:00:00 1388225" \ 0x000000cd \ 1.1.3.9 \ 0xcf5a3fe0 \ SEXP_113E # StarCraft - Broodwar (Expansion) 1.13e - (Starcraft Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 09/07/105 10:00:00 1388225" \ 0x000000cd \ 1.1.3.9 \ 0xcf5a3fe0 \ STAR_113E # StarCraft - Broodwar (Expansion) 1.13c - (Broodwar Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 08/18/105 16:00:00 1387936" \ 0x000000cd \ 1.1.3.5 \ 0xae03c804 \ SEXP_113C # StarCraft - Broodwar (Expansion) 1.13c - (Starcraft Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 08/18/105 16:00:00 1387936" \ 0x000000cd \ 1.1.3.5 \ 0xae03c804 \ SEXP_113C_STAR # Starcraft - Broodwar (Expansion) 1.13 - (Broodwar mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 06/24/105 10:00:00 1387810" \ 0x000000cd \ 1.1.3.1 \ 0x23813cb6 \ SEXP_113 # Starcraft - Broodwar (Expansion) 1.13 - (Starcraft mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 06/24/105 10:00:00 1387810" \ 0x000000cd \ 1.1.3.1 \ 0x23813cb6 \ SEXP_113_STAR # Starcraft - Broodwar (Expansion) 1.12 - (Broodwar mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 02/09/105 22:00:00 1387464" \ 0x000000cb \ 1.1.2.1 \ 0x5ecb12a9 \ SEXP_112 # Starcraft - Broodwar (Expansion) 1.12 - (Starcraft mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 02/09/105 22:00:00 1387464" \ 0x000000cb \ 1.1.2.1 \ 0x5ecb12a9 \ SEXP_112_STAR # Starcraft - Broodwar (Expansion) 1.11b - (Broodwar mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 05/25/104 17:00:00 1358712" \ 0x000000c9 \ 1.1.1.3 \ 0x510432e3 \ SEXP_111B # Starcraft - Broodwar (Expansion) 1.11b - (Starcraft mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 05/25/104 17:00:00 1358712" \ 0x000000c9 \ 1.1.1.3 \ 0x510432e3 \ SEXP_111B_STAR # Starcraft - Broodwar (Expansion) 1.11 - (Broodwar mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 04/26/104 21:00:00 1358518" \ 0x000000c9 \ 1.1.1.1 \ 0x0c065d2d \ SEXP_111 # Starcraft - Broodwar (Expansion) 1.11 - (Starcraft Mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 04/26/104 21:00:00 1358518" \ 0x000000c9 \ 1.1.1.1 \ 0x0c065d2d \ SEXP_111_STAR # Starcraft - Broodwar (Expansion) 1.10 - (Broodwar mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 03/24/103 19:00:00 1350192" \ 0x000000c7 \ 1.1.0.1 \ 0x8ae3c718 \ SEXP_110 # Starcraft - Broodwar (Expansion) 1.10 - (Starcraft mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ STAR \ "Starcraft (Carbon) 03/24/103 19:00:00 1350192" \ 0x000000c7 \ 1.1.0.1 \ 0x8ae3c718 \ SEXP_110_STAR # Starcraft - Broodwar (Expansion) 1.09b - (Broodwar mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 02/27/102 13:00:00 1360535" \ 0x000000c5 \ 1.0.9.3 \ 0xf744ebdb \ SEXP_109B # Starcraft - Broodwar (Expansion) 1.08b - (Broodwar mode) MacOS X "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "XMACver1.mpq" \ XMAC \ SEXP \ "Starcraft (Carbon) 11/20/101 16:00:00 1362631" \ 0x000000c3 \ 1.0.8.3 \ 0x6fc0e12d \ SEXP_108B ##### Mac OS Classic (PMAC) ################################################## # -=-=-=-=-=- Older Versions -=-=-=-=-=-=- Update Required -=-=-=-=-=- # ================== StarCraft (original) entries =================== # StarCraft v1.12 MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 02/09/105 22:00:00 1592719" \ 0x000000cb \ 1.1.2.0 \ 0xd120708b \ STAR_112 # StarCraft v1.11b MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 05/25/104 17:00:00 1563500" \ 0x000000c9 \ 1.1.1.2 \ 0x050a61c9 \ STAR_111B # StarCraft v1.11 MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 04/26/104 21:00:00 1563244" \ 0x000000c9 \ 1.1.1.0 \ 0x780fe83e \ STAR_111 # StarCraft v1.10 MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 03/24/103 19:01:00 1561070" \ 0x000000c7 \ 1.1.0.0 \ 0xec432fff \ STAR_110 # StarCraft v1.09b MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ NULL \ 0x000000c5 \ 1.0.9.2 \ 0x0 \ STAR_109B # ================== StarCraft Broodwar entries ===================== # Starcraft - Broodwar (Expansion) 1.12 - (Broodwar mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ SEXP \ "Starcraft 02/09/105 22:00:00 1592719" \ 0x000000cb \ 1.1.2.1 \ 0xd120708b \ SEXP_112 # Starcraft - Broodwar (Expansion) 1.12 - (Starcraft mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 02/09/105 22:00:00 1592719" \ 0x000000cb \ 1.1.2.1 \ 0xd120708b \ SEXP_112_STAR # Starcraft - Broodwar (Expansion) 1.11b - (Broodwar mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ SEXP \ "Starcraft 05/25/104 17:00:00 1563500" \ 0x000000c9 \ 1.1.1.3 \ 0x050a61c9 \ SEXP_111B # Starcraft - Broodwar (Expansion) 1.11b - (Starcraft mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 05/25/104 17:00:00 1563500" \ 0x000000c9 \ 1.1.1.3 \ 0x050a61c9 \ SEXP_111B_STAR # Starcraft - Broodwar (Expansion) 1.11 - (Broodwar mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ SEXP \ "Starcraft 04/26/104 21:00:00 1563244" \ 0x000000c9 \ 1.1.1.1 \ 0x780fe83e \ SEXP_111 # Starcraft - Broodwar (Expansion) 1.11 - (Starcraft Mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 04/26/104 21:00:00 1563244" \ 0x000000c9 \ 1.1.1.1 \ 0x780fe83e \ SEXP_111_STAR # Starcraft - Broodwar (Expansion) 1.10 - (Broodwar Mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ SEXP \ "Starcraft 03/24/103 19:00:00 1561070" \ 0x000000c7 \ 1.1.0.1 \ 0xec432fff \ SEXP_110 # Starcraft - Broodwar (Expansion) 1.10 - (Starcraft Mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ STAR \ "Starcraft 03/24/103 19:00:00 1561070" \ 0x000000c7 \ 1.1.0.1 \ 0xec432fff \ SEXP_110_STAR # Starcraft - Broodwar (Expansion) 1.09b - (Broodwar Mode) MacOS Classic "A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ "PMACver1.mpq" \ PMAC \ SEXP \ NULL \ 0x000000c5 \ 1.0.9.11 \ 0x0 \ SEXP_109B # ==================== Diablo 2 (original) entries ================== # Diablo II v1.09d MacOS Classic "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ "PMACver1.mpq" \ PMAC \ D2DV \ NULL \ 0 \ 1.0.9.0 \ 0x0 \ D2DV_109D ##### Intel (IX86) ########################################################### # -=-=-=-=-=-=-=-=-=-=-=-=-=-=- NULL Versionchecks -=-=-=-=-=-=-=-=-=-=-=-=-=- # You probably don't wont to enable these since they will match fake versions. # WarCraft III - TFT (Expansion) #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # W3XP \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # W3XP_1xx # WarCraft III - RoC #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # WAR3 \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # WAR3_1xx # Diablo II - LoD (Expansion) #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # D2XP \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # D2XP_1xx # Diablo II #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # D2DV \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # D2DV_1xx # Starcraft - Broodwar (Expansion) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # SEXP \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # SEXP_1xx # Starcraft # (Unfortunately it also matches Brood War in StarCraft original mode.) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # STAR \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # STAR_1xx # Diablo #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # DRTL \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # DRTL_1xx # Warcraft II BNE #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "IX86ver1.mpq" \ # IX86 \ # W2BN \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # W2BN_1xx ##### Mac OS X (XMAC) ######################################################## # -=-=-=-=-=-=-=-=-=-=-=-=-=-=- NULL Versionchecks -=-=-=-=-=-=-=-=-=-=-=-=-=- # You probably don't wont to enable these since they will match fake versions. # Diablo II - LoD (Expansion) #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "XMACver1.mpq" \ # XMAC \ # D2XP \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # D2XP_1xx # Diablo II #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "XMACver1.mpq" \ # XMAC \ # D2DV \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # D2DV_1xx # Starcraft - Broodwar (Expansion) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "XMACver1.mpq" \ # XMAC \ # SEXP \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # SEXP_1xx # StarCraft # (Unfortunately it also matches Brood War in StarCraft original mode.) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "XMACver1.mpq" \ # XMAC \ # STAR \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # STAR_1xx # Diablo #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "XMACver1.mpq" \ # XMAC \ # DRTL \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # DRTL_1xx ##### Mac OS Classic (PMAC) ################################################## # -=-=-=-=-=-=-=-=-=-=-=-=-=-=- NULL Versionchecks -=-=-=-=-=-=-=-=-=-=-=-=-=- # You probably don't wont to enable these since they will match fake versions. # Diablo II - LoD (Expansion) #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "PMACver1.mpq" \ # PMAC \ # D2XP \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # D2XP_1xx # Diablo II #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "PMACver1.mpq" \ # PMAC \ # D2DV \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # D2DV_1xx # Starcraft - Broodwar (Expansion) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "PMACver1.mpq" \ # PMAC \ # SEXP \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # SEXP_1xx # StarCraft # (Unfortunately it also matches Brood War in StarCraft original mode.) #"A=2521522835 B=3428392135 C=218673704 4 A=A^S B=B-C C=C+A A=A-B" \ # "PMACver1.mpq" \ # PMAC \ # STAR \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # STAR_1xx # Diablo #"A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B" \ # "PMACver1.mpq" \ # PMAC \ # DRTL \ # NULL \ # 0 \ # 0.0.0.0 \ # 0x0 \ # DRTL_1xx # # ############################################################################## pvpgn-1.8.5/conf/d2server.ini0000644000175000017500000000526611151345317015035 0ustar aaronaaron;Standard windows INI file format [D2GE] DebugDumpThread=1 [World Event] Enable=1 ;update interval in seconds UpdateInterval=30 ;Notes: even if DC spawns in non-hell difficulty, it can only drop USC in hell difficulty ;e.g: Difficulty=normal,nightmare,hell means spawn DC in any difficulty Difficulty=hell ;you will be happy when SpawnMinions set to non zero... SpawnMinions=0 ItemDataFile=ItemConfig.dat ;World event trigger item config Item=The Stone of Jordan ;Total items needed to trigger DC is: ;[ItemRangeMin, ItemRangeMax] + (ItemNormalGameFactor * NormalGames)/100 ;+ (ItemNormalPlayerFactor * NormalPlayers)/100 + ... ;NormalGame, NormalPlayers ... all are current dyanmic count on this server ItemRangeMin=10 ItemRangeMax=20 ItemNormalGameFactor=0 ItemNightmareGameFactor=0 ItemHellGameFactor=100 ItemNormalPlayerFactor=0 ItemNightmarePlayerFactor=0 ItemHellPlayerFactor=100 [Key] Mods = code=key [The Stone of Jordan] Mods = code=rin & quality=unique & prefix=122 [7% mf sc] Mods = code=cm1 & quality=magical & mf=7 [UM Rune] Mods = code=r22 [Unique or Set ring] Mods = code=rin & quality=unique, quality=set [UnID unique ring or unID set amulet] Mods = code=rin & quality=unique | code=amu & quality=set ;Item Format: ;Logical operators: ;'|' ';' high priority OR ;'&' normal priority AND ;',' low priority OR ;e.g: ;mod1 | mod2, mod3 & mod4 = mod1 ; mod2, mod3 & mod4 = mod1 || ((mod2 || mod3) && mod4) (unsupported c like expression) ;all spaces are ignored ;any character after '/' will be treated as comment and ignored ;Mod format: ;[mod] [<|=|>|<=|>=] [value] ;Currently supported mod list: ;Type -> item base type id ;can be found from weapons.txt armor.txt misc.txt ;notes: the ID start from 0 instead of 1 ;code -> item code ;can be found from weapons.txt armor.txt misc.txt ;quality -> tempered, craft,unique,set,rare,magical,superior,normal,inferior ;prefix -> item prefix id ;actually, for unique/set/runeword items, it is the name index. ;can be found from UniqueItems.txt, SetItems.txt, Runes.txt ;notes: the ID start from 0 instead of 1 ;ilvl -> item ilvl ;stat[n] -> stats value ;see ItemStatCost.txt ID column ;flag[n] -> item flag value ;see alias for common used flags ;MPQVersion -> item version ;ItemClassic for classic item, ItemExpansion for expansion item, ItemExpansion110 for items after 1.10 ;Common used alias ;socket = number of socket ;ethereal = [1|0] ;ear = [1|0] ;runeword = [1|0] ;broken = [1|0] ;identified = [1/0] ;personalized = [1/0] ;gems = number of gems socketed ;unsupported now ;gem[n] = mod of certain gem ;suffix = item suffix id ;and item magical prefix/suffix, use Stat[n] to check them now ;e.g: mf=7 & code=cm1 or stat80=7 & code=cm1 means 7% mf sc pvpgn-1.8.5/conf/anongame_infos.conf0000644000175000017500000002100511151345317016417 0ustar aaronaaron# # this file shows a sample config of a Frozen Throne ladder URL config # replace www.your-ladder-page.com with your actual ladder stats URL # [URL] server_URL = "http://www.your-ladder-page.com" player_URL = "http://www.your-ladder-page.com/?game=W3XP&user=" tourney_URL = "http://www.your-tourney-page.com" clan_URL = "http://www.your-clan-page/?clan=" ladder_PG_1v1_URL = "http://www.your-ladder-page.com/?game=W3XP&type=solo" ladder_PG_ffa_URL = "http://www.your-ladder-page.com/?game=W3XP&type=team" ladder_PG_team_URL = "http://www.your-ladder-page.com/?game=W3XP&type=ffa" ladder_AT_2v2_URL = "http://www.your-ladder-page.com/?game=W3XP&type=at" ladder_AT_3v3_URL = "http://www.your-ladder-page.com/?game=W3XP&type=at" ladder_AT_4v4_URL = "http://www.your-ladder-page.com/?game=W3XP&type=at" ladder_clan_1v1_URL = "http://www.your-ladder-page.com/?game=W3XP&type=clan_1v1" ladder_clan_2v2_URL = "http://www.your-ladder-page.com/?game=W3XP&type=clan_2v2" ladder_clan_3v3_URL = "http://www.your-ladder-page.com/?game=W3XP&type=clan_3v3" ladder_clan_4v4_URL = "http://www.your-ladder-page.com/?game=W3XP&type=clan_4v4" [DEFAULT_DESC] ladder_PG_1v1_desc = "Solo Games" ladder_PG_ffa_desc = "Free For all Games" ladder_PG_team_desc = "Team Games" ladder_AT_2v2_desc = "2 Player Team" ladder_AT_3v3_desc = "3 Player Team" ladder_AT_4v4_desc = "4 Player Team" ladder_clan_1v1_desc = "Solo Games" ladder_clan_2v2_desc = "2 Player Team" ladder_clan_3v3_desc = "3 Player Team" ladder_clan_4v4_desc = "4 Player Team" gametype_1v1_short = "One vs. One" gametype_1v1_long = "Two players fight to the death" gametype_2v2_short = "Two vs. Two" gametype_2v2_long = "Two teams of two vie for dominance" gametype_3v3_short = "Three vs. Three" gametype_3v3_long = "Two teams of three face off on the battlefield" gametype_4v4_short = "Four vs. Four" gametype_4v4_long = "Two teams of four head to battle" gametype_5v5_short = "Five vs. Five" gametype_5v5_long = "Two teams of five - who will prevail?" gametype_6v6_short = "Six vs. Six" gametype_6v6_long = "Two teams of six - get ready to rumble!" gametype_sffa_short = "Small Free for All" gametype_sffa_long = "Can you defeat 3-5 opponents alone?" gametype_tffa_short = "Team Free for All" gametype_tffa_long = "Can your team defeat 1-2 others?" gametype_2v2v2_short = "Two vs. Two vs. Two" gametype_2v2v2_long = "Three teams of two, can you handle it?" gametype_3v3v3_short = "Three vs. Three vs. Three" gametype_3v3v3_long = "Three teams of three battle each other" gametype_4v4v4_short = "Four vs. Four vs. Four" gametype_4v4v4_long = "Three teams of four - things getting crowded?" gametype_2v2v2v2_short = "Two vs. Two vs. Two vs. Two" gametype_2v2v2v2_long = "Four teams of two, is this a challenge?" gametype_3v3v3v3_short = "Three vs. Three vs. Three vs. Three" gametype_3v3v3v3_long = "Four teams of three, the ultimate challenge!" [deDE] ladder_PG_1v1_desc = "Solo-Spiele" ladder_PG_ffa_desc = "J.g.J.-Spiele" ladder_PG_team_desc = "Team-Spiele" ladder_AT_2v2_desc = "2 Spieler Team" ladder_AT_3v3_desc = "3 Spieler Team" ladder_AT_4v4_desc = "4 Spieler Team" ladder_clan_1v1_desc = "Solo-Spiele" ladder_clan_2v2_desc = "2 Spieler-Spiele" ladder_clan_3v3_desc = "3 Spieler-Spiele" ladder_clan_4v4_desc = "4 Spieler-Spiele" gametype_1v1_short = "Einer gegen Einen" gametype_1v1_long = "Zwei Spieler kämpfen bis zum Tod." gametype_2v2_short = "Zwei gegen Zwei" gametype_2v2_long = "Zwei Zweier-Teams ringen um die Vorherrschaft." gametype_3v3_short = "Drei gegen Drei" gametype_3v3_long = "Zwei Dreier-Teams stehen sich auf dem Schlachfeld gegenüber." gametype_4v4_short = "Vier gegen Vier" gametype_4v4_long = "Zwei Vierer-Teams stürmen in die Schlacht." gametype_5v5_short = "Fünf gegen Fünf" gametype_5v5_long = "Zwei Fünfer-Teams, wer wird vorherschen?" gametype_6v6_short = "Sechs gegen Sechs" gametype_6v6_long = "Zwei Sechser-Teams, macht euch bereit zur Schlacht!" gametype_sffa_short = "Jeder gegen Jeden - klein" gametype_sffa_long = "Können Sie allein 3-5 Gegener besiegen?" gametype_tffa_short = "Jeder gegen Jeden - Team" gametype_tffa_long = "Kann dein Team 1-2 andere besiegen?" gametype_2v2v2_short = "Zwei gegen Zwei gegen Zwei" gametype_2v2v2_long = "Drei Zweier-Teams, können sie das schaffen?" gametype_3v3v3_short = "Drei gegen Drei gegen Drei" gametype_3v3v3_long = "Drei Dreier-Teams bekämpfen sich gegenseitig" gametype_4v4v4_short = "Vier gegen Vier gegen Vier" gametype_4v4v4_long = "Drei Vierer-Teams - wirds langsam eng?" gametype_2v2v2v2_short = "2 gegen 2 gegen 2 gegen 2" gametype_2v2v2v2_long = "Vier Zweier-Teams, ist das eine Herausforderung?" gametype_3v3v3v3_short = "3 gegen 3 gegen 3 gegen 3" gametype_3v3v3v3_long = "Vier Dreier-Teams, die ultimative Herausforderung!" [zhCN] ladder_PG_1v1_desc = "啿Œ‘" ladder_PG_ffa_desc = "混战" ladder_PG_team_desc = "群殴" ladder_AT_2v2_desc = "两人队ä¼" ladder_AT_3v3_desc = "三人队ä¼" ladder_AT_4v4_desc = "四人队ä¼" gametype_1v1_short = "1对1" gametype_1v1_long = "两个玩家一定è¦åˆ†å‡ºä¸ªèƒœè´Ÿã€‚" gametype_2v2_short = "2对2" gametype_2v2_long = "两个队ä¼å±•开对决。" gametype_3v3_short = "3对3" gametype_3v3_long = "两个三人队ä¼è¿›è¡Œå¯¹å†³ã€‚" gametype_4v4_short = "4对4" gametype_4v4_long = "两个四人队ä¼è¿›è¡Œå¯¹å†³ã€‚" gametype_5v5_short = "5对5" gametype_5v5_long = "两个五人队ä¼è¿›è¡Œå¯¹å†³ã€‚" gametype_6v6_short = "6对6" gametype_6v6_long = "两个六人队ä¼è¿›è¡Œå¯¹å†³ã€‚" gametype_sffa_short = " å°åž‹çš„FFA" gametype_sffa_long = "你能å•独击败3到5个对手么?" gametype_tffa_short = " 组队的FFA" gametype_tffa_long = "你能和队å‹åˆä½œå‡»è´¥1到2个对手么?" gametype_2v2v2_short = "2对2对2" gametype_2v2v2_long = "三个队ä¼è¿›è¡Œå¯¹å†³ã€‚" gametype_3v3v3_short = "3对3对3" gametype_3v3v3_long = "三个三人队ä¼è¿›è¡Œå¯¹å†³ã€‚" gametype_4v4v4_short = "4对4对4" gametype_4v4v4_long = "三个四人队ä¼è¿›è¡Œå¯¹å†³ã€‚" gametype_2v2v2v2_short = "2对2对2对2" gametype_2v2v2v2_long = "四个二人队ä¼è¿›è¡Œå¯¹å†³ã€‚" gametype_3v3v3v3_short = "3对3对3对3" gametype_3v3v3v3_long = "四个三人队ä¼è¿›è¡Œå¯¹å†³ã€‚" [ruRU] ladder_PG_1v1_desc = "Игры без правил" ladder_PG_ffa_desc = "Без правил" ladder_PG_team_desc = "Клановые игры" ladder_AT_2v2_desc = "2 Player Team" ladder_AT_3v3_desc = "3 Player Team" ladder_AT_4v4_desc = "4 Player Team" gametype_1v1_short = "1x1" gametype_1v1_long = "ДуÑль двух игроков." gametype_2v2_short = "2x2" gametype_2v2_long = "Два враждующих клана, по 2 игрока в каждом." gametype_3v3_short = "3x3" gametype_3v3_long = "Два враждующих клана, по 3 игрока в каждом." gametype_4v4_short = "4x4" gametype_4v4_long = "Два враждующих клана, по 4 игрока в каждом." gametype_5v5_short = "5x5" gametype_5v5_long = "Два враждующих клана, по 5 игроков в каждом." gametype_6v6_short = "6x6" gametype_6v6_long = "Два враждующих клана, по 6 игроков в каждом." gametype_sffa_short = "ÐœÐ°Ð»Ð°Ñ Ð¸Ð³Ñ€Ð° БП" gametype_sffa_long = "СправишÑÑ Ð² одиночку Ñ 3-5 противниками?" gametype_tffa_short = "Team Free for All" gametype_tffa_long = "СправишÑÑ Ñ 1-2 противниками?" gametype_2v2v2_short = "2x2x2" gametype_2v2v2_long = "Три враждующих клана, по 2 игрока в каждом." gametype_3v3v3_short = "3x3x3" gametype_3v3v3_long = "Три враждующих клана, по 3 игрока в каждом." gametype_4v4v4_short = "4x4x4" gametype_4v4v4_long = "Три враждующих клана, по 4 игрока в каждом." gametype_2v2v2v2_short = "2x2x2x2" gametype_2v2v2v2_long = "Четыре враждующих клана, по 2 игрока в каждом." gametype_3v3v3v3_short = "3x3x3x3" gametype_3v3v3v3_long = "Четыре враждующих клана, по 3 игрока в каждом." [THUMBS_DOWN_LIMIT] PG_1v1 = 3 PG_2v2 = 2 PG_3v3 = 1 PG_4v4 = 1 PG_5v5 = 1 PG_6v6 = 1 PG_ffa = 2 AT_2v2 = 3 AT_3v3 = 2 AT_4v4 = 1 AT_ffa = 0 PG_2v2v2 = 0 PG_3v3v3 = 0 PG_4v4v4 = 0 PG_2v2v2v2 = 0 PG_3v3v3v3 = 0 [ICON_REQUIRED_RACE_WINS_WAR3] Level1 = 25 Level2 = 250 Level3 = 500 Level4 = 1500 [ICON_REQUIRED_RACE_WINS_W3XP] Level1 = 25 Level2 = 150 Level3 = 350 Level4 = 750 Level5 = 1500 [ICON_REQUIRED_TOURNEY_WINS] Level1 = 10 Level2 = 75 Level3 = 150 Level4 = 250 Level5 = 500 pvpgn-1.8.5/conf/sql_DB_layout.conf0000644000175000017500000001156011151345317016202 0ustar aaronaaron# this file determines the layout of the PvPGN SQL database # the server will create the tables with their columns as specified in here # don't forget to create the DB yourself # no empty lines allowed, no whitespaces in front of any entries allowed # file format: # [name_of_a_table] # "column_name with format infos","default value" [&& "sqlcommand to execute on success"] [|| "sqlcommand to execute on failure"] # :"sqlcommand to execute" [&& "sqlcommand to execute on success"] [|| "sqlcommand to execute on failure"] # you might also notice some variables of the form ${variable}. these are # replaced with their meaning when the server starts # ${prefix} is replaced with the configured table prefix from bnetd.conf/storage_path # # For the "sql" SQL layout # [${prefix}BNET] "uid int NOT NULL PRIMARY KEY","'0'" "acct_username varchar(32)","NULL" "username varchar(32)","NULL" && "UPDATE ${prefix}BNET SET username = lower(acct_username)" "acct_userid int","NULL" "acct_passhash1 varchar(128)","NULL" "acct_email varchar(128)","NULL" "auth_admin varchar(16)","'false'" "auth_normallogin varchar(16)","'true'" "auth_changepass varchar(16)","'true'" "auth_changeprofile varchar(16)","'true'" "auth_botlogin varchar(16)","'true'" "auth_operator varchar(16)","'false'" "new_at_team_flag int","'0'" "auth_lockk varchar(16)","'0'" "auth_command_groups varchar(128)","'1'" "acct_lastlogin_time int","'0'" "acct_lastlogin_owner varchar(128)","NULL" "acct_lastlogin_clienttag varchar(128)","NULL" "acct_lastlogin_ip varchar(32)","NULL" :"DROP INDEX username" :"CREATE UNIQUE INDEX username2 ON ${prefix}BNET (username)" [${prefix}WOL] "uid int NOT NULL PRIMARY KEY","'0'" "auth_apgar varchar(8)","NULL" [${prefix}friend] "uid int NOT NULL PRIMARY KEY","'0'" [${prefix}profile] "uid int NOT NULL PRIMARY KEY","'0'" "sex varchar(16)","NULL" "location varchar(128)","NULL" "description varchar(256)","NULL" "age varchar(16)","NULL" "clanname varchar(48)","NULL" [${prefix}Record] "uid int NOT NULL PRIMARY KEY","'0'" "WAR3_solo_xp int","'0'" "WAR3_solo_level int","'0'" "WAR3_solo_wins int","'0'" "WAR3_solo_rank int","'0'" "WAR3_solo_losses int","'0'" "WAR3_team_xp int","'0'" "WAR3_team_level int","'0'" "WAR3_team_rank int","'0'" "WAR3_team_wins int","'0'" "WAR3_team_losses int","'0'" "WAR3_ffa_xp int","'0'" "WAR3_ffa_rank int","'0'" "WAR3_ffa_level int","'0'" "WAR3_ffa_wins int","'0'" "WAR3_ffa_losses int","'0'" "WAR3_orcs_wins int","'0'" "WAR3_orcs_losses int","'0'" "WAR3_humans_wins int","'0'" "WAR3_humans_losses int","'0'" "WAR3_undead_wins int","'0'" "WAR3_undead_losses int","'0'" "WAR3_nightelves_wins int","'0'" "WAR3_nightelves_losses int","'0'" "WAR3_random_wins int","'0'" "WAR3_random_losses int","'0'" "WAR3_teamcount int","'0'" "WAR3_userselected_icon varchar(16)","NULL" "W3XP_solo_xp int","'0'" "W3XP_solo_level int","'0'" "W3XP_solo_wins int","'0'" "W3XP_solo_rank int","'0'" "W3XP_solo_losses int","'0'" "W3XP_team_xp int","'0'" "W3XP_team_level int","'0'" "W3XP_team_rank int","'0'" "W3XP_team_wins int","'0'" "W3XP_team_losses int","'0'" "W3XP_ffa_xp int","'0'" "W3XP_ffa_rank int","'0'" "W3XP_ffa_level int","'0'" "W3XP_ffa_wins int","'0'" "W3XP_ffa_losses int","'0'" "W3XP_orcs_wins int","'0'" "W3XP_orcs_losses int","'0'" "W3XP_humans_wins int","'0'" "W3XP_humans_losses int","'0'" "W3XP_undead_wins int","'0'" "W3XP_undead_losses int","'0'" "W3XP_nightelves_wins int","'0'" "W3XP_nightelves_losses int","'0'" "W3XP_random_wins int","'0'" "W3XP_random_losses int","'0'" "W3XP_teamcount int","'0'" "W3XP_userselected_icon varchar(16)","NULL" "STAR_0_wins int","'0'" "STAR_0_losses int","'0'" "STAR_0_disconnects int","'0'" "STAR_1_wins int","'0'" "STAR_1_losses int","'0'" "STAR_1_disconnects int","'0'" "STAR_0_last_game int","'0'" "STAR_0_last_game_result varchar(128)","NULL" "STAR_1_last_game int","'0'" "STAR_1_last_game_result varchar(128)","NULL" "STAR_1_rating int","'0'" "STAR_1_high_rating int","'0'" "STAR_1_rank int","'0'" "STAR_1_high_rank int","'0'" "SEXP_0_wins int","'0'" "SEXP_0_losses int","'0'" "SEXP_0_disconnects int","'0'" "SEXP_1_wins int","'0'" "SEXP_1_losses int","'0'" "SEXP_1_disconnects int","'0'" "SEXP_0_last_game int","'0'" "SEXP_0_last_game_result varchar(128)","NULL" "SEXP_1_last_game int","'0'" "SEXP_1_last_game_result varchar(128)","NULL" "SEXP_1_rating int","'0'" "SEXP_1_high_rating int","'0'" "SEXP_1_rank int","'0'" "SEXP_1_high_rank int","'0'" [${prefix}clan] "cid int NOT NULL PRIMARY KEY","'0'" "short int","'0'" "name varchar(32)","NULL" "motd varchar(255)","NULL", "creation_time int","'0'" [${prefix}clanmember] "uid int NOT NULL PRIMARY KEY","'0'" "cid int","'0'" "status int","'0'" "join_time int","'0'" [${prefix}arrangedteam] "teamid int NOT NULL PRIMARY KEY","'0'" "size int","0" "clienttag varchar(8)","NULL" "lastgame int","'0'" "member1 int","'0'" "member2 int","'0'" "member3 int","'0'" "member4 int","'0'" "wins int","'0'" "losses int","'0'" "xp int","'0'" "level int","'0'" "rank int","'0'" pvpgn-1.8.5/conf/command_groups.conf0000644000175000017500000001354211151345317016460 0ustar aaronaaron# /////////////////////////////////////////////////////////////////////// # ////////////// Command Groups Configuration File ////////////// # /////////////////////////////////////////////////////////////////////// # # Format of this file is simple. There are 8 different groups. # # Each line must start with the group number followed by as many # commands as you wish. # # Group '1' is common user commands and can be used by any user. # # Rights to use commands in Groups '2' through '8' must be given # to a user using the /commandgroups or /cg command. # # usage /cg [] # # ie. /cg list pvpgnplayer <-- list the current command groups for user # ie. /cg add pvpgnplayer 234 <-- adds groups 2, 3, & 4 to user # ie. /cg del pvpgnplayer 24 <-- deletes groups 2 & 4 from user # # If the following commands were done, pvpgnplayer would have access # to commands in groups 1 & 3 # # Commands not listed in this file will be deactivated by the server # # FILE MODE: # Add the following line to your user file to get access to all groups: # "BNET\\auth\\command_groups"="255" # # For regualar users to be able to use the regualr commands make sure to # use the updated 'bnetd_default_user' file # # SQL MODE: # Issue the following commands to get access to all groups: # ALTER TABLE BNET ADD COLUMN auth_command_groups VARCHAR(128) default '1'; # UPDATE BNET SET auth_command_groups='255' WHERE uid='youruserid' # # For regular users to be able to use the reqular commands # issue the following command: # UPDATE BNET SET auth_command_groups='1' WHERE uid='0' # # [ <...>] # //////////////////////////////////////////////// # ///// Regular commands usable by all users ///// # //////////////////////////////////////////////// 1 /c /clan 1 /f /friends 1 /me 1 /msg /whisper /w /m /r /reply 1 /status /users /lusers 1 /who /whois /whereis /where /whoami 1 /beep /nobeep 1 /version /copyright /warrenty /license 1 /uptime /stats /astat /time 1 /channel /join /rejoin 1 /away /dnd /ignore /squelch /unignore /unsquelch 1 /watch /unwatch /watchall /unwatchall 1 /news /games /channels /chs /admins 1 /logout /quit /exit 1 /ladderinfo 1 /timer /quota 1 /help 1 /mail 1 /motd 1 /tos 1 /bitsinfo 1 /latency /ping /p 1 /topic # ///////////////////////////// # ///// Operator commands ///// # ///////////////////////////// # # -- These commands require the user to be one of the following: # # -- Server Admin - admin status set to true - use --> /admin + # -- can /aop users for any channel # -- can /op & /deop users for any channel # -- can /kick /ban & /unban users for any channel # -- can /vop users for any channel # -- can /voice & /devoice users for any channel # -- Server Operator - operator status set to true - use --> /operator + # -- can /op & /deop users for any channel # -- can /kick /ban & /unban users for any channel # -- can /voice & /devoice users for any channel # -- Channel Admin - admin starus for channel set to true - use --> /aop # -- can /aop users for the channel they are admin of # -- can /op & /deop users for the channel they are admin of # -- can /kick /ban & /unban users for the channel they are admin of # -- can /vop users for the chnnel they are admin of # -- can /voice & /devoice users for the channel they are admin of # -- Channel Operator - operator status for channel set to true - use --> /op # -- can /op & /deop users for the channel they are operator of # -- can /kick /ban & /unban users for the channel they are operator of # -- can /voice & /devoice users for the channel they are operator of # # -- You must be in the channel you wish to give or take Channel Operator or # Channel Admin status too or from. ** /aop /op & /deop ** # -- P.S. You may now have more than one operator and/or admin per channel. # -- No need to make everyone Server Admins. 1 /kick /ban /unban /op /deop /aop /voice /devoice /vop /devop /tmpop /moderate # //////////////////////////////// # ///// Commands with limits ///// # //////////////////////////////// # # -- Although set to Group '1', these command have the following limitations for users. # # -- /admin-con & /admin-addr /admin-chpass are not real commands. # # -- Without 'enable_conn_all = true' in bnetd.conf, only users with access to # /admin-con may use the /con or /connections. 1 /connections /con # -- Without 'hide_addr = false' in bnetd.conf, only users with access to # /admin-addr will see IP Numbers. 1 /games /finger /gameinfo # -- Users may use /chpass on themselves, but require access to # /admin-chpass to change others. # -- Users may use /netinfo on themselves, but require access to # /admin-addr to see others info. 1 /netinfo /chpass # -- /admin-con & /admin-addr /admin-chpass are not real commands. # -- Access to these commands gives more info for the following commands: # /connections /con /games /finger /gameinfo /netinfo /chpass # as described above. 6 /admin-con /admin-addr /admin-chpass # ////////////////////////////////////////// # ///// Command Groups Access Required ///// # ////////////////////////////////////////// # # -- All the following do not require Server Admin Status. # -- They are all locked out for regular users and require access to the Group to Use. # -- Use the /cg command to assign groups to users. 2 /realmann /ann /announce 3 /serverban /ipban 4 /kill /killsession /addacct /lockacct /unlockacct 5 /ladderactivate # 5 /rank_all_accounts # -- Access to group '6' allows users to not only make others Server Admins & Server Operators # but will allow them to make themselves Server Admin & Server Operator. 6 /operator /admin /flag /tag 7 /set /commandgroups /cg /clearstats 8 /shutdown /rehash # ////////////////////////////////////// # ///// End of Command Groups File ///// # ////////////////////////////////////// pvpgn-1.8.5/conf/tournament.conf0000644000175000017500000000611711151345317015637 0ustar aaronaaron# Tournament Settings # # time format: quotes required: # # "MM/DD/YYYY HH:MM:SS" start_preliminary = "08/01/2003 08:00:00" end_signup = "08/01/2003 09:00:00" end_preliminary = "08/01/2003 10:00:00" start_round_1 = "08/01/2003 11:00:00" start_round_2 = "08/01/2003 12:00:00" start_round_3 = "08/01/2003 13:00:00" start_round_4 = "08/01/2003 14:00:00" tournament_end = "08/01/2003 15:00:00" # game selection: # # PG = 1 # AT = 2 game_selection = 1 # game type: # # 1v1 = 1 # 2v2 = 2 # 3v3 = 3 # 4v4 = 4 game_type = 1 # game client: # # due to the fact RoC and FT clients can not play # games together, tournaments must be specified # for one or the other but not both # # RoC = 1 # FT = 2 game_client = 2 # available races: quotes required: # # H = Humans # O = Orcs # N = Night Elves # U = Undead # R = Random races = "HONUR" # Notice Format: quotes required: format = "PvPGN 1v1 Tournament" # Notice Sponsor: quotes required: sponsor = "The PvPGN Team" # Notice Icon: quotes required: #-----------------------------------------------------------------# # Frozen Throne # Reign of Chaos # # R = Ramdom # R = Ramdom # # 2 = Myrmidon # 2 = Green Dragon Whelp # # 3 = Siren # 3 = Blue Dragon # # 4 = Dragon Turtle # 4 = Red Dragon # # 5 = Sea Witch # 5 = Deathwing # # 6 = Illidan # # # H = Human # H = Human # # 2 = Rifleman # 2 = Footman # # 3 = Sorceress # 3 = Knight # # 4 = Spellbreaker # 4 = Archmage # # 5 = Blood Mage # 5 = Medivh # # 6 = Jaina # # # O = Orcs # O = Orcs # # 1 = Peon # 1 = Peon # # 2 = Troll Headhunter # 2 = Grunt # # 3 = Shaman # 3 = Tauren # # 4 = Spirit Walker # 4 = Far Seer # # 5 = Shadow Hunter # 5 = Thrall # # 6 = Rexxar # # # U = Undead # U = Undead # # 2 = Crypt Fiend # 2 = Ghoul # # 3 = Banshee # 3 = Abomination # # 4 = Destroyer # 4 = Lich # # 5 = Crypt Lord # 5 = Tichondrius # # 6 = Sylvanas # # # N = Night Elves # N = Night Elves # # 2 = Huntress # 2 = Archer # # 3 = Druid of the Talon # 3 = Druid of the Claw # # 4 = Dryad # 4 = Priestess of the Moon # # 5 = Keeper of the Grove # 5 = Furion Stormrage # # 6 = Maiev # # # D = Demons # # # 2 = Felguard # # # 3 = Infernal # # # 4 = Doomguard # # # 5 = Pit Lord # # # 6 = Archimonde # # # # # # W3XP = Frozen Throne Icon # WAR3 = Reign of Chaos Icon # #-----------------------------------------------------------------# icon = "R4" # Thumbs down limit: thumbs_down = 0 # Maps section: # # all maps used for tournaments must be included between [MAPS] & [ENDMAPS] # DO NOT use quotes around client tag or map name in this section [MAPS] WAR3 Maps\(8)Battleground.w3m WAR3 Maps\(8)PlainsOfSnow.w3m WAR3 Maps\(8)BloodvenomFalls.w3m WAR3 Maps\(8)GardenOfWar.w3m W3XP Maps\FrozenThrone\(8)Mur'gulOasis.w3x W3XP Maps\FrozenThrone\(8)PlainsOfSnow.w3x W3XP Maps\FrozenThrone\(8)RockQuarry.w3x W3XP Maps\FrozenThrone\(8)Sanctuary.w3x [ENDMAPS] pvpgn-1.8.5/conf/bnalias.conf0000644000175000017500000000655111151345317015056 0ustar aaronaaron############################################################################## # bnalias.list - List of Locally Defined Alias Commands # #----------------------------------------------------------------------------# # # # This file can be used to define shortcuts for often-used commands or for # # unusually long commands. It can also be used to make custom emotes which # # are especially useful for non-English servers. # # # # Lines starting with a # are considered to be comments. # # The format is: # # @ # # aliasname [aliasshortcut1 [aliasshortcut2 [...]]] # # [!]text or command to type as if the player typed it # # [!]%Iinformation to print to the player # # [!]%Eerror to print to the player # # # # Where ! is either an integer representing the number of arguments given to # # the alias by the user or an asterisk (*) meaning it will match any number # # of arguments. The plus sign (+) will match with any non-zero number of # # arguments. # # # # There may be as many lines as you want following the aliasname. If # # multiple lines match they will be executed in the order they are listed. # # # # The text or command is actually formatted text as used in the bnmotd file. # # It contains special formatting characters which can be used to specify the # # type of message or substitue special values (the hostname, the player's # # own name, and many more). These all start with a percent sign (%). There # # are also special formatters which subsitute arguments which were entered # # by the user. These start with a dollar sign. # # # # $* - substitute all arguments here # # $0 through $9 - substitute that argument here (0 means the command) # # ${43} - substitute that argument here (0 means the command) # # ${-19} - substitute arguments 0-19 here # # ${2-} - substitue all arguments from 2 until the end here # # # @ //doubt //dt //d [0]/me looks with doubt [1+]/me looks at ${1-} with doubt @ //numusers //nu [0]%IThere are %u users online. [0]%IThere are %g games online. [0]%IThere are %c channels online. [1+]%EThat command does not take any arguments. @ //askban //ab [2+]/w $1 Please ban ${2-}. @ //statsme //sm [0]/stats %u @ //pvpgn [*]/announce PVPGN rulez! # # ############################################################################## pvpgn-1.8.5/conf/bnissue.txt0000644000175000017500000000015511151345317015001 0ustar aaronaaronBOT or Telnet Connection from [%r] Enter your account name and password. Sorry, there is no guest account. pvpgn-1.8.5/conf/ad.conf0000644000175000017500000000741611151345317014032 0ustar aaronaaron############################################################################## # ad.list - Configuration for bnetd ad banners # #----------------------------------------------------------------------------# # # # Quotes (") are required around the strings, but they are not allowed # # inside them. # # # # The "file name" field should be in the form llXXXXXX.eee where the X's are # # the ad id. The ad id is a non-zero hexadecimal number. The files must be # # in the files/ directory and no path components should be listed here, only # # the filename portion. # # # # The "when" field determines which ad banners should be picked to start a # # sequence. These can be used to make the server avoid picking an "answer" # # banner before its corresponding "question" banner by setting it to "start" # # or "init". The first banner that is chosen when the user logs in is an # # "init" banner. These banners are not reused, so you may want to double # # list them as "start" banners. # # # # The "time" field is the number of seconds that the banner should be # # displayed on the client. If it is zero, the ad will be displayed forever. # # # # The "URL" field is the location that the user will be sent to if (s)he # # clicks on the ad. # # # # The "next" field determines which banner will be displayed next. If it is # # zero, then a start banner may be chosen randomly. # # # # The "client" field determines which banner will be displayed to which # # client. Starting with Warcraft III banners are .mng files which are not # # visible by all clients (and .pcx files dont show on Warcraft III). If this # # field is NULL than it will be shown to all clients _except_ those who have # # a specific clienttag line. # # # --file name-- when- time ---------------URL--------------- --next-- --client-- # "ad000001.mng" init 30 "http://www.pvpgn.org" 0x000000 "WAR3" "ad000001.mng" start 30 "http://www.pvpgn.org" 0x000000 "WAR3" "ad000004.mng" init 30 "http://www.pvpgn.org" 0x000000 "WAR3" "ad000004.mng" start 30 "http://www.pvpgn.org" 0x000000 "WAR3" "ad000001.mng" init 30 "http://www.pvpgn.org" 0x000000 "W3XP" "ad000001.mng" start 30 "http://www.pvpgn.org" 0x000000 "W3XP" "ad000004.mng" init 30 "http://www.pvpgn.org" 0x000000 "W3XP" "ad000004.mng" start 30 "http://www.pvpgn.org" 0x000000 "W3XP" "ad000001.smk" init 30 "http://www.pvpgn.org" 0x000000 "NULL" "ad000001.smk" start 30 "http://www.pvpgn.org" 0x000000 "NULL" #"ad000003.pcx" start 30 "http://www.place.edu/~clanpage" 0x000000 #"ad000002.smk" start 30 "http://www.blah.com/" 0x000004 #"ad000004.smk" norm 30 "http://foo.com/" 0x000000 # # ############################################################################## pvpgn-1.8.5/conf/d2dbs.conf.win320000644000175000017500000001062611151345317015402 0ustar aaronaaron################################################################################# # d2dbs.conf - Configuration file for the Diablo2 Game database server # #-------------------------------------------------------------------------------# # # # This file is an example configuration and may require modification to # # suit your needs or your site. Blank lines and lines starting with a "#" # # are ignored. Use quotes around values that contain spaces. # # # ################################################################################# ################################################################################# # Server Major Settings # #-------------------------------------------------------------------------------# # This is a comma delimited list of hostnames that the server should # listen on. Generally, YOU DONT NEED TO TOUCH THIS but it might be useful # to make an internal-only server on a gateway machine for example. If the # list is not set or if it has a entry with no host component, the server will # bind to that port on all interfaces. # d2dbs default listening port is 6114 # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! servaddrs = 0.0.0.0:6114 # Put here EXACTLY the same thing you put in d2cs.conf gameservlist setting. # For more information about this setting consult the d2cs.conf comments # above it. # # YOU MUST CHANGE THIS OR D2DBS WON'T WORK PROPERLY # # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! gameservlist = , # # ################################################################################# ################################################################################# # Message logs # #-------------------------------------------------------------------------------# # Multiple log levels can be defined by connecting them with a comma (,) # Available loglevels are: # none # trace # debug # info # warn # error # fatal #loglevels = fatal,error,warn,info loglevels = fatal,error,warn,info,debug,trace # # ################################################################################# ################################################################################# # File and Path section # # Use absolute paths in these lines to avoid problems! # #-------------------------------------------------------------------------------# logfile = var\d2dbs.log logfile-gs = var\d2dbs-gs.log charsavedir = var\charsave charinfodir = var\charinfo ladderdir = var\ladders bak_charsavedir = var\bak\charsave bak_charinfodir = var\bak\charinfo # # ################################################################################# ################################################################################# # Misc # #-------------------------------------------------------------------------------# # # # Ladder save interval laddersave_interval = 3600 # Time that allow characters create after it insert into ladder # These code should be rewritted to support string formmated time ladderinit_time = 0 # create extra ladder file in XML format that can be parsed more easy # 0 = turn extra output off (default) # 1 = turn on the XML output XML_ladder_output = 0 # Amount of time to delay shutting down server in seconds. shutdown_delay = 360 # Amount of time delay period is decremented by either a SIGTERM or SIGINT # (control-c) signal in seconds. shutdown_decr = 60 # connection max idle time in seconds idletime = 300 # connection keep alive interval keepalive_interval = 60 # connection time out check interval timeout_checkinterval = 60 # experience threshold, minimum experience needed to register on the ladder ladderupdate_threshold = 0 # What chars will be added to ladder? # 0 = ladder and non-ladder chars # 1 = only ladder chars ladder_chars_only = 1 # This setting activates a workaround for the well known "Lvl 100" bug. # It should be activated for mods where the max level is greater than 99. # Activating this should work for mods with any max level # If level is greater than 255, it will be set to 255 # 0 = deactivated # 1 = activated difficulty_hack = 0 # # ################################################################################# pvpgn-1.8.5/conf/realm.conf0000644000175000017500000000255211151345317014542 0ustar aaronaaron################################################################################# # realm.list - List of Diablo II Realms # #-------------------------------------------------------------------------------# # # # Realms are areas that hold closed characters and games. # # Users are given this list of realms to choose from when # # creating a new character. Next time the character is # # used, they will automatically join the same realm. # # # # The realm server runs on port 6113 by default. # # If you do not specify a port number, it will use this by default. # # # # : the realm name (mandatory; must start and end with " ) # # : the realm description (optional; must start and end with " ) # # ip:port - actual ip the d2cs server is running on (mandatory) # # # # --- realm name --- --- description --- --- real address --- # # (mandatory) (optional) (mandatory) # #-------------------------------------------------------------------------------# # "" [""] # # # ################################################################################# # WARNING!! DO NOT USE "127.0.0.1" or "localhost" FOR ANY IP ADDRESS # example (having a d2cs server running on IP 1.2.3.4): #"D2CS" "PvPGN Closed Realm" 1.2.3.4:6113 pvpgn-1.8.5/conf/d2cs.conf.in0000644000175000017500000001770311151345317014706 0ustar aaronaaron################################################################################# # d2cs.conf - Configuration file for the diablo2 game control server # #-------------------------------------------------------------------------------# # # # This file is an example configuration and may require modification to # # suit your needs or your site. Blank lines and lines starting with a "#" # # are ignored. Use quotes around values that contain spaces. # # # ################################################################################# ################################################################################# # Server Major Settings # #-------------------------------------------------------------------------------# # # # Your realm server name # # Here you put the value of the first column from the realm line in realm.conf # Example, if you have the line # "MyRealm" "My Super Realm" :6113 # in realm.conf then here you put realmname = "MyRealm" realmname = D2CS # This is a comma delimited list of hostnames that the server should # listen on. Generally, YOU DONT NEED TO TOUCH THIS but it might be useful # to make an internal-only server on a gateway machine for example. If the # list is not set or if it has a entry with no host component, the server will # bind to that port on all interfaces. # d2cs default listening port is 6113 # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! servaddrs = 0.0.0.0:6113 # This is a comma delimited list of game servers. Put here the IPs # (without ports) of the machines running d2gs. If you run d2gs on the same # machine as d2cs you put the IP of that machine here. # Example: gameservlist = 192.168.1.10 # (if you have a d2gs running on a machine with the IP 192.168.1.10) # # YOU MUST CHANGE THIS OR D2CS WON'T WORK PROPERLY # # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! gameservlist = , # Put here the address and port of the machine running bnetd (or pvpgn.exe). # If you run d2cs on the same machine as bnetd (or pvpgn.exe) then here you # put the IP of that machine. # # YOU MUST CHANGE THIS OR D2CS WON'T WORK PROPERLY # # bnetd default listening port is 6112 # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! bnetdaddr = :6112 # Set this to the maximum number of concurrent connections allowed on # this server. DO NOT TOUCH UNLESS STRICTLY NECESSARY! max_connections = 1000 # This sets the realm to Classic or LOD or Both # Classic = 0 # LOD = 1 # Both = 2 (default) lod_realm = 2 # This sets whether you can convert a clasic char to # an expansion char. # Allow Convert = 1 # Don't allow Convert = 0 allow_convert = 0 # here u can enter the symbols allowed in accountnames (additional to # alphanumerical symbals which are always accepted). please note that # it is absolutly mandatory that u set up the same symbols here as in # bnetd.conf or else u wont be able to play D2 with some characters # (those whose symbols are allowed in bnetd.conf but not here) # same warnings as in bnetd.conf apply here - be warned - and just # change something if you know what you are doing #default setting is "-_[]" account_allowed_symbols = "-_[]" # # ################################################################################# ################################################################################# # Message logs # #-------------------------------------------------------------------------------# # Multiple log levels can be defined by connecting them with a comma (,) # Available loglevels are: # none # trace # debug # info # warn # error # fatal #loglevels = fatal,error,warn,info loglevels = fatal,error,warn,info,debug,trace # # ################################################################################# ################################################################################# # File and Path section # # Use absolute paths in these lines to avoid problems! # #-------------------------------------------------------------------------------# # # logfile = /usr/local/var/d2cs.log charsavedir = /usr/local/var/charsave charinfodir = /usr/local/var/charinfo bak_charsavedir = /usr/local/var/bak/charsave bak_charinfodir = /usr/local/var/bak/charinfo ladderdir = /usr/local/var/ladders newbiefile = /usr/local/var/files/newbie.save transfile = /usr/local/etc/address_translation.conf d2gsconffile = /usr/local/etc/d2server.ini #pidfile = /usr/local/var/d2cs.pid # # ################################################################################# ################################################################################# # Misc # #-------------------------------------------------------------------------------# # # # Message Of The Day motd = "No Message Of The Day Set" # Set to non-zero to allow creation of new realm character allow_newchar = 1 # Do you want d2cs to check client for multilogin for security reason? check_multilogin = 0 # Maxinum number of character per account # Max allowed value is 18 (enforced by server) maxchar = 8 # Character sorting. Options are: level, mtime, name, none. (none assumed if # not specified). #charlist_sort = "none" # Do we need ascending or descending order for charlist? #charlist_sort_order = "ASC" # Maxinum number of games will be shown in join game list # Zero = infinite maxgamelist = 20 # Set to non-zero to allow show all games with difficulty < character difficulty # Otherwise, only game with difficulty = character difficulty will be shown gamelist_showall = 0 # Maxinum time in seconds that a user can idle # Zero = infinite idletime = 3600 # Amount of time to delay shutting down server in seconds. shutdown_delay = 300 # Amount of time delay period is decremented by either a SIGTERM or SIGINT # (control-c) signal in seconds. shutdown_decr = 60 # ################################################################################# ################################################################################# # Internal System Settings # # You may just ignore them and use the default value # #-------------------------------------------------------------------------------# # # How often will the server purge all list to clean unused data (in seconds) listpurgeinterval = 300 # How often will the server check game queues (in seconds) gqcheckinterval = 60 # How often will the server retry to connect to bnetd # when connection lost (in seconds) s2s_retryinterval = 10 # How long time the s2s connection will timeout s2s_timeout = 10 # How often the server will check server queues for expired data sq_checkinterval = 300 # How long time will a server queue data expire sq_timeout = 300 # Game serer binary files checksum, use zero to skip this checking d2gs_checksum = 0 # Game server version, use zero to skip this checking d2gs_version = 0 # Game server password d2gs_password = "" # Maxinum number of second that a game will be shown on list( zero = infinite ) game_maxlifetime = 0 # A game will be automatically destroied after how long time idle max_game_idletime = 0 # Allow Limitation created game with password, player number or level limit? allow_gamelimit = 1 # Ladder refresh time ladder_refresh_interval = 3600 # server to server connection max idle time in seconds s2s_idletime = 300 # server to server connection keepalive interval s2s_keepalive_interval = 60 # all connection timeout check interval timeout_checkinterval = 60 # game server restart interval # when sending SIGUSR2 signal to your d2cs this issues a restart # of all connected d2gs after d2gs_restart_delay seconds d2gs_restart_delay = 300 # ladder start time # format: yyyy-mm-dd hh:mm:ss # be carefull: # all chars created before this date will revert to non-ladder chars ladder_start_time = "" # number of days before a char expires (default 0=unlimited) char_expire_day = 0 # ################################################################################# pvpgn-1.8.5/conf/d2dbs.conf.in0000644000175000017500000001101011151345317015032 0ustar aaronaaron################################################################################# # d2dbs.conf - Configuration file for the Diablo2 Game database server # #-------------------------------------------------------------------------------# # # # This file is an example configuration and may require modification to # # suit your needs or your site. Blank lines and lines starting with a "#" # # are ignored. Use quotes around values that contain spaces. # # # ################################################################################# ################################################################################# # Server Major Settings # #-------------------------------------------------------------------------------# # This is a comma delimited list of hostnames that the server should # listen on. Generally, YOU DONT NEED TO TOUCH THIS but it might be useful # to make an internal-only server on a gateway machine for example. If the # list is not set or if it has a entry with no host component, the server will # bind to that port on all interfaces. # d2dbs default listening port is 6114 # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! servaddrs = 0.0.0.0:6114 # Put here EXACTLY the same thing you put in d2cs.conf gameservlist setting. # For more information about this setting consult the d2cs.conf comments # above it. # # YOU MUST CHANGE THIS OR D2DBS WON'T WORK PROPERLY # # WARNING!! DO NOT USE "127.0.0.1" or "localhost" !!! gameservlist = , # # ################################################################################# ################################################################################# # Message logs # #-------------------------------------------------------------------------------# # Multiple log levels can be defined by connecting them with a comma (,) # Available loglevels are: # none # trace # debug # info # warn # error # fatal #loglevels = fatal,error,warn,info loglevels = fatal,error,warn,info,debug,trace # # ################################################################################# ################################################################################# # File and Path section # # Use absolute paths in these lines to avoid problems! # #-------------------------------------------------------------------------------# logfile = /usr/local/var/d2dbs.log logfile-gs = /usr/local/var/d2dbs-gs.log charsavedir = /usr/local/var/charsave charinfodir = /usr/local/var/charinfo ladderdir = /usr/local/var/ladders bak_charsavedir = /usr/local/var/bak/charsave bak_charinfodir = /usr/local/var/bak/charinfo #pidfile = /usr/local/var/d2dbs.pid # # ################################################################################# ################################################################################# # Misc # #-------------------------------------------------------------------------------# # # # Ladder save interval laddersave_interval = 3600 # Time that allow characters create after it insert into ladder # These code should be rewritted to support string formmated time ladderinit_time = 0 # create extra ladder file in XML format that can be parsed more easy # 0 = turn extra output off (default) # 1 = turn on the XML output XML_ladder_output = 0 # Amount of time to delay shutting down server in seconds. shutdown_delay = 360 # Amount of time delay period is decremented by either a SIGTERM or SIGINT # (control-c) signal in seconds. shutdown_decr = 60 # connection max idle time in seconds idletime = 300 # connection keep alive interval keepalive_interval = 60 # connection time out check interval timeout_checkinterval = 60 # experience threshold, minimum experience needed to register on the ladder ladderupdate_threshold = 0 # What chars will be added to ladder? # 0 = ladder and non-ladder chars # 1 = only ladder chars ladder_chars_only = 1 # This setting activates a workaround for the well known "Lvl 100" bug. # It should be activated for mods where the max level is greater than 99. # Activating this should work for mods with any max level # If level is greater than 255, it will be set to 255 # 0 = deactivated # 1 = activated difficulty_hack = 0 # # ################################################################################# pvpgn-1.8.5/conf/bnmaps.conf0000644000175000017500000002604711151345317014727 0ustar aaronaaron######### WARCRAFT 3 REIGN OF CHAOS ################# WAR3 1v1 Maps\(2)PlunderIsle.w3m WAR3 1v1 Maps\(4)Frostsabre.w3m WAR3 1v1 Maps\(4)Legends.w3m WAR3 1v1 Maps\(4)LostTemple.w3m WAR3 1v1 Maps\(4)TranquilPaths.w3m WAR3 1v1 Maps\(6)GnollWood.w3m WAR3 1v1 Maps\(6)Moonglade.w3m WAR3 1v1 Maps\(6)ScorchedBasin.w3m WAR3 2v2 Maps\(4)Duskwood.w3m WAR3 2v2 Maps\(4)HarvestMoon.w3m WAR3 2v2 Maps\(4)LostTemple.w3m WAR3 2v2 Maps\(6)GnollWood.w3m WAR3 2v2 Maps\(6)ScorchedBasin.w3m WAR3 2v2 Maps\(6)Stromguarde.w3m WAR3 2v2 Maps\(6)SwampOfSorrows.w3m WAR3 2v2 Maps\(8)GolemsInTheMist.w3m WAR3 2v2 Maps\(8)TheCrucible.w3m WAR3 3v3 Maps\(6)DarkForest.w3m WAR3 3v3 Maps\(6)DragonFire.w3m WAR3 3v3 Maps\(6)Stromguarde.w3m WAR3 3v3 Maps\(6)SwampOfSorrows.w3m WAR3 3v3 Maps\(6)TimbermawHold.w3m WAR3 3v3 Maps\(8)Battleground.w3m WAR3 3v3 Maps\(8)PlainsOfSnow.w3m WAR3 3v3 Maps\(8)TheCrucible.w3m WAR3 4v4 Maps\(8)BlastedLands.w3m WAR3 4v4 Maps\(8)BloodvenomFalls.w3m WAR3 4v4 Maps\(8)GardenOfWar.w3m WAR3 4v4 Maps\(8)GolemsInTheMist.w3m WAR3 4v4 Maps\(8)PetrifiedForest.w3m WAR3 4v4 Maps\(8)PlainsOfSnow.w3m WAR3 4v4 Maps\(8)TheCrucible.w3m WAR3 sffa Maps\(4)HarvestMoon.w3m WAR3 sffa Maps\(4)LostTemple.w3m WAR3 sffa Maps\(4)MysticIsles.w3m WAR3 sffa Maps\(6)GnollWood.w3m WAR3 sffa Maps\(6)ScorchedBasin.w3m WAR3 sffa Maps\(6)Stromguarde.w3m WAR3 sffa Maps\(6)SwampOfSorrows.w3m WAR3 sffa Maps\(8)Battleground.w3m WAR3 sffa Maps\(8)TheCrucible.w3m WAR3 at2v2 Maps\(4)Duskwood.w3m WAR3 at2v2 Maps\(4)HarvestMoon.w3m WAR3 at2v2 Maps\(4)LostTemple.w3m WAR3 at2v2 Maps\(6)GnollWood.w3m WAR3 at2v2 Maps\(6)ScorchedBasin.w3m WAR3 at2v2 Maps\(6)Stromguarde.w3m WAR3 at2v2 Maps\(6)SwampOfSorrows.w3m WAR3 at2v2 Maps\(8)GolemsInTheMist.w3m WAR3 at2v2 Maps\(8)TheCrucible.w3m WAR3 at3v3 Maps\(6)DarkForest.w3m WAR3 at3v3 Maps\(6)DragonFire.w3m WAR3 at3v3 Maps\(6)Stromguarde.w3m WAR3 at3v3 Maps\(6)SwampOfSorrows.w3m WAR3 at3v3 Maps\(6)TimbermawHold.w3m WAR3 at3v3 Maps\(8)Battleground.w3m WAR3 at3v3 Maps\(8)PlainsOfSnow.w3m WAR3 at3v3 Maps\(8)TheCrucible.w3m WAR3 at4v4 Maps\(8)BlastedLands.w3m WAR3 at4v4 Maps\(8)BloodvenomFalls.w3m WAR3 at4v4 Maps\(8)GardenOfWar.w3m WAR3 at4v4 Maps\(8)GolemsInTheMist.w3m WAR3 at4v4 Maps\(8)PetrifiedForest.w3m WAR3 at4v4 Maps\(8)PlainsOfSnow.w3m WAR3 at4v4 Maps\(8)TheCrucible.w3m WAR3 tffa Maps\(4)HarvestMoon.w3m WAR3 tffa Maps\(4)LostTemple.w3m WAR3 tffa Maps\(4)MysticIsles.w3m WAR3 tffa Maps\(6)GnollWood.w3m WAR3 tffa Maps\(6)ScorchedBasin.w3m WAR3 tffa Maps\(6)Stromguarde.w3m WAR3 tffa Maps\(6)SwampOfSorrows.w3m WAR3 tffa Maps\(8)Battleground.w3m WAR3 tffa Maps\(8)TheCrucible.w3m WAR3 5v5 Maps\(10)DustwallowKeys.w3m WAR3 5v5 Maps\(12)DivideAndConquer.w3m WAR3 5v5 Maps\(12)IceCrown.w3m WAR3 6v6 Maps\(12)DivideAndConquer.w3m WAR3 6v6 Maps\(12)IceCrown.w3m WAR3 2v2v2 Maps\(6)DarkForest.w3m WAR3 2v2v2 Maps\(6)DragonFire.w3m WAR3 2v2v2 Maps\(6)Stromguarde.w3m WAR3 2v2v2 Maps\(6)SwampOfSorrows.w3m WAR3 2v2v2 Maps\(6)TimbermawHold.w3m WAR3 2v2v2 Maps\(8)Battleground.w3m WAR3 2v2v2 Maps\(8)PlainsOfSnow.w3m WAR3 2v2v2 Maps\(8)TheCrucible.w3m WAR3 3v3v3 Maps\(9)Riverrun.w3m WAR3 3v3v3 Maps\(10)DustwallowKeys.w3m WAR3 3v3v3 Maps\(12)DivideAndConquer.w3m WAR3 3v3v3 Maps\(12)IceCrown.w3m WAR3 4v4v4 Maps\(12)DivideAndConquer.w3m WAR3 4v4v4 Maps\(12)IceCrown.w3m WAR3 2v2v2v2 Maps\(8)BlastedLands.w3m WAR3 2v2v2v2 Maps\(8)BloodvenomFalls.w3m WAR3 2v2v2v2 Maps\(8)GardenOfWar.w3m WAR3 2v2v2v2 Maps\(8)GolemsInTheMist.w3m WAR3 2v2v2v2 Maps\(8)PetrifiedForest.w3m WAR3 2v2v2v2 Maps\(8)PlainsOfSnow.w3m WAR3 2v2v2v2 Maps\(8)TheCrucible.w3m WAR3 3v3v3v3 Maps\(12)DivideAndConquer.w3m WAR3 3v3v3v3 Maps\(12)IceCrown.w3m WAR3 at2v2v2 Maps\(6)DarkForest.w3m WAR3 at2v2v2 Maps\(6)DragonFire.w3m WAR3 at2v2v2 Maps\(6)Stromguarde.w3m WAR3 at2v2v2 Maps\(6)SwampOfSorrows.w3m WAR3 at2v2v2 Maps\(6)TimbermawHold.w3m WAR3 at2v2v2 Maps\(8)Battleground.w3m WAR3 at2v2v2 Maps\(8)PlainsOfSnow.w3m WAR3 at2v2v2 Maps\(8)TheCrucible.w3m ######### WARCRAFT 3 THE FROZEN THRONE ################# W3XP 1v1 Maps\FrozenThrone\(2)SecretValley.w3x W3XP 1v1 Maps\FrozenThrone\(2)MeltingValley.w3x W3XP 1v1 Maps\FrozenThrone\(2)RoadToStratholme.w3x W3XP 1v1 Maps\FrozenThrone\(2)EchoIsles.w3x W3XP 1v1 Maps\FrozenThrone\(2)TerenasStand.w3x W3XP 1v1 Maps\FrozenThrone\(2)TirisfalGlades.w3x W3XP 1v1 Maps\FrozenThrone\(4)BrokenShard.w3x W3XP 1v1 Maps\FrozenThrone\(4)CentaurGrove.w3x W3XP 1v1 Maps\(4)LostTemple.w3m W3XP 1v1 Maps\FrozenThrone\(4)TidewaterGlades.w3x W3XP 1v1 Maps\FrozenThrone\(4)TurtleRock.w3x W3XP 1v1 Maps\FrozenThrone\(4)TwistedMeadows.w3x W3XP 1v1 Maps\FrozenThrone\(6)GnollWood.w3x W3XP 2v2 Maps\FrozenThrone\(4)CentaurGrove.w3x W3XP 2v2 Maps\FrozenThrone\(4)ExcavationSite.w3x W3XP 2v2 Maps\FrozenThrone\(4)Goldshire.w3x W3XP 2v2 Maps\(4)LostTemple.w3m W3XP 2v2 Maps\FrozenThrone\(4)PhantomGrove.w3x W3XP 2v2 Maps\(4)TranquilPaths.w3m W3XP 2v2 Maps\FrozenThrone\(4)TidewaterGlades.w3x W3XP 2v2 Maps\FrozenThrone\(4)TurtleRock.w3x W3XP 2v2 Maps\FrozenThrone\(4)TwistedMeadows.w3x W3XP 2v2 Maps\FrozenThrone\(4)Wetlands.w3x W3XP 2v2 Maps\FrozenThrone\(6)GnollWood.w3x W3XP 3v3 Maps\FrozenThrone\(6)BloodstoneMesa.w3x W3XP 3v3 Maps\FrozenThrone\(6)CopperCanyon.w3x W3XP 3v3 Maps\FrozenThrone\(6)Dragonblight.w3x W3XP 3v3 Maps\FrozenThrone\(6)Everfrost.w3x W3XP 3v3 Maps\FrozenThrone\(6)GnollWood.w3x W3XP 3v3 Maps\FrozenThrone\(6)Highperch.w3x W3XP 3v3 Maps\FrozenThrone\(6)Monsoon.w3x W3XP 3v3 Maps\FrozenThrone\(6)RiceFields.w3x W3XP 3v3 Maps\FrozenThrone\(6)SilverpineForest.w3x W3XP 3v3 Maps\FrozenThrone\(6)SunrockCove.w3x W3XP 3v3 Maps\FrozenThrone\(6)Typhoon.w3x W3XP 3v3 Maps\FrozenThrone\(6)UpperKingdom.w3x W3XP 4v4 Maps\FrozenThrone\(8)Battleground.w3x W3XP 4v4 Maps\FrozenThrone\(8)Cherryville.w3x W3XP 4v4 Maps\FrozenThrone\(8)Deadlock.w3x W3XP 4v4 Maps\FrozenThrone\(8)DragonFalls.w3x W3XP 4v4 Maps\FrozenThrone\(8)Friends.w3x W3XP 4v4 Maps\FrozenThrone\(8)FullScaleAssault.w3x W3XP 4v4 Maps\FrozenThrone\(8)GoldRush.w3x W3XP 4v4 Maps\(8)GolemsInTheMist.w3m W3XP 4v4 Maps\FrozenThrone\(8)HurricaneIsle.w3x W3XP 4v4 Maps\FrozenThrone\(8)MarketSquare.w3x W3XP 4v4 Maps\FrozenThrone\(8)Mur'gulOasis.w3x W3XP 4v4 Maps\FrozenThrone\(8)Slalom.w3x W3XP sffa Maps\FrozenThrone\(4)Deathrose.w3x W3XP sffa Maps\FrozenThrone\(4)TwistedMeadows.w3x W3XP sffa Maps\FrozenThrone\(6)Duststorm.w3x W3XP sffa Maps\FrozenThrone\(6)EmeraldShores.w3x W3XP sffa Maps\FrozenThrone\(6)Monsoon.w3x W3XP sffa Maps\FrozenThrone\(6)SilverpineForest.w3x W3XP sffa Maps\FrozenThrone\(8)Deadlock.w3x W3XP sffa Maps\FrozenThrone\(8)GoldRush.w3x W3XP sffa Maps\FrozenThrone\(8)HurricaneIsle.w3x W3XP sffa Maps\FrozenThrone\(8)MarketSquare.w3x W3XP sffa Maps\FrozenThrone\(8)Mur'gulOasis.w3x W3XP sffa Maps\FrozenThrone\(8)TwilightRuins.w3x W3XP at2v2 Maps\FrozenThrone\(4)Avalanche.w3x W3XP at2v2 Maps\FrozenThrone\(4)LostTemple.w3x W3XP at2v2 Maps\FrozenThrone\(4)Predators.w3x W3XP at2v2 Maps\FrozenThrone\(4)StoneColdMountain.w3x W3XP at2v2 Maps\FrozenThrone\(4)TwistedMeadows.w3x W3XP at2v2 Maps\FrozenThrone\(6)CopperCanyon.w3x W3XP at2v2 Maps\FrozenThrone\(6)GnollWood.w3x W3XP at2v2 Maps\FrozenThrone\(6)RiverOfSouls.w3x W3XP at2v2 Maps\FrozenThrone\(6)RollingHills.w3x W3XP at2v2 Maps\FrozenThrone\(6)Typhoon.w3x W3XP at3v3 Maps\FrozenThrone\(6)BloodstoneMesa.w3x W3XP at3v3 Maps\FrozenThrone\(6)CopperCanyon.w3x W3XP at3v3 Maps\FrozenThrone\(6)GnollWood.w3x W3XP at3v3 Maps\FrozenThrone(6)HinterlandRaid.w3x W3XP at3v3 Maps\FrozenThrone\(6)Monsoon.w3x W3XP at3v3 Maps\FrozenThrone\(6)RiverOfSouls.w3x W3XP at3v3 Maps\FrozenThrone\(6)RuinsOfStratholme.w3x W3XP at3v3 Maps\FrozenThrone\(6)Typhoon.w3x W3XP at3v3 Maps\FrozenThrone\(6)UpperKingdom.w3x W3XP at3v3 Maps\FrozenThrone\(8)Mur'gulOasis.w3x W3XP at4v4 Maps\FrozenThrone\(8)Battleground.w3x W3XP at4v4 Maps\FrozenThrone\(8)Deadlands.w3x W3XP at4v4 Maps\FrozenThrone\(8)Deadlock.w3x W3XP at4v4 Maps\FrozenThrone\(8)DragonFalls.w3x W3XP at4v4 Maps\FrozenThrone\(8)Feralas.w3x W3XP at4v4 Maps\FrozenThrone\(8)GoldRush.w3x W3XP at4v4 Maps\FrozenThrone\(8)MarketSquare.w3x W3XP at4v4 Maps\FrozenThrone\(8)Mur'gulOasis.w3x W3XP at4v4 Maps\FrozenThrone\(8)TwilightRuins.w3x W3XP tffa Maps\FrozenThrone\(4)Deathrose.w3x W3XP tffa Maps\FrozenThrone\(4)TwistedMeadows.w3x W3XP tffa Maps\FrozenThrone\(6)Duststorm.w3x W3XP tffa Maps\FrozenThrone\(6)EmeraldShores.w3x W3XP tffa Maps\FrozenThrone\(6)Monsoon.w3x W3XP tffa Maps\FrozenThrone\(6)SilverpineForest.w3x W3XP tffa Maps\FrozenThrone\(8)Deadlock.w3x W3XP tffa Maps\FrozenThrone\(8)GoldRush.w3x W3XP tffa Maps\FrozenThrone\(8)HurricaneIsle.w3x W3XP tffa Maps\FrozenThrone\(8)MarketSquare.w3x W3XP tffa Maps\FrozenThrone\(8)Mur'gulOasis.w3x W3XP tffa Maps\FrozenThrone\(8)TwilightRuins.w3x W3XP 5v5 Maps\FrozenThrone\(10)RagingStream.w3x W3XP 5v5 Maps\FrozenThrone\(12)EmeraldGardens.w3x W3XP 6v6 Maps\FrozenThrone\(12)EmeraldGardens.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)BloodstoneMesa.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)CopperCanyon.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)Dragonblight.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)Everfrost.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)GnollWood.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)Highperch.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)Monsoon.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)RiceFields.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)SilverpineForest.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)SunrockCove.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)Typhoon.w3x W3XP 2v2v2 Maps\FrozenThrone\(6)UpperKingdom.w3x W3XP 3v3v3 Maps\FrozenThrone\(9)RoundVillage.w3x W3XP 3v3v3 Maps\FrozenThrone\(10)RagingStream.w3x W3XP 3v3v3 Maps\FrozenThrone\(12)EmeraldGardens.w3x W3XP 4v4v4 Maps\FrozenThrone\(12)EmeraldGardens.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)Battleground.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)Cherryville.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)Deadlock.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)DragonFalls.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)Friends.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)FullScaleAssault.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)GoldRush.w3x W3XP 2v2v2v2 Maps\(8)GolemsInTheMist.w3m W3XP 2v2v2v2 Maps\FrozenThrone\(8)HurricaneIsle.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)MarketSquare.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)Mur'gulOasis.w3x W3XP 2v2v2v2 Maps\FrozenThrone\(8)Slalom.w3x W3XP 3v3v3v3 Maps\FrozenThrone\(12)EmeraldGardens.w3x W3XP at2v2v2 Maps\FrozenThrone\(6)BloodstoneMesa.w3x W3XP at2v2v2 Maps\FrozenThrone\(6)CopperCanyon.w3x W3XP at2v2v2 Maps\FrozenThrone\(6)GnollWood.w3x W3XP at2v2v2 Maps\FrozenThrone(6)HinterlandRaid.w3x W3XP at2v2v2 Maps\FrozenThrone\(6)Monsoon.w3x W3XP at2v2v2 Maps\FrozenThrone\(6)RiverOfSouls.w3x W3XP at2v2v2 Maps\FrozenThrone\(6)RuinsOfStratholme.w3x W3XP at2v2v2 Maps\FrozenThrone\(6)Typhoon.w3x W3XP at2v2v2 Maps\FrozenThrone\(6)UpperKingdom.w3x W3XP at2v2v2 Maps\FrozenThrone\(8)Mur'gulOasis.w3x pvpgn-1.8.5/conf/address_translation.conf0000644000175000017500000001540511151345317017506 0ustar aaronaaron######################################################################################################## #------------------------------------------------------------------------------------------------------# # Address Translation table # #---------------------------------------------------------------------------- # # DO NOT, I REPEAT, DO NOT TOUCH THIS FILE UNLESS YOU RUN THE SERVER ON A # COMPUTER INSIDE A LAN AND YOU NEED TO HAVE PLAYERS FROM "OUTSIDE" YOUR LAN # # This is a list of ip:port addresses that get translated # EVERYTHING AFTER A "#" IS IGNORED (ie COMMENTED) # # The entries are broken into four parts: # # * the IP address w/port to be translated (what pvpgn wants to send initially) # * the output IP address w/port (what pvpgn WILL send after translation) # * comma delimited list of networks to be excluded from translation # * comma delimited list of networks to be included in translation # # Each line must contain all four parts or the entire entry will be rejected # There are no default ports, make sure input and output include the port number # # The entries are searched in the order listed in this file # Exclude networks are searched before include networks # Only the first matching line is used # Lines begining with '#' are ignored # # If no match is found, the input ip will be returned. # # Network specification can be either NONE, ANY or x.y.z.t/bitlen: # - NONE = no neworks (same as 0.0.0.0/32) # - ANY = All networks (same as 0.0.0.0/0) # x.y.z.t/bitlen : means matching the first bitlen bits from the x.y.z.t value # Example: if you have the network 192.168.0.x (where x is from 1 to 255) to # match any IP in it you use "192.168.0.0/24" meaning the first 24 bits of # 192.168.0.0 HAVE TO match (the first 24 bits means the first 3 digits) # ################################################################################# ################################################################################ # w3route server ip translation # # Here you can translate the IP/port of the w3route IP/port as sent by pvpgn # to the WAR3 clients. You need this ONLY if you want to have external W3 # players that will play PlayGame/ArrangedTeam games. # Set exclude to the range of clients you want to recieve the input address # instead of the output address # Set include to the range of clients you want to recieve the output address # # input (ip:port) output (ip:port) exclude (ip/netmask) include (ip/netmask) #----------------- ------------------ ---------------------- ---------------------- # Example, if you left w3route = 0.0.0.0:6200 as it is by default in bnetd.conf # AND you have the external IP 1.2.3.4 AND you want to exclude from translation # the internal W3 clients (those with IPs 192.168.0.x) AND you port forward # port 6200 TCP from your router to the pvpgn server port 6200 then here put: # 0.0.0.0:6200 1.2.3.4:6200 192.168.0.0/24 ANY ############################################################################### # Game Translations for clients/games (client data ports) # # You need this ONLY if you will have internal players that want to play with # external ones. # # This setting is NOT NEEDED for D2 closed realm clients (they connect to d2gs # to play games not to eachover). # # Set input address to the client to be translated # Set output address to the address to be sent to the other clients # Set exclude to the range of clients you want to recieve the input address # instead of the output address # Set include to the range of clients you want to recieve the output address # # input (ip:port) output (ip:port) exclude (ip/netmask) include (ip/netmask) #----------------- ------------------ ---------------------- ---------------------- # Example, if you have an internal client on IP 192.168.1.10 AND you have the # external IP 1.2.3.4 AND you want to exclude from translation the internal # clients (those with IPs 192.168.1.x and 10.x.y.z) AND you port forward # port 6118 TCP AND UDP from your router to the client IP and port 6112 then # here put: #192.168.1.10:6112 1.2.3.4:6118 192.168.1.0/24,10.0.0.0/8 ANY ################################################################################ # Diablo II Character Server translation (d2cs) # # You need this ONLY if you run a d2cs (ie ONLY if you will host a Diablo2 # closed realm). # # Set input address to the ip of d2cs (same as the ip in the realm.conf) # Set output address to the address to be sent to the clients # Set exclude to the range of clients you want to recieve the input address # instead of the output address # Set include to the range of client you want to recieve the output address # # input (ip:port) output (ip:port) exclude (ip/netmask) include (ip/netmask) #----------------- ------------------ ---------------------- ---------------------- # Example, if you run a d2cs on IP 192.168.1.10 port 6113 and you have put the # same IP/port in realm.conf AND you have the external IP 1.2.3.4 AND you want # to exclude from translation the internal clients (those with IPs 192.168.1.x) # AND you port forward port 6113 TCP from your router to the machine running # d2cs and port 6113 then here put: #192.168.1.10:6113 1.2.3.4:6113 192.168.1.0/24 ANY ################################################################################ # Diablo II Game Server Translation (d2gs) # # Set input address to the ip of d2gs (same as the gameservlist in d2cs.conf) # Set output address to the address to be sent to the clients # Set exclude to the range of clients you want to recieve the input address # instead of the output address # Set include to the range of client you want to recieve the output address # # input (ip:port) output (ip:port) exclude (ip/netmask) include (ip/netmask) #----------------- ------------------ ---------------------- ---------------------- # Example, if you run a d2gs on IP 192.168.1.100 (and port 4000, d2gs cannot # listen on other port, it will automatically listen on port 4000) and you have # put the same IP in d2cs.conf and d2dbs.conf gameservlist setting AND you have # the external IP 1.2.3.4 AND you dont want to exclude from translation anyone # AND you port forward port 4000 TCP from your router to the machine running # d2gs and port 4000 then here put: #192.168.1.100:4000 1.2.3.4:4000 NONE ANY ################################################################################ # Westwood Online Game Server Translation (wwol) # # # input (ip:port) output (ip:port) exclude (ip/netmask) include (ip/netmask) #----------------- ------------------ ---------------------- ---------------------- #192.168.1.10:4005 1.2.3.4:4005 192.168.1.0/24 ANY pvpgn-1.8.5/conf/bnetd_default_user.cdb0000644000175000017500000001331511151345317017102 0ustar aaronaaronííííýýýýýý    -==MMMmm}}}}­½ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÝÝÝíýýý  ----==MMMMM]]]]]]mmmmm}}}}­­½ÍÍÍÝýýýýýýýýýýýýý     --=MM]]]m­­­­­½½½ÝÝÝÝÝíííýýýýýýýý    ---=======M]]]}}}}}}}}}}}½½ÍÍÍÍÍÍÍÍÍÍÍÍíííííííííííý        -MM]]mmm}­½Record\SEXP\0\last game resultNONERecord\SEXP\0\last game0Record\SEXP\0\disconnects0Record\SEXP\0\losses0Record\SEXP\0\wins0Record\SEXP\1\last game resultNONERecord\SEXP\1\last game0Record\SEXP\1\high rank0Record\SEXP\1\rank0Record\SEXP\1\high rating0Record\SEXP\1\rating0Record\SEXP\1\disconnects0Record\SEXP\1\losses0Record\SEXP\1\wins0Record\Star\0\last game resultNONERecord\Star\0\last game0Record\Star\0\disconnects0Record\Star\0\losses0Record\Star\0\wins0Record\Star\1\last game resultNONERecord\Star\1\last game0Record\Star\1\high rank0Record\Star\1\rank0Record\Star\1\high rating0Record\Star\1\rating0Record\Star\1\disconnects0Record\Star\1\losses0Record\Star\1\wins0Record\SSHR\0\last game resultNONERecord\SSHR\0\last game0Record\SSHR\0\disconnects0Record\SSHR\0\losses0Record\SSHR\0\wins0BNET\Record\DRTL\0\level0BNET\Record\DRTL\0\class99BNET\Record\DRTL\0\diablo kills0BNET\Record\DRTL\0\strength0BNET\Record\DRTL\0\magic0BNET\Record\DRTL\0\dexterity0BNET\Record\DRTL\0\vitality0BNET\Record\DRTL\0\gold0Record\W2BN\0\last game resultNONERecord\W2BN\0\last game0Record\W2BN\0\disconnects0Record\W2BN\0\losses0Record\W2BN\0\wins0Record\W2BN\1\last game resultNONERecord\W2BN\1\last game0Record\W2BN\1\high rank0Record\W2BN\1\rank0Record\W2BN\1\high rating0Record\W2BN\1\rating0Record\W2BN\1\disconnects0Record\W2BN\1\losses0Record\W2BN\1\wins0Record\W2BN\3\last game resultNONERecord\W2BN\3\last game0Record\W2BN\3\high rank0Record\W2BN\3\rank0Record\W2BN\3\high rating0Record\W2BN\3\rating0Record\W2BN\3\disconnects0Record\W2BN\3\losses0Record\W2BN\3\wins0profile\descriptionprofile\location profile\age profile\sexBNET\acct\usernamebnetd_default_userBNET\acct\userid0(BNET\acct\passhash167452301efcdab8998badcfe10325476c3d2e1f0 BNET\flags\initial0x00000000BNET\auth\command_groups1BNET\auth\normallogintrueBNET\auth\changepasstrueBNET\auth\changeprofiletrueBNET\auth\botlogintrueBNET\auth\w3_require_ipfalseHk Ê!©J “«rÎ eY) ä„ âQé  ýɧ ð ‡ë z` ® €* !0-G#=ãŠ$€{šL %CiI 6ëñg 9e +Ë:×0iO=^x ?ði¿Gñ?hK"ð MKàvRõi X‹?n­ ]P)ˆaÛó²å e§TÜjg (ˆi$¼ªj¤Å¡-m”úÉ n#GtÊ nËz\Š {w‰é€¤jA €Ð†yÉ‚XòÁ* ƒ–ûî…ûkÔ. ˆÚh ‰\ìÕý ‰ÿ}¯° ŠÝŒ· .iè”ͳeì —Iðk —Ú›±œïWógŸ”¦–Χ“öÐ «ÂxŒ«V! ®£»`“ µ¨ßØ ¶ƒV&¤¹Hðlj¹o¸µÄi}&Ê­žå«ÏFk–lÏ+" <Ñ+XóTÝ {( Ý{§»Â èêqzéXk ñ‹\¦óGèK ô¬E´/ô\?!ö†™ÛMøãvmû±-úzüû2K ü$b0f ýrIBÇþñû6‹ ÿϾy©pvpgn-1.8.5/conf/news.txt0000644000175000017500000000155711151345317014314 0ustar aaronaaron{10/01/2006} Welcome To The Player-vs-Player Gaming Network! Bringing Emulation To New Levels! =-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-= ** IF YOU EXPERIENCE PROBLEMS USING THIS SERVER PLEASE REPORT IT TO THE ** ********* ADMINISTRATOR OF THE SERVER NOT TO THE PVPGN TEAM ************ Project development homepage: http://pvpgn.berlios.de Support channels (ONLY for the admins): ======================================== 1. BugTracker (preffered support method): http://sourceforge.net/tracker/?atid=470605&group_id=53514&func=browse 2. Mailing List: pvpgn-users@lists.sourceforge.net (to subscribe go here http://lists.sourceforge.net/lists/listinfo/pvpgn-users ) 3. Forums: https://forums.pvpgn.org 4. Wiki documentation at http://wiki.pvpgn.org 5. IRC live support: #pvpgn on irc.pvpgn.org Enjoy! The PvPGN Team http://www.PvPGN.org pvpgn-1.8.5/conf/supportfile.conf0000644000175000017500000000061511151345317016014 0ustar aaronaaron# this file contains the names of all files that need to be installed in the filedir # (but that aren't any longer part of the pvpgn package) # some lines are commented out, cause they weren't installed by default in older versions IX86ver1.mpq ver-ix86-1.mpq #PMACver1.mpq #XMACver1.mpq bnserver-D2DV.ini #bnserver-D2XP.ini bnserver-WAR3.ini bnserver.ini icons-WAR3.bni icons.bni icons_STAR.bni pvpgn-1.8.5/conf/sql_DB_layout2.conf0000644000175000017500000000534511151345317016270 0ustar aaronaaron# this file determines the layout of the PvPGN SQL database # the server will create the tables with their columns as specified in here # don't forget to create the DB yourself # no empty lines allowed, no whitespaces in front of any entries allowed # file format: # [name_of_a_table] # "column_name with format infos","default value" [&& "sqlcommand to execute on success"] [|| "sqlcommand to execute on failure"] # :"sqlcommand to execute" [&& "sqlcommand to execute on success"] [|| "sqlcommand to execute on failure"] # you might also notice some variables of the form ${variable}. these are # replaced with their meaning when the server starts # ${prefix} is replaced with the configured table prefix from bnetd.conf/storage_path # # For the "sql2" SQL layout # [${prefix}BNET] "uid int NOT NULL","'0'" "name varchar(128) NOT NULL","''" "value varchar(200) NOT NULL","''" :"CREATE UNIQUE INDEX ${prefix}user ON ${prefix}BNET (uid,name)" :"CREATE INDEX ${prefix}user2 ON ${prefix}BNET (name,value)" :"CREATE INDEX ${prefix}user3 ON ${prefix}BNET (uid)" :"INSERT INTO ${prefix}BNET (uid, name, value) VALUES ('0', 'auth\normallogin', 'true')" :"INSERT INTO ${prefix}BNET (uid, name, value) VALUES ('0', 'auth\changepass', 'true')" :"INSERT INTO ${prefix}BNET (uid, name, value) VALUES ('0', 'auth\changeprofile', 'true')" :"INSERT INTO ${prefix}BNET (uid, name, value) VALUES ('0', 'auth\botlogin', 'true')" :"INSERT INTO ${prefix}BNET (uid, name, value) VALUES ('0', 'auth\command_groups' ,'1')" [${prefix}WOL] "uid int NOT NULL","'0'" "name varchar(128) NOT NULL","''" "value varchar(200) NOT NULL","''" :"CREATE UNIQUE INDEX ${prefix}woluser ON ${prefix}WOL (uid,name)" [${prefix}friend] "uid int NOT NULL","'0'" "name varchar(128) NOT NULL","''" "value varchar(200) NOT NULL","''" :"CREATE UNIQUE INDEX ${prefix}friends ON ${prefix}friend (uid,name)" [${prefix}profile] "uid int NOT NULL","'0'" "name varchar(128) NOT NULL","''" "value varchar(200) NOT NULL","''" :"CREATE UNIQUE INDEX ${prefix}profiles ON ${prefix}profile (uid,name)" [${prefix}Record] "uid int NOT NULL","'0'" "name varchar(128) NOT NULL","''" "value varchar(200) NOT NULL","''" :"CREATE UNIQUE INDEX ${prefix}Records ON ${prefix}Record (uid,name)" [${prefix}clan] "cid int NOT NULL PRIMARY KEY","'0'" "short int","'0'" "name varchar(32)","NULL" "motd varchar(255)","NULL", "creation_time int","'0'" [${prefix}clanmember] "uid int NOT NULL PRIMARY KEY","'0'" "cid int","'0'" "status int","'0'" "join_time int","'0'" [${prefix}arrangedteam] "teamid int NOT NULL PRIMARY KEY","'0'" "size int","0" "clienttag varchar(8)","NULL" "lastgame int","'0'" "member1 int","'0'" "member2 int","'0'" "member3 int","'0'" "member4 int","'0'" "wins int","'0'" "losses int","'0'" "xp int","'0'" "level int","'0'" "rank int","'0'" pvpgn-1.8.5/conf/bnetd_default_user.plain0000644000175000017500000001236211151345317017456 0ustar aaronaaron############################################################################## # bnetd_default_user - Default values for user accounts # #----------------------------------------------------------------------------# # # # When a value is not stored in a player's account file, the value is taken # # from this file instead. # # # ############################################################################## ############################################################################## # Game record section # #----------------------------------------------------------------------------# # Brood War stats "Record\\SEXP\\0\\last game result"="NONE" "Record\\SEXP\\0\\last game"="0" "Record\\SEXP\\0\\disconnects"="0" "Record\\SEXP\\0\\losses"="0" "Record\\SEXP\\0\\wins"="0" "Record\\SEXP\\1\\last game result"="NONE" "Record\\SEXP\\1\\last game"="0" "Record\\SEXP\\1\\high rank"="0" "Record\\SEXP\\1\\rank"="0" "Record\\SEXP\\1\\high rating"="0" "Record\\SEXP\\1\\rating"="0" "Record\\SEXP\\1\\disconnects"="0" "Record\\SEXP\\1\\losses"="0" "Record\\SEXP\\1\\wins"="0" # Starcraft stats "Record\\Star\\0\\last game result"="NONE" "Record\\Star\\0\\last game"="0" "Record\\Star\\0\\disconnects"="0" "Record\\Star\\0\\losses"="0" "Record\\Star\\0\\wins"="0" "Record\\Star\\1\\last game result"="NONE" "Record\\Star\\1\\last game"="0" "Record\\Star\\1\\high rank"="0" "Record\\Star\\1\\rank"="0" "Record\\Star\\1\\high rating"="0" "Record\\Star\\1\\rating"="0" "Record\\Star\\1\\disconnects"="0" "Record\\Star\\1\\losses"="0" "Record\\Star\\1\\wins"="0" # Starcraft Shareware stats "Record\\SSHR\\0\\last game result"="NONE" "Record\\SSHR\\0\\last game"="0" "Record\\SSHR\\0\\disconnects"="0" "Record\\SSHR\\0\\losses"="0" "Record\\SSHR\\0\\wins"="0" # Diablo Retail stats "BNET\\Record\\DRTL\\0\\level"="0" "BNET\\Record\\DRTL\\0\\class"="99" "BNET\\Record\\DRTL\\0\\diablo kills"="0" "BNET\\Record\\DRTL\\0\\strength"="0" "BNET\\Record\\DRTL\\0\\magic"="0" "BNET\\Record\\DRTL\\0\\dexterity"="0" "BNET\\Record\\DRTL\\0\\vitality"="0" "BNET\\Record\\DRTL\\0\\gold"="0" # WarCraft II BNE stats "Record\\W2BN\\0\\last game result"="NONE" "Record\\W2BN\\0\\last game"="0" "Record\\W2BN\\0\\disconnects"="0" "Record\\W2BN\\0\\losses"="0" "Record\\W2BN\\0\\wins"="0" "Record\\W2BN\\1\\last game result"="NONE" "Record\\W2BN\\1\\last game"="0" "Record\\W2BN\\1\\high rank"="0" "Record\\W2BN\\1\\rank"="0" "Record\\W2BN\\1\\high rating"="0" "Record\\W2BN\\1\\rating"="0" "Record\\W2BN\\1\\disconnects"="0" "Record\\W2BN\\1\\losses"="0" "Record\\W2BN\\1\\wins"="0" # FIXME: what is 2 for? "Record\\W2BN\\3\\last game result"="NONE" "Record\\W2BN\\3\\last game"="0" "Record\\W2BN\\3\\high rank"="0" "Record\\W2BN\\3\\rank"="0" "Record\\W2BN\\3\\high rating"="0" "Record\\W2BN\\3\\rating"="0" "Record\\W2BN\\3\\disconnects"="0" "Record\\W2BN\\3\\losses"="0" "Record\\W2BN\\3\\wins"="0" # # ############################################################################## ############################################################################## # Default profile info # #----------------------------------------------------------------------------# # No good defaults for these :) "profile\\description"="" "profile\\location"="" "profile\\age"="" "profile\\sex"="" # These 3 are ignored in the template, but they make it easier # to use this file by hand to create a new account... "BNET\\acct\\username"="bnetd_default_user" "BNET\\acct\\userid"="0" "BNET\\acct\\passhash1"="67452301efcdab8998badcfe10325476c3d2e1f0" #"BNET\\fakeclienttag"="WAR3" # # ############################################################################## ############################################################################## # Authorization flags (comments show defaults) # #----------------------------------------------------------------------------# # "BNET\\auth\\admin"="false" "BNET\\auth\\command_groups"="1" # "BNET\\auth\\announce"="false" # "BNET\\auth\\botlogin"="false" # "BNET\\auth\\operator"="false" "BNET\\auth\\normallogin"="true" "BNET\\auth\\changepass"="true" "BNET\\auth\\changeprofile"="true" # "BNET\\auth\\createnormalgame"="true" # "BNET\\auth\\joinnormalgame"="true" # "BNET\\auth\\createladdergame"="true" # "BNET\\auth\\joinladdergame"="true" # "BNET\\auth\\lock"="false" # Specific channels can be specified to override the # channel defaults and the plain operator setting: # (use the long channel name) # "BNET\\auth\\operator\\example channel"="false" "BNET\\auth\\botlogin"="true" # "BNET\\auth\\operator"="false" # Set to "false" to not check IP, set to IP # (like: "192.168.1.2" to require an IP to login for warcraft3) "BNET\\auth\\w3_require_ip"="false" # # ############################################################################## pvpgn-1.8.5/conf/bnetd.conf.in0000644000175000017500000006600111151345317015142 0ustar aaronaaron############################################################################## # bnetd.conf - Configuration file for the main PvPGN service # #----------------------------------------------------------------------------# # # # ############ READ THIS ######### READ THIS ########## READ THIS ############ # This file is an example configuration that should work UNMODIFIED for most # # of the PvPGN setups and may require modification to suit your needs. # # Blank lines and everything after a "#" are ignored. Use quotes around # # values that contain spaces. # # # ############################################################################## ############################################################################## # Privileges to work under # # Use either the names from the corresponding files or numerical id's (with # # a leading '#'). If none are specified, the userid will not be changed. # #----------------------------------------------------------------------------# #effective_user = games #effective_group = games # effective_user = #12 # effective_group = #20 # # ############################################################################## ############################################################################## # Storage section # # storage_path will tell pvpgn how and where from/to to read/write accounts # # right now it supports 2 "drivers" : file and sql # # # # Syntax: # # * for plain file driver: # # storage_path = file:mode=plain;dir=;clan=;default=/path/to/default/account # # * for cdb file driver: # # storage_path = file:mode=cdb;dir=;clan=;default=/path/to/default/account # # * for sql/sql2 driver: # # storage_path = sql:variable=value;...;default=0 (0 is the default uid) # # or storage_path = sql2:variable=value;...;default=0 (0 is the default uid) # # # # Variables for sql/sql2 can be: # # - "mode" : tells PVPGN the sql mode you will use (mysql/pgsql/etc..) # # - "host" : the database host # # - "port" : the TCP/IP port if needed # # - "socket" : the UNIX local socket if needed # # - "name" : database name # # - "user" : db username # # - "pass" : db password # # - "default" : specify the UID to use for the default account data # # - "prefix" : prefix to use for all pvpgn tables (default "") # # # # Examples: # # storage_path = file:mode=plain;dir=/usr/local/var/users;clan=/usr/local/var/clans;team=/usr/local/var/teams;default=/usr/local/etc/bnetd_default_user.plain # storage_path = file:mode=cdb;dir=/usr/local/var/userscdb;clan=/usr/local/var/clans;team=/usr/local/var/teams;default=/usr/local/etc/bnetd_default_user.cdb # storage_path = sql:mode=mysql;host=127.0.0.1;name=PVPGN;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn_ # storage_path = sql:mode=pgsql;host=127.0.0.1;name=pvpgn;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn_ # storage_path = sql:mode=sqlite3;name=/usr/local/var/users.db;default=0;prefix=pvpgn_ # storage_path = sql:mode=odbc;name=PVPGN;prefix=pvpgn_ # # WARNING!! you MUST change "DBlayoutfile" bellow configuration directive to # sql_DB_layout2.conf to be able to use "sql2" !!! # storage_path = sql2:mode=mysql;host=127.0.0.1;name=PVPGN;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn2_ # storage_path = sql2:mode=pgsql;host=127.0.0.1;name=pvpgn;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn2_ # storage_path = sql2:mode=sqlite3;name=/usr/local/var/users.db;default=0;prefix=pvpgn2_ # storage_path = sql2:mode=odbc;name=PVPGN;prefix=pvpgn2_ #----------------------------------------------------------------------------# storage_path = file:mode=plain;dir=/usr/local/var/users;clan=/usr/local/var/clans;team=/usr/local/var/teams;default=/usr/local/etc/bnetd_default_user.plain # # ############################################################################## ############################################################################## # File section # # The pidfile can be set to "" to turn it off. # # Use absolute paths in these lines to avoid problems! # #----------------------------------------------------------------------------# filedir = /usr/local/var/files reportdir = /usr/local/var/reports chanlogdir = /usr/local/var/chanlogs motdfile = /usr/local/etc/bnmotd.txt issuefile = /usr/local/etc/bnissue.txt channelfile = /usr/local/etc/channel.conf newsfile = /usr/local/etc/news.txt adfile = /usr/local/etc/ad.conf topicfile = /usr/local/etc/topics.conf ipbanfile = /usr/local/etc/bnban.conf helpfile = /usr/local/etc/bnhelp.conf mpqfile = /usr/local/etc/autoupdate.conf logfile = /usr/local/var/bnetd.log realmfile = /usr/local/etc/realm.conf maildir = /usr/local/var/bnmail versioncheck_file = /usr/local/etc/versioncheck.conf mapsfile = /usr/local/etc/bnmaps.conf xplevelfile = /usr/local/etc/bnxplevel.conf xpcalcfile = /usr/local/etc/bnxpcalc.conf #pidfile = /usr/local/var/bnetd.pid ladderdir = /usr/local/var/ladders command_groups_file = /usr/local/etc/command_groups.conf tournament_file = /usr/local/etc/tournament.conf statusdir = /usr/local/var/status aliasfile = /usr/local/etc/bnalias.conf anongame_infos_file = /usr/local/etc/anongame_infos.conf DBlayoutfile = /usr/local/etc/sql_DB_layout.conf supportfile = /usr/local/etc/supportfile.conf transfile = /usr/local/etc/address_translation.conf fortunecmd = /usr/games/fortune # # ############################################################################## ############################################################################## # Message logs # #----------------------------------------------------------------------------# # Multiple log levels can be defined by connecting them with a comma (,) # Available loglevels are: # none # trace # debug # info # warn # error # fatal loglevels = fatal,error,warn,info,debug,trace #loglevels = fatal,error,warn,info # # ############################################################################## ############################################################################## # D2CS realm server settings # #----------------------------------------------------------------------------# # Version of D2CS server to connect with (set to zero to disable version check) d2cs_version = 0 # Allow the D2CS server to change realm names? allow_d2cs_setname = true # # ############################################################################## ############################################################################## # Downloadable files # #----------------------------------------------------------------------------# # These filenames are reported directly to the client and are relative to # the "filedir" directory specified above. iconfile = "icons.bni" war3_iconfile = "icons-WAR3.bni" star_iconfile = "icons_STAR.bni" tosfile = "tos.txt" # # ############################################################################## ############################################################################## # Client verification and upgrades # #----------------------------------------------------------------------------# # This option lists the client types allowed to connect (only valid for # the bnet protocol). The list is a comma separated list of any of the # following elements: # all : all client types allowed (default) # chat : client type "CHAT" allowed (used by some bot software) # dshr : client type Diablo 1 Shareware # drtl : client type Diablo 1 (Retail) # sshr : client type Starcraft Shareware # star : client type Starcraft # sexp : client type Starcraft Broodwar # w2bn : client type Warcraft II Battle.Net Edition # d2dv : client type Diablo 2 # d2xp : client type Diablo 2 LOD # war3 : client type Warcraft III (Reign Of Chaos) # w3xp : client type Warcraft III Frozen Throne # # Example: allowed_clients = war3,w3xp allowed_clients = all # If this option is enabled, the verification step is skipped if possible. # This only works with clients < 109. It is useful because you no longer # need any of the IX86AUTH?.MPQ and PMACAUTH?.MPQ files. Note that it will # also skip over all the autoupdate checks effectively disabling it. # # If you disable this you must have one or more of the MPQ files. Otherwise # clients will hang when they first connect because they are attempting to # download them. The versioncheck can only be skipped for clients older # than 109. Starting with version 109 the clients will always do version # checking since they do not function properly if the server does not # request it. skip_versioncheck = false # If you enable the version checks but want to allow clients that don't pass # the checksum test then enable this. allow_bad_version = false # If you enable the version checks but want to allow clients that aren't # listed in the versioncheck configuration file then enable this. Unless # you have a very complete file or are very paranoid about cheaters this # is a good idea. allow_unknown_version = true # This defines how the exeinfo field in the versioncheck file is being # checked. You can choose between no match at all [none] (default), # exact match [exact], exact case-sensitive match [exactcase], dumb wildcard # match [wildcard], and parsed value comparison [parse]. # NOTE: [parse] needs the mktime() function and might therefore not work on # every system. version_exeinfo_match = none # If you have choosen [parse] above, this is the tolerance with which # the time can differ. The value must be given in seconds. If it's 0 this # check is disabled. version_exeinfo_maxdiff = 0 # # ############################################################################## ############################################################################## # Time values # #----------------------------------------------------------------------------# # Time in seconds between account file updates, 0 means wait forever. usersync = 300 # Number of seconds of inactivity before file is unloaded from memory. # (only checked during account file updates) userflush = 1200 # Number of users checked for updates at once. Higher values make sense if you # either have very fast hardware or you don't have many number of accounts. # Lower values make sense if you have very high CPU usage on the system you run # the server (dont make it too low or your system will save accounts continously). # Modify this value ONLY if you know what you are doing!! userstep = 100 # How often to send user latency tests in seconds. latency = 600 # How often to send null or keepalive packets in seconds. nullmsg = 120 # Amount of time to delay shutting down server in seconds. shutdown_delay = 300 # Amount of time delay period is decremented by either a SIGTERM or SIGINT # (control-c) signal in seconds. shutdown_decr = 60 # How often should bans be checked for expiration? (in seconds) #ipban_check_int = 30 # # ############################################################################## ############################################################################## # Policy options # #----------------------------------------------------------------------------# # If you don't want people to be able to create new accounts, set this to # false. new_accounts = true # Set this to the maximum number of accounts you want to allow to be # created on your server. A value of 0 means infinite and is the default. #max_accounts = 0 # If someone attempts to log in more than once, should it kick off the old # login, or deny the new one? kick_old_login = true #kick_old_login = false # With no passwords, this is bad to have enabled --NonReal # load_new_account option has been eliminated and the functionality now is # always active in PvPGN # If a user is creating a new channel, should it be added automatically, or # prompt them first? ask_new_channel = true # Should a game report be written for every game played or just ladder # games? #report_all_games = false report_all_games = true # Should Diablo I/II reports be written? There are no winners/losers. report_diablo_games = false # Should games with passwords be hidden on the game list? hide_pass_games = true # Should games already started be hidden on the game list? (for heavily # loaded servers) hide_started_games = true # Should non-permanent channels hidden on the channel list? hide_temp_channels = true # Should the extended /-commands be avaliable? (of course!) extra_commands = true # Should any and all disconnects to be counted as losses? # (Turning this on will override the user's choice in ladder games!) disc_is_loss = false # List additional game types to be counted as ladder games # Curently allowed types: topvbot, melee, ffa, oneonone # Example: ladder_games = "topvbot,oneonone" ladder_games = "none" # If additional game types are configured (see above) to be counted as ladder # games then this setting configures a game name prefix to make only games # which match this game name prefix be counted as ladder. This allows to # still have normal games of the game types configured with "ladder_games" # directive. However if this setting is commented or "" then ALL games # which match the game types configured with "ladder_games" are to be # considered as ladder games. The prefix checking is CASE SENSITIVE! # Example: ladder_prefix = "ldr_" ladder_prefix = "" # Should all users be able to use the /con and /connections commands? enable_conn_all = true # Should client IP addresses (from /con, /games, /gameinfo, /netinfo) # be hidden from non-admins? hide_addr = false # Should private channel messages be logged to files in the chanlogdir # directory? (see channels.list for public channels) chanlog = false # Do you want to use the channel quota feature? quota = yes # The following options deal with flood prevention. # # How many lines do you accept in quota_time seconds? # (The default should allow 5 lines in 5 seconds, # longer time periods allow "bursts" of traffic before the quota is full.) quota_lines = 5 # must be between 1 and 100 lines quota_time = 5 # must be between 1 and 60 seconds # "virtual wrapping", so long lines count as multiple lines quota_wrapline = 40 # must be between 1 to 256 chars # absolute maximum characters allowed in a line quota_maxline = 200 # must be between 1 to 256 chars # # How many lines do you accept in quota_time seconds before user is # disconnected? # (According to Jung-woo, Dobae is a Korean term for flooding the game server... # it originally meant "to paint the wallpaper on a new or refurbished house"). # If it less than or equal to quota_lines, there is no warning before # disconnection so don't set this too low. quota_dobae = 10 # must be between 1 and 100 lines # Mail support mail_support = true mail_quota = 5 # Channel logging message log_notice = "*** Please note this channel is logged! ***" # Ban on repeated password fails against bruteforce password thieves # Fails required to get ip banned (0 to disable ban on password fail) passfail_count = 0 # Password fail IP ban duration (in seconds) passfail_bantime = 300 # Max users limit in private channels (0 = unlimited) maxusers_per_channel = 0 # # ############################################################################## ############################################################################## # Account configuration # #----------------------------------------------------------------------------# # Should account files be named by the account number or the player name? savebyname = true # Save the account data on logoff sync_on_logoff = false # How man rows should the account lookup hash table have? Servers with # more accounts should use a larger table for better performance. hashtable_size = 61 # Per default, only alphanumerical symbols are allowed in account names # with this variable you can add some extra symbols to be allowed # but be warned - that some of them might cause trouble - at least with # savebyname=true (some symbols are forbidden in filenames or might cause # you real trouble - plz neither allow wildcard symbols like '*' or '?'. # Path delimiters like '/' or '\' are hardcoded filtered and can't be allowed. # Also note that allowing the '.' might cause u some headache on win32 systems. # You have been warned - the rest is up to you. # default setting is "-_[]" as it was previous versions account_allowed_symbols = "-_[]" # This setting affects users that login with their uid rather than their # username. If set to true their displayed username will be forcefully # converted to their registered account name. account_force_username = false # maximum number of friends a user can add to there friends list # default setting is 20 max_friends = 20 # # ############################################################################## ############################################################################## # Tracking server info # #----------------------------------------------------------------------------# # Set track=0 to disable tracking. Any other number will set number # of seconds between sending tracking packets. This is OFF by default. #track = 0 track = 60 # 10 minutes # Tracking server(s) # Use a comma delimited list of hostnames with optional UDP port numbers # after colons. (port 6114 is the default for the newer tracking protocol) #trackaddrs = "track.bnetd.org,localhost:9999" #trackaddrs = "track.pvpgn.org" # Change these to match your system, for example: location = "unknown" description = "unknown" url = "unknown" contact_name = "a PvPGN user" contact_email = "unknown" # # ############################################################################## ############################################################################## # Server network info # #----------------------------------------------------------------------------# # Servername by which the server identifies itself (default: "PvPGN Realm") #servername = "PvPGN Realm" # Set this to the maximum number of concurrent connections allowed on # this server (minimum 32). This limit sets a general server connection # limit, NOT the concurrent user limit (for that see next option) max_connections = 1000 # Maximum number of concurrent users (0 means unlimited). max_concurrent_logins = 0 # Set this option to true to allow TCP to detect and close stale # connections. use_keepalive = false # Limit maximum number of connections per IP (0 = unlimited) # this feature is new, so no recommended value so far max_conns_per_IP = 0 # This is a comma delimited list of hostnames that the server should # listen on. It might be useful to make an internal-only server on a # gateway machine for example. If the list is not set or if it has a # entry with no host component, the server will bind to that port on all # interfaces. #servaddrs = ":9999" #servaddrs = "myinternalname.some.com,localhost" servaddrs = ":" # default interface (all) and default port (6112) # Don't change these unless you really need to! You will need to run a proxy # or modify the clients. Also note that these will not change when simply # sending a HUP signal to the server; they are only read on startup. # This is the port the server send the UDP test packets to by default. # Setting it to zero makes the server use the same port as the TCP connection # comes from. Newer clients can override this setting on a per connection # basis. #udptest_port = 6112 # W3 Play Game router address. Just put your server address in here # or use 0.0.0.0:6200 for server to bind to all interfaces, # but make sure you set up w3trans if you do. w3routeaddr = "0.0.0.0:6200" # w3routeshow has been removed. # see the address_translation.conf for translating the w3route ip for local networks # initkill_timer sets up a periodic timer on init/defer class connections # this should detect and clean up stale connections to your server initkill_timer = 120 # # ############################################################################## ############################################################################## # Westwood Online (WOL) configuration # #----------------------------------------------------------------------------# # NOTE: WOL support is still experimental! # This specifies the addresses where IRC connections should be accepted. See # the description of servaddrs for formatting information. Leave this field # blank if you do not want to accept IRC connections. If the port is not # specifed then 4005 will be used. Note: DO NOT SET THE PORT TO ANYTHING OTHER # THEN 4005, WOL WILL FAIL IF YOU DO! #woladdrs = ":4005" # Just leave these as default (unless you know the timezone, longitiude and latitude # of your server woltimezone = "-8" wollongitude = "36.1083" wollatitude = "-115.0582" # # ############################################################################## ############################################################################## # Internet Relay Chat (IRC) configuration # #----------------------------------------------------------------------------# # NOTE: IRC support is still experimental! # This specifies the addresses where IRC connections should be accepted. See # the description of servaddrs for formatting information. Leave this field # blank if you do not want to accept IRC connections. If the port is not # specified then 6667 will be used. #ircaddrs = ":6667" # This is the IRC network name. If this is not specified then the default of # "PvPGN" will be used. #irc_network_name = "PvPGN" # This is the hostname used for IRC connections. Set this to your # hostname, if the automatic detection doesn't correctly. #hostname = "none" # Set this to the desired IRC connection timeout in seconds. #irc_latency = 180 # # ############################################################################## ############################################################################## # Telnet configuration # #----------------------------------------------------------------------------# # This specifies the addresses where telnet connections should be accepted. # See the description of servaddrs for formatting information. Leave this # field # blank if you do not want to accept telnet connections. If the port # is not specifed then 23 will be used. #telnetaddrs = ":23" ############################################################################### # war3 ladder textual output # #-----------------------------------------------------------------------------# # this is for all the guys, that want Warcraft 3 ladder, but don't want their # server to run with MySQL support. # For each ladder (solo, team, ffa, at) a corresponing file is created, # so it's easy to build your ladder pages with them # the following value determines, at which rate, these files are created # set to 0 if you don't want or need these files war3_ladder_update_secs = 300 # jfro's latest ladder is based on XML... so we can switch to XML output of ladder # on demand XML_output_ladder = false ############################################################################### # server status textual output # #-----------------------------------------------------------------------------# # This is for writing status of the server in an attempt to see number of user # on line actually, and games/chans. # This is store in file var\status\warcraft3.dat as a *.ini format. # Shouldn't be so hard in php to create dynamic website using this content. # the following value determines, at which rate, these files are created # set to 0 if you don't want or need these files output_update_secs = 60 # jfro's latest ladder is based on XML... so we can switch to XML output of ladder # on demand. Maybe we should set update interval bigger cause XML output version # is much more verbose than the standard output XML_status_output = false ############################################################################### # clan settings # #-----------------------------------------------------------------------------# # Time in hours for a new member of clan to be a newer(Peon icon, cannot promote to Grunt) # default value 168(7 days). If set to 0, all new members could be promote in no time clan_newer_time = 0 # max members count allowed in a clan, set between 10 and 100, default 50. clan_max_members = 50 # Default clan channel status when create a clan, 1 for private, 0 for public clan_channel_default_private = 0 pvpgn-1.8.5/conf/bnetd.conf.win320000644000175000017500000006360611151345317015506 0ustar aaronaaron############################################################################## # bnetd.conf - Configuration file for the Unix Battle.net daemon # #----------------------------------------------------------------------------# # # # This file is an example configuration and may require modification to # # suit your needs or your site. Blank lines and lines starting with a "#" # # are ignored. Use quotes around values that contain spaces. # # # ############################################################################## ############################################################################## # Storage section # # storage_path will tell pvpgn how and where from/to to read/write accounts # # right now it supports 2 "drivers" : file and sql # # # # Syntax: # # * for plain file driver: # # storage_path = file:mode=plain;dir=;clan=;team=;default=/path/to/default/account # # * for cdb file driver: # # storage_path = file:mode=cdb;dir=;clan=;team=;default=/path/to/default/account # # * for sql/sql2 driver: # # storage_path = sql:variable=value;...;default=0 (0 is the default uid) # # or storage_path = sql2:variable=value;...;default=0 (0 is the default uid) # # # # Variables for sql/sql2 can be: # # - "mode" : tells PVPGN the sql mode you will use (mysql/pgsql/etc..) # # - "host" : the database host # # - "port" : the TCP/IP port if needed # # - "socket" : the UNIX local socket if needed # # - "name" : database name # # - "user" : db username # # - "pass" : db password # # - "default" : specify the UID to use for the default account data # # - "prefix" : prefix to use for all pvpgn tables (default "") # # # # Examples: # # storage_path = file:mode=plain;dir=var\users;clan=var\clans;team=var\teams\;default=conf\bnetd_default_user.plain # storage_path = file:mode=cdb;dir=var\userscdb;clan=var\clans;team=var\teams\;default=conf\bnetd_default_user.cdb # storage_path = sql:mode=mysql;host=127.0.0.1;name=PVPGN;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn_ # storage_path = sql:mode=pgsql;host=127.0.0.1;name=pvpgn;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn_ # storage_path = sql:mode=sqlite3;name=var\users.db;default=0;prefix=pvpgn_ # storage_path = sql:mode=odbc;name=PVPGN;prefix=pvpgn_ # storage_path = sql2:mode=mysql;host=127.0.0.1;name=PVPGN;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn_ # storage_path = sql2:mode=pgsql;host=127.0.0.1;name=pvpgn;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn_ # storage_path = sql2:mode=sqlite3;name=var\users.db;default=0;prefix=pvpgn_ # storage_path = sql2:mode=odbc;name=PVPGN;prefix=pvpgn_ #----------------------------------------------------------------------------# storage_path = file:mode=plain;dir=var\users;clan=var\clans;team=var\teams;default=conf\bnetd_default_user.plain # # ############################################################################## ############################################################################## # File section # # The pidfile can be set to "" to turn it off. # # Use absolute paths in these lines to avoid problems! # #----------------------------------------------------------------------------# filedir = files reportdir = var\reports chanlogdir = var\chanlogs motdfile = conf\bnmotd.txt issuefile = conf\bnissue.txt channelfile = conf\channel.conf newsfile = conf\news.txt adfile = conf\ad.conf topicfile = conf\topics.conf ipbanfile = conf\bnban.conf helpfile = conf\bnhelp.conf transfile = conf\address_translation.conf mpqfile = conf\autoupdate.conf logfile = var\bnetd.log realmfile = conf\realm.conf versioncheck_file = conf\versioncheck.conf mapsfile = conf\bnmaps.conf xplevelfile = conf\bnxplevel.conf xpcalcfile = conf\bnxpcalc.conf #pidfile = var\bnetd.pid ladderdir = var\ladders command_groups_file = conf\command_groups.conf statusdir = var\status aliasfile = conf\bnalias.conf anongame_infos_file = conf\anongame_infos.conf DBlayoutfile = conf\sql_DB_layout.conf supportfile = conf\supportfile.conf fortunecmd = bin\fortune.exe # # ############################################################################## ############################################################################## # Message logs # #----------------------------------------------------------------------------# # Multiple log levels can be defined by connecting them with a comma (,) # Available loglevels are: # none # trace # debug # info # warn # error # fatal #loglevels = fatal,error,warn,info,debug,trace loglevels = fatal,error # # ############################################################################## ############################################################################## # D2CS realm server settings # #----------------------------------------------------------------------------# # Version of D2CS server to connect with (set to zero to disable version check) d2cs_version = 0 # Allow the D2CS server to change realm names? allow_d2cs_setname = true # # ############################################################################## ############################################################################## # Downloadable files # #----------------------------------------------------------------------------# # These filenames are reported directly to the client and are relative to # the "filedir" directory specified above. iconfile = "icons.bni" war3_iconfile = "icons-WAR3.bni" star_iconfile = "icons_STAR.bni" tosfile = "tos.txt" # # ############################################################################## ############################################################################## # Client verification and upgrades # #----------------------------------------------------------------------------# # This option lists the client types allowed to connect (only valid for # the bnet protocol). The list is a comma separated list of any of the # following elements: # all : all client types allowed (default) # chat : client type "CHAT" allowed (used by some bot software) # dshr : client type Diablo 1 Shareware # drtl : client type Diablo 1 (Retail) # sshr : client type Starcraft Shareware # star : client type Starcraft # sexp : client type Starcraft Broodwar # w2bn : client type Warcraft II Battle.Net Edition # d2dv : client type Diablo 2 # d2xp : client type Diablo 2 LOD # war3 : client type Warcraft III (Reign Of Chaos) # w3xp : client type Warcraft III Frozen Throne # # Example: allowed_clients = war3,w3xp allowed_clients = all # If this option is enabled, the verification step is skipped if possible. # This only works with clients < 109. It is useful because you no longer # need any of the IX86AUTH?.MPQ and PMACAUTH?.MPQ files. Note that it will # also skip over all the autoupdate checks effectively disabling it. # # If you disable this you must have one or more of the MPQ files. Otherwise # clients will hang when they first connect because they are attempting to # download them. The versioncheck can only be skipped for clients older # than 109. Starting with version 109 the clients will always do version # checking since they do not function properly if the server does not # request it. skip_versioncheck = false # If you enable the version checks but want to allow clients that don't pass # the checksum test then enable this. allow_bad_version = false # If you enable the version checks but want to allow clients that aren't # listed in the versioncheck configuration file then enable this. Unless # you have a very complete file or are very paranoid about cheaters this # is a good idea. allow_unknown_version = true # This defines how the exeinfo field in the versioncheck file is being # checked. You can choose between no match at all [none] (default), # exact match [exact], exact case-sensitive match [exactcase], dumb wildcard # match [wildcard], and parsed value comparison [parse]. # NOTE: [parse] needs the mktime() function and might therefore not work on # every system. version_exeinfo_match = none # If you have choosen [parse] above, this is the tolerance with which # the time can differ. The value must be given in seconds. If it's 0 this # check is disabled. version_exeinfo_maxdiff = 0 # # ############################################################################## ############################################################################## # Time values # #----------------------------------------------------------------------------# # Time in seconds between account file updates, 0 means wait forever. usersync = 300 # Number of seconds of inactivity before file is unloaded from memory. # (only checked during account file updates) userflush = 1200 # Number of users checked for updates at once. Higher values make sense if you # either have very fast hardware or you don't have many number of accounts. # Lower values make sense if you have very high CPU usage on the system you run # the server (dont make it too low or your system will save accounts continously). # Modify this value ONLY if you know what you are doing!! userstep = 100 # How often to send user latency tests in seconds. latency = 600 # How often to send null or keepalive packets in seconds. nullmsg = 120 # Amount of time to delay shutting down server in seconds. shutdown_delay = 300 # Amount of time delay period is decremented by either a SIGTERM or SIGINT # (control-c) signal in seconds. shutdown_decr = 60 # How often should bans be checked for expiration? (in seconds) #ipban_check_int = 30 # # ############################################################################## ############################################################################## # Policy options # #----------------------------------------------------------------------------# # If you don't want people to be able to create new accounts, set this to # false. new_accounts = true # Set this to the maximum number of accounts you want to allow to be # created on your server. A value of 0 means infinite and is the default. #max_accounts = 0 # If someone attempts to log in more than once, should it kick off the old # login, or deny the new one? kick_old_login = true #kick_old_login = false # With no passwords, this is bad to have enabled --NonReal # load_new_account option has been eliminated and the functionality now is # always active in PvPGN # If a user is creating a new channel, should it be added automatically, or # prompt them first? ask_new_channel = true # Should a game report be written for every game played or just ladder # games? #report_all_games = false report_all_games = true # Should Diablo I/II reports be written? There are no winners/losers. report_diablo_games = false # Should games with passwords be hidden on the game list? hide_pass_games = true # Should games already started be hidden on the game list? (for heavily # loaded servers) hide_started_games = true # Should non-permanent channels hidden on the channel list? hide_temp_channels = true # Should the extended /-commands be avaliable? (of course!) extra_commands = true # Should any and all disconnects to be counted as losses? # (Turning this on will override the user's choice in ladder games!) disc_is_loss = false # List additional game types to be counted as ladder games # Curently allowed types: topvbot, melee, ffa, oneonone # Example: ladder_games = "topvbot,oneonone" ladder_games = "none" # If additional game types are configured (see above) to be counted as ladder # games then this setting configures a game name prefix to make only games # which match this game name prefix be counted as ladder. This allows to # still have normal games of the game types configured with "ladder_games" # directive. However if this setting is commented or "" then ALL games # which match the game types configured with "ladder_games" are to be # considered as ladder games. The prefix checking is CASE SENSITIVE! # Example: ladder_prefix = "ldr_" ladder_prefix = "" # Should all users be able to use the /con and /connections commands? enable_conn_all = true # Should client IP addresses (from /con, /games, /gameinfo, /netinfo) # be hidden from non-admins? hide_addr = false # Should private channel messages be logged to files in the chanlogdir # directory? (see channels.list for public channels) chanlog = false # Do you want to use the channel quota feature? quota = yes # The following options deal with flood prevention. # # How many lines do you accept in quota_time seconds? # (The default should allow 5 lines in 5 seconds, # longer time periods allow "bursts" of traffic before the quota is full.) quota_lines = 5 # must be between 1 and 100 lines quota_time = 5 # must be between 1 and 60 seconds # "virtual wrapping", so long lines count as multiple lines quota_wrapline = 40 # must be between 1 to 256 chars # absolute maximum characters allowed in a line quota_maxline = 200 # must be between 1 to 256 chars # # How many lines do you accept in quota_time seconds before user is # disconnected? # (According to Jung-woo, Dobae is a Korean term for flooding the game server... # it originally meant "to paint the wallpaper on a new or refurbished house"). # If it less than or equal to quota_lines, there is no warning before # disconnection so don't set this too low. quota_dobae = 10 # must be between 1 and 100 lines # Mail support mail_support = true mail_quota = 5 # Channel logging message log_notice = "*** Please note this channel is logged! ***" # Ban on repeated password fails against bruteforce password thieves # Fails required to get ip banned (0 to disable ban on password fail) passfail_count = 0 # Password fail IP ban duration (in seconds) passfail_bantime = 300 # Max users limit in private channels (0 = unlimited) maxusers_per_channel = 0 # # ############################################################################## ############################################################################## # Account configuration # #----------------------------------------------------------------------------# # Should account files be named by the account number or the player name? savebyname = true # Save the account data on logoff sync_on_logoff = false # How man rows should the account lookup hash table have? Servers with # more accounts should use a larger table for better performance. hashtable_size = 61 # Per default, only alphanumerical symbols are allowed in account names # with this variable you can add some extra symbols to be allowed # but be warned - that some of them might cause trouble - at least with # savebyname=true (some symbols are forbidden in filenames or might cause # you real trouble - plz neither allow wildcard symbols like '*' or '?'. # Path delimiters like '/' or '\' are hardcoded filtered and can't be allowed. # Also note that allowing the '.' might cause u some headache on win32 systems. # You have been warned - the rest is up to you. # default setting is "-_[]" as it was previous versions account_allowed_symbols = "-_[]" # This setting affects users that login with their uid rather than their # username. If set to true their displayed username will be forcefully # converted to their registered account name. account_force_username = false # maximum number of friends a user can add to there friends list # default setting is 20 max_friends = 20 # # ############################################################################## ############################################################################## # Tracking server info # #----------------------------------------------------------------------------# # Set track=0 to disable tracking. Any other number will set number # of seconds between sending tracking packets. This is OFF by default. #track = 0 track = 60 # 10 minutes # Tracking server(s) # Use a comma delimited list of hostnames with optional UDP port numbers # after colons. (port 6114 is the default for the newer tracking protocol) #trackaddrs = "track.bnetd.org,localhost:9999" #trackaddrs = "track.pvpgn.org" # Change these to match your system, for example: location = "unknown" description = "unknown" url = "unknown" contact_name = "a PvPGN user" contact_email = "unknown" # # ############################################################################## ############################################################################## # Server network info # #----------------------------------------------------------------------------# # Servername by which the server identifies itself (default: "PvPGN Realm") #servername = "PvPGN Realm" # Set this to the maximum number of concurrent connections allowed on # this server (minimum 32). This limit sets a general server connection # limit, NOT the concurrent user limit (for that see next option) max_connections = 1000 # Maximum number of concurrent users (0 means unlimited). max_concurrent_logins = 0 # Set this option to true to allow TCP to detect and close stale # connections. use_keepalive = false # Limit maximum number of connections per IP (0 = unlimited) # this feature is new, so no recommended value so far max_conns_per_IP = 0 # This is a comma delimited list of hostnames that the server should # listen on. It might be useful to make an internal-only server on a # gateway machine for example. If the list is not set or if it has a # entry with no host component, the server will bind to that port on all # interfaces. #servaddrs = ":9999" #servaddrs = "myinternalname.some.com,localhost" servaddrs = ":" # default interface (all) and default port (6112) # Don't change these unless you really need to! You will need to run a proxy # or modify the clients. Also note that these will not change when simply # sending a HUP signal to the server; they are only read on startup. # This is the port the server send the UDP test packets to by default. # Setting it to zero makes the server use the same port as the TCP connection # comes from. Newer clients can override this setting on a per connection # basis. #udptest_port = 6112 # W3 Play Game router address. Just put your server address in here # or use 0.0.0.0:6200 for server to bind to all interfaces, # but make sure you set up w3trans if you do. w3routeaddr = "0.0.0.0:6200" # w3routeshow has been removed. # see the address_translation.conf for translating the w3route ip for local networks # initkill_timer sets up a periodic timer on init/defer class connections # this should detect and clean up stale connections to your server initkill_timer = 120 # # ############################################################################## ############################################################################## # Westwood Online (WOL) configuration # #----------------------------------------------------------------------------# # NOTE: WOL support is still experimental! # This specifies the addresses where IRC connections should be accepted. See # the description of servaddrs for formatting information. Leave this field # blank if you do not want to accept IRC connections. If the port is not # specifed then 4005 will be used. Note: DO NOT SET THE PORT TO ANYTHING OTHER # THEN 4005, WOL WILL FAIL IF YOU DO! #woladdrs = ":4005" # Just leave these as default (unless you know the timezone, longitiude and latitude # of your server woltimezone = "-8" wollongitude = "36.1083" wollatitude = "-115.0582" # # ############################################################################## ############################################################################## # Internet Relay Chat (IRC) configuration # #----------------------------------------------------------------------------# # NOTE: IRC support is still experimental! # This specifies the addresses where IRC connections should be accepted. See # the description of servaddrs for formatting information. Leave this field # blank if you do not want to accept IRC connections. If the port is not # specifed then 6667 will be used. #ircaddrs = ":6667" # This is the IRC network name. If this is not specified then the default of # "PvPGN" will be used. #irc_network_name = "PvPGN" # This is the hostname used for IRC connections. Set this to your # hostname, if the automatic detection doesn't correctly. #hostname = "none" # Set this to the desired IRC connection timeout in seconds. #irc_latency = 180 # # ############################################################################## ############################################################################## # Telnet configuration # #----------------------------------------------------------------------------# # This specifies the addresses where telnet connections should be accepted. # See the description of servaddrs for formatting information. Leave this # field # blank if you do not want to accept telnet connections. If the port # is not specifed then 23 will be used. #telnetaddrs = ":23" # # ############################################################################## ############################################################################### # war3 ladder textual output # #-----------------------------------------------------------------------------# # this is for all the guys, that want Warcraft 3 ladder, but don't want their # server to run with MySQL support. # For each ladder (solo, team, ffa, at) a corresponing file is created, # so it's easy to build your ladder pages with them # the following value determines, at which rate, these files are created # set to 0 if you don't want or need these files war3_ladder_update_secs = 300 # jfro's latest ladder is based on XML... so we can switch to XML output of ladder # on demand. Maybe we should set update interval bigger cause XML output version # is much more verbose than the standard output XML_output_ladder = false ############################################################################### # server status textual output # #-----------------------------------------------------------------------------# # This is for writing status of the server in an attempt to see number of user # on line actually, and games/chans. # This is store in file var\status\warcraft3.dat as a *.ini format. # Shouldn't be so hard in php to create dynamic website using this content. # the following value determines, at which rate, these files are created # set to 0 if you don't want or need these files output_update_secs = 60 # jfro's latest ladder is based on XML... so we can switch to XML output of ladder # on demand. Maybe we should set update interval bigger cause XML output version # is much more verbose than the standard output XML_status_output = false ############################################################################### # clan settings # #-----------------------------------------------------------------------------# # Time in hours for a new member of clan to be a newer(Peon icon, cannot promote to Grunt) # default value 168(7 days). If set to 0, all new members could be promote in no time clan_newer_time = 0 # max members count allowed in a clan, set between 10 and 100, default 50. clan_max_members = 50 # Default clan channel status when create a clan, 1 for private, 0 for public clan_channel_default_private = 0 pvpgn-1.8.5/conf/bnxpcalc.conf0000644000175000017500000000107311151345317015231 0ustar aaronaaron# This file is used to compute the XP points gained/lost by Warcraft III # anonymous matchmaking games # # # # Note: you may notice that blizzard has columns for points win/loss by # higher and lower opponets but because they must keep constant the sum # of points the columns are in "mirror" # used for all players 50 0 100 100 100 100 50 1 95 105 115 85 50 2 90 110 130 70 50 3 85 115 145 55 50 4 80 120 155 45 50 5 75 125 165 35 50 6 70 130 175 25 pvpgn-1.8.5/conf/bnxplevel.conf0000644000175000017500000000225511151345317015441 0ustar aaronaaron# This file is used mainly for computing the level of players and # teams on W3 Anonymous Matchmaking, the format is: # # # # FIXME: Min Games is not used right now 1 0 0 0.11 0 2 100 100 0.11 0 3 200 200 0.11 0 4 400 200 0.25 0 5 600 300 0.25 0 6 900 300 0.43 0 7 1200 400 0.43 0 8 1600 400 0.67 0 9 2000 500 0.67 0 10 2500 500 1.00 0 11 3000 500 1.00 1 12 3500 500 1.00 1 13 4000 500 1.00 1 14 4500 500 1.00 1 15 5000 500 1.00 1 16 5500 500 1.00 1 17 6000 500 1.00 1 18 6500 500 1.00 1 19 7000 500 1.00 1 20 7500 500 1.00 1 21 8000 500 1.00 1 22 8500 500 1.00 2 23 9000 500 1.00 2 24 9500 500 1.00 2 25 10000 500 1.00 2 26 10500 500 1.00 2 27 11000 500 1.00 2 28 11500 500 1.00 2 29 12000 500 1.00 2 30 12500 500 1.00 2 31 13000 500 1.00 3 32 13500 500 1.00 3 33 14000 500 1.00 3 34 14500 500 1.00 3 35 15000 500 1.00 3 36 15500 500 1.00 3 37 16000 500 1.00 3 38 16500 500 1.00 3 39 17000 500 1.00 3 40 17500 500 1.00 3 41 18000 500 1.00 4 42 18500 500 1.00 4 43 19000 500 1.00 4 44 19500 500 1.00 4 45 20000 500 1.00 4 46 20500 500 1.00 4 47 21000 500 1.00 4 48 21500 500 1.00 4 49 22000 500 1.00 4 50 22500 500 1.00 4 pvpgn-1.8.5/IGNOREME0000644000175000017500000000350711151345317012777 0ustar aaronaaronNOTE: we believe that most people are more likely to read IGNOREME file than the README file so we moved the actual contents of README into this file. We hope that this will improve the quality of questions on support channels. Readme for Player vs. Player Gaming Network --------------------------------------------- PvPGN is a BNETD mod which aims to provide support for all Blizzard clients (thus it supports all BNETD supported clients plus the most recent ones). The list of supported clients and their minimum verion required is: * Battle.Net games: - Diablo 1 v1.09 - Starcraft v1.08 - BroodWar v1.08 - Warcraft II Battle.Net Edition v2.02 - Diablo 2 v1.10 - Diablo 2 LOD v1.10 - Warcraft III Reign Of Chaos v1.13 - Warcraft III Frozen Throne v1.13 * Westwood Online games: - Dune 2000 v1.06 - Tiberian Sun v2.03 ST-10 - Red Alert 2 v1.006 - Yuri's Revenge v1.001 ----- The documentation is located in the docs directory. Please read docs/INDEX for a list of files and what they contain. If you are updating from a previous PvPGN version check the file UPDATE first. ----- We're always looking for good coders (C coders) or anyone who can contribute to our project in any way. Project homepages/distribution sites: - project home and main distribution site: http://pvpgn.berlios.de - alternate project home: http://www.pvpgn.org - alternate distribution site: http://developer.berlios.de/project/showfiles.php?group_id=2291 Support channels: 1. BugTracker (preffered support method): http://developer.berlios.de/bugs/?group_id=2291 2. Mailing List: pvpgn-users@lists.berlios.de ( to subscribe go here https://lists.berlios.de/mailman/listinfo/pvpgn-users ) 3. Wiki: http://wiki.pvpgn.org 4. Forums: http://forums.pvpgn.org 5. IRC live support: #pvpgn on irc.pvpgn.org pvpgn-1.8.5/man/0000755000175000017500000000000011151345372012416 5ustar aaronaaronpvpgn-1.8.5/man/bntext.50000644000175000017500000000601411151345317014010 0ustar aaronaaron.\" .\" Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) .\" Copyright (C) 1998,1999,2000 Ross Combs (ross@bnetd.org) .\" Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH bntext 5 "2 August, 2001" .SH NAME bnmotd.txt, bnnews.txt bnissue.txt \- messages for the Unix Battle.net daemon .SH DESCRIPTION The file .I bnmotd.txt contains text displayed by .BR bnetd (1), when users first log into the server. .LP The file .I bnnews.txt contains text displayed when the user uses the /news chat command. .LP The files consist of raw text with printf-style formatting escapes. Each line of a file can contain a type formatter from the following list: .RS .TP .B %B Use the broadcast attribute (???). .TP .B %C Execute the line as if the user entered it as a command. .TP .B %E Use the error attribute (red). .TP .B %I Use the info attribute (yellow). This is the same was .B %W. .TP .B %M Normal chat message (white). This will appear as if the user said it. .TP .B %T Emote chat message (???). This will appear as if the user said it. .TP .B %W Use the warning attribute (yellow). This is the same was .B %I. .RE .LP Within a line, any of the following format formatters may be used: .RS .TP .B %% Expand to a literal percent sign (%). .TP .B %a Expand to the number of accounts on the server. .TP .B %c Expand to the number of channels on the server. This includes all permanent and current temporary channels. .TP .B %g Expand to the number of games on the server. This includes both public and private (passworded) games. .TP .B %h Expand to the hostname of the server (as returned by .BR gethostname (2)). .TP .B %i Expand to this user's account ID number, formatted with a leading pound (#) sign and leading zeros. .TP .B %l Expand to this user's current chat name which is usually the same .TP .B %r Expand to the IP of the remote machine (the client). .TP .B %t Expand to four character client tag. .TP .B %u Expand to the number of users logged into the server. .TP .B %v Expand to the version number of the server. .RE .SH "SEE ALSO" .TP .BR bnetd (1) .SH AUTHOR .TP Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bnftp.10000644000175000017500000000622711151345317013617 0ustar aaronaaron.\" .\" Copyright (C) 1998,1999 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNFTP 1 "11 June, 2000" "BNETD" "BNETD User's Manual" .SH NAME bnftp \- Battle.net file transfer client .SH SYNOPSIS .B bnftp [\fIoptions\fP] [\fIservername\fP [\fIserverport\fP]] .SH DESCRIPTION .B bnftp is a simple program for downloading data files from a bnetd server. These files include \fItos.txt\fP, upgrade MPQ archives, and ad banners. .LP If no \fIservername\fP is specified, localhost is assumed. If no \fIserverport\fP is specified, 6112 is assumed. .LP After the program is started it will connect to the server and then prompt for the filename to download. No directory components may be used in the filename. The file is copied to a file with the same name in the current directory. .SH OPTIONS .TP .B \-b Causes .B bnftp to emulate a Brood Wars client. .TP .B \--client Causes .B bnftp to emulate a specific client. The following client tags are recognized: DRTL DSHR STAR SSHR SEXP W2BN. There are short options which may be used instead for the common clients. .TP .B \-d Causes .B bnftp to emulate a Diablo client. .TP .B \-h --help --usage Print usage information and exit. .TP .B \-s Causes .B bnftp to emulate a Starcraft client. .TP .B \-v --version Print its version number and exit. .TP .B \-w Causes .B bnftp to emulate a Warcraft II BNE client. .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS This program assumes that the terminal will move to the beginning of the current line when the carriage return character (^M) is printed. It also assumes the backspace character (^H) will move one column to the left that character printed after that will replace those already on the screen. .LP The terminal settings are not consulted for keybindings. The following are assumed: .TP ^H delete the character to the left of the cursor .TP ^J accept current line .TP ^M (return) accept current line .TP ^T transpose the last two characters .TP ^W delete word to the left of the cursor .TP ^U delete the whole input line .TP ^[ (escape) cancel the current input line .TP ^? (delete) delete the character to the left of the cursor .SH "SEE ALSO" .BR bnetd (1) .SH AUTHOR Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bniextract.10000644000175000017500000000417311151345317014647 0ustar aaronaaron.\" .\" Copyright (C) 2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNIEXTRACT 1 "6 November, 2000" "BNETD" "BNETD User's Manual" .SH NAME bniextract \- extract a directory of Targa icon files from a Battle.net icon file .SH SYNOPSIS .B bniextract [\fIoptions\fP] [--] \fIbnifile\fP \fIoutputdir\fP .SH DESCRIPTION .B bniextract is a simple program which will convert a single Battle.net icon file into a directory with a text file named .I bniindex.lst and associated Targa image file. If .I bnifile is specified as "-", the standard input will be used. .SH OPTIONS .TP .B \-h --help --usage Print usage information and exit. .TP .B \-v --version Print its version number and exit. .TP .B -- Signal end of options. Any further arguments will be treated as filenames even if they begin with a "-". .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS The purpose of some of the fields in the BNI format are not known. Only true-color formats are currently supported. .SH "SEE ALSO" .BR bnetd (1), .BR bni2tga (1), .BR bnibuild (1), .BR bnilist (1), .BR tgainfo (1) .SH AUTHORS .TP Marco Ziech (\fImmz@gmx.net\fP) and Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bnibuild.10000644000175000017500000000426611151345317014277 0ustar aaronaaron.\" .\" Copyright (C) 2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNIBUILD 1 "6 November, 2000" "BNETD" "BNETD User's Manual" .SH NAME bnibuild \- build a Battle.net icon file from a directory of Targa icon files .SH SYNOPSIS .B bnibuild [\fIoptions\fP] [--] \fIinputdir\fP [\fIbnifile\fP] .SH DESCRIPTION .B bnibuild is a simple program which will convert a directory with a text file named .I bniindex.lst and associated Targa image file into a single Battle.net icon file. .LP If .I bnifile is not specified or is specified as "-", the standard output will be used. .LP FIXME: specify format of bniindex.lst .SH OPTIONS .TP .B \-h --help --usage Print usage information and exit. .TP .B \-v --version Print its version number and exit. .TP .B -- Signal end of options. Any further arguments will be treated as filenames even if they begin with a "-". .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS The purpose of some of the fields in the BNI format are not known. Only true-color formats are currently supported. .SH "SEE ALSO" .BR bnetd (1), .BR bni2tga (1), .BR bniextract (1), .BR bnilist (1), .BR tgainfo (1) .SH AUTHORS .TP Marco Ziech (\fImmz@gmx.net\fP) and Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bni2tga.10000644000175000017500000000454611151345317014036 0ustar aaronaaron.\" .\" Copyright (C) 2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNI2TGA 1 "6 November, 2000" "BNETD" "BNETD User's Manual" .SH NAME bni2tga \- convert a Battle.net icon file to a Targa file .SH SYNOPSIS .B bni2tga [\fIoptions\fP] [--] [\fIbnifile\fP [\fItgafile\fP]] .SH DESCRIPTION .B bni2tga is a simple program which will convert the icons in a Battle.net icon file into a TGA file with the icons arranged vertically. .LP The specific variant of TGA that is used will depend on the input file, but typically it will be a 28 pixel wide, true-color, 24bit, run-length encoded image with no attributes. .LP If .I bnifile is not specified or is specified as "-", the standard input will be used. If .I tgafile is not specified or is specified as "-", the standard output will be used. .SH OPTIONS .TP .B \-h --help --usage Print usage information and exit. .TP .B \-v --version Print its version number and exit. .TP .B -- Signal end of options. Any further arguments will be treated as filenames even if they begin with a "-". .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS The purpose of some of the fields in the BNI format are not known. Only true-color formats are currently supported. .SH "SEE ALSO" .BR bnetd (1), .BR bnibuild (1), .BR bniextract (1), .BR bnilist (1), .BR tgainfo (1) .SH AUTHORS .TP Marco Ziech (\fImmz@gmx.net\fP) and Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/tgainfo.10000644000175000017500000000406211151345317014130 0ustar aaronaaron.\" .\" Copyright (C) 2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH TGAINFO 1 "6 November, 2000" "BNETD" "BNETD User's Manual" .SH NAME tgainfo \- display information about a Targa image .SH SYNOPSIS .B tgainfo [\fIoptions\fP] [--] [\fItgafile\fP] .SH DESCRIPTION .B tgainfo is a simple program which will display information from the TGA header. This information may be useful for determining if a file is in the correct format for .BR bnibuild (1) or other programs. .LP If .I tgafile is not specified or is specified as "-", the standard input will be used. .SH OPTIONS .TP .B \-h --help --usage Print usage information and exit. .TP .B \-v --version Print its version number and exit. .TP .B -- Signal end of options. Any further arguments will be treated as filenames even if they begin with a "-". .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS Only a subset of all the possible Targa formats are recognized properly. .SH "SEE ALSO" .BR bnetd (1), .BR bni2tga (1), .BR bnibuild (1), .BR bniextract (1), .BR bnilist (1) .SH AUTHOR .TP Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bnilist.10000644000175000017500000000441711151345317014151 0ustar aaronaaron.\" .\" Copyright (C) 2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNILIST 1 "6 November, 2000" "BNETD" "BNETD User's Manual" .SH NAME bnilist \- list contents of a Battle.net icon file .SH SYNOPSIS .B bnilist [\fIoptions\fP] [--] [\fIbnifile\fP] .SH DESCRIPTION .B bnilist is a simple program which will list all the icons stored in a BNI file along with their attributes. Additionally, information is displayed from the TGA header in the same format as .BR tgainfo (1) would use. Some simple sanity checks are also done to verify the file is using the same format as expected by the other bni utilities. .LP If .I bnifile is not specified or is specified as "-", the standard input will be used. .SH OPTIONS .TP .B \-h --help --usage Print usage information and exit. .TP .B \-v --version Print its version number and exit. .TP .B -- Signal end of options. Any further arguments will be treated as filenames even if they begin with a "-". .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS The purpose of some of the fields in the BNI format are not known. Only true-color formats are currently supported. .SH "SEE ALSO" .BR bnetd (1), .BR bni2tga (1), .BR bnibuild (1), .BR bniextract (1), .BR tgainfo (1) .SH AUTHORS .TP Marco Ziech (\fImmz@gmx.net\fP) and Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bnchat.10000644000175000017500000001021011151345317013730 0ustar aaronaaron.\" .\" Copyright (C) 1998,1999,2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNCHAT 1 "09 April, 1999" "BNETD" "BNETD User's Manual" .SH NAME bnchat \- Battle.net text-based chat client .SH SYNOPSIS .B bnchat [\fIoptions\fP] [\fIservername\fP [\fIserverport\fP]] .SH DESCRIPTION .B bnchat is a simple Battle.net client emulator that can be used as a minimal chat client with .BR bnetd (1) in order to test certain aspects of the server configuration or to do server administration from the Unix command line. It is also compatible with FSGS servers, but has difficulty with real Battle.net servers. .LP If no \fIservername\fP is specified, localhost is assumed. If no \fIserverport\fP is specified, 6112 is assumed. .SH OPTIONS .TP .B \-a --ansi-color Allows .B bnchat to use ANSI terminal color escapes to make things more readable. You must be using a terminal compatible with VT100 positioning and ANSI color codes. The program will not attempt to determine your terminal type. .TP .B \-b Causes .B bnchat to emulate a Brood Wars client. .TP .B \-c --change-password Causes .B bnchat to prompt for a new login password on the .BR bnetd (1) server. .TP .B \--client Causes .B bnchat to emulate a specific client. The following client tags are recognized: DRTL DSHR STAR SSHR SEXP W2BN. There are short options which may be used instead for the common clients. .TP .B \-d Causes .B bnchat to emulate a Diablo client. .TP .B \-h --help --usage Print usage information and exit. .TP .B \-k --cdkey Causes .B bnchat to report an alternate key to the .BR bnetd (1) server. .TP .B \-o --owner Causes .B bnchat to report an alternate owner to the .BR bnetd (1) server. .TP .B \-n --new-account Causes .B bnchat to prompt to create a new player account on the .BR bnetd (1) server. .TP .B \-s Causes .B bnchat to emulate a Starcraft client. .TP .B \-v --version Print its version number and exit. .TP .B \-w Causes .B bnchat to emulate a Warcraft II BNE client. .SH NOTES The terminal width is attempted to be determined at runtime but if it does not work you may need to try running .BR resize (1) . As a final act of desperation you can try setting the COLUMNS environmental variable. .LP If SIGWINCH and its associated .BR ioctl (2) are supported on your system, resizing the window while the program is running should immediately update width of the entry line. .LP The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS This program assumes that the terminal will move to the beginning of the current line when the carriage return character (^M) is printed. It also assumes the backspace character (^H) will move one column to the left that character printed after that will replace those already on the screen. .LP The terminal settings are not consulted for keybindings. The following are assumed: .TP ^H delete the character to the left of the cursor .TP ^J accept current line .TP ^M (return) accept current line .TP ^T transpose the last two characters .TP ^W delete word to the left of the cursor .TP ^U delete the whole input line .TP ^[ (escape) cancel the current input line .TP ^? (delete) delete the character to the left of the cursor .SH "SEE ALSO" .BR bnetd (1) .SH AUTHOR Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bntrackd.10000644000175000017500000000670511151345317014277 0ustar aaronaaron.\" .\" Copyright (C) 2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNPROXY 1 "12 September, 2000" "BNETD" "BNETD User's Manual" .SH NAME bnproxy \- bnetd tracking daemon .SH SYNOPSIS .B bntrackd [\fIoptions\fP] .BR .SH DESCRIPTION .B bntrackd is a simple daemon which will listen for UDP announcement packets sent by .BR bnetd (1) servers. The list of servers and their statistics is written to a text file an optionally processed by an external program. A .BR perl (1) script is provided which processes this information to produce an HTML document suitable for display on the web. .LP .BR bnetd (1) servers must be configured to report to tracking servers. The .BR bnetd.conf (5) file allows for multiple tracking servers to be listed separated by commas. The master server is track.bnetd.org. Please consider including that server in your configuration. .SH OPTIONS .TP .B \-c --command Run the specified command after writing server information to \fIoutfile\fP. If this option is not specified, the command "scripts/process.pl" is executed from the directory that .B bntrackd was started. If an empty string is provided for \fIcommand\fP, no command will be executed. .TP .B \-e --expire Set the period of time in seconds to keep server information without receiving new updates. If this option is not specified, 600 seconds is used. .TP .B \-d --debug Place additional informational messages in the event log. .TP .B \-h --help --usage Print usage information and exit. .TP .B \-l --logfile Put the event log messages into the specified file. If this option is not specified, the file "logs/bntrackd.log" will be written from the directory that .B bntrackd was started. If an empty string is provided for \fIlogfile\fP, no event messages will be written. .TP .TP .B \-o --outfile Put the server information into the specified file \fIoutfile\fP.. .TP .B \-p --port Listen for announcements on the specified UDP port number. If this option is not specified, the port number defaults to 6114. .TP .B \-P --pidfile Record the process ID of the tracking daemon in the specified file. If this option is not specified, this information is not written to any file. .TP .B \-u --update Set the period of time in seconds between updates of the \fIoutfile\fP. If this option is not specified, 150 seconds is used. .TP .B \-v --version Causes .B bntrackd to print its version number and exit. .SH NOTES .TP The current version is available at: .LP .RS .I http://www.bnetd.org/ .RE .SH "SEE ALSO" .BR bnetd (1), .BR perl (1) .SH AUTHOR Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bnstat.10000644000175000017500000000725711151345317014005 0ustar aaronaaron.\" .\" Copyright (C) 2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNSTAT 1 "11 June, 2000" "BNETD" "BNETD User's Manual" .SH NAME bnstat \- Battle.net statisics client .SH SYNOPSIS .B bnstat [\fIoptions\fP] [\fIservername\fP [\fIserverport\fP]] .SH DESCRIPTION .B bnstat is a simple Battle.net client emulator that can be used to gather player statistics. It is also compatible with FSGS servers, but has difficulty with real Battle.net servers. .LP If no \fIservername\fP is specified, localhost is assumed. If no \fIserverport\fP is specified, 6112 is assumed. If no player is specified on the command line, .BR bnstat (1) will connect to the server and prompt for one from stdin. All avaliable statistics for the emulated client type are formatted and displayed on stdout. .SH OPTIONS .TP .B \-b Causes \fBbnstat\fP to emulate a Brood Wars client. .TP .B \--client Causes \fBbnstat\fP to emulate a specific client. The following client tags are recognized: DRTL DSHR STAR SSHR SEXP W2BN. There are short options which may be used instead for the common clients. .TP .B \--bnetd Also attempt to gather .BR bnetd (1) specific information. .TP .B \-d Causes \fBbnstat\fP to emulate a Diablo client. .TP .B \--fsgs Also attempt to gather FSGS specific information. .TP .B \-h --help --usage Print usage information and exit. .TP .B \-k --cdkey Causes \fBbnstat\fP to report an alternate key to the .BR bnetd (1) server. .TP .B \-o --owner Causes \fBbnstat\fP to report an alternate owner to the .BR bnetd (1) server. .TP .B \-p --player Gather statistics only for the specified player and then exit. This also avoids using login and terminal functions allowing it to be used in shell scripts. .TP .B \-s Causes \fBbnstat\fP to emulate a Starcraft client. .TP .B \-v --version Print its version number and exit. .TP .B \-w Causes \fBbnstat\fP to emulate a Warcraft II BNE client. .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS This program assumes that the terminal will move to the beginning of the current line when the carriage return character (^M) is printed. It also assumes the backspace character (^H) will move one column to the left that character printed after that will replace those already on the screen. .LP The terminal settings are not consulted for keybindings. The following are assumed: .TP ^H delete the character to the left of the cursor .TP ^J accept current line .TP ^M (return) accept current line .TP ^T transpose the last two characters .TP ^W delete word to the left of the cursor .TP ^U delete the whole input line .TP ^[ (escape) cancel the current input line .TP ^? (delete) delete the character to the left of the cursor .SH "SEE ALSO" .BR bnetd (1) .SH AUTHOR Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bnpcap.10000644000175000017500000000327411151345317013750 0ustar aaronaaron.\" .\" Copyright (C) 2001 Hakan Tandogan (hakan@gurkensalat.com) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNPCAP 1 "07 July, 2001" "BNETD" "BNETD Developers's Manual" .SH NAME bnpcap .SH SYNOPSIS .B bnpcap [\fB-d\fP] [\fB-v\fP] <\fIpcap-filename\fP> .SH DESCRIPTION .B bnpcap is a utility to decode packet dumps from .B tcpdump into a developer-readable format .SH OPTTIONS .TP .B \-h Print usage information and exit .TP .B \-d Print out debugging information .TP .B \-v Be more verbose .LP You have to generate the dumps with .B tcpdump \-i <\fIyour_interface\fP> \-s 2000 \-w <\fIpcap-filename\fP> .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH "SEE ALSO" .BR bnetd (1), .BR tcpdump (1) .SH AUTHOR Marco Ziech (\fmmz@gmx.net\fP) pvpgn-1.8.5/man/bnetd.10000644000175000017500000000763611151345317013607 0ustar aaronaaron.\" .\" Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) .\" Copyright (C) 1998,1999 Ross Combs (ross@bnetd.org) .\" Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNETD 1 "12 June, 2000" "BNETD" "The bnetd Project" .SH NAME bnetd \- Unix Battle.net daemon .SH SYNOPSIS .B bnetd [\fB-f\fP] [\fB-c\fP \fIconfigfile\fP] [\fB-d\fP \fIdumpfile\fP] .SH DESCRIPTION .B bnetd is a program that will eventually completely emulate a Blizzard Battle.net server. Currently Starcraft, Brood War, Diablo, and Warcraft II BNE are supported as clients. .LP It is known to work under most versions of Unix and can also be used under Windows as a win32 console application. .SH OPTIONS .TP .B \-c --config Use this configuration file instead of the compiled-in default location. .TP .B \-d --hexdump Put a hex dump of packets sent and received into the specified file. .TP .B \-f --foreground The server normally acts as a daemon and goes into the background. This forces the server to run in the foreground. .TP .B \-h --help --usage Print server usage information and exit. .TP .B \-v --version Print its version number and exit. .SH FILES .TP .I bnetd.conf The main configuration file. Among other things, it specifies the locations for the other files used by the daemon. .TP .I bnmotd.txt The "message of the day" file. This is displayed when the user enters the first chat channel. .TP .I bnetd_default_user This is the default account file. The contains all default account attributes which are used when an attribute is not set on an actual account. .I channel.list This is the permanent channel list. Short names, target clients, and other attributes may be specified here. .TP .I news.txt The contensts of this file are printed when the /news command is used. .TP .I ad.list This is the ad banner list which determines which banners to display at which times. The order of display for the banners may be specified as well as the URL which they should follow when clicked. .TP .I bnban The IP ban file can be used to block connections from certain addresses. .TP .I bnhelp This file contains the the chat command help. .TP .I gametrans The game address translation file can be used to allow players from behind a NAT firewall to play with those outside of the firewall. .TP .I autoupdate This is the autoupdate MPQ archive list. It chooses which versions of which clients to update. .TP .I tos.txt This is the Terms Of Service file that is displayed before a user can create a new account. .TP .I icons.bni The icons which the client displays for players in the chat rooms. .TP .I ad000001.pcx This is the ad Banner. Currently, it says "Welcome to... BNETD". .SH NOTES The current version is available at: .LP .RS .I http://www.bnetd.org/ .RE .SH "SEE ALSO" .BR bntrackd (1), .BR bnproxy (1), .BR bnchat (1), .BR bnbot (1), .BR bnpass (1), .BR bnftp (1), .BR bnetd.conf (5), .BR bnmotd.txt (5) .SH AUTHORS Ross Combs (\fIross@bnetd.org\fP), Rob Crittenden (\fIrob@bnetd.org\fP), and Mark Baysinger (\fImark@bnetd.org\fP) pvpgn-1.8.5/man/bnetd.conf.50000644000175000017500000002543411151345317014533 0ustar aaronaaron.\" .\" Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) .\" Copyright (C) 1998,1999,2000 Ross Combs (ross@bnetd.org) .\" Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNETD.CONF 5 "12 June, 2000" "BNETD" "BNETD User's Manual" .SH NAME bnetd.conf \- configuration for the Unix Battle.net daemon .SH DESCRIPTION The file .I bnetd.conf contains information used by the Unix Battle.net daemon .BR bnetd (1) to obtain system-specific information such as file locations and policies. .LP The file consists of a list of configuration entries and comments. A comment starts with a pound (#) sign and continues to the end of the line. Blank lines and whitespace are ignored between entries. A configuration entry is composed of two fields separated by an equals (=) sign: .IP \f2directive\f1 = \f2value\f1 .LP The .I directive field contains the name of the configuration item you want to set to the value of \f2value\f1. If the value contains spaces it should be surrounded by quotation marks ("). The value may not contain quotation marks. Multiple entries are not allowed on a single line. .LP If the field is Boolean, any of \fBtrue\fP, \fBfalse\fP, \fByes\fP, \fBno\fP, \fB1\fP, or \fB0\fP may be used. If the field is numeric, it must be in base ten. If the field is an address list, it must be delimited by commas. Each element may contain a hostname (or IP) and a port number. If a port number is given, it must be preceded by a colon (:). A colon by itself may be used to represent the wildcard address. If the field is a file or directory path, use of an absolute pathname is recommended. The values for \fBiconfile\fP, \fBtosfile\fP, and \fBmpqauthfile\fP are not pathnames but just the names of the files. They must be in the \fBfiledir\fP directory. .LP Recognized values for \f2directive\f1 include: .RS .TP 10 .B filedir Specifies the path where downloadable files are stored. These files are include the TOS (terms of service), icons, and ad banners. (Normally "files/") .TP .B userdir Specify the path where user accounts are stored. (Normally "users/") .TP .B reportdir Specify the path where game reports are stored. (Normally "reports/") .TP .B chanlogdir Specify the path where channel logs are stored. (Normally "chanlogs/") .TP .B defacct Specify the path of the default account file. This file contains all default account attributes which are used when an attribute is not set on an actual account. (Normally "bnetd_default_user") .TP .B motdfile Specify the path of the "message of the day" text file. This is displayed when a user enters the first chat channel. (Normally "bnmotd.txt") .TP .B channelfile Specify the path of the permanent channel list. (Normally "channel.list") .TP .B newsfile Specify the path of the file that is printed when the /news command is used. If no file is specified or the file doesn't exist then the server prints "No news today" to the user. (Normally "news.txt") .TP .B adfile Specify the path of the ad banner list which determines which banners to display at which times. (Normally "ad.list") .TP .B ipbanfile Specify the path of the IP ban file which can be used to block connections from certain addresses. (Normally "bnban") .TP .B helpfile Specify the path of the chat command help file. (Normally "bnhelp") .TP .B transfile Specify the path of the game address translation file which can be used to allow players from behind a NAT firewall to play with those outside of the firewall. (Normally "gametrans") .TP .B mpqfile Specify the path of the autoupdate MPQ archive list. It chooses which versions of which clients to update. (Normally "autoupdate") .TP .B logfile Specifies the file where the server appends the event messages selected with the \f3loglevels\f1 field. (Normally "bnetd.log") .TP .B pidfile Specify the path of the file where the server records its process ID. (Normally "bnetd.pid") .TP .B fortunecmd The path for the program to be executed when /fortune is used. See .BR fortune (6). (Normally "/usr/games/fortune") .TP .B loglevels Specify A comma-delimited list of message levels to log. The avaliable levels are: .RS .TP .B trace flow tracing statements .TP .B debug debugging information .TP .B info potentially useful informational .TP .B warn potentially serious events .TP .B error error messages and unexpected events .TP .B fatal fatal errors .RE .TP .B iconfile Specify the name of the BNI chat icons file which must be inside of the .B filedir directory. (Normally "icons.bni") .TP .B tosfile Specify the name of the TOS file which must be inside of the .B filedir directory. (Normally "tos.txt") .TP .B allow_autoupdate Enable or disable to automatic client update facility. If you want to allow different client versions to connect, set this to false. If you want to update all clients to the same version, be sure to also download the MPQ auth file, and the update MPQ. .TP .B mpqauthfile Specify the name of the MPQ authorization file which must be inside of the .B filedir directory. This file is used to determine the current client version. This is only needed if .B allow_autoupdate is turned on. (Normally "IX86ver1.mpq") .TP .B usersync Specify the time in seconds between account file saves. A value of 0 means to wait until shutdown to save account files and not do do periodic updates. .TP .B userflush Specify the number of seconds of inactivity before a user is unloaded from memory (only checked during file account updates, see usersync. After the account has been unloaded, it must be read from disk when accessed again. .TP .B latency How often to send user latency tests to the user, in seconds. These are used to decide how many "lag bars" to print next to users in channels. .TP .B shutdown_delay Specify the amount of time in seconds to delay shutting down the server when it receives a SIGTERM or SIGINT .BR signal (7). .TP .B shutdown_decr You can decrease the amount of time to wait by this value by sending another SIGTERM or SIGINT .BR signal (7). .TP .B newaccounts If this value is true then new accounts may be created by users on the system. Administrators can always use the /addacct chat command. .TP .B kick_oldlogin If this value is true then a second login by the same user will kick off the first, otherwise the second login will get message saying that they are already logged in. .TP .B ask_new_channel If this value is true, a user using the "Channels" button to join a non-existing channel will be asked if they wish to create it just like Battle.net. Otherwise, the channel will be created silently. .TP .B report_all_games If this value is true, all games with more than one player lasting for more than 5 minutes will be logged. Otherwise, only ladder games are logged. .TP .B hide_pass_games If this value is true, private (passworded) games will not be shown in the game list just like Battle.net. Otherwise all games will be listed. .TP .B hide_started_games If this value is true, games which have already stated will not be sent to the clients. The clients filter these games out for Starcraft and Brood War already. .TP .B hide_temp_channels If this value is true, private channels will not be shown in the channel list just like Battle.net. Otherwise all channels will be listed. .TP .B extra_commands If this value is true then all the extended chat commands are enabled, otherwise only those which exist on Battle.net are enabled. .TP .B disc_is_loss If this value is true then any disconnect will be treated as a loss (regardless of the setting in ladder games). .TP .B enable_conn_all If this value is true then all users may use the /con and /connections commands. Otherwise only administrators may use them. .TP .B hide_addr If this value is true then IP addresses will be hidden from non-admins in the output of the /con, /games, /gameinfo, and /netinfo commands. .TP .B chanlog If this value is true then private channels will be logged to files in the .B chanlogdir direcotry. The logging of public (permanent) channels is controlled in the .B channelfile file. .TP .B track Set this value to 0 to disable sending updates to the tracking server. Any other number will set the number of seconds between tracking packets. Try to use a number above 60 seconds unless you know the tracking server administrator doesn't mind being spammed. .TP .B trackaddrs Specify a comma-delimited list of addresses of tracking servers to send updates to. The address for the master server is "track.bnetd.org". A port may be specified after a colon numerically or by name from .BR /etc/services (5). If a port number is not specified, it defaults to 6114. .TP .B location Give a description of the physical location of the server such as "San Diego, CA, USA". This is reported to the tracking server. .TP .B description Give a description of title or role of the server such as "Joe's Spiffy Server". This is reported to the tracking server. .TP .B url Give a URL for the homepage or contact for the server such as "http://www.foo.com/joeserv.html". This is reported to the tracking server. .TP .B contact_name Give the name of the contact for the server such as "Joe Blockhead". This is reported to the tracking server. .TP .B contact_email Give the email address of the contact for the server such as "joe@foo.com". This is reported to the tracking server. .TP .B use_keepalive If this value is set to true, the server will enable the TCP keepalive option to allow the system to detect stale connections. .TP .B servaddrs Specify the comma-delimited list of addresses the server should listen on. A port may be specified after a colon numerically or by name from .BR /etc/services (5). If a port number is not specified, it defaults to 6112. .TP .B udptest_port The UDP port number which is assumed for clients if they don't send SESSIONADDR packets. If it is set to zero, the server will use the remote TCP port number as the default UDP port number. .SH SEE ALSO .BR bnetd (1) .SH AUTHOR Rob Crittenden (\fIrob@bnetd.org\fP), Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bnbot.10000644000175000017500000000531011151345317013602 0ustar aaronaaron.\" .\" Copyright (C) 2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNBOT 1 "11 June, 2000" "BNETD" "BNETD User's Manual" .SH NAME bnbot \- Battle.net text-based chat bot client .SH SYNOPSIS .B bnbot [\fIoptions\fP] \fIservername\fP [\fIserverport\fP] .SH DESCRIPTION .B bnbot is a simple program which will allow communication through the bot protocol of a Battle.net server from the command line. Input from stdin is sent to the server and output from the server is send to stdout. The interface is so simple that .BR telnet (1) could be used. The only complicating factor is that a control-C character must be sent to the server before any other input. .LP It is hoped that this program can be used with a scripting language like .BR expect (1) to make creation of chat bots for Unix easier. To date, I don't know of anyone doing this. This program may also be used to test bot login permissions for accounts. .LP If no \fIservername\fP is specified, localhost is assumed. If no \fIserverport\fP is specified, 6112 is assumed. .SH OPTIONS .TP .B \-h --help --usage Print usage information and exit. .TP .B \-v --version Print its version number and exit. .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS The terminal settings are not consulted for keybindings. The following are assumed: .TP ^H delete the character to the left of the cursor .TP ^J accept current line .TP ^M (return) accept current line .TP ^T transpose the last two characters .TP ^W delete word to the left of the cursor .TP ^U delete the whole input line .TP ^[ (escape) cancel the current input line .TP ^? (delete) delete the character to the left of the cursor .SH "SEE ALSO" .BR bnetd (1), .BR bnchat (1) .SH AUTHOR .TP Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bnproxy.10000644000175000017500000000507211151345317014204 0ustar aaronaaron.\" .\" Copyright (C) 2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNPROXY 1 "12 June, 2000" "BNETD" "BNETD User's Manual" .SH NAME bnproxy \- Battle.net proxy daemon .SH SYNOPSIS .B bnproxy [\fB-f\fP] [\fB-d\fP \fIdumpfile\fP] [\fB-l\fP \fIlogfile\fP] [\fB-p\fP \fIport\fP] [\fIservername\fP [\fIserverport\fP]] .BR .SH DESCRIPTION .B bnproxy is a simple daemon which will relay client connections to a Battle.net server like .BR bnetd (1). It has the capability of saving a hexadecimal/ASCII dump of the network records (packets) into a log file. Someday this command might be useful for people playing from behind a NAT firewall. .LP If no \fIservername\fP is specified, localhost is assumed. If no \fIserverport\fP is specified, 6112 is assumed. .SH OPTIONS .TP .B \-d --hexdump Put a hex dump of packets sent and received into the specified file. .TP .B \-f --foreground The server normally acts as a daemon and goes into the background. This forces the server to run in the foreground. .TP .B \-h --help --usage Print server usage information and exit. .TP .B \-l --logfile Put the event log messages into the specified file. .TP .B \-p --port Listen on the specified TCP and UDP port number. .TP .B \-v --version Causes .B bnproxy to print its version number and exit. .SH NOTES .TP The current version is available at: .LP .RS .I http://www.bnetd.org/ .RE .SH BUGS No support for dynamic UDP address determination (SESSIONADDR[12] packets) has been added. Support for multiple clients is broken because the server becomes confused as to which client to relay UDP server traffic to. .SH "SEE ALSO" .BR bnetd (1) .SH AUTHOR Ross Combs (\fIross@bnetd.org\fP) pvpgn-1.8.5/man/bnpass.10000644000175000017500000000376511151345317014000 0ustar aaronaaron.\" .\" Copyright (C) 1998,1999,2000 Ross Combs (ross@bnetd.org) .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .TH BNPASS 1 "09 April, 1999" "BNETD" "BNETD User's Manual" .SH NAME bnpass \- bnetd password utility .SH SYNOPSIS .B bnpass [\fIoptions\fP] [--] [\fIcleartextpassword\fP] .SH DESCRIPTION .B bnpass is a small utility which will output the ASCII hashed version of the clear text password in the same format as used in bnetd account files. This may be useful for writing a script to generate accounts or to reset a password in the bnetd user database. .LP If .I cleartextpassword is not specified you will be prompted to enter it into the standard input. .SH OPTIONS .TP .B \-h --help --usage Print usage information and exit. .TP .B \-v --version Print its version number and exit. .TP .B -- Signal end of options. Any further arguments will be treated as passwords even if they begin with a "-". .SH NOTES The current version is available with the bnetd distribution at: .LP .RS .I http://www.bnetd.org/ .RE .SH "SEE ALSO" .BR bnetd (1), .BR bnchat (1), .BR bnftp (1) .SH AUTHOR Ross Combs (\fIross@bnetd.org\fP)