EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Commands.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Zhur, Bloody.Rabbit
24 */
25 
26 #include "eve-tool.h"
27 
28 #include "Commands.h"
29 
30 /************************************************************************/
31 /* Commands declaration */
32 /************************************************************************/
33 void DestinyDumpLogText( const Seperator& cmd );
34 void CRC32Text( const Seperator& cmd );
35 void ExitProgram( const Seperator& cmd );
36 void PrintHelp( const Seperator& cmd );
37 void ObjectToSQL( const Seperator& cmd );
38 void PrintTimeNow( const Seperator& cmd );
39 void LoadScript( const Seperator& cmd );
40 void TimeToString( const Seperator& cmd );
41 void TriToOBJ( const Seperator& cmd );
42 void UnmarshalLogText( const Seperator& cmd );
43 void StuffExtract( const Seperator& cmd );
44 
45 /************************************************************************/
46 /* Command array stuff */
47 /************************************************************************/
49 {
50  { "destiny", &DestinyDumpLogText, "Converts given string to binary and dumps it as destiny binary." },
51  { "crc32", &CRC32Text, "Computes CRC-32 checksum of given arguments." },
52  { "exit", &ExitProgram, "Quits current session." },
53  { "help", &PrintHelp, "Lists available commands or prints help about specified one." },
54  { "now", &PrintTimeNow, "Prints current time in Win32 time format." },
55  { "obj2sql", &ObjectToSQL, "Converts specified cache object into an SQL update." },
56  { "script", &LoadScript, "Loads input from specified file(s)." },
57  { "time", &TimeToString, "Interprets given integer as Win32 time." },
58  { "tri2obj", &TriToOBJ, "Dumps specified TRI file." },
59  { "unmarshal", &UnmarshalLogText, "Converts given string to binary and unmarshals it." },
60  { "xstuff", &StuffExtract, "Dumps specified STUFF file." }
61 };
62 const size_t EVETOOL_COMMAND_COUNT = ( sizeof( EVETOOL_COMMANDS ) / sizeof( EVEToolCommand ) );
63 
64 const EVEToolCommand* FindCommand( const char* name )
65 {
66  return FindCommand( std::string( name ) );
67 }
68 
69 const EVEToolCommand* FindCommand( const std::string& name )
70 {
71  for( size_t i = 0; i < EVETOOL_COMMAND_COUNT; ++i )
72  {
73  const EVEToolCommand* c = &EVETOOL_COMMANDS[i];
74 
75  if( c->name == name )
76  return c;
77  }
78 
79  return NULL;
80 }
81 
82 void ProcessCommand( const Seperator& cmd )
83 {
84  const char* cmdName = cmd.arg( 0 ).c_str();
85  const EVEToolCommand* c = FindCommand( cmdName );
86 
87  if( NULL == c )
88  sLog.Error( "input", "Unknown command '%s'.", cmdName );
89  else
90  ( *c->callback )( cmd );
91 }
92 
93 /************************************************************************/
94 /* Commands implementation */
95 /************************************************************************/
96 void DestinyDumpLogText( const Seperator& cmd )
97 {
98  const char* cmdName = cmd.arg( 0 ).c_str();
99 
100  if( 1 == cmd.argCount() )
101  {
102  sLog.Error( cmdName, "Usage: %s destiny-binary [destiny-binary] ...", cmdName );
103  return;
104  }
105 
106  for( size_t i = 1; i < cmd.argCount(); ++i )
107  {
108  const std::string& destinyBinaryStr = cmd.arg( i );
109 
110  Buffer destinyBinary;
111  if( !PyDecodeEscape( destinyBinaryStr.c_str(), destinyBinary ) )
112  {
113  sLog.Error( cmdName, "Failed to decode destiny binary." );
114  continue;
115  }
116 
117  Destiny::DumpUpdate( DESTINY__MESSAGE, &destinyBinary[0], destinyBinary.size() );
118  }
119 }
120 
121 void CRC32Text( const Seperator& cmd )
122 {
123  const char* cmdName = cmd.arg( 0 ).c_str();
124 
125  if( 1 == cmd.argCount() )
126  {
127  sLog.Error( cmdName, "Usage: %s text-to-checksum [text-to-checksum] ...", cmdName );
128  return;
129  }
130 
131  for( size_t i = 1; i < cmd.argCount(); ++i )
132  {
133  const std::string& s = cmd.arg( i );
134 
135  sLog.Log( cmdName, "%X", CRC32::Generate( (const uint8*)s.c_str(), s.size() ) );
136  }
137 }
138 
139 void ExitProgram( const Seperator& cmd )
140 {
141  // just close standart input
142  fclose( stdin );
143 }
144 
145 void PrintHelp( const Seperator& cmd )
146 {
147  const char* cmdName = cmd.arg( 0 ).c_str();
148 
149  if( 1 == cmd.argCount() )
150  {
151  sLog.Log( cmdName, "Available commands:" );
152 
153  for( size_t i = 0; i < EVETOOL_COMMAND_COUNT; ++i )
154  {
155  const EVEToolCommand* c = &EVETOOL_COMMANDS[i];
156 
157  sLog.Log( cmdName, "%s", c->name );
158  }
159 
160  sLog.Log( cmdName, "You can get detailed help by typing '%s <command> [<command>] ...'.", cmdName );
161  }
162  else
163  {
164  for( size_t i = 1; i < cmd.argCount(); ++i )
165  {
166  const std::string& cmdStr = cmd.arg( i );
167  const EVEToolCommand* c = FindCommand( cmdStr );
168 
169  if( NULL == c )
170  sLog.Error( cmdName, "Unknown command '%s'.", cmdStr.c_str() );
171  else
172  sLog.Log( cmdName, "%s: %s", c->name, c->description );
173  }
174  }
175 }
176 
177 void PrintTimeNow( const Seperator& cmd )
178 {
179  const char* cmdName = cmd.arg( 0 ).c_str();
180 
181  sLog.Log( cmdName, "Now in Win32 time: %" PRIu64 ".", Win32TimeNow() );
182 }
183 
184 void ObjectToSQL( const Seperator& cmd )
185 {
186  const char* cmdName = cmd.arg( 0 ).c_str();
187 
188  if( 5 != cmd.argCount() )
189  {
190  sLog.Error( cmdName, "Usage: %s [cache_file] [table_name] [key_field] [file_name]", cmdName );
191  return;
192  }
193  const std::string& cacheFile = cmd.arg( 1 );
194  const std::string& tableName = cmd.arg( 2 );
195  const std::string& keyField = cmd.arg( 3 );
196  const std::string& fileName = cmd.arg( 4 );
197 
198  std::string abs_fname( "../data/cache/" );
199  abs_fname += cacheFile;
200  abs_fname += ".cache";
201 
202  sLog.Log( cmdName, "Converting cached object %s:\n", abs_fname.c_str() );
203 
204  CachedObjectMgr mgr;
205  PyCachedObjectDecoder* obj = mgr.LoadCachedObject( abs_fname.c_str(), cacheFile.c_str() );
206  if( obj == NULL )
207  {
208  sLog.Error( cmdName, "Unable to load or decode '%s'!", abs_fname.c_str() );
209  return;
210  }
211 
212  obj->cache->DecodeData();
213  if( obj->cache->decoded() == NULL )
214  {
215  sLog.Error( cmdName, "Unable to load or decode body of '%s'!", abs_fname.c_str() );
216 
217  SafeDelete( obj );
218  return;
219  }
220 
221  FILE* out = fopen( fileName.c_str(), "w" );
222  if( out == NULL )
223  {
224  sLog.Error( cmdName, "Unable to open output file '%s'", fileName.c_str() );
225 
226  SafeDelete( obj );
227  return;
228  }
229 
230  SetSQLDumper dumper( tableName.c_str(), keyField.c_str(), out );
231  if( obj->cache->decoded()->visit( dumper ) )
232  sLog.Success( cmdName, "Dumping of %s succeeded.", tableName.c_str() );
233  else
234  sLog.Error( cmdName, "Dumping of %s failed.", tableName.c_str() );
235 
236  fclose( out );
237  SafeDelete( obj );
238 }
239 
240 void LoadScript( const Seperator& cmd )
241 {
242  const char* cmdName = cmd.arg( 0 ).c_str();
243 
244  if( 1 == cmd.argCount() )
245  {
246  sLog.Error( cmdName, "Usage: %s file [file] ...", cmdName );
247  return;
248  }
249 
250  for( size_t i = 1; i < cmd.argCount(); ++i )
251  ProcessFile( cmd.arg( i ) );
252 }
253 
254 void TimeToString( const Seperator& cmd )
255 {
256  const char* cmdName = cmd.arg( 0 ).c_str();
257 
258  if( 1 == cmd.argCount() )
259  {
260  sLog.Error( cmdName, "Usage: %s win32-time [win32-time] ...", cmdName );
261  return;
262  }
263 
264  for( size_t i = 1; i < cmd.argCount(); ++i )
265  {
266  const std::string& timeStr = cmd.arg( i );
267 
268  uint64 t;
269  sscanf( timeStr.c_str(), "%" SCNu64, &t );
270  const std::string time = Win32TimeToString( t );
271 
272  sLog.Log( cmdName, "%s is %s.", timeStr.c_str(), time.c_str() );
273  }
274 }
275 
276 void TriToOBJ( const Seperator& cmd )
277 {
278  const char* cmdName = cmd.arg( 0 ).c_str();
279 
280  if( 4 != cmd.argCount() )
281  {
282  sLog.Error( cmdName, "Usage: %s [trifile] [objout] [mtlout]", cmdName );
283  return;
284  }
285  const std::string& trifile = cmd.arg( 1 );
286  const std::string& objout = cmd.arg( 2 );
287  const std::string& mtlout = cmd.arg( 3 );
288 
289  TriExporter::TriFile f;
290  if( !f.LoadFile( trifile.c_str() ) )
291  {
292  sLog.Error( cmdName, "Failed to load trifile '%s'.", trifile.c_str() );
293  return;
294  }
295 
296  f.DumpHeaders();
297  f.ExportObj( objout.c_str(), mtlout.c_str() );
298 
299  sLog.Success( cmdName, "%s - %s - written.", objout.c_str(), mtlout.c_str() );
300 }
301 
302 void UnmarshalLogText( const Seperator& cmd )
303 {
304  const char* cmdName = cmd.arg( 0 ).c_str();
305 
306  if( 1 == cmd.argCount() )
307  {
308  sLog.Error( cmdName, "Usage: %s marshal-binary [marshal-binary] ...", cmdName );
309  return;
310  }
311 
312  for( size_t i = 1; i < cmd.argCount(); ++i )
313  {
314  const std::string& marshalBinaryStr = cmd.arg( i );
315 
316  Buffer marshalBinary;
317  if( !PyDecodeEscape( marshalBinaryStr.c_str(), marshalBinary ) )
318  {
319  sLog.Error( cmdName, "Failed to decode string into binary." );
320  continue;
321  }
322 
323  PyRep* r = InflateUnmarshal( marshalBinary );
324  if( NULL == r )
325  sLog.Error( cmdName, "Failed to unmarshal binary." );
326  else
327  {
328  sLog.Success( cmdName, "Result:" );
329  r->Dump( stdout, " " );
330 
331  PyDecRef( r );
332  }
333  }
334 }
335 
336 #pragma pack( 1 )
338 {
341 };
342 #pragma pack()
343 
345 {
347  size_t offset;
348  std::string filename;
349 };
350 
351 void StuffExtract( const Seperator& cmd )
352 {
353  const char* cmdName = cmd.arg( 0 ).c_str();
354 
355  if( 2 != cmd.argCount() )
356  {
357  sLog.Error( cmdName, "Usage: %s [.stuff file]", cmdName );
358  return;
359  }
360  const std::string& filename = cmd.arg( 1 );
361 
362  FILE* in = fopen( filename.c_str(), "rb" );
363  if( NULL == in )
364  {
365  sLog.Error( cmdName, "Unable to open %s.", filename.c_str() );
366  return;
367  }
368 
369  uint32 file_count;
370  if( 1 != fread( &file_count, sizeof( file_count ), 1, in ) )
371  {
372  sLog.Log( cmdName, "Unable to read file count." );
373  return;
374  }
375 
376  sLog.Log( cmdName, "There are %u files in %s.", file_count, filename.c_str() );
377 
378  std::vector<FileHeaderObj> headers;
379  headers.resize( file_count );
380 
381  size_t offset = 0;
382  for( uint32 i = 0; i < file_count; i++ )
383  {
384  FileHeader head;
385  if( 1 != fread( &head, sizeof( head ), 1, in ) )
386  {
387  sLog.Error( cmdName, "Unable to read header of file #%u.", i );
388  return;
389  }
390 
391  FileHeaderObj& obj = headers[ i ];
392  obj.length = head.file_size;
393  obj.offset = offset;
394 
395  ++head.path_len; // NULL term
396 
397  //read path name.
398  obj.filename.resize( head.path_len );
399  if( head.path_len != fread( &obj.filename[0], 1, head.path_len, in ) )
400  {
401  sLog.Error( cmdName, "Unable to read name of file #%u.", i );
402  return;
403  }
404  //drop read NULL term
405  obj.filename.resize( head.path_len - 1 );
406 
407  sLog.Log( cmdName, "File #%u has length %u and path %s.", i, obj.length, obj.filename.c_str() );
408  offset += head.file_size;
409  }
410 
411  std::vector<FileHeaderObj>::const_iterator cur, end;
412  cur = headers.begin();
413  end = headers.end();
414  for(; cur != end; cur++)
415  {
416  //split the path into components, make the intermediate directories
417  //if needed, and then finally open the file and write it out.
418  std::vector<std::string> components;
419  SplitPath( cur->filename, components );
420 
421  std::string pathname = ".";
422 
423  std::vector<std::string>::const_iterator curc, endc;
424  curc = components.begin();
425  endc = components.end();
426  for(; curc != endc; curc++ )
427  {
428  pathname += "/";
429  pathname += *curc;
430 
431  if( ( curc + 1 ) == endc )
432  {
433  //this is the file component.
434  FILE* out = fopen( pathname.c_str(), "wb" );
435  if( NULL == out )
436  {
437  sLog.Error( cmdName, "Unable to create file %s: %s.", pathname.c_str(), strerror( errno ) );
438  break;
439  }
440 
441  sLog.Log( cmdName, "Extracting file %s of length %u.", pathname.c_str(), cur->length );
442 
443  Buffer buf( cur->length );
444  if( cur->length != fread( &buf[0], 1, cur->length, in ) )
445  {
446  sLog.Error( cmdName, "Unable to read file %s: %s.", cur->filename.c_str(), strerror( errno ) );
447  break;
448  }
449 
450  if( cur->length != fwrite( &buf[0], 1, cur->length, out ) )
451  {
452  sLog.Error( cmdName, "Unable to write file %s: %s", pathname.c_str(), strerror( errno ) );
453  break;
454  }
455 
456  fclose( out );
457  }
458  else
459  {
460  //this is an intermediate directory.
461  struct stat stat_struct;
462 
463  if( -1 == stat( pathname.c_str(), &stat_struct ) )
464  {
465  if( ENOENT == errno )
466  {
467  if( 0 == CreateDirectory( pathname.c_str(), NULL ) )
468  {
469  sLog.Error( cmdName, "Failed to make intermediate directory %s: %s", pathname.c_str(), strerror( errno ) );
470  break;
471  }
472  }
473  else
474  {
475  sLog.Error( cmdName, "Unable to stat %s: %s", pathname.c_str(), strerror( errno ) );
476  break;
477  }
478  }
479  }
480  }
481  }
482 
483  fclose( in );
484 
485  sLog.Log( cmdName, "Extracting from archive %s finished.", filename.c_str() );
486 }
487 
Base Python wire object.
Definition: PyRep.h:66
unsigned __int8 uint8
Definition: eve-compat.h:46
uint32 file_size
Definition: Commands.cpp:339
bool PyDecodeEscape(const char *str, Buffer &into)
Decodes string escapes into actual characters.
void UnmarshalLogText(const Seperator &cmd)
Definition: Commands.cpp:302
PyRep * InflateUnmarshal(const Buffer &data)
Turns possibly inflated marshal stream into Python object.
const std::string & arg(size_t index) const
Definition: Seperator.h:43
void LoadScript(const Seperator &cmd)
Definition: Commands.cpp:240
size_t offset
Definition: Commands.cpp:347
void(* callback)(const Seperator &cmd)
Definition: Commands.h:35
void SplitPath(const std::string &path, std::vector< std::string > &into)
Splits path to its components.
uint32 length
Definition: Commands.cpp:346
Python object SQL dumper.
Definition: RowsetReader.h:191
void ProcessFile(FILE *file)
Loads commands from given file.
Definition: eve-tool.cpp:76
Separates string to arguments.
Definition: Seperator.h:36
void Dump(FILE *into, const char *pfx) const
Dumps object to file.
Definition: PyRep.cpp:84
void PrintTimeNow(const Seperator &cmd)
Definition: Commands.cpp:177
uint32 path_len
Definition: Commands.cpp:340
void SafeDelete(T *&p)
Deletes and nullifies a pointer.
Definition: SafeMem.h:83
void CRC32Text(const Seperator &cmd)
Definition: Commands.cpp:121
void TimeToString(const Seperator &cmd)
Definition: Commands.cpp:254
PyRep * decoded() const
Definition: PyRep.h:1048
#define sLog
Evaluates to a NewLog instance.
Definition: LogNew.h:250
size_t argCount() const
Definition: Seperator.h:44
Generic class for buffers.
Definition: Buffer.h:40
void DecodeData() const
Definition: PyRep.cpp:1125
const char * name
Definition: Commands.h:33
std::string filename
Definition: Commands.cpp:348
const EVEToolCommand * FindCommand(const char *name)
Finds a command.
Definition: Commands.cpp:64
void ExitProgram(const Seperator &cmd)
Definition: Commands.cpp:139
int CreateDirectory(const char *name, void *)
Definition: eve-compat.cpp:46
void StuffExtract(const Seperator &cmd)
Definition: Commands.cpp:351
int64 Win32TimeNow()
Definition: utils_time.cpp:70
static uint32 Generate(const uint8 *buf, size_t bufsize)
Definition: crc32.h:41
void TriToOBJ(const Seperator &cmd)
Definition: Commands.cpp:276
#define PyDecRef(op)
Definition: PyRep.h:57
const EVEToolCommand EVETOOL_COMMANDS[]
Definition: Commands.cpp:48
unsigned __int32 uint32
Definition: eve-compat.h:50
void ProcessCommand(const Seperator &cmd)
Processed given command.
Definition: Commands.cpp:82
#define PRIu64
Definition: eve-compat.h:85
size_type size() const
Definition: Buffer.h:610
void DumpUpdate(LogType into, const uint8 *data, uint32 len)
void ObjectToSQL(const Seperator &cmd)
Definition: Commands.cpp:184
void DestinyDumpLogText(const Seperator &cmd)
Definition: Commands.cpp:96
std::string Win32TimeToString(int64 win32t)
Definition: utils_time.cpp:59
#define SCNu64
Definition: eve-compat.h:110
PyCachedObjectDecoder * LoadCachedObject(const char *filename, const char *oname)
void PrintHelp(const Seperator &cmd)
Definition: Commands.cpp:145
const size_t EVETOOL_COMMAND_COUNT
Definition: Commands.cpp:62
const char * description
Definition: Commands.h:37
virtual bool visit(PyVisitor &v) const =0
Visits object.