Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

391 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implementation of CLogEvent
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. //
  8. //------------------------------------------------------------------------------------------------------
  9. // $Log: $
  10. //
  11. // $NoKeywords: $
  12. //=============================================================================//
  13. #include <stdio.h>
  14. #include <time.h>
  15. #include <string.h>
  16. #include "LogEvent.h"
  17. #include "util.h"
  18. #include "memdbg.h"
  19. //For debugging more than anything
  20. const char* CLogEvent::TypeNames[]=
  21. {
  22. {"No Type/Invalid!"},
  23. {"Log File Initialize"},
  24. {"Server Spawn"},
  25. {"Server Shutdown"},
  26. {"Log Closed"},
  27. {"Server Misc"},
  28. {"Server Name"},
  29. {"Team Rename"},
  30. {"Level Change"},
  31. {"Cvar Assignment"},
  32. {"Map CRC"},
  33. {"Team Join"},
  34. {"Connect"},
  35. {"Enter game"},
  36. {"Disconnect"},
  37. {"Name Change"},
  38. {"Frag!"},
  39. {"Team frag!"},
  40. {"Suicide!"},
  41. {"Killed by world!"},
  42. {"Build"},
  43. {"Match Results Marker"},
  44. {"Match Draw"},
  45. {"Match Victor"},
  46. {"Match Team Results"},
  47. {"Talk"},
  48. {"Team Talk"},
  49. {"Cure"},
  50. {"Named Goal Activated"},
  51. {"Anon Goal Activated"},
  52. {"Named Broadcast"},
  53. {"Anon Broadcast"},
  54. {"Change Class"},
  55. };
  56. //------------------------------------------------------------------------------------------------------
  57. // Function: CLogEvent::getArgument
  58. // Purpose: returns the iWhichArg'th argument
  59. // Input: iWhichArg - the desired argument
  60. // Output: const CLogEventArgument*
  61. //------------------------------------------------------------------------------------------------------
  62. const CLogEventArgument* CLogEvent::getArgument(int iWhichArg) const
  63. {
  64. if (iWhichArg < m_args.size())
  65. return m_args[iWhichArg];
  66. else
  67. return NULL;
  68. }
  69. //------------------------------------------------------------------------------------------------------
  70. // Function: CLogEvent::parseArgs
  71. // Purpose: extracts the arguments out of the event text.
  72. //------------------------------------------------------------------------------------------------------
  73. void CLogEvent::parseArgs()
  74. {
  75. char temp[512];
  76. char* write=temp;
  77. const char* read=m_EventMessage;
  78. int i=0;
  79. while (*read)
  80. {
  81. if (*read == '\"')
  82. {
  83. //parseArgument moves the read pointer to the char after the closing "
  84. parseArgument(++read);
  85. *(write++)='[';
  86. *(write++)=(char)(i++)+48; //convert int to char by adding 48
  87. *(write++)=']';
  88. }
  89. else
  90. *write++=*read;
  91. *read++;
  92. }
  93. *write=0;
  94. Util::str2lowercase(temp,temp);
  95. m_StrippedText=new TRACKED char[strlen(temp)+1];
  96. strcpy(m_StrippedText,temp);
  97. }
  98. //------------------------------------------------------------------------------------------------------
  99. // Function: CLogEvent::parseArgument
  100. // Purpose: helper function for parseArgs, this actually removes the argument
  101. // Input: raw - the string from which we want to remove the argument
  102. //------------------------------------------------------------------------------------------------------
  103. void CLogEvent::parseArgument(const char*& raw)
  104. {
  105. char* atemp;
  106. if (!(atemp=strchr(raw,'\"')))
  107. return;
  108. *atemp=0; //null out the closing "
  109. CLogEventArgument* newarg=new CLogEventArgument(raw);
  110. newarg->init(raw);
  111. m_args.push_back(newarg);
  112. *atemp='\"'; //restore it.
  113. raw=atemp; //advance the pointer
  114. }
  115. //------------------------------------------------------------------------------------------------------
  116. // Function: CLogEvent::keywordsOccur
  117. // Purpose: tests to see if all of the given keywords occur in the text for this event
  118. // Input: s1 - first keyword (required)
  119. // s2 - second keyword (optional)
  120. // s3 - third keyword (optional)
  121. // Output: Returns true if the event text contains all of the keywords passed in
  122. //------------------------------------------------------------------------------------------------------
  123. bool CLogEvent::keywordsOccur(char* s1,char* s2,char* s3)
  124. {
  125. bool result=(strstr(m_StrippedText,s1)!=NULL);
  126. if (s2)
  127. {
  128. result = result && (strstr(m_StrippedText,s2)!=NULL);
  129. if (s3)
  130. {
  131. result = result && (strstr(m_StrippedText,s3)!=NULL);
  132. }
  133. }
  134. return result;
  135. }
  136. //------------------------------------------------------------------------------------------------------
  137. // Function: CLogEvent::determineType
  138. // Purpose: this is a big dumb if statement to determine the type of this event
  139. //------------------------------------------------------------------------------------------------------
  140. //this is pretty cheesy
  141. void CLogEvent::determineType()
  142. {
  143. //for now just do this in a big dumb if statement
  144. if (keywordsOccur("killed","self","with"))
  145. m_EventType=SUICIDE;
  146. else if (keywordsOccur("log closed"))
  147. m_EventType=LOG_CLOSED;
  148. else if (keywordsOccur("server name is"))
  149. m_EventType=SERVER_NAME;
  150. else if (keywordsOccur("team name of"))
  151. m_EventType=TEAM_RENAME;
  152. else if (keywordsOccur("killed","by","world"))
  153. m_EventType=KILLED_BY_WORLD;
  154. else if (keywordsOccur("killed","(teammate)"))
  155. m_EventType=TEAM_FRAG;
  156. else if (keywordsOccur("killed","with"))
  157. m_EventType=FRAG;
  158. else if (keywordsOccur("say_team"))
  159. m_EventType=SAY_TEAM;
  160. else if (keywordsOccur("say"))
  161. m_EventType=SAY;
  162. else if (keywordsOccur("joined team"))
  163. m_EventType=TEAM_JOIN;
  164. else if (keywordsOccur("changed to team"))
  165. m_EventType=TEAM_JOIN;
  166. else if (keywordsOccur("log file started"))
  167. m_EventType=LOG_FILE_INIT;
  168. else if (keywordsOccur("spawning server"))
  169. m_EventType=SERVER_SPAWN;
  170. else if (keywordsOccur("connected","address"))
  171. m_EventType=CONNECT;
  172. else if (keywordsOccur("has entered the game"))
  173. m_EventType=ENTER_GAME;
  174. else if (keywordsOccur("disconnected"))
  175. m_EventType=DISCONNECT;
  176. else if (keywordsOccur("changed name to"))
  177. m_EventType=NAME_CHANGE;
  178. else if (keywordsOccur("built"))
  179. m_EventType=BUILD;
  180. else if (keywordsOccur("map crc"))
  181. m_EventType=MAP_CRC;
  182. else if (keywordsOccur("match","results","=------="))
  183. m_EventType=MATCH_RESULTS_MARKER;
  184. else if (keywordsOccur("activated the goal"))
  185. m_EventType=NAMED_GOAL_ACTIVATE;
  186. else if (keywordsOccur("goal", "was activated"))
  187. m_EventType=ANON_GOAL_ACTIVATE;
  188. else if (keywordsOccur("named broadcast"))
  189. m_EventType=NAMED_BROADCAST;
  190. else if (keywordsOccur("broadcast"))
  191. m_EventType=ANON_BROADCAST;
  192. else if (keywordsOccur("changed class"))
  193. m_EventType=CLASS_CHANGE;
  194. else if (keywordsOccur("-> draw <-"))
  195. m_EventType=MATCH_DRAW;
  196. else if (keywordsOccur("defeated"))
  197. m_EventType=MATCH_VICTOR;
  198. else if (keywordsOccur("results"))
  199. m_EventType=MATCH_TEAM_RESULTS;
  200. else if (keywordsOccur("="))
  201. m_EventType=CVAR_ASSIGN;
  202. else m_EventType=SERVER_MISC;
  203. }
  204. //------------------------------------------------------------------------------------------------------
  205. // Function: CLogEvent::CLogEvent
  206. // Purpose: CLogEvent constructor
  207. //------------------------------------------------------------------------------------------------------
  208. CLogEvent::CLogEvent()
  209. :m_EventCode('\0'),m_EventTime(0),m_Valid(false),m_Next(NULL),m_StrippedText(NULL),m_EventType(INVALID),m_EventMessage(NULL)
  210. {}
  211. //------------------------------------------------------------------------------------------------------
  212. // Function: CLogEvent::~CLogEvent
  213. // Purpose: CLogEvent destructor
  214. //------------------------------------------------------------------------------------------------------
  215. CLogEvent::~CLogEvent()
  216. {
  217. //this errors?!
  218. if (m_EventMessage)
  219. delete[] m_EventMessage;
  220. if (m_StrippedText)
  221. delete[] m_StrippedText;
  222. }
  223. //------------------------------------------------------------------------------------------------------
  224. // Function: CLogEvent::print
  225. // Purpose: debugging function, prints this event to a file
  226. // Input: f - the file to print to
  227. //------------------------------------------------------------------------------------------------------
  228. void CLogEvent::print(FILE* f)
  229. {
  230. fprintf(f,"(%li) Event: %s\n",m_EventTime,m_EventMessage);
  231. }
  232. //------------------------------------------------------------------------------------------------------
  233. // Function: CLogEvent::CLogEvent
  234. // Purpose: CLogEvent constructor that reads an event from the specified file
  235. // Input: f - the file to read from
  236. //------------------------------------------------------------------------------------------------------
  237. CLogEvent::CLogEvent(FILE* f)
  238. :m_EventCode('\0'),m_EventTime(0),m_Valid(false),m_Next(NULL),m_StrippedText(NULL),m_EventType(INVALID),m_EventMessage(NULL)
  239. {
  240. readEvent(f);
  241. }
  242. //------------------------------------------------------------------------------------------------------
  243. // Function: CLogEvent::readEvent
  244. // Purpose: reads an event by reading each part, then checking if it was successful
  245. // Input: f - the file to read from
  246. //------------------------------------------------------------------------------------------------------
  247. void CLogEvent::readEvent(FILE* f)
  248. {
  249. m_Valid=true;
  250. if (m_Valid) readEventCode(f);
  251. if (m_Valid) readEventTime(f);
  252. if (m_Valid) readEventMessage(f);
  253. if (m_Valid) parseArgs();
  254. if (m_Valid) determineType();
  255. if (m_Valid) m_Valid=!feof(f);
  256. }
  257. //------------------------------------------------------------------------------------------------------
  258. // Function: CLogEvent::readEventCode
  259. // Purpose: reads the event code, the first character on the line (should be 'L')
  260. // Input: f - the file to read from
  261. //------------------------------------------------------------------------------------------------------
  262. void CLogEvent::readEventCode(FILE* f)
  263. {
  264. fscanf(f," %c ",&m_EventCode);
  265. if (m_EventCode!='L')
  266. m_Valid=false;
  267. if (feof(f))
  268. m_Valid=false;
  269. }
  270. //------------------------------------------------------------------------------------------------------
  271. // Function: CLogEvent::readEventMessage
  272. // Purpose: reads the text of the event message.
  273. // Input: f - the file to read from
  274. //------------------------------------------------------------------------------------------------------
  275. void CLogEvent::readEventMessage(FILE* f)
  276. {
  277. char temp[512];
  278. fgets(temp,512,f);
  279. //special case hack for broadcasts
  280. if (strncmp(temp,"Named Broadcast:",16)==0 || strncmp(temp,"Broadcast:",16)==0)
  281. {
  282. while(1)
  283. {
  284. fpos_t temp_pos;
  285. fgetpos(f,&temp_pos);
  286. CLogEvent cle(f);
  287. fseek(f,temp_pos,SEEK_SET);
  288. if (cle.isValid())
  289. {
  290. //if the next log event is valid, then this broadcast did not span lines
  291. break;
  292. }
  293. else
  294. {
  295. temp[strlen(temp)-1]=' '; //rid ourselves of newline
  296. temp[strlen(temp)]=0; //rid ourselves of newline
  297. char buf[512];
  298. fgets(buf,512,f);
  299. strcat(temp,buf);
  300. }
  301. }
  302. }
  303. if (feof(f))
  304. {
  305. m_Valid=false;
  306. }
  307. else
  308. {
  309. temp[strlen(temp)-1]=0; //rid ourselves of newline
  310. m_EventMessage=new TRACKED char[strlen(temp)+1];
  311. strcpy(m_EventMessage,temp);
  312. }
  313. }
  314. //------------------------------------------------------------------------------------------------------
  315. // Function: CLogEvent::readEventTime
  316. // Purpose: reads and converts the time the event happened into a time_t
  317. // Input: f - the file to read from
  318. //------------------------------------------------------------------------------------------------------
  319. void CLogEvent::readEventTime(FILE* f)
  320. {
  321. int month=-1,day=-1,year=-1;
  322. int hour=-1,minute=-1,second=-1;
  323. fscanf(f," %d/%d/%d - %d:%d:%d: ",&month,&day,&year,&hour,&minute,&second);
  324. if (month==-1 ||day==-1 ||year==-1 || hour==-1 || minute==-1 || second==-1)
  325. m_Valid=false;
  326. else if (feof(f))
  327. m_Valid=false;
  328. else
  329. {
  330. tm t;
  331. t.tm_isdst=0;
  332. t.tm_hour=hour;
  333. t.tm_mday=day;
  334. t.tm_min=minute;
  335. t.tm_sec=second;
  336. t.tm_year=year-1900; //note no y2k prob here, so says the CRT manual
  337. //this allows values greater than 99, but it
  338. //just wants the input with 1900 subtracted.
  339. t.tm_mon=month-1; //jan = 0
  340. m_EventTime=mktime(&t);
  341. }
  342. }